i-school - AddComponentTestクラス

学習内容


 ゲームオブジェクトにアタッチするコンポーネントは、ゲーム実行前にインスペクターでアタッチしておく他、
ゲーム実行内にスクリプトを利用してアタッチすることができます。同様に、アタッチを解除することも出来ます。

 ここでは、オブジェクトに対してスクリプト(クラス)を通じてコンポーネントを新たに追加したり、または削除したりする方法を学びます。
 

スクリプトを作成し、コンポーネントを追加する機能を記述する


 Projects内のAsset → Scripts をダブルクリックして開き
その中で Create → C# Script を選択します。名前はAddComponentTestにします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// ゲーム実行中にコンポーネントの追加/削除のテスト用クラス
/// ここではCubeオブジェクトにだけRigidBodyコンポーネントを後から追加したり、削除したり、プロパティを操作するクラス
/// </summary>
public class AddComponentTest : MonoBehaviour
{    
    [Header("Planeかどうかの判定用 trueならPlane")]
    public bool isPlaneFlag;

    private bool isRigidGet;    // 指定した条件(ここではRigidBodyコンポーネントを持っている)かどうかを判定するフラグ

    void Start()
    {

    }

    void Update()
    {        
        // ボタンを押したとき
        if (Input.GetKeyDown(KeyCode.G)) {

            // isPlaneFlagがfalseであり、かつisRigidGetがfalseである場合
            if (!isPlaneFlag && !isRigidGet) {  // isPlaneFlag == false && isRigidGet == false と同義

                // このゲームオブジェクトに新しくRigidBodyコンポーネントを追加する
                gameObject.AddComponent<Rigidbody>();

                // RigidBodyを持っているかどうかのフラグをオンにし、持っている状態にする
                isRigidGet = true;

                Debug.Log(isRigidGet);
            }
        }
    }
}

 書き間違えがないか、確認したらセーブをしてコンパイルしましょう。


スクリプトをアタッチしてゲームを実行する


 スクリプトを Cube ゲームオブジェクトにアタッチし、ゲームを実行してみましょう。
スクリプト内で書いたキーを入力したときに、想定している挙動になっているか確認しましょう。


スクリプトを修正して、コンポーネントがアタッチされている場合にのみ機能する制御を追加する


 スクリプトに追記し、特定の状態にあるときだけ制御を行えるように分岐を作成します。
 
 今回の実装例のように「こういう場合だけ、何かをする」という記述を実装することがとても多いです。
例えば、お金が100以上なら薬草が買える、というようなケースです。

 まずは日本語で処理の内容を書きだしてみて、それを元にプログラムを作っていくようにすると、制御文の学習になります。

 教材を見て書き写すだけではなく、どのように処理になっているのかをイメージしながら、スクリプトを書いていくようにしてください。
漫然と書くだけではスキルは身につかないためです。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// ゲーム実行中にコンポーネントの追加/削除のテスト用クラス
/// ここではCubeオブジェクトにだけRigidBodyコンポーネントを後から追加したり、削除したり、プロパティを操作するクラス
/// </summary>
public class AddComponentTest : MonoBehaviour
{    
    [Header("Planeかどうかの判定用 trueならPlane")]
    public bool isPlaneFlag;

    private bool isRigidGet;    // 指定した条件(ここではRigidBodyコンポーネントを持っている)かどうかを判定するフラグ

    void Start()
    {

    }

    void Update()
    {        
        // ボタンを押したとき
        if (Input.GetKeyDown(KeyCode.G)) {

            // isPlaneFlagがfalseであり、かつisRigidGetがfalseである場合
            if (!isPlaneFlag && !isRigidGet) {  // isPlaneFlag == false && isRigidGet == false

                // このゲームオブジェクトに新しくRigidBodyコンポーネントを追加する
                gameObject.AddComponent<Rigidbody>();

                // RigidBodyを持っているかどうかのフラグをオンにし、持っている状態にする
                isRigidGet = true;

                Debug.Log(isRigidGet);
            }


////* ここから処理を追加します *////


      // isRigidGet == true なら
            if (isRigidGet) {  

                // すでにRigidBodyを追加している状態である場合
                // RigidBody型の変数rbを宣言し、RigidBodyを取得してアクセスできるようにする
                Rigidbody rb = GetComponent<Rigidbody>();

                // RigidBodyコンポーネントの持つIsKinematicプロパティの状態を見て、オン・オフを切り替える
                if (!rb.isKinematic) {

                    rb.isKinematic = true;
                } else {

                    rb.isKinematic = false;
                }
            }
        }


////* ここまで *////


    }
}


