45
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Unity初心者Tips]確実に!必要なComponentを入れるRequire ComponentとReset()

Last updated at Posted at 2018-01-23

Unityでゲームを作っていると、GameObjectにComponentを沢山、ぶらさげていくことになります。この時に、コンポーネント同士でお互いの機能を使うために参照するなど、「互いに必須のコンポーネント」が要るようになります。そうした場合の方法を考えてみましょう。

コンポーネントを必須化するRequire Component

UnityEngineで用意された、Require Componentを使うと、同じGameObjectでアタッチされたコンポーネントをチェックして、それがないとビルドでエラーになるようにできます。

例えば、以下のコードがあったとします。

TestClassA.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestClassA : MonoBehaviour {

    [SerializeField]
    TestClassB testClassB;
    [SerializeField]
    TestClassC testClassC;

    private void Start()
    {
        testClassB = GetComponent<TestClassB>();
        testClassC = GetComponent<TestClassC>();

    }
}

TestClassAというコンポーネントから、TestClassB,TestClassCを参照しているとします。ただし、GameObjectにアタッチされているかは判りませんから、場合によってはGetComponentが失敗することがあります。それを防ぐために、以下の形にします。

TestClassA.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//必要なコンポーネントを定義
[RequireComponent(typeof(TestClassB))]
[RequireComponent(typeof(TestClassC))]

public class TestClassA : MonoBehaviour {

    [SerializeField]
    TestClassB testClassB;
    [SerializeField]
    TestClassC testClassC;

    private void Start()
    {
        testClassB = GetComponent<TestClassB>();
        testClassC = GetComponent<TestClassC>();

    }
}

TestClassAをアタッチすると、Require Componentで指定されたコンポーネントTestClassBTestClassCが自動的にアタッチされます。
https://gyazo.com/93f9c5862fb6502eef72b89f6ed2bb8f

https://gyazo.com/4fa4e60f51ecc5c9e3f6fca7328c74f2
また、指定されアタッチされたコンポーネントは外せません。この例の場合では、TestClassAを外さないままでTestClassBを外そうとすると、エラーになります。
書式は以下になります。

[RequireComponent(typeof(追加したいコンポーネント名))]

#初期化をしてくれるReset()
上記でコンポーネントの追加を自動化できましたが、Start()でGetComponentするまで、参照は入りません。初期化で負荷がかかるので、同様のGameObjectが多い場合には、起動前に代入しておきたいものです。その時にEditor上で実行できるメソッドがReset()です。

前記コードを以下に変更します。

TestClassA.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//必要なコンポーネントを定義
[RequireComponent(typeof(TestClassB))]
[RequireComponent(typeof(TestClassC))]

public class TestClassA : MonoBehaviour {

    [SerializeField]
    TestClassB testClassB;
    [SerializeField]
    TestClassC testClassC;

    private void Reset()
    {
        testClassB = GetComponent<TestClassB>();
        testClassC = GetComponent<TestClassC>();

    }
}

これを実行すると、コンポーネント追加やギアアイコンからResetしたときに、Reset()が実行されます。

https://gyazo.com/e3eaebcc90a4b96eb852a367e8a77a8d

https://gyazo.com/246ea789115a9bcdde172ee1a3063f3b

同じようにTestClassAだけ追加していますが、今度はTestClassBTestClassCが自動的にアタッチされると同時に、参照の代入も実行されます。

使い方のあれこれ

  • Require Componentだけの場合、必須にしたいものはRigidbody等でも使えます。特定の初期化する部分をReset()に書くことも可能です。
  • 最初のサンプルから入れてあるので触れていませんが、[SerializeField]Reset()で設定したい場合は必須です。RequireComponent[SerializeField]が無くとも有効です。
  • SceneでStaticなどで保証されるものなら、Resetでfind等を用いて検索することも可能です。
TestClassA.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(TestClassB))]
[RequireComponent(typeof(TestClassC))]
[RequireComponent(typeof(Rigidbody))]
public class TestClassA : MonoBehaviour
{

    [SerializeField]
    TestClassB testClassB;
    [SerializeField]
    TestClassC testClassC;
    [SerializeField]
    Rigidbody rigidBody;
    [SerializeField]
    GameController gameController;
    [SerializeField]
    TestEnemy testEnemy;
    private void Reset()
    {
        testClassB = GetComponent<TestClassB>();
        testClassC = GetComponent<TestClassC>();
        rigidBody = GetComponent<Rigidbody>();
        gameController = FindObjectOfType<GameController>();
        if (gameController == null) {
            Debug.Log("ERROR!Gamecontroller not found");
        }
    } 
}

必須になるものをGameControllerにいろいろ記述して参照できるようにしておくと、Scene内での相互参照したいGameObject同士のアクセスが楽になります。そうした場合に、上記方法を使うと便利ですね。

参考

45
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?