Unityではゲームオブジェクトを選択するとインスペクタの項目に取り付けてあるコンポーネントが表示されます。
通常であればUnityエディター上であらかじめコンポーネントを取り付けておき、設定値を変更したりして使用します。
ですがゲーム実行中にRigidbodyやスクリプト等のコンポーネントをスクリプトから取り付けたい事もあると思います。
そこで、今回はスクリプトからゲームオブジェクトにコンポーネントを取り付けてみようと思います。
スクリプトからコンポーネントを取り付ける方法
スクリプトからゲームオブジェクトにコンポーネントを取り付ける方法は簡単です。
1 2 3 | ゲームオブジェクト.AddComponent <コンポーネント> (); |
と記述するだけです。
取り付けるゲームオブジェクトにAddComponentで取り付けるコンポーネントの型を指定するだけです。
↑の例ではジェネリクス版を使用しましたが他のやり方もあります。
1 2 3 4 5 6 7 8 | // ジェネリクス版 ゲームオブジェクト.AddComponent <コンポーネント>() as コンポーネントの型; // 文字列で指定版 ゲームオブジェクト.AddComponent ("コンポーネント") as コンポーネントの型; // typeof使用版 ゲームオブジェクト.AddComponent(typeof(コンポーネント)) as コンポーネントの型; |
as コンポーネントの型
という部分は取り付けたコンポーネントの型をキャスト(強制で型変更)する為の記述です。
取り付けたコンポーネントを別の変数等に入れる時にしっかり型指定をして変数に代入したい時に指定します。
1番目は先ほど紹介したジェネリクス版で<>の中にコンポーネントの型を入れます。
2番目は()の中に文字列のコンポーネントを指定します。
3番目は()の中にtypeofで型を指定しています。
これらの事を考慮し、例えばCharacterControllerコンポーネントをスクリプトから取り付けたい場合は
1 2 3 | gameObject.AddComponent<CharacterController>(); |
とすればいい事になります。
コンポーネントと言うとあらかじめ用意されている何らかの機能という大げさな感じがしますが、自身で作成したスクリプトもコンポーネントなので、自前のスクリプトをゲームオブジェクトに取り付ける場合もAddComponentを使用する事が出来ます。
スクリプトからコンポーネントを取り付けてみる
スクリプトからコンポーネントを取り付ける方法がわかったので、実際に取り付けてみましょう。
サンプルの舞台を整える
まずは地面とキー操作で動かせるキャラクターをシーン上に設置します。
地面はヒエラルキー上で右クリック→3D Object→Planeを選択し作成します。
キャラクターはStandardAssets→Characters→ThirdPersonCharacter→Prefabs→ThirdPersonControllerをヒエラルキー上にドラッグ&ドロップします。
もちろん自前のキャラクターでもかまいません。
その他にヒエラルキー上で右クリック→3D Object→Cubeを選択し地面の上にいくつか設置しておきます。
それぞれのCubeにはTagにBlockという名前のタグを作成し設定しておきます。
↑が地面、キャラクター、Cubeをいくつか設置した画面です。
キャラクターが接触出来る範囲であればCubeは空中に浮いていても構いません。
↑が設置したCubeの一つのインスペクタです。
設置して位置やサイズを変更しただけで特別コンポーネントを取り付けたりはしていません。
キャラクターがCubeに接触した時にコンポーネントを取り付けるスクリプト
サンプルの舞台が出来上がったので次にキャラクターがCubeと接触した時にCubeにコンポーネントを取り付けるスクリプトを作成していきましょう。
今回はキャラクターがCubeと接触した時にCubeにRigidbodyを取り付け、キャラクターが接触した方向に力を加えてCubeを動かしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | using UnityEngine; using System.Collections; public class CollisionCube : MonoBehaviour { // ぶつかったブロックを動かす力 public float power; // キャラクターが他のゲームオブジェクトにぶつかったら public void OnControllerColliderHit(ControllerColliderHit col) { // ぶつかった相手がBlockタグを持つ相手だったら if (col.gameObject.tag == "Block") { // ぶつかった相手のRigidbodyコンポーネントを取得 Rigidbody rigid = col.transform.GetComponent <Rigidbody> (); // Rigidbodyを持っていなかったらAddComponentで取り付ける if (rigid == null) { // まったく関係ないが自作のスクリプトを取り付けてみる col.gameObject.AddComponent <AddComponentTest>(); // ジェネリクス版 rigid = col.gameObject.AddComponent <Rigidbody>() as Rigidbody; // 文字列で指定版 // rigid = col.gameObject.AddComponent ("Rigidbody") as Rigidbody; // typeof使用版 // rigid = col.gameObject.AddComponent(typeof(Rigidbody)) as Rigidbody; // constraintsのX、Y、Z軸で移動し、回転しないようにする rigid.constraints = ~RigidbodyConstraints.FreezePosition | RigidbodyConstraints.FreezeRotation; } // Rigidbodyに力を加える rigid.AddForce (transform.forward * power); } } } |
powerは接触したCubeに加える力の度合いでインスペクタで設定出来るようにしておきます。
CubeはデフォルトではIsTriggerのチェックが入っていないので物理的にぶつかるようになっています。
Cube側ではキャラクターを検知出来ないので(キャラクターをRigidbodyで動かしている場合は別)、キャラクター側でCubeを検知するようにします。
キャラクター側で他のゲームオブジェクトの接触を確認するにはOnControllerColliderHitメソッドを使用します。
引数でControllerColliderHit型の値を受け取り、そのゲームオブジェクトのタグにBlockが設定されていたらそのゲームオブジェクトのRigidbodyを取得します。
Rigidbodyがnullだったら最初の接触なので、AddComponentを使ってCubeに自前のスクリプトAddComponentTextとRigidbodyコンポーネントを取り付けます。
Cubeに力を加える時にCubeが回転しないようにする為Constraintsの値を設定しています。
Constraintsの値の設定については
ビット演算に関しては
を参照してください。
~RigidbodyConstraints.FreezePosition
はX、Y、ZをFreeze(動かないようにする)にする設定を~で反転させ、X、Y、Z軸全てで動くようにしています。
スクリプト中でCubeに取り付けているAddComponentTextスクリプトは自前のスクリプトで
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using UnityEngine; using System.Collections; public class AddComponentTest : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } } |
↑の用にデフォルトで作成されるスクリプトそのままを使用しています。
今回はスクリプトも他のコンポーネントと同じように取り付けられるというのを確認する為だけなので特別な処理は行っていません。
これでスクリプトは完成です。
スクリプトからコンポーネントが設定されるか確認する
CollisionCubeをキャラクターに取り付けてください。
Unityを実行したら設置したCubeに接触するようにキャラクターを動かし、Cubeにコンポーネントが取り付けられ力を加えられるか確認してください。
↑のようになりました。
キャラクターがCubeに接触すると、そのCubeにはRigidbodyが取り付けられ主人公が向いている方向に力を加えられて移動している事が確認出来ました。