2011年05月12日

うにばな (講座みたいなもの 第一回)

講座みたいなもの 第一回です。

まずUnityでゲームを作成するときに必要な部分をまとめてみました。
Unityエンジンはスクリプトをインスペクタにアタッチすることで作成しますが、スクリプト同士のデータのやりとり
についてあまり解説がなされていないようですので簡単に解説します。


■型宣言

var 変数名:型名;
static var XXXX:int;
public var XXXX:int;
private var XXXX:int;


型名のところには 
int(整数)、float(実数)、String(文字列), Array(配列) の他に
Transform(移動座標系データ)、Rigidbody(物理演算データ)、Renderer(CG描画データ)、Camera(カメラデータ)、Animation(アニメーションデータ)、Collider(コリジョンデータ) ...
などといったコンポーネント型が入ります。
1


var
標準の宣言の仕方です。 インスペクタ上でデータに値を与えることができます
エディタ上での実行時にデータ値を確認することが可能です。(デバッグ時などに)

private var 
スクリプト内部でのみ使用するための宣言でインスペクタに表示されることはありません。
外部から参照することはできません。

static var
静的にメモリが割りつけられます。インスペクタ上に値は表示はされません。
他のスクリプトから main.variable (= スクリプト名.変数名) のように手続き無く
参照することが可能です。新規シーンファイル読み込み時に破壊されることがないので
ゲームのスコアなどデータを引き継ぐときにも使えるようです。

静的ってなに?
fig3



静的なデータはデータが解放されないため メモリを消費することになりますので
上手く活用してください。 Unityエンジンではstatic型を積極使用することで高速化が図れるという説明がされています。

public var
外部から参照するときに使用する宣言 データの参照については次の項で。
fig2



