解説

スクリプトからコンポーネントにアクセスする

この記事では、コンポーネントにアクセスするための方法を説明します。コンポーネントはゲームオブジェクトの性質を決めるものです。Unityにおけるゲーム制作の基本はコンポーネントの設定をプレイヤーのキー入力に対して操作することです。これにより、プレイヤーキャラクターの移動などのアクションが実現されます。

Unityプログラミング講座一覧はこちら

Unityプログラミング講座
ゲームエンジンUnityを使ってゲーム制作を始めようと思っている人へ向けた解説記事です。初心者がUnityをインストールするところから始めてゲームを制作するのに必要な知識をできる限りステップバイステップでまとめるつもりです。

ここがポイント

  • コンポーネントTにアクセスする場合はGetComponent<T>()メソッドを使用する。
  • 使いたい機能にはドット.を用いてアクセスする。

Transformコンポーネントにアクセスする

Transformはすべてのゲームオブジェクトが持っているコンポーネントであり、使用頻度も高いため、簡単にアクセスできるようになっています。具体的にはtransformと打つだけでアクセスできます。

大文字と小文字は区別されるので、間違えないようにしましょう。小文字で始まるtransformが自分自身のTransformコンポーネントを表します。

位置を変更する

何か処理をしたい場合にはドット.を打って使用したい機能を指定します。例えば、位置を(1, 0, 0)に変更するスクリプトは以下のようになります。

using UnityEngine;
class ChangePosition : MonoBehaviour
{
    void Start()
    {
        // Transformコンポーネントにアクセスして位置を変える
        transform.position = new Vector3(1f, 0f, 0f);
    }
}

前にも述べたように、コンポーネントとスクリプトのファイル名は同じにし、ゲームオブジェクトにアタッチしてください。

positionに代入できるのはデータ型がVector3の変数です。Vector3は3次元ベクトルを表す型で座標などに用いられます。Vector3型は内部にfloat型の変数x, y, zを持ちます。新しくVector3型のデータを作成する場合はnew Vector3(x, y, z)のように書きます。

// (1, 2.5, 3)のベクトルを作成して変数vecに代入
Vector3 vec = new Vector3(1f, 2.5f, 3f);

必要なデータ型を調べるには?

スクリプトを書くのにVisual Studioを使用している場合にはマウスを合わせると確認できます。例えば、positionの場所にマウスを合わせると、次のように表示されます。

Vector3 Transform.position {get; set;}

ポップアップの最初に書かれているVector3がデータ型になります。(get; set;というのは読み書き可能かどうかを表していて、getが書かれていたら読取可能、setが書かれていたら書込可能という意味です。)

キー入力に対応する

上記の例ではStartメソッドで座標を変更しているため、ゲーム開始と同時に位置が変更された後は何も起こりません。せっかくですから、ボタンを押すたびに位置が変わるコンポーネントを書いてみましょう。(キー入力については前回の記事を見てください。)

クリックするたびにx座標が1増える自作コンポーネントは以下のように書けます。

using UnityEngine;
class ChangePosition : MonoBehaviour
{
    void Update()
    {
        // 左クリックが押されたら処理を行う
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            // 現在位置を変数posに代入
            Vector3 pos = transform.position;
            // 変数posのxの値を1増やす
            pos.x += 1f;
            // 変数posをTransformコンポーネントのpositionに代入
            transform.position = pos;
        }
    }
}

「動けばよい」だったらこれでも良いのですが、実行速度を気にする場合には注意点があります。transformによるアクセスは時間のかかる重い処理ですので、何度も使用する場合はtransformを変数に代入して保持しておくのが良いです。

using UnityEngine;
class ChangePosition : MonoBehaviour
{
    // transform保持用の変数
    Transform myTransform;

    void Start()
    {
        // 変数に代入してキャッシュする
        myTransform = transform;
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            // 変数myTransformを使用
            Vector3 pos = myTransform.position;
            pos.x += 1f;
            myTransform.position = pos;
        }
    }
}

GetComponentでコンポーネントにアクセスする

Transformコンポーネント以外にアクセスする場合にはGetComponentメソッドを使用します。以下の形で使用することが多いと思います。

コンポーネント名 変数名 = GetComponent<コンポーネント名>();

<>の意味が気になる人は「C# ジェネリック」で調べてみましょう。内容的には中級者以上な気がします。

Transformコンポーネントにアクセスする

小文字で始まるtranformでもアクセスできますが、当然GetComponentを用いてもアクセスできます。というより、小文字のtransformは内部でGetComponentを呼び出しているので、実質同じです。

上記のスクリプトのStartメソッドの部分をGetComponentで書くとこうなります。

...
    void Start()
    {
        // GetComponentメソッドでTransformコンポーネントを取得
        myTransform = GetComponent<Transform>();
    }
