AnimatorControllerのメモ

  • AnimatorControllerはVisualScriptingと考えること
    • 再利用できるようにする
    • コードと同じように常にメンテナンスする
  • パラメーターの数は多くてもいい.アニメーションが多ければ必要なパラメータが増えるのは当然.
    • Firewatchではこれくらいパラメータがある f:id:SiunCyclone:20210614162548p:plain:w400
    • 大切なのはパラメーターの数を減らすことではなくて,パラメーターをどう扱うか

forpro.unity3d.jp

www.youtube.com

FPSSampleのアニメーションの実装を読む(後編)

前回の
FPSSampleのアニメーションの実装を読む(前編) - siunのメモ

基本的に大まかな流れはここ読めばわかる
FPSSample/Animation.md at master · Unity-Technologies/FPSSample · GitHub

三人称視点の実装

  • すべてPlayableAPIを使って実装してる
    • AnimatorControllerの代わりはテンプレートになっていて,AnimGraph_StateSelectorで処理されてる
  • 自分以外のすべてのプレイヤーのアニメーションは,以下二つで毎フレーム更新されている
    • class ApplyPresentationState : BaseComponentSystem
      • AnimStateController.ApplyPresentationState()を毎フレーム実行
    • class UpdateCharPresentationState : BaseComponentSystem
      • AnimStateController.UpdatePresentationState()を毎フレーム実行
  • ラグの補間は各AnimGraphでやってる

WindowsのVSCodeでGitを認識しないときはgit.pathを設定する

背景

Macでは何も設定しなくてもVSCodeのGitを認識したが,Windowsでは認識してなかった

f:id:SiunCyclone:20200923212529p:plain

原因

git.pathが設定されてなかった
普段msys2でgitを使用していたため,VSCodeがgitを認識できていなかった

解決策

  1. 公式サイトからWindows版のGitを入れる
  2. VSCodeのsettings.jsonのgit.pathに,Windows版Gitのパスを設定する
  "git.path": "C:/Program Files/Git/bin/git.exe",

備考

msys2で既に入れているgitのパスを設定してみたが認識しなかったので,Windows版のGitを入れること

UnityのDrawLineとDrawRayのメモ

1. DrawLineは2点を結ぶ線

点Aと点Bがある時,その2つを結ぶ線を引きたい時使う

2. DrawRayは1点と1距離から作る線

点Aがある時,そこからある方向へ,ある長さの線を引きたい時使う*1

3. メモ

DrawRayは内部でDrawLineを使っている f:id:SiunCyclone:20200806002850p:plain UnityCsReference/Gizmos.cs at master · Unity-Technologies/UnityCsReference · GitHub
DrawLineだけじゃなくDrawRayも存在してるのは,単純に使いやすさのため.
ある点から100右向きの線引きたい時に
DrawLine(origin, origin + Vector3.right * 100);
と書くより
DrawRay(origin, Vector3.right * 100);
と書けるほうが便利だから

4. 注意点

Rayのdirectionは自動で正規化されるが,DrawRayのdirectionは正規化されない

*1:DrawRay(Ray r)を使う場合は正規化された長さしか引けない.長さを指定する場合はDrawRay(Vector3 from, Vector3 direction)を使う.

C#の構造体は参照渡しで代入するのが一番速い

目次

  1. newするよりも値を代入するほうが速い
  2. 返り値にすると一番遅い

1. newするよりも値を代入するほうが速い

gist.github.com 100万回呼んだ場合
f:id:SiunCyclone:20200805124721p:plainf:id:SiunCyclone:20200805124724p:plain 代入の方が速い

2. 返り値にすると一番遅い

gist.github.com 100万回呼んだ場合 f:id:SiunCyclone:20200805130952p:plainf:id:SiunCyclone:20200805130957p:plain Aとあまり差がないように見えるが,これは構造体のサイズが小さいからである

構造体のサイズが大きい場合

gist.github.com gist.github.com 100万回呼んだ場合 f:id:SiunCyclone:20200805133639p:plainf:id:SiunCyclone:20200805133642p:plain 差がはっきり見て取れる

まとめ

gist.github.com

FPSSampleのアニメーションの実装を読む(前編)

1. はじめに

UnityのAnimatorControllerは,ステートの状態が多くなると管理しづらくなる(矢印だらけになる)という問題がある.
そこでUnity公式のサンプルではどのようにアニメーションを実装しているのか知るためソースを読んだ.

github.com

2. 前知識

まずソースを読む前に公式のドキュメントを読んでみる.
FPSSample/Animation.md at master · Unity-Technologies/FPSSample · GitHub

  • 三人称視点
    FPSSampleはマルチプレイヤーシューティングなので,アニメーションをネットワーク上で同期(複製,ロールバック,予測,ラグ処理など)するためにカスタムPlayable Graphを使用している.

  • 一人称視点
    ローカルクライアントでのみ再生されるので,AnimatorControllerを使用している. AnimatorControllerを使うとは言ったが,PlayableAPIを使わないとは言っていない(

PlayableAPIのドキュメントも読んでおく.
* Playable API - Unity マニュアル
* PlayableGraph - Unity マニュアル
* ScriptPlayable と PlayableBehaviour - Unity マニュアル
* Playable の例 - Unity マニュアル

3. 一人称視点の実装

まず簡単そうな方から読んでいく.

3.1 ファイル構成

f:id:SiunCyclone:20200601164210p:plain
f:id:SiunCyclone:20200601164608p:plain
Robot_A_1Pのコンポーネント f:id:SiunCyclone:20200601191753p:plain f:id:SiunCyclone:20200601165217p:plain

3.2 Animatorで再生される大まかな流れ

f:id:SiunCyclone:20200601200744p:plain 1. AnimGraph_AnimatorController.csAnimatorControllerの参照を持つ
2. AnimGraph_Stack.csAnimGraph_AnimatorController.csの参照を持つ
3. AnimStateController.csAnimGraph_Stack.csの参照を持つ

AnimatorはAnimationPlayableOutputのsource Playableを再生するので*1それによりアニメーションが再生されている

3.3 PlayableGraph

f:id:SiunCyclone:20200602202925p:plain ソースを読んで作った図.
この1枚にすべてが集約されている.

3.4 AnimGraph_AnimatorController.cs

  1. まずソースを簡略化してみる gist.github.com

    • RuntimeAnimatorControllerを保持している
    • AnimGraphAssetを継承している
    • 内部クラスとして,IAnimGraphInstanceを継承したInstanceがある f:id:SiunCyclone:20200601190107p:plain
  2. 親クラスとインターフェースをみる gist.github.com gist.github.com

    • InstantiateがInstatiateになっているが,おそらくUnityのAPIと被らないようにするためだと思われる
  3. 内部クラスInstanceをみる gist.github.com

    • 主な処理をCharacterAnimatorControllerに委譲していることが見て取れる
    • EntityManagerがあるので,ECSを使っている模様
  4. CharacterAnimatorControllerをみる
    コンストラクタとvoid Update()が大きい処理をしているので,その2つをみていく

    4.1 CharacterAnimatorControllerのコンストラク
    gist.github.com

    • AnimatorControllerPlayableでRuntimeAnimatorControllerをラップしてる
    • AnimatorController内のパラメータへのハッシュを,AnimStateParams型やActionStateParams型の配列として保持してる(文字列でパラメータにアクセスするよりint型のハッシュでアクセスする方が早いから)
       
      パラメータ一覧
      f:id:SiunCyclone:20200602011116p:plain
       
      4.2 CharacterAnimatorControllerのUpdate gist.github.com gist.github.com
    • AnimatorController内のパラメータを更新している

以上からCharacterAnimatorControllerのUpdateに,アニメーションがとるべき次の状態(CharacterPredictedData.LocoStateや.Action)を渡すことで,アニメーションの状態(AnimatorController内のパラメータ)を更新していることがわかった.

3.5 AnimGraph_Stack.cs

  1. 簡略化 gist.github.com

    • AnimGraph_AnimatorController.csと同じような構造
    • しかしRuntimeAnimatorControllerではなく,List<AnimGraphAsset> を保持している f:id:SiunCyclone:20200601190101p:plain
  2. 内部クラスGraphInstance gist.github.com コンストラクタで下図の部分の処理をしてる
    f:id:SiunCyclone:20200602204043p:plain

3.6 AnimStateController.cs

  1. 簡略化 gist.github.com

    • コンポーネントが非アクティブになるとDeinitialize()が呼ばれる
    • public関数が4つある
  2. public関数の中身をみる(簡略化ver) gist.github.com

    • Deinitialize()でグラフの終了処理
    • UpdatePresentationState()でグラフロジックを更新
    • ApplyPresentationState()でグラフに現在のStateを適用(多分)
  3. Initializeの中身をみる(簡略化ver) gist.github.com

    • PlayableGraphを作って再生している
    • AnimationPlayableOutputを作る時に,情報源としてAnimGraphのOutputを使っている
      Initializeで下図の部分の処理をしている
      f:id:SiunCyclone:20200602204518p:plain

UV座標のOverrideを理解する

背景

f:id:SiunCyclone:20200508230243p:plain

上の画像で,左上にあるテクスチャのUV空間を,GradientNoiseでOverrideした場合,右下のようなテクスチャが得られる.
この時Overrideは具体的にどのような処理を行っているのか理解できなかったので調べた.

UVの基本

f:id:SiunCyclone:20200508231210p:plain

  1. まず,UV空間は左下を(0,0)右上を(1,1)として定義されている.
    f:id:SiunCyclone:20200509000053p:plain

  2. 次にこのUV空間をX軸方向成分,Y軸方向成分のみ取り出すと以下のような1次元配列となる.
    f:id:SiunCyclone:20200509000115p:plain

  3. この1次元配列をUVに繋げた場合,0は(0,0),0.1は(0.1,0.1),1は(1,1)のようにして渡される(注1) f:id:SiunCyclone:20200509000415p:plain

  4. UV座標の(0,0),(0.1,0.1),・・・(1,1)が意味するのは画像のピンクの直線部分である f:id:SiunCyclone:20200509000826p:plain

  5. 対応関係を示すと以下のようになる f:id:SiunCyclone:20200509001150p:plain

本題

以上を踏まえると最初の画像が読み解けるようになる f:id:SiunCyclone:20200509002730p:plain  
   

注1

シェーダコードを実際にみて確かめた
上:今回のように値が1つの場合
f:id:SiunCyclone:20200509001350p:plain 下:デフォルト f:id:SiunCyclone:20200509001358p:plain なおvec = (1,2,3)があった場合
vec.xx = (1, 1)
vec.xy = (1, 2)
vec.zz = (3, 3)
となる