ゲームを実行して確認する


 今回のスクリプトの処理をまずは読み解いてみてください
どのような制御が行われれば制御が成功なのか、その判断を行うのは、スクリプトを書いた本人です。
自分自身が、どういった処理ならOKであるのか、把握しておかなければ、制御の成否の判断が付けられません

 スクリプトを Cube ゲームオブジェクトにアタッチし、ゲームを実行してみましょう。
スクリプト内で書いたキーを入力したときに、想定している挙動になっているか確認しましょう。



スクリプトを修正し、コンポーネントを削除する制御を追加する


 最後に、コンポーネントを削除する命令を記述します。

 該当するコンポーネントがあるかどうかを判定し、ある場合のみ削除するように制御しています。
こういった制御方法は活用事例が多いため、ただ削除する処理だけではなく、特定の場合のみ削除する、という制御文を学習しておきましょう


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// ゲーム実行中にコンポーネントの追加/削除のテスト用クラス
/// ここではCubeオブジェクトにだけRigidBodyコンポーネントを後から追加したり、削除したり、プロパティを操作するクラス
/// </summary>
public class AddComponentTest : MonoBehaviour
{    
    [Header("Planeかどうかの判定用 trueならPlane")]
    public bool isPlaneFlag;

    private bool isRigidGet;    // 指定した条件(ここではRigidBodyコンポーネントを持っている)かどうかを判定するフラグ

    void Start()
    {

    }

    void Update()
    {        
        // ボタンを押したとき
        if (Input.GetKeyDown(KeyCode.G)) {

            // isPlaneFlagがfalseであり、かつisRigidGetがfalseである場合
            if (!isPlaneFlag && !isRigidGet) {  // isPlaneFlag == false && isRigidGet == false

                // このゲームオブジェクトに新しくRigidBodyコンポーネントを追加する
                gameObject.AddComponent<Rigidbody>();

                // RigidBodyを持っているかどうかのフラグをオンにし、持っている状態にする
                isRigidGet = true;

                Debug.Log(isRigidGet);
            }

      // isRigidGet == true なら
            if (isRigidGet) {  

                // すでにRigidBodyを追加している状態である場合
                // RigidBody型の変数rbを宣言し、RigidBodyを取得してアクセスできるようにする
                Rigidbody rb = GetComponent<Rigidbody>();

                // RigidBodyコンポーネントの持つIsKinematicプロパティの状態を見て、オン・オフを切り替える
                if (!rb.isKinematic) {

                    rb.isKinematic = true;
                } else {

                    rb.isKinematic = false;
                }
            }
        }


////* ここから処理を追加します *////


        // ボタンを押したとき
        if (Input.GetKeyDown(KeyCode.H)) {

            // isRigidGetがtrueなら = RigidBodyコンポーネントを持っているなら
            if (isRigidGet) {

                // RigidBodyコンポーネントを削除する
                Destroy(GetComponent<Rigidbody>());

                // 所有フラグをfalseにし、RigidBodyコンポーネント持っていない状態にする
                isRigidGet = false;

                // 落下しているCubeの位置を初期位置に戻す
                float pos = 3.0f;

                transform.position = new Vector3(transform.position.x,pos,transform.position.z);
            }
        }


////* ここまで *////


    }
}

 スクリプトを書いたらセーブします。


ゲームを実行して確認する


 想定しているような制御が行えるかどうか、どうなればOKであるのかを、しっかりとイメージしてから、ゲームを実行して処理をおこなってください。

 インスペクターを確認しながらデバッグを行うと効率が上がります。