301.Transformコンポーネント
コンポーネント概要
コンポーネントとは
GameObjectに
追加することでその機能を有効にするオブジェクトです。
コンポーネントには、大きく分けて
更新系コンポーネントと
描画系コンポーネントがあります。
更新系コンポーネントは動きや回転、スケーリングなどの動的な変化を制御します。
描画系コンポーネントは
形状の指定や
色や明るさの設定そして
描画方法の指定を行います。
シェーダとの橋渡しの意味合いもあります。
コンポーネントを実装するには
GameObjectの
OnCreate()関数などで、
auto Ptr = AddComponent<コンポーネント型>(引数);
のように記述します。引数はないものが多いです(全部ではない)。
AddComponent()関数は
テンプレート関数です。
型を渡すことでその型のインスタンスを作成し、
GameObjectに結び付けます。
戻り値は、作成したコンポーネントの
shared_ptrです。そのポインタを利用して、コンポーネントのパラメータの設定などを行います。
auto Ptr = AddComponent<コンポーネント型>(引数);
Ptr->Function();
上記
Function()はそのコンポーネントが持っている関数の例です。多くはアクセサや振る舞いの設定などです。
AddComponent()関数はすでにそのコンポーネントが設定されていたらそのポインタを返します。なかった場合だけ新規に作成します。ですから、取得後も常に
AddComponent()関数でコンポーネントの取得も行えますが、関数名的にも的確ではありません。ですのですでに作成したコンポーネントを利用する場合は、多くは
OnUpdate()などでの処理になりますが
auto Ptr = GetComponent<コンポーネント型>(なかった時に例外を送出するかどうか);
Ptr->Function();
のように
GetComponent()関数を使用します。
引数は
trueかfalseを指定します。デフォルト引数になっていまして、デフォルト値は
true(送出する)です。
falseを渡した場合
nullptrが返ってくる可能性があります。ですから、そのコンポーネントが間違いなく存在する場合
auto Ptr = GetComponent<コンポーネント型>();
Ptr->Function();
のような記述をします。しかし、
存在したら何かの処理をする場合
auto Ptr = GetComponent<コンポーネント型>(false);
if(Ptr){
//存在した場合の処理
Ptr->Function();
}
else{
//存在しなかったときの処理
}
のように記述します。
更新系コンポーネントが評価される(計算される)タイミングは
OnUpdate()関数が呼ばれた後で、かつ、
OnLastUpdate()関数が呼ばれる前です。
この項では
更新系コンポーネントのなかでも、特殊な
Transformコンポーネントについて述べます。
Transformコンポーネント
Transformコンポーネントは一番大事で、そして特殊なコンポーネントです。
Transformだけは、すべての
GamaObjectがデフォルトで保持しています。
Transformは
スケーリング、重心、回転、移動の4つのパラメータを持ち、
1ターン前の
スケーリング、重心、回転、移動を持ちます。
デフォルトで保持しているので、
AddComponent()関数を実行しなくても取得できます。例えば
OnCreate()関数で
auto PtrTrans = GetComponent<Transform>();
PtrTrans->SetPosition(Vec3(0.0f,0.0f,0.0f));
のように
位置の設定を行います。
次項以降で説明する
Action系コンポーネントや
Rigidbodyコンポーネント、そして
Collision系コンポーネントなどはこの
Transformの値を変更します。
ですから
直接Transformを変更するのかもしくは
更新系コンポーネントに任せるのかあるいは
任せつつも直接変更もするのかは、オブジェクトの作成方法にもよりますが、慎重に設計する必要があります。
前述しましたように、GameObjectの更新処理(仮想関数が呼び出されるタイミング)と、更新系コンポーネントが計算されるタイミングは以下のような順番になります。
【1】各GameObjectの、OnUpdate()関数呼び出し
【2】各GameObjectが持つコンポーネントの計算
【3】衝突判定と衝突メッセージの発行
【4】各GameObjectの、OnUpdate2()関数呼び出し
【5】ステージのビューの計算
また
【2】各GameObjectが持つコンポーネントの計算は、特殊なコンポーネントとそうでないコンポーネントの評価順があります。以下にその順番を述べます。
*各GameObjectが持つコンポーネントの計算内の計算順番
1、特殊なコンポーネント以外のコンポーネントの計算(場合によってはTransformに影響を与える)
2、Gravityコンポーネント(重力コンポーネント)の計算(Transformに影響を与える)
3、Rigidbodyコンポーネント(速度を管理するコンポーネント)の計算(Transformに影響を与える)
4、Transformの計算(何もしない。ワールド行列は描画系コンポーネントが取得する)
またその後
が行われます。
このような形になっていますので、
【1】各GameObjectの、OnUpdate()関数呼び出しで、Transformの値を変更しても、その後、各コンポーネントが影響を与えますので、あまり意味がありません。(場合によっては変な動きになります)
ですから、
Transformの値を直接変更したいのであれば
Update系コンポーネントは追加しないか、もしくは
【4】各GameObjectの、OnUpdate2()関数呼び出しで行ったほうが比較的思い通りに行くことがあります。
基本的に以下の方針で設計すればよいと思います。
*Transformの値を直接変更したい場合は、できれば、更新系コンポーネントは追加しない。
*RigidbodyやCollisionを利用したい場合は、Rigidbodyの速度や、Gravity行動で現在の速度を変更する
*OnUpdate2()関数ならTransformの値を直接変更しても比較的安全。
直接
Transformの値を変更するサンプルとして
FullTutorial002があります。
このサンプルでは
Transform以外の更新系コンポーネントは持ちません。
OnUpdate()関数でオブジェクトの位置を変更しています。