2014年1月19日日曜日

UnityでのC#クラスのインスタンス化を調査試行

Unityのクラスインスタンスがいろいろ面倒で超調査した(普通のC#とは異なる)。

だいたいわかってきた。


以上w。









いや、まとめると結構大変というか面倒。どうりでネットで情報がみつけにくい。
 ココが参考になった。

 参考リンク:CHO DESIGN LAB[Unity]他のスクリプトを参照する




とりあえず細かい話以前の大前提がまずあって、
 事前にスクリプトとオブジェクトを紐付けて「ある」か「否」か

の2パターンがある。

さらに重要な点は

C#のクラスは勝手にnewでインスタンス化できない

ということになっている。 一見できるのだが罠である。実はキチンと動作しない(どうオカシクなるか一応検証)。
Unityではスクリプトもコンポーネントのひとつとして管理されている為、その概念からするとナルホドなのである。

実はnewでこっそりインスタンス化できるんじゃないの?とか思ってみたがムダだった。一部の実装ではできた「ように」みえたが、よりワカリニクイ罠にハマったw。
(インスタンスが複数できてしまったりで、更新したメンバ変数と代入しているメンバ変数の整合が取れなくなるなど。多分メンバ関数とメンバ変数の指すインスタンスに整合が取れなくなるのか、ヒープ領域の問題なのかブツブツ・・・)


細かい話はいつか書くかもとして(ぇ)、まずはその2パターンについて以下にメモ。

ポイントはオブジェクトとスクリプト(クラス)の紐付けについて。


【予め紐付けておくパターン】

Unity画面の Hierarchyにあるオブジェクトに予めAssetsからC#スクリプトをドラッグ&ドロップしておいた場合はUnity画面のInspector欄にスクリプトの名前が見える。

これでオブジェクトとスクリプト(クラス)の紐付けができている状態。
※Unityでは基本クラス名=スクリプト名となる様子。異なるとドラッグ&ドロップできない。

なので実行するとそのオブジェクト内のC#スクリプトに記述されているクラスが「ひとつ」自動的にインスタンス化する。


よって、そのインスタンスへのハンドル(ポインタ)を取得すればメンバにアクセスできる。
その際に用いるのが GetComponent()。これでハンドルを取得すれば handle.func() 等としてアクセスできる。

なのでインスタンスがひとつでいいのなら予めUnity上でオブジェクトにドラッグ&ドロップで放り込んでおくのがお手軽。



【予め紐付けて無いパターン】

この場合は自前でスクリプトから紐付ける。
当該オブジェクトに紐付けるには、

   className handle = gameObject.AddComponent<className>();

とする。gameObjectが「当該」であることを指す。
クラス名classNameがAssetのスクリプト群から見つからない場合等の際はnull が返る。

これで実行した場合、Unity画面で当該オブジェクトのInspector欄をチラっとみるといつのまにかそのクラスのスクリプト名が追加されている。
つまり手動でドラッグ&ドロップする作業を、スクリプトで行っていることが視覚で確認できる。これは意外と便利。



 と、おおまかにこの2つのパターンがある上で、

他のオブジェクトの紐付け済みクラスへのアクセス
他のオブジェクトにクラスを自前で紐付けてアクセス
 といったパターンもでてくる。
 
多くの場合は予め紐付けておけば良いのだが、ゲームの敵機などは無数にインスタンス化するのでそうもいかないので後者が重要になってくる。



0 件のコメント:

コメントを投稿