ブルーノのC#プログラミング & unity勉強日記

プログラミング素人、ブルーノの自主勉強ノートです。他のプログラミングを勉強したい方の助けになれば幸いです。その他趣味の雑記もしていきたいです

Unityスクリプト / ゲームオブジェクトの相関性編

f:id:covory10101101276:20180408223218j:plain

万里の長城

みなさんこんにちは🌚

家事に勉強に大忙しのブルーノです。大量の卵をうまく消費する方法はないものか...

 

さて今回は、またこれも基礎的な内容ですがゲームオブジェクトの親子関係、その設定の仕方をスクリプトで学んでいきたいと思います。

 

ゲームオブジェクトの親子関係について

あるゲームオブジェクトを別のオブジェクトにドラッグ&ドロップするとそのオブジェクトの子になり、傘下に入るというのはこれまでなんども経験してきました。

f:id:covory10101101276:20180409150444p:plain

こんな風になりましたね。エディタ上では設定することが簡単なこの操作ですが、スクリプト上で制御するにはTransformクラスのparentプロパティを使い、以下のように行います。

parentプロパティ

public Transform parent{get; set;}

あるゲームオブジェクトAを別のゲームオブジェクトBの子に設定したい場合、親となるAのtransformプロパティから取得したTransformオブジェクトを、ゲームオブジェクトBのtransformプロパティから取得したTransformオブジェクトparentプロパティに設定します。何いってるかわからないと思うので実際に書いてみます。

f:id:covory10101101276:20180409153146p:plain

子のtransform.parentプロパティに親のtransform情報を入れていますね。結果は以下のようになります。

f:id:covory10101101276:20180409153157p:plain

一瞬でこれらのオブジェクトとその親子関係が築かれました。個人的にはとてもわかりやすい例なのですが、ラディッツは兄貴だから悟空より上ではとかいうのはこの際気にしないでください。

 

ゲームオブジェクトの移動について

シーン内のゲームオブジェクトの移動には、変形ツールの以下の上下左右に伸びた矢印から行いますよね。

f:id:covory10101101276:20180409153650p:plain

これも親子関係を引き継いでおり、親を動かすと全く同じように子もついてきます。これは子の座標が親の座標を参照して得られているからです。このような座標をローカル座標といい、親のような何者にも属さない世界から絶対的な座標を与えられているものワールド座標といいます。

オブジェクトの空間内におけるワールド座標は、positionプロパティで表されています。

positionプロパティ

public Vector3 position{get; set;}

以下のように書きます。

f:id:covory10101101276:20180409155645p:plain

結果は以下の通りになります。

f:id:covory10101101276:20180409155716p:plain

インスペクターを見てわかる通り座標がpositionプロパティで設定されたものになっていますね。

さて、今やったpositionプロパティはワールド座標を表すプロパティですが、子の親との距離、つまりローカル座標を変更したい場合、また別のプロパティを使います。それがlocalPositionプロパティです。そのままですね。

f:id:covory10101101276:20180409160805p:plain

先ほどのを少しだけ変え、CubeをSphereの親にしました。そしてSphereをCubeの少し隣をキープするよう指定しました。

f:id:covory10101101276:20180409160818p:plain

子であるSphereは自由に動かせますが親であるCubeを動かすとSphereも一緒についてきますね。ゲームなどでカメラを追従させるの等に使えそうです。

では移動について最後に、先ほどやった二つのプロパティはワールドにしろローカルにしろいきなり決められた座標に移動するので前者は常に座標を考えなくてはならず、後者は親依存の距離を常に保つだけなので単純な移動としては使いにくいです。指定した向きに指定した量だけ移動させることができればより移動の考え方が楽になりますよね。そこでTranslate()メソッドが役に立ちます。

Translateメソッド

public void Translate(Vector3 translation);

public void Translate(Vector3 translation, Space relativeTo);

public void Translate(Vector3 translation, Transform relativeTo);

 translationパラメータに移動量のVector3型のベクトルもしくはfloat型の(float x, float y, float z)を指定します。

SpaceというのはTranslateで移動させる向きと量をオブジェクトを軸とするか世界を軸とするかを設定できるSpace列挙型というものです

Space列挙型

public enum Space

この列挙型には自身を軸とするSelfメンバと世界を軸にするWorldメンバが宣言されています。いずれかをrelativeToパラメータに入力して使います。

Transformを入れた場合はそのtransformパラメータを軸とします。つまり他のゲームオブジェクト等を軸として移動させられるわけですね。ここで自身のtransformを入れればSpace.Selfと同じになります。

