2014年1月11日土曜日

#04.C#実装検討~Unity故の特殊性調査

C#での実装の検討をしはじめました。以下にいろいろ雑感&メモなど。


■C#での文字列定数
.net系(?)の継承が無いせいかネームスペースの問題なのか、UnityではReadonly等を用いた文字列の固定定数がうまくいかなかった。そもそも。これらはあまり好きではないので、以下の方法で華麗にかわしますっ。

public const string LABEL = "文字列定数";


とってもシンプルw。

Unity上ではヘッダファイルを作るメニューが見当たらないので、#defineにてヘッダをincludeするのもちょっとどうなのかな?とも思った。
プリプロはもはや過去の遺物なのかもしれない・・・。文字列がマッチングすると置換されるのでわかりにくいバグも埋め込むし。

※まじめな話enumやdefine定義を使いまわすにはヘッダファイルに記述すると楽なのだが、C#だとどうにも使いにくく、それ用にクラスを書くようなことにもなりかねない。そもそもこれらの手法は今日においてはオブジェクト指向的ではない・・・ということですかね。



■オブジェクトとスクリプト
Unityはオブジェクト内に複数のスクリプトを放り込める。
同オブジェクト内の別スクリプトへのアクセスならばそのメンバがpublicであればアクセスは簡単で、

ScriptName.MemberName

でアクセスできてしまう。これは従来のC++、C#と大差ない。

Unity故の特殊ケースは別のオブジェクトにあるスクリプトのメンバへのアクセス。
それにはまず、対象オブジェクトのインスタンスへのポインタ(というか某所風味で言うとUUIDか?)を取得する必要がある。
オブジェクトはすべて GameObject型となっているので、

GameObject ptr =  GameObject.Find("対象オブジェクト名");

にてインスタンスのポインタを取得する。ここでの GameObject.Findはインスタンス検索関数、対象オブジェクト名はHierarchy上に存在している名前。よって名前はユニークになるように自分で管理しておく方が良い。

 これで ptr には対象オブジェクトのインスタンスのポインタが格納されるが、まだ終わらない。
なぜならば、そのオブジェクト内のスクリプト~クラスが複数ある可能性があるので。

ClassName ptr2 =  ptr.GetComponent<ClassName>();

にて、そのオブジェクト内でインスタンス化されているクラス名を指定して、そのクラスのポインタを得る。と、いう二段構えで目的のクラスを絞り込む。これで、

ptr2.Func()
 
などと、目的クラスのpublicメンバへアクセスが可能になる。
ただしポインタの取得は検索を行う為非常に重いらしい。常時使用するとfpsがとんでもないことになるとのこと。
よって、Awake()かStart() で先んじてポインタだけ拾っておけば良い。


■Awake()やStart()
先の流れでAwake()がでてくるがこれも把握しておかないと危ない。コンストラクタのようではあるがそうでもない。Unityではコンストラクタの使用は推奨されていないらしい(そもそもC#がコンストラクタを基本的に扱わないし)。

【Awake()が呼ばれるタイミング】
オブジェクトがインスタンス化した時=オブジェクト内のスクリプト(クラス)がインスタンス化完了時。
ただしこの時全てのインスタンス化されたクラスのAwake()が呼び出されている保証はないとのこと(マルチスレッドの初期化時みたいなものか?)。
よって、各クラスのAwake()内処理はまだ完了していない点に注意。つまりできることはインスタンスのポインタを拾うくらい。(か、ハード由来の処理か?ハードは常に実在しているので)

【Start()が呼ばれるタイミング】
初回のUpdate()がStart()である。と、説明されている。
よって全てのインスタンスのAwake()の呼び出し済みは保証される。
他のオブジェクトとの連携が絡まない初期化はココで良い感じ。絡む場合はAwake()を利用することも視野に入れる。



■オブジェクトに無関係なクラスはどうするか?
オブジェクトを制御するスクリプトはそのオブジェクトに放り込むわけだが、純粋に演算だけを行うクラス等はオブジェクトを特に必要とはしない。
が、Unityでは「器」はやっぱり必要なので適当に空のGameObjectを作ってしまいそこに放りこめば良さそうだ。



と、いうことで、別オブジェクト内の任意のスクリプト>クラスへのアクセス方法もわかったので、なんとかなりそう。ネットの情報が多いのは助かりますね~。本家マニュアルも一部和訳されているし。

本当はAstahあたりで、きちんと設計過程を通しておきたいとこでもあるが、ま~ココは勢いでサクサク進む(進みたい)予定。

どうもUnityはコンポーネントという概念が導入されているのが良いらしい。コードの実装的にも余計な面倒さを感じさせないのが良い感じです。(MFCより全然わかりやすいっ! )




補足:
某SL向けな言い回しをすると、GameObjectはプリムと言える。もうそれだけで作れそうな気になったよね?w
RayCast,Colission等も、まんまそっくりなので、製作概念~スキルはほぼそのままいけそうです。

0 件のコメント:

コメントを投稿