C#Scriptから以下のようにGameObjectを操作するチュートリアルです。
- 自分がアタッチされている以外のGameObjectを取得する。
- 取得したGameObjectのインスタンスを複製する。
- GameObjectを移動する。
- GameObjectを回転する。
プロジェクトを作成する
Unity Hubで新規プロジェクトを作成します。
どのバージョンでも構いませんが、ここではUnity 2020.2.5f1でプロジェクトを作成しています。プロジェクト名、保存先はお好きなように入力してください。
レイアウトを変更する
デフォルトのLayoutのままでも大丈夫ですが、ここではSceneとGame windowが見たいのでToolbarの一番右でLayoutをDefaultから[nmxi style]に変更しています。
GameObjectを生成する
Hierarchy windowのコンテキストメニューで[3D Object]-[Sphere]を選択しSphereを生成します。これでシーン上にnameが”Sphere”というGameObjectクラスのインスタンスが生成されます。このSphereをC#Scriptで複製します。
Hierarchy windowのコンテキストメニューで[3D Object]-[Create Empty]を選択し空のGameObjectを生成します。GameObjectクラスのインスタンスは生成されますが、Scene windowでは見えないGameObjectです。C#Scriptをアタッチする用のGameObjectとします。
C#ScriptではSphereを見つけ出し、複製し、複製したものを移動、回転させます。
C#Scriptを生成する
Assetsフォルダの下であればどこでもいいですし、C#Scriptの名前も何でもいいですが、ここでは、Project windowのコンテキストメニューでAssetsフォルダの下にScriptsフォルダを生成しその下にControllという名前のC#Scriptを生成します。
Project windowのAssetsフォルダを選択します。
コンテキストメニューの[Create]-[Folder]でScriptsフォルダを生成します。
Scriptsフォルダを開きます。
コンテキストメニューで[Create]-[C#Script]を生成し名前を”Controll”とします。ファイル名決定後はコンテキストメニューの[Rename]でファイル名を変更できます。
ControllをダブルクリックするとVisual Studioが開きます。他のツールを使っている場合はそれで編集しても大丈夫です。
C#Scriptを編集する
Controll.csを編集します。名前はControll.csでなくても構いませんが、ファイル名とクラス名は同じになるようにしてください。そうしないとGameObjectにアタッチできません。
デフォルトのコードを読む
C#Scriptを生成した直後は次のようなコードになっています。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Controll : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } }
コードを簡単に説明します。
using System.Collections; using System.Collections.Generic; using UnityEngine;
usingで使用するnamespace(名前空間)を指定します。指定したnamespaceにあるクラスはクラス名だけで使用できるようになります。
GameObjectクラスをコードで使用するときにusing宣言がないと、UnityEngine.GameObjectとnamespaceから指定する必要がありますが、using UnityEngine;を宣言すると、GameObjectだけで使用できます。
public class Controll : MonoBehaviour { ...(略)... }
MonoBehaviourクラスから派生したpublicなControllクラスの宣言です。宣言内でメソッドやフィールドを定義できます。
// Start is called before the first frame update void Start() { }
Start()メソッドは初期化を行うメソッドです。
// Update is called once per frame void Update() { }
Update()メソッドはフレーム毎に呼ばれるメソッドです。
コードを編集する
次のように編集します。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Controll : MonoBehaviour { // Start is called before the first frame update void Start() { GameObject target = GameObject.Find("Sphere"); if (target != null) { for (int x = -1; x <= 1; ++x) { for (int y = -1; y <= 1; ++y) { for (int z = -1; z <= 1; ++z) { // 複製する GameObject clone = Instantiate(target, this.transform); // 移動する clone.transform.position = new Vector3(x * 1.1f, y * 1.1f, z * 1.1f); } } } // 元のGameObjectは破棄する Destroy(target); } } // Update is called once per frame void Update() { transform.Rotate(new Vector3(0.1f, 0.2f, 0.3f)); } }
コードを説明します。
GameObject target = GameObject.Find("Sphere");
GameObjectクラスのFindという静的メソッドで”Sphere”という名前のGameObjectを検索します。見つかったGameObjectのインスタンスをtargetという名前のローカル変数に設定します。”Sphere”という名前はHierarchyにある名前と一致する必要があります。Hierarchyで名前を変更した場合はその名前にしてください。
GameObject clone = Instantiate(target, this.transform);
Monobehaviourの基底クラスはBehaviourクラス、その基底クラスがComponentクラス、そのまた基底クラスがObjectクラスです。基底クラスのpublic及びprotectedメソッドはメソッド名だけで呼び出すことができます。InstantiateはObjectのメソッドです。Visual Studio上で”Instantiate”の上にマウスを持っていくとどのクラスのメソッドがわかります。第一引数でコピー元のインスタンスを指定します。第二引数で親のTransformを指定します。ここでは自分のtransformを指定しています。
コードだけみると、Controller C#Scriptインスタンス自身のtransformを操作しているように見えますが、基底クラスのComponentクラスのメソッドやプロパティではgameObjectへ移譲することで、MonoBehaviourから派生したクラスが、あたかもGameObject自身であるかのように振舞えるようにしています。便利になっていますが、ここを理解しないと混乱する元になります。
public class Component : Object { ... public Component GetComponent(Type type) { return this.gameObject.GetComponent(type); } ... public string tag { get { return this.gameObject.tag; } set { this.gameObject.tag = value; } }
clone.transform.position = new Vector3(x * 1.1f, y * 1.1f, z * 1.1f);
複製したGameObjectのインスタンスの座標を変更します。
for (int x = -1; x <= 1; ++x) { for (int y = -1; y <= 1; ++y) { for (int z = -1; z <= 1; ++z) { // 複製する GameObject clone = Instantiate(target, this.transform); // 移動する clone.transform.position = new Vector3(x * 1.1f, y * 1.1f, z * 1.1f); } } }
xを-1、0、1、yやzも-1、0、1に変更し3x3x3の27個のGameObjectの複製を作り、座標をx,y,zに移動します。間にちょっと空間を作るために1.1倍しています。
Destroy(target);
複製して不要になったので元の”Sphere”GameObjectインスタンスを破壊します。
void Update() { transform.Rotate(new Vector3(0.1f, 0.2f, 0.3f)); }
フレーム毎にちょっとずつ回転させます。親を回転させることで子も一緒に回転します。
編集後にCtrol-Sや保存アイコン等で保存します。
C#Scriptをアタッチする
Unity Editorに戻りControll C#ProjectをHierarchy上のGameObjectにアタッチします。アタッチすることでControll C#ScriptはGameObjectのコンポーネントとして登録されます。アタッチする方法はいくつかあります。
- Project上のC#ScriptのControllをHierarchy上のGameObjectにドラッグ&ドロップする。
- Hierarchy上のGameObjectを選択し、Inspector上にControll C#Scriptをドラッグ&ドロップする。
- Hierarchy上のGameObjectを選択し、Inspectorの[Add Component]でControll C#Scriptを選択する。
Playする
上記はツールバーの中央にあるボタンです。左からPlay、Pause、Stepです。Play(再生)中にPlayボタンを押すとPlayを終了します。
Cubeに変えてみる
Cubeでもやってみましょう。
Hierarchyの[+]あるいはコンテキストメニューで[3D Object]-[Cube]を選択しCube GameObjectを生成します。
HierarchyでSphereを選択し、Inspector windowでSphereの左側のチェックボックスを外して非アクティブにします。
Controll C#Scriptの”Sphere”を”Cube”に変えて保存します。
Playボタンを押します。
コメント