実際に見てみましょう

f:id:covory10101101276:20180409164341p:plain

x座標が3より大きくなれば左に1ずつ、つまりxが-1、逆にxが3より小さくなれば右に1ずつ、つまりxが+1されるようになっています。21行目の(_direction * 0.1f ~ の後に座標軸の情報を入力できます。

f:id:covory10101101276:20180409164756p:plain

ひたすら左右に移動しますね。

 

ゲームオブジェクトの回転

ゲームオブジェクトの回転は変形ツールのリサイクルのようなマークで行いますよね。

f:id:covory10101101276:20180409165224p:plain

これにも軸があり、シーン上ではX, Y, Z を自由に回転させられます。

f:id:covory10101101276:20180409165429p:plain

オブジェクトの向きをスクリプトから変更するにはTransformクラスのrotationプロパティで変更します。

rotationプロパティ

public Quaternion rotation {get; set;} 

rotationプロパティはQuaternion構造体という四元数を格納する構造体を計算し簡単なX, Y, Zで表してくれるのですが、私のような数学が苦手な人を含む一般の人には四元数を入力したQuaternion構造体は手動ではとても用意できないのでQuaternion.Eulerメソッドというものを併用します。これはX, Y, Zをパラメータとして送るとそれを四元数に計算しQuaternion構造体として使用してくれるすごいメソッドなのです。なんだかコンパイラみたいですね。例を載せます

f:id:covory10101101276:20180409172014p:plain

Quaternion.Eulerメソッドのおかげで我々でもわかりやすい形式で角度を指定できます。

f:id:covory10101101276:20180409172026p:plain

カクンってなってます。カクンって。

そしてこれもワールド座標での向きなので、ローカル座標の向きも指定できます。それがlocalRotationプロパティです。

localRotationプロパティ

publicQuaternion localRotation{get; set;}

使い方は先ほどのlocalPositionプロパティ等と同じです。例を載せておきます。

f:id:covory10101101276:20180409173717p:plain

f:id:covory10101101276:20180409173729p:plain

左から、手前に45度、左の角度を軸としてYに45度、真ん中を軸としてZ軸に45となっています。

ローカルときたら次は単純な回転ですね。これにはRotate()メソッドを使います。

Rotate()メソッド

public void Rotate(Vector3 axis, float angle);

public void Rotate(Vector3 eulerAngles, Space relativeTo);

axisに方向、angleにその量を入力するか、eulerAnglesに回転量、その後に軸を指定することで使うことができます。簡単そうなのは下の方ですね。

f:id:covory10101101276:20180409175609p:plain

f:id:covory10101101276:20180409175619p:plain

ゆっくり回転してます。。。

 

ゲームオブジェクトの拡縮

さて最後に大きさの変更の仕方を学んでおきます。シーン上のゲームオブジェクトの拡縮にはでっかくなってる感じのボタンから行えますね

f:id:covory10101101276:20180409180106p:plain

スクリプトでこれを行う場合はTransformクラスのlocalScaleプロパティを用います。

localScaleプロパティ

public Vector3 localScale{get; set}

実はこの大きさ(Scale)だけは常に親を継承するのでローカルしかなく、逆にワールド座標系のサイズ指定を行うことはできません。一応ワールド座標系の実際のサイズを取得したい場合はlossyScaleプロパティから取得できるのですが、読み取り専用プロパティなのでこれに値を入れてサイズを変更といったことはできません。

lossyScaleプロパティ

public Vector3 lossyScale{get;}

では実際に書いていきます。

f:id:covory10101101276:20180409181234p:plain

まずは親のみサイズ変更してみます。すると...

f:id:covory10101101276:20180409181247p:plain

子供もおっきくなりました。

f:id:covory10101101276:20180409181649p:plain

では次に子に同じようにスケールを与えると...

f:id:covory10101101276:20180409181718p:plain

めっちゃでかくなりました。今回はここまでにしておきます。

 

いやー久しぶりの投稿ときたらこれですよ。普段から使えるツールバーのメニューもスクリプトで制御しようとしたらこんなに色々あるんですね。でもゲーム中は自由にツールバーで動かしながらゲームを進行できるわけではないのでこれらの知識は非常に活きてくるはずです!!

 

最近はソシャゲにも色々手を出していて、ゴッドイーターのオンラインとレゾナントオプスを両方ともやっています。ソシャゲって据え置きや製品ゲームとは全くシステムものめり方も違いますよね。これも勉強しなければ...