今すぐ入れろ‼︎ おすすめAsset紹介(Unity)
こんにちは、昨日ぶりです。
coading課のguuです。
今日はUnityのおすすめAssetを紹介していきます。
軽く使い方も解説しているので、参考にしてください。
最後に、おまけで買ってよかったAssetも紹介します。
目次
生活インフラ
UniTask
待つ処理は全部こいつでできます。
Unityには標準でコルーチンという待つ処理を行うためのものがありますが、コルーチンよりもUniTaskの方が簡単でわかりやすいので、UniTaskをお勧めします。
良いところ
- コルーチンよりも簡単に使える
- 並列処理ができる
- Taskよりも処理が速い
- UniTaskで定義した関数を待てるので、コードが複雑になりにくい
- Monobehaviourを継承してなくても動く
- 待つ処理の停止をキャンセレーショントークンで一括管理できる
- 簡単にタイムアウトを実装できる
- 学習コストが低い
- 無料
悪いところ
- GitHub経由でしかダウンロードできない
使い方
private async UniTask 関数名()
{
await UniTaskの待つ処理;
}
待つ処理は主に上記のコードのように書きます。
待つ処理を書くときのポイントは以下のものです。
- 関数の修飾子にasyncを追加
- 返り値をUniTaskにする(voidでも動きはする)
- UniTaskの待つ処理の前に、awaitをつける
- UniTaskの処理には、キャンセレーショントークンを設定する
使用上の注意
UniTaskの待つイベントは、明示的に止めてあげないと裏で永遠に動いています。
つまり、「ゲームオブジェクト破壊したし、UniTaskも止まっているでしょ」とはならない
UniTaskを止めるためには、キャンセレーショントークンというものを定義する必要があります。
キャンセレーショントークンの使い方は、下記の使用例を見てください。
使用例
1秒待ってみる
private async UniTask WaitAsync(CancellatioonToken ct)
{
await UniTask.Delay(1, cancellationToken : ct);
}
boolがtrueになるまで待つ
public bool IsFinish = false;
private async UniTask WaitTrue(CancellationToken ct)
{
await UniTask.WaitUntil(() => IsFinsh, cancellationToken:ct);
}
複数の待つイベントがすべて終わるまで待つ
public bool IsFirst=false;
public bool IsSecound=false;
private async UniTask WaitSomeEvent(CancellationToken ct)
{
await UniTask.WhenAll(
UniTask.WaitUntil(() => IsFirst, cancellationToken: ct),
UniTask.WaitUntil(() => IsSecond, cancellationToken: ct)
);
}
キャンセレーショントークンの定義
/// <summary>
/// ゲームオブジェクト破壊時に停止を命令するキャンセレーショントークン
/// </summary>
private CancellationToken _ct => this.GetCancellationTokenOnDestroy();
/// <summary>
/// 任意のタイミングで停止を命令できるキャンセレーショントークンを持つキャンセレーショントークンソース
/// </summary>
private CancellationTokenSource _cts = new();
private Awake()
{
// 上で定義した_ct が停止したら、一緒にキャンセレーショントークンソースも停止する
_cts = CancellationTokenSource.CreateLinkedTokenSource(_ct);
// _cts.Tokenがキャンセレーショントークン
await UniTask.WaitUntil(() => Input.GetKeyDown(KeyCode.Space), cancellationToken: _cts.Token);
}
private void OnDestoroy()
{
// キャンセレーショントークンソースを停止
_cts.Cancel();
}
Asset
参考記事
DOTween
アニメーションをスクリプトで簡単に書けます。
定義したアニメーションは、ポーズやりすたーと
特に、UIのアニメーションで重宝するので、とてもおすすめです。
良いところ
- 簡単なアニメーションを楽に書ける
- Toが強すぎて大体何でもアニメーションを作れる
- 豊富なイージングでアニメーションの時間の使い方が選び放題
- オプションも豊富でカスタマイズしやすい
- Sequenceでアニメーションの実行順を簡単に決めれる
- TweenやSequeceで簡単にポースや最初から再生などができる
- UniTaskと連携できるので、簡単に待てる
- 学習コストが低い
- 基本無料(DOTweenProは有料)
悪いところ
- パフォーマンスがめちゃくちゃいいわけではない
- Proを買わないとTextMeshProのアニメーションができない
使い方
一般的なアニメーション
await アニメーションさせる対象
.DO~(最終的な値, アニメーションの時間)
.SetEase(イージング)
.ToUniTask(cancellationToken: ct);
アニメーションのコマンドは主に上記のように書きます。(今回は、UniTaskと連携している前提で進めます)
アニメーションさせる対象とは、座標の移動をするならTransform型、UIの画像の色を変えるならImage型の変数です。
DO~の部分で、どのようなアニメーションをするかを定義し、移動ならDOMoveのようなコマンドが用意されており、DOと打って予測変換で自分がしたいアニメーションをしてくれそうなものを探すのがおすすめです。()の引数部分は、コマンドによって内容が変わりますが、だいたいこんな感じです。
イージングは、アニメーションの遷移をどのようにするかで、以下の記事を参考にしてください。
DOTweenのイージング一覧を世界一詳しく&分かりやすく説明する
最後にアニメーションが永遠に待たれないように、キャンセレーショントークンで停止できるようにしておきましょう。
To
主に数値を一定時間でどんどん変更したいときに使います。
これを活用するとアニメーションの幅が広がるのでおすすめです。
await DOTween.To
(
() => 初期値,
値 => 値に関する処理,
最終値,
アニメーションの時間
)
.SetEase(イージング)
.ToUniTask(cancellationToken: ct);
主に、上記のように書きます。
Tween, Sequence
TweenやSequenceを使うことで、アニメーションのポーズやリスタートなどが簡単に実装できます。
Tweenは、一つのアニメーションに使用するもので、Sequenceは複数のアニメーションを一括で管理するときに使います。
使用上の注意
アニメーションの再生タイミング
DOTweenのアニメーションは、定義したタイミングで再生が開始されます。
もし、アニメーション定義時に実行したくない場合は、最後にPauseオプションを設定しましょう。(詳しくは、Sequenceの使用例)
TextMeshProのアニメーション
DOTweenには、DOTextというUIのテキストのアニメーションをできるコマンドがありますが、これはTextMeshProには対応していません。
TextMeshProでDOTextを行う場合は、DOTweenProを買う必要がありま
DOTweenUtilityPanel
DOTweenの設定を行えるウィンドウです。
ここの設定をしないとDOTextやDOAudioが使えないので、設定し忘れないようにしましょう。
Unityの上のツールバーのTools>Demigiant>DOTween Utility Panelで、パネルを開けます。
Setup DOTweenをクリックすると、DOTextなどのチェックボックスがあるので、チェックをいれてApplyしましょう。
UniTaskとの連携
初期設定のままだと、UniTaskと連携できていません。
UniTasと連携するためには、ProjectSettingsを修正する必要があります。
まず、Unityの上のツールバーのEdit>ProjectSettingsで、ProjectSettingsウィンドウを開きます。
そして、Player>Other Settings>Scripting Define Symbolsに、UNITASK_DOTWEEN_SUPPORTを追加しましょう。
使用例
移動してみる
// 現在地からdirection方向にspeed分だけduration秒で等速移動
private async UniTask MoveAsync(Vector3 direction, float speed, float duration, CancellationToken ct)
{
await transform
.DOMove(direction*speed, duration)
.SetRelative(true)
.SetEase(Ease.Linear)
.ToUniTask(cancellationToke: ct);
}
To
public float Time;
// Timeをduration秒掛けて、一定速度で0から1に増やす
private async UniTask TimeAsync(float duration, CancellationToken ct)
{
await DOTween.To(
() => 0f,
x => Time = x,
1f,
duration
)
.SetEase(Ease.Linear)
.ToUniTask(cancellationToken: ct);
}
Tween、 Sequence
private Sequence _sequence;
// アニメーションを設定
private void BindAnimation()
{
// gameobject破壊時に停止し、勝手にアニメーションが終了しないSequenceを定義
// 勝手に再生されないようにポーズしている
_sequece = DOTween.Sequence()
.SetAutoKill(false)
.SetLink(gameObject)
.Pause();
// 1秒かけて大きさを1にして、1秒待った後、1秒かけて大きさを0にしている
_sequence
.Append(SizeAnim(1f, 1f, Ease.InSine))
.AppendInterval(1f)
.Append(SizeAnim(0f, 1f, Ease.OutSize));
// duration秒で大きさをsizeにするアニメーションを取得
Tween SizeAnim(float size, float duration, Ease ease)
{
return transform.DOScale(size, duration)
.SetEase(ease);
}
}
// 初めから再生
private void Restart()
{
_sequence.Restart();
}
// ポーズ
private void Pause()
{
_sequence.Pause();
}
// 再生
private void Resume()
{
_sequence.Resume();
}
DOTweenProを買うべき人
DOTweenProの買うべき理由として、よくTextMeshProのアニメーションができると聞きますが、実はToコマンドを使うとTextMeshProのアニメーションは大体再現できます。(めんどくさいけど)
DOTweenProがおすすめな人
- GUIでDOTweenのアニメーションを作成したい人
- TextMeshProのアニメーションを自作するのがめんどくさい人
Asset
参考記事
絶対入れたい
R3(UniRx)
イベントが発生した時に実行
これができるだけで世界が変わります。
みなさんも一度はこんなコードを書いたことがあると思います。
private bool isStart=false;
private bool isEnd=false;
// ゲームがスタートしてから、終わるまでの間実行したい
private void Update()
{
if(!isStart || isEnd)
{
return;
}
if(Input.GetKeyDown(KeyCode.A))
{
//右に移動
}
}
毎フレームif文で、処理を実行するかどうか判定することを無駄に感じた人も少なくないと思います。
このコードをR3で書くと、下記のコードになります。
private bool isStart=false;
private bool isEnd=false;
private void Start()
{
var ct = this.GetCancellationTokenOnDestroy();
Observable.EvetyUpdate() // Update関数
.SkipUntil(_ => isStart) // ゲームがスタートするまで実行しない
.TakeUntil(_ => isEnd) // ゲームが終了したら実行を停止
.Where(_ => Input.GetKeyDown(KeyCode.A)) // Aキーが押されたら
.Subscribe(_ => {
//右に動く
}).RegisterTo(ct); // キャンセレーショントークンが停止するまで
}
このように、処理の停止を行えるようになるので、Updateを使うより効率的なプログラムを作成することができます。
良いところ
- パフォーマンスが劇的に変わる
- Unityが決めた関数の有効化、無効化を簡単に決められる
- 自分でどの処理をいつまで有効にするか決められる
- 値が変わった時に処理を実行できる
- イベント発生時の処理をまとめて実行できる
- 無料
悪いところ
- 学習コストが高い
使い方
よく使うものは、ReactivePropertyとSubjectです。
ReactiveProperty
値の変化を検知してくれる。
使用例
// 本日の主役
// <>には、変更を検知したい値の型名
// newし忘れないように注意
private ReactiveProperty<bool> _isChangeProp = new(false);
// 外部に公開するときは、ReadOnlyReactivePropertyを使った方が安全
// ReadOnlyReactivePropertyは、外部から値を変更できない
public ReadOnlyReactiveProperty<bool> IsChangeProp => _isChangeProp;
public void Change()
{
// 値を変えるときは、.Valueをつける必要がある
_isChangeProp.Value = true;
}
// R3の処理は基本的に1回呼ぶとずっと実行される
private void Start()
{
Bind(this.GetCancellationTokenOnDestroy());
}
private void Bind(CancellationToken ct)
{
IsChangeProp
.where(value => value) // IsChangePropがtrueになったとき
.DistinctuntilChanged() // IsChangePropの値が前と同じときは、実行しない
.Sunbscribe(_ => {
Debug.Log("change");
}).RegisterTo(ct) // キャンセレーショントークンが停止するまで購読
}
Subject
登録されている処理を一気に実行できる。
使用例
// まとめて実行する処理を登録するもの
// Unitの部分は、実行する時に何か値を渡したい場合は、その渡したい型名にする
private Subject<Unit> _clickEvent = new();
public IObservable<Unit> ClickEvent => _clickEvent; // 外部に登録専用のものを公開する
// クリックされたとき
public void OnPointerClick(PointerEventData eventData)
{
// _clickEventに登録されている処理をすべて実行
// Unit.Defaultは、何も引数がないと同義
_clickEvent.OnNext(Unit.Default);
}
// _clickEventに処理を登録
// UniRxのよくあるSubscribeの書き方で登録できる
public void SetEvent(CancellationToken ct)
{
ClickEvent
.Subscribe(_ => {
Debug.Log("click"); // クリック時の処理
}).RegisterTo(ct) // キャンセレーショントークンが停止するまで購読
}
使用上の注意
何度もイベントを発行しない
R3で発行したイベントは、停止させるまで永遠に動いています。
なので、基本的にはStart関数などで1度だけ呼ばれるようにしましょう。
発行したイベントは、停止させる処理を忘れず書く
前述したとおり、R3で発行したイベントは、停止させるまで永遠に動いています。
停止させなければ、スクリプトをアタッチしているオブジェクトが破壊されても動いています。
なので、RegisterToオプションやAddToオプションの設定し忘れに気をつけましょう。
検索はUniRxで探した方がいい
情報を検索する時に、R3で調べるとUniRxとの比較が大半であまり情報が出てきません。
R3もUniRxも基本は同じなので、R3の情報を調べるときもUniRxで調べましょう。
R3とUniRxの違い
R3は、次世代のUniRxでUniRxよりも非同期の扱いや紛らわしい表現の修正など、よりUniRxを使いやすくしています。
そのため、ほとんどR3とUniRxは同じです。
比較は、まとめ記事があるので、丸投げします。
Asset
R3
UniRx
参考記事
ZString
文字列を操作するならこいつを使うべき
良いところ
- 文字列操作時のメモリを効率的に使ってくれる
- StringBuilderを使うよりも早い
- intやfloatの値を結合する時に、stringにキャストしなくても使える
- 学習コストが低い
- 無料
悪いところ
- 導入時にエラーが出ることが多い
使い方
よく使うコマンドは、Concat、Format(SetTextFormat)、Join、SetTextの4つです。
他にも色々あるので、GitHubのREADMEを読んでみてください‼︎
Concat
文字列を結合する時に使います。
使用例
// "x"+"y"+"z"した結果と同じ
// 結合する数は、何個でも大丈夫
// 出力: xyz
var ans = ZString.Concat("x", "y", "z");
Format(SetTextFormat)
指定したフォーマットに沿った文字列を取得できます。
SetTextFormatは、取得した文字列を直接TextMeshProに登録します。
使用例
// formatに沿った形で出力する
// {}で囲まれた数字の小さい順に、値を設定できる
// 出力: x:1, y:2, z:3
var format = "x:{0}, y:{1}, z:{2}";
var ans = ZString.Format(format, 1, 2, 3);
// SetTextFormatで、直接tmpに登録
// 数値書式指定文字列も使用できます
// 出力: x:1, y:002, z:30
TMP_Text tmp.SetTextFormat("x:{0}, y:{1:000}, z:{2:P}", 1, 2, 0.3);
Join
文字列を結合するときに、間に指定した文字を入れられるようにします。
使用例
// a,b,cの間に:を挿入する
// 出力: a:b:c
var ans = ZString.Join(':', "a", "b", "c");
SetText
TextMeshProに直接文字列を登録します。
使用例
// tmpにaaaという文字列を登録
TMP_Text tmp.SetText("aaa");
使用上の注意
Asset導入時のエラー対策
Asset導入時に、ZStringはアセンブリが分割されています。
それなのに、なぜかScriptsフォルダに保存されるので、PluginsフォルダにZStringのフォルダを移動しましょう。
Asset
参考記事
使えるようになれば神
VConatiner
DIで最強のUnityエンジニアになろう‼︎
DIに関しては、記事を1個書けるほど奥が深く、同様にVContainerも奥が深いので、ここでは使い方の紹介はしません。
後述する参考記事から学んでみてください‼︎
良いところ
- MonoBehaviourとC#だけのクラスを分けて実装できる
- インタフェースにクラスを設定していくので、クラスの差し替えが簡単
- 影響範囲を設定できるので、シングルトンのような全体に影響するゴミクラスを減らせる
- 無料
悪いところ
- 学習コストが高すぎる
Asset
参考記事
- VContainer
- VContainer入門
- UnityのDI超ざっくり入門 1 – そもそもUnityのDIって何?
- 2018/10/02 (Tue) キッズスター開発合宿 / CAFU v3 Zenject
→ Zenjectの説明ですが、DIの理解に役立ちます
おまけ
買ってよかったAsset
素材系
3Dモデルや2Dイラスト、音源、エフェクトなど、素材系は探したり作ったりするのは大変です。
ゲームを作る手助けにとてもなるので、1つ買っておくのがおすすめです。
UnityAssetStoreは、50%offセールや75%offをよくやるのでその時を狙って、できるだけたくさん入っている素材集を買うのがおすすめです。
ちなみに、次は正月にNewYearセールをすると思います。
Unityスターターキット Easy Custom VFX/UI Vol.1
シェーダやVFX、パーティクルシステムなどグラフィックの理解を深めることができます。
きちんと、シェーダーグラフにコメントがあったり、購入特典のDiscordチャンネルで参考記事の紹介があるので、とても学びやすいです。
さらに、テクスチャやエフェクトの配布も定期的にあるので、素材集めにも使えます。
Asset
おわりに
おすすめのAssetの紹介と使い方を説明しました。
紹介したものは、導入するとゲーム作りがより快適になるものばかりなので、ぜひ使ってみてください‼︎
明日は、ko-kiくんのアニメーションの紹介記事です。