2013年4月3日水曜日

他のGameObjectの持つスクリプトのフィールドを参照する

たとえばライフポイント.
ディスプレイするために表示用クラスで見たいけど, 体力管理としてプレイヤーでも参照したい, でも2か所に持つとかキモすぎる!щ(゚Д゚#щ) 絶対バグる!<(゚Д゚#<)
なんて状態.
なお今回からC#で書いてみます. ほとんど変わらないから問題ないかと.


他のスクリプトのフィールドを参照する


1. 状況

たとえば Playerのタグを持った PlayerObjectがいたとする. 
こいつはこんな LifeManagerという名のスクリプトを持っている. 
public int life = 10;
void Update(){
…
たとえば残りライフを描画する GUIのクラス, LifeMonitorがあったとする.
LifeMonitorは残りライフを表示するために PlayerObjectの残りライフが知りたい.
でもまさかダメージが入るたびに SendMessageメソッドで報告を受けるのもなんかヤダ('A`).
まさか LifeMonitorの方でも同じようにライフを減らすなんてありえない.

たとえばこんなシチュエーション.

2. 対策

LifeMonitorのほうのスクリプトに
GameObject player = GameObject.FindWithTag("Player").gameObject;
LifeManager script = player.getComponent(typeof(LifeManager)) as LifeManager;
int currentLife = script.life;
これで参照できる.
1行目は単純に PlayerのGameObjectを取得しているだけ. やり方は他にもいろいろ.

問題はその下.
1行目で取得した Playerから, コンポーネント名を指定して取得する.
ここが最初の問題.

必要なパーツは2つ. 「型宣言」と「キャスト」. 上記2行目なら,  typeof(クラス名)が型の宣言. as LifeManager がキャスト. 他のやり方もあり,
LifeManager script = (LifeManager)player.getComponent<LifeManager>();
とするパターンも. <LifeManager> で型宣言し, (LifeManager)でキャストするやり方の組み合わせ.
2つのパーツがそろっていればやり方は自由なのだが, 実はUnityScriptなら,
var script: LifeManager = player.getComponent(LifeManager);
とか書けちゃったりする.

あとは3行目のように, 取得したコンポーネントからフィールドの lifeをいただけば一丁上がり.
他のフィールドも同様に参照してやればおk. 意外とイメージはしやすいはず.
まぁディスプレイする側から体力操作し始めるようなことはないだろうけど.

3. 応用?

実は同様に, メソッドの呼び出しも可能. LifeManagerに以下のメソッドを追加してみる.
public void addLife(int inc){
    life += inc;
}
今更だけどたとえが悪かったなぁ…('A`) lifeに引数に指定した incだけ足すだけの簡単なメソッド.
LifeMonitorの方では,
script.addLife(1);
とでもしてやればOK. この後 lifeを読むと, ちゃんと 1加算されている.
戻り値も取り出せるし, 当然複数の引数も渡せる.
また直接,
script.life = 11;
とかぶち込むことも. やりたい放題である.

これらの注意点は,  必ず publicであること. パッケージ分けとかがあるわけではないので, アクセス修飾子に注意. 特に C#のデフォルトは privateな点など, 言語的なところにも注意. protectedも当然NG.

フィールドを参照したい, (基本ないだろうけど)フィールドの値を書き換えたい, 何度も同じスクリプトのメソッドを呼び出したい,戻り値が欲しい, 引数は複数持たせたい!なんて時はこの手法がよろしいのかな?

逆にゲームオーバーのように1回だけ呼べばいいものは, sendMessage()を使えばよろしいかと.





なんか変な文章(・ω・`)

0 件のコメント:

コメントを投稿

AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...