補足
function の{ }の内部で設定された値はそのfunction内でしか有効ではありません
外部参照する場合はその都度 外部から参照できる形の変数にコピーしてやる必要があります。
return文 を使用すれば呼び出した場所に値を引き渡すことができます。これはJavaなどの構文
function Update(){
   XXX=Move();

function Move(){
return 値;

この場合はXXXにMove()内で計算した値が帰ります。

注意:
型名は必ずしも宣言しなければならないわけではなく省略することもできます。
その場合はコンパイラが自動判別を行って最適化してくれます。 ただし手動でキャスト(型変換)しない場合 実行速度に影響が出ますので カウンターなどを表示させて
確認しながら高速化を図ってください。



■他のゲームオブジェクト、コンポーネントへのアクセス
リファレンスの該当ページは次のリンク↓
http://unity3d.com/support/documentation/ScriptReference/index.Accessing_Other_Game_Objects.html
http://unity3d.com/support/documentation/ScriptReference/index.Accessing_Other_Components.html


◯コンポーネントへのアクセス

コンポーネントのアクセスは非常に重要なのですが、リファレンスでは殆ど触れられていないようなので説明します。
リファレンスの説明は次のとおり

1.通常の取得

function Update () {
var otherScript = GetComponent(OtherScript);
otherScript.DoSomething();
}

DoSomething() がよくわからないかもしれませんが、要するにOtherScriptがゲームオブジェクトに設定されたスクリプト名で otherScriptという変数に一度取ってから
DoSomething()(ここには function か 変数名がはいります)。
もちろん
var otherScript = GetComponent(OtherScript).function名();
または
var otherScript = GetComponent(OtherScript).変数名();
とひとつづきに記述しても構いません。

2.ツリー構造中から取得する場合。

ツリー階層の内部を移動して検索する場合
transform.Find("Hand").GetComponent(OtherScript).foo = 2;
この場合階層内の”Hand"というオブジェクトを検索してOtherScriptに宣言された
fooに2を代入することになります。
transform.Find("Hand").GetComponent(OtherScript).function名(XXX);
この場合はfunction名で指定する関数にXXXの値を渡します。

まとめ
gameObject.GetComponent("XXXX").変数名
gameObject.GetComponent("XXXX").ファンクション()

などの形式でXXXXにはコンポーネント名がはいります。


コンポーネントの値を取る場合varの中では
private var 変数名:XXXX
XXXXにはコンポーネント名として宣言しなければなりません。

private var target : SeagullFlightPath;
private var origin : Transform;

function Start(){
origin = transform.parent;
target = origin.GetComponent(SeagullFlightPath);


これは公式のチュートリアルの南の島?のカモメに飛行パスを設定する部分です。
この場合はカモメの親が飛行パスを設定するオブジェクトです。ここでは
origin という変数に transform.parent を代入しています Unityエンジン内ではparentで一つ上の階層のオブジェクトを指定することになっているようです。
(階層の一番上に移動したい場合はrootを指定します)
targetの型宣言でSeagullFlightPath としています これは親のインスペクタに
あるコンポーネント(スクリプト)です。
この例の場合はtarget.XXX のようにXXXにSeagullFlightPath内でVarで宣言された
値をコールできます。XXXは 『public var』の指定をしてください。

子オブジェクトからコンポーネントを取得したい場合は
GetComponentInChildren()を使用します。


Static型のfunction
ちなみにコルーチンを static宣言をすれば 変数のstatic宣言と同様に
static function XXXX(){

とすれば
compo.XXXX (= コンポーネント名.XXXX())
の形で直接呼び出すことができます。

SendMessage・・・・・・・・・・・・・・・・・

手続きを経ずにファンクションコールをする方法としてUnityエンジンには
SendMessageという関数が用意されています。

SendMessage ("ApplyDamage", 5.0);

↓対象のコンポーネントに記述されたファンクション。
function ApplyDamage (damage : float) {
print (damage);
}
特定のゲームオブジェクトに送信する場合は
gameObject.SendMessage ("ApplyDamage", 5.0);

↓対象のゲームオブジェクト内のコンポーネントに記述されたファンクション。
function ApplyDamage (damage : float) {
print (damage);
}

SendMessageの欠点として 引数をひとつしか取れない点が上げられます。
どうしても複数の値を送信したい場合は
var arg1 = "test";
var arg2 = "test2";
var arr = new string[arg1,arg2];

object.SendMessage("yourfunctionname", arr);
のように配列に値をいれてからメッセージを送ることで複数のデータを送信することが可能なようです。

似た関数に BroadcastMessage() がありますそちらはゲーム中に存在する
(子のオブジェクトを含む)全てのスクリプト中にあるファンクションに対してメッセージを送信します。
使用方法はSendMessageと同じです。






◯ゲームオブジェクトへのアクセス
話が前後しますが他のゲームオブジェクトにアクセスする方法についてです。
リファレンスの内容説明をします。

1. インスペクタにアサインする方法
var target : Transform;
function Update () {
target.Translate(0, 1, 0);
}

fig4


2. ツリー構造内のオブジェクトを参照する

transform.Find()でツリー構造内を移動できます。
これもやはり
transform.root  =ツリーのトップ
transform.parent =一つ上のオブジェクト
という指定することができます。

transform.Find("Hand").GetComponent(OtherScript).DoSomething();
オブジェクト”Hand”を検索して OtherScriptというコンポーネントに作用するスクリプトです。

for (var child : Transform in transform) {
child.Translate(0, 10, 0);
}
子に連なる複数オブジェクトのトランスフォームをとって制御します。

3. Tagで探す場合。
この場合GameObject.FindWithTagを使用してPlayerのタグを検索しy方向に1.0の
移動をすることになります。
var player = GameObject.FindWithTag("Player");
player.transform.Translate(0, 1, 0);

よくある例

for(go in gameObject.FindGameObjectsWithTag("Enemy"))
{
var difference = (go.transform.position-myTrans.position);
 distance = difference.magnitude;
   }
などのようにEnemyタグの複数オブジェクトと自機の距離を判定するような使い方をします。


4. パラメータから取得する場合
OnTriggerStay()はコリジョン内に存在するゲームオブジェクトの判定をします
other:Collider でコリジョン衝突しているオブジェクトの情報を返してきます。
よくでてくる書き方ですが、エネミーの弾丸のスクリプトでこの場合はotherObjectにコリジョン情報が帰ってきます
if(otherObject.gameObject.tag == "Player")
Playerタグが検出されたら 処理を起こすスクリプトです。

function OnTriggerEnter(otherObject: Collider){
if(otherObject.gameObject.tag == "Player"){
var tempExplosion: Transform;

tempExplosion = Instantiate(explosion, transform.position,    transform.rotation);

GameController.playerLives --;
Destroy(gameObject);
    }



5. オブジェクトのタイプで探す場合
FindObjectOfType()を使用して as HingeJoint(=HingeJoint型にキャスト(変換))
forループの中で HingeJoint in hingesを使用して hingesの中からデータをhingeに
移しながらループ実行します。 hingesはHingeJoint型の配列です。

function OnMouseDown () {
var hinges : HingeJoint[] = FindObjectsOfType(HingeJoint) as HingeJoint[];
for (var hinge : HingeJoint in hinges) {
hinge.useSpring = false;
}
}





すこし情報量が多いですがUnityエンジンのゲーム作成に非常に重要なものですので
いまわからなくても 作成の途中で見返して理解してみてください。
一回目は少し難解だったと思いますが、次回からは簡単になります スローペースにいきましょう
最初に高い山にのぼるのが ぶぎょう流ですw

次回からサンプルのプロジェクトの解説をします。 それではー




akinow at 22:03│Comments(2)TrackBack(0) Clip to Evernote Unity3d | シリーズ講座

トラックバックURL

この記事へのコメント

1. Posted by Linoal   2012年04月06日 22:42
5 ちょうどチュートリアルを読んで疑問だったところが解決しました。
ありがとうございました。
2. Posted by ぶぎょう17   2012年04月06日 22:48
Linoalさん>コメントありがとうございます。
お役に立ててよかったです。 疑問があればコメントしていただければ出来る限り
解説していきますので 遠慮なさらずどうぞ

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