...

Rendererコンポーネントにアクセスする

描画を行うRendererコンポーネントにアクセスして、マテリアルを変更してみます。

using UnityEngine;

class ChangeMaterial : MonoBehaviour
{
    // Rendererコンポーネントを保持するための変数
    private Renderer myRenderer;
    void Start()
    {
        // Rendererコンポーネントにアクセスして変数に代入
        myRenderer = GetComponent<Renderer>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            // Rendererに設定されているマテリアルの色を変更する
            myRenderer.material.color = new Color(1f, 0f, 0f);
        }        
    }
}

Rendererコンポーネントに設定されているマテリアルはmaterialによってアクセス可能です。ここでは、色を変更するために、materialの設定の一つであるcolorにアクセスしています。colorに代入できるのはColor型のデータなので、Vector3型と同様にnew Color(r, g, b)と書いて色を指定しています。(r, g, bは色の三原色である赤、緑、青の成分で、0から1のfloat値で指定します。)

自作コンポーネントにアクセスする

GetComponentは好きなコンポーネントにアクセスすることができるメソッドです。ということは当然、スクリプトを書いて作成した自作コンポーネントにもアクセスができます。

実際に試してみましょう。はじめに、変数countの値が0以下になったらRendererコンポーネントの機能をOFFにするCountDownコンポーネントを作成してみます。コンポーネントの機能をOFFにするにはenabledの値をfalseに設定することで実現できます。

using UnityEngine;

class CountDown : MonoBehaviour
{
    // カウントダウン用の変数
    public int count = 3; // 外部からアクセスできるようにpublicをつける

    private Renderer myRenderer;

    void Start()
    {
        myRenderer = GetComponent<Renderer>();
    }

    void Update()
    {
        if(count <= 0)
        {
            // Rendererコンポーネントの機能をOFFにする
            myRenderer.enabled = false;
        }        
    }
}

これだけでは、countの値が変更されることがないため、Rendererの機能がOFFになることはありません。そこで、CountDownコンポーネントにアクセスしてcountの値を変えるコンポーネントを作成します。

using UnityEngine;

public class ChangeCount : MonoBehaviour
{
    // CountDownコンポーネントを保持するための変数を用意
    CountDown countDown;

    void Start()
    {
        // CountDownコンポーネントにアクセスして変数に代入
        countDown = GetComponent<CountDown>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            // CountDownコンポーネントのcountの値を1減らす
            countDown.count--;
        }        
    }
}

作成した2つのコンポーネントを同じゲームオブジェクトにアタッチしてください。

同じゲームオブジェクトにアタッチしていない場合には、CountDownコンポーネントが見つからないため、エラーが起こります。

NullReferenceExceptionは存在しないものにアクセスしようとした場合に起こるエラーです。非常に良く見るエラーなので、気をつけましょう。

コンポーネントを2つに分ける意味は?

自作コンポーネントを2つ作成してアクセスする方法を書きましたが、現段階ではわざわざ2つのプログラムファイルに分ける意味(メリット)がわからないかもしれません。

プログラムを複数のファイルに分ける利点は「分類して扱いやすくすること」にあります。例えば、学校で授業を受けるときには国語の授業なら国語のノート、算数の授業なら算数のノートというようにノートを変えるはずです。もし、課目ごとに分けずに1つのノートにすべての板書を写したとしたらどうなるでしょうか。あとで見返すときに、目当ての科目がどのページにあるかわからず、混乱するでしょう。プログラムでも同様です。機能ごとに分けたほうが整理やチェックが楽になります。

良いことは他にもあります。それは使いまわしが可能になることです。部品を取って変えるかのように、機能ごとに分かれたプログラムを組み合わせて様々な機能が実現できるようになります。

実際、Unityが用意しているコンポーネントも位置や大きさを担当するTransform、描画を担当するRenderer、衝突判定を担当するColliderなど機能ごとに分かれて作られています。このおかげで、似たような処理を何度も書かずに済むのです。

まとめ

この記事ではコンポーネントにアクセスする方法を学びました。コンポーネントに自由にアクセスできるようになれば、あとはコンポーネントの機能を操作してやるだけでゲームらしい動きが実現できるようになります。

ここまでくれば、Unityの基本的な考え方は身に着けたといっても過言ではありません。あとは実際のゲーム制作を通して、必要なコンポーネントの機能を少しずつ学ぶだけです。

Unityプログラミング講座一覧はこちら

Unityプログラミング講座
ゲームエンジンUnityを使ってゲーム制作を始めようと思っている人へ向けた解説記事です。初心者がUnityをインストールするところから始めてゲームを制作するのに必要な知識をできる限りステップバイステップでまとめるつもりです。
タイトルとURLをコピーしました