CodingReptile

ゆるゆると技術に関するメモを貯めていく

【Unity】SampleAsset の ThirdPersonCharacter のスクリプトを読む(変数の宣言編)

先日、MMD モデルを Unity 上で動かす際、SampleAsset の ThirdPersonController を利用することでお手軽にやりたかったことが実現できました。(ref. Unity内でMMDモデルを自由に走らせる手軽な方法 - テラシュールブログ

f:id:bcsaitama:20161027023050p:plain

unity および c# の初心者としては、オブジェクトの操作という基本的な実装を担っているスクリプトはしっかり抑えておきたいところです。将来的に拡張して利用したりすることも考えて、勉強がてら以下の2つのスクリプトの中身をじっくり読んでいきます。なお、参考資料は記事の最後にまとめています。

  • ThirdPersonCharacter.cs
  • ThirdPersonUserControl.cs

一度にスクリプトの全てを読んでまとめるのは骨が折れるので、今回は変数の宣言部分に絞ってみます。

[SerializeField] float m_MovingTurnSpeed = 360;
[SerializeField] float m_StationaryTurnSpeed = 180;
[SerializeField] float m_JumpPower = 12f;
[Range(1f, 4f)][SerializeField] float m_GravityMultiplier = 2f;
[SerializeField] float m_RunCycleLegOffset = 0.2f; //specific to the character in sample assets, will need to be modified to work with others
[SerializeField] float m_MoveSpeedMultiplier = 1f;
[SerializeField] float m_AnimSpeedMultiplier = 1f;
[SerializeField] float m_GroundCheckDistance = 0.1f;

Rigidbody m_Rigidbody;
Animator m_Animator;
bool m_IsGrounded;
float m_OrigGroundCheckDistance;
const float k_Half = 0.5f;
float m_TurnAmount;
float m_ForwardAmount;
Vector3 m_GroundNormal;
float m_CapsuleHeight;
Vector3 m_CapsuleCenter;
CapsuleCollider m_Capsule;
bool m_Crouching;

パッと見てまず思ったのは private なのか public なのか分からない! ということ。
c# では変数の宣言時にアクセス修飾子を付けない場合は、自動的に private になるそうです。へ〜。

次に目につくのは、いちいち変数の先頭についている m_。 inspecter 上では消えている。 f:id:bcsaitama:20161027025533p:plain

調べてみると、m_ , _ , k などはどれも private 変数の先頭につけて他の変数と明確に区別するためのもののよう。 今プロジェクトで書いている perl のコードでは _ を使っていますが、それと同じということでした。 unity では ObjectNames.NicifyVariableName が inspecter に表示するときにこれを消してくれている。

次に、[SerializeField]。これは 公式ドキュメント によると

Unity が private フィールドを強制的にシリアライズします。
...
Unity がスクリプトをシリアライズする際、public フィールドのみシリアライズします。 それに加えて Unity で private フィールドをシリアライズさせたい場合、 フィールドに SerializeField 属性を追加できます。

と書いてあります。 シリアライズは「オブジェクトをバイト列に変換して外部と受け渡しできるようにすること」なので、シリアライズしていないものはスクリプトの中でしか利用できません。端的に言うと、 private 変数は inspecter 上に表示されず、値の操作ができません、ということ。
しかし、それでは不便なので SerializeField 属性を付けて inspecter から気軽に値を変えられるようにしているのですね。

最後に、もうひとつの attribute である [Range(1f, 4f)]
m_GravityMultiplier がこれを利用していますが、名前通り変数のレンジを指定するものです。inspecter 上では値を調整するための UI が提供さています。便利!

まとめ

  • c# では変数宣言時にアクセス修飾子を付けない場合は、自動的に private になる
  • m_ , s_ , _ などを変数の先頭につけていても inspecter 上はそれらが除かれて表示される
  • inspecter から気軽に private 変数の値を変えたい場合には、SerializeField 属性を付ける
  • Range 属性を付けると値の制約が設定され、inspecter 上の UI が提供される

変数の宣言だけ見てみましたがしっかり収穫がありました。 どれも基礎的なことですが、ちゃんと理解しておくの大事。

参考URL