Unity(C#)のクラスやGameObject、Componentの呼び出しでよく使うパターンをまとめています。
頻出レベル
まず知らないと困りそうな手法達です。
インスペクタを介してインスタンスを取得する
Unityスクリプトの基本ですが、GameObjectやComponent、画像などのリソースをインスペクタを介してフィールドで受ける方法です。
GameObjectとComponentはインスペクタ上の指定方法は同じですが、スクリプト側は区別するので注意してください。
// 設計とか考えずにとにかく使いたいなら
public GameObject enemy; // Prefabを含むあらゆるGameObjectが対象
public Image userImage; // UI>Imageの画像書き換えなど
// 外部から参照されたくないなら
// 注意:Unity2018頃から初期値がnull相当の値だと警告が出ます
// インスペクタで値を指定させる前提の場合は、publicで対応しましょう
[SerializeField]
private Collider hitTarget; // GameObject内のCollider系コンポーネントだけ取得する
ちなみに配列も可能です。
public GameObject[] enemies; // デフォルトは空の配列
public GameObject[] players = new GameObject[4]; // デフォルトの配列サイズも指定可能
ProjectViewのリソースを取得する
可変的にデータを参照したい場合や、大量のデータを名前で管理したいような状況では、「リソース」として取得する方法があります。「Resources」フォルダに入っているデータがリソースとして扱われます。
リソースはビルド時にゲームデータとして使用されるデータとして扱われます。通常は、シーン上で使用されていないデータはビルド時に除外されるようになっており、アセットのサンプルデータなどのような不要なデータとして扱われます。リソースの場合は、シーン上から直接使われていなくても必ずビルドデータに含まれるようになります。
void Start() {
// リソースの名前だけで取得する
var enemyTexture = Resource.Load("enemyTex") as Texture;
// Prefab(GameObject)に限定して取得する
var mobChar = Resource.Load("mobchan", typeof(GameObject)) as GameObject;
}
UnityDoc - https://docs.unity3d.com/jp/540/ScriptReference/Resources.Load.html
GameObject上のComponentを取得する
フィールドなどからGameObjectを取得したあとに、内包しているComponentを取得する方法です。
実行中にComponentが追加されるようなAssetsで連携する場合は必須です。
public GameObject root;
void Update() {
// 取得するComponentをテンプレートのクラスに指定して取得する
Renderer rend = root.GetComponent<Renderer>();
}
クラスそのものを取得する(参照する)
インスタンスではなくクラスそのものを使いたい場合があります。
特にAssetsのコンポーネントを参照したい、生成したいなどはスクリプトが同じ名前空間にないとアクセスできないので、usingします。
サンプルとして、MyGameAssetという名前空間にMyGameObjectクラスを作ったとします。
namespace MyGameAsset {
public class MyGameObject : MonoBehavior {
/* Your Program */
}
}
このクラスを外部のスクリプトからアクセスする場合は、次のようになります。
using MyGameAsset; // ←ココ
public class MyScript : MyGameObject {
/* Your Program */
}
なお、名前空間はProjectViewの階層とかは関係なく、あくまでもnamespaceで決まるので注意してください。
時々レベル
パフォーマンスや可読性の観点からあまり使いたくない手法です。
インスペクタを介さずにステージ上のインスタンス取得
動的に生成されたGameObjectなどのシーン上のGameObjectを手軽に取得する方法です。文字列で名前指定するだけで取得できますが、結構重い処理なのでUpdate()
内などで定期的に取得し直すとボトルネックになる可能性があります。
private GameObject pointTarget;
void Awake() {
// シーンに配置されたGameObjectの名前から取得する
pointTarget = GameObject.Find("GameObjectName");
}
あとがき
いろいろ不十分な部分あると思います。
指摘あれば修正加筆するかもなので、よろしくお願いします。