【Unity】他オブジェクトのスクリプトのメソッドがどうしても取ってこれない原因と対処法
概要
Unityでほかのスクリプトで定義されているObjectを取ってきたいシーンがありました。がVisual Studioでどうしても認識してくれず、かなり悩みましたのでその対処法についてメモします。
環境
Windows10
Unity 2020.1f.1
まず最初に確認すべきこと
他のゲームオブジェクトにアタッチされているスクリプトのメソッドを別のスクリプト内で呼び出して使用したい場合に、まず確認すべき事項として以下があります。
- 取得元のclassがpublic classで宣言されているか
- 取得元のclassで定義されているメソッドがpublicで宣言されているか
上記の条件を満たした上で以下の流れでコードを書けば問題なく呼び出すことができるはずです。
- 取得したいスクリプトがアタッチされているオブジェクトをGameObject.Findなどで指定して取得する。
- 取得したGameObjectのclassをGetComponentで取得する
- 取得したclass.メソッド名で使用する
参考になったサイト
https://htsuda.net/archives/1702
しかし、何故か私のが触っていたスクリプトでは上手くいかず、Visual Studioが他オブジェクトのメソッドを認識せず、メソッドが見つからないというエラーが出っぱなしでした。
結論:名前空間を指定していなかった
なぜ認識してくれなかったか。
結論から言うと、classの上位で 名前空間(NameSpace)が宣言されていたにも関わらず、名前空間を指定していなかった ということが原因でした。
上位側で名前空間が定義されている場合、名前空間から指定しないとちゃんと相手先のclassやメソッドを認識してくれません。
エラーの実例
実例を踏まえて解説します。
まず、3D ObjectとしてSphere1とCube1というものを作成します。
Sphere1には以下のスクリプトをアタッチしてあるとします。このスクリプトは呼び出される側のスクリプトとします。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TestNamespace
{
public class OtherClass : MonoBehaviour
{
public void TestMethod()
{
Debug.Log("This is from other class");
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
}
次にCube1オブジェクトには以下のスクリプトをアタッチするとします。
これはSphere1にアタッチされているスクリプトからTestMethodを呼び出して使用するスクリプトです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThisClass : MonoBehaviour
{
GameObject sphereObj;
OtherClass otherClass;
// Start is called before the first frame update
void Start()
{
sphereObj = GameObject.Find("Sphere1");
}
// Update is called once per frame
void Update()
{
otherClass = sphereObj.GetComponent<OtherClass>();
otherClass.TestMethod();
}
}
しかし、この時、Visual StudioではOtherClassを認識してくれてておらず、赤の波線がでています。当然このままコンパイルしてもこのオブジェクトは宣言されてません的なエラーが発生します。
原因
この原因はSphere1側にアタッチしたスクリプトで名前空間を定義しているからです。
namespace TestNamespace //これが名前空間
{
...
}
この場合は呼び出す側のスクリプトでも名前空間から指定してあげないといけません。具体的には以下のような形です。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThisClass : MonoBehaviour
{
GameObject sphereObj;
TestNamespace.OtherClass otherClass; //名前空間から指定
// Start is called before the first frame update
void Start()
{
sphereObj = GameObject.Find("Sphere1");
}
// Update is called once per frame
void Update()
{
otherClass = sphereObj.GetComponent<TestNamespace.OtherClass>();
otherClass.TestMethod(); //名前空間から指定
}
}
ちゃんと認識された。
まとめ
UnityでCreateからC#を作ると普通は名前空間が定義されていないため意識しないですが、他から持ってきたスクリプトなどでは名前空間が定義されていることがあります。そのような場合は名前空間からオブジェクトを指定する必要があります。C#に精通している人なら当たり前のことかもしれませんが、Unity初心者の私は少しハマってしまいました…
以上
Unityを一から学ぶのにおすすめの本はコチラ