ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

20220329162023

Unity入門 - Prefabをスクリプトから操作する -

初めに

f:id:fineworks_fine:20220326160233p:plain

 Prefabをスクリプトから生成、操作する方法を解説します。

 Prefabとはどのようなものか、Prefabの作り方、使い方については前回の記事をご覧ください。
fineworks-fine.hatenablog.com

生成(Instantiate)

 Prefabからオブジェクトを生成するには、Instantiate関数を用います。
 今回は、Prefab化したCubeをスクリプトから生成してみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeInstScript : MonoBehaviour
{
    //InspectorからPrefabを取得する
    public GameObject PrefabCube;

    void Start()
    {
      //Instantiate(インスタンスにするオブジェクト)
      GameObject _prefabcube = Instantiate(PrefabCube);
    }
}
  • スクリプトをアタッチしたオブジェクトにPrefabを取得させる

f:id:fineworks_fine:20220326150341p:plain

 実行すると、Cubeが生成されます。

f:id:fineworks_fine:20220326150557p:plain

Instantiate関数の引数について

 上の説明では、Instantiate関数の引数をGameObjectのみとしていましたが、PositionやQuaternion(回転)、親オブジェクトを引数に追加することもできます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeInstScript : MonoBehaviour
{
    public GameObject PrefabCube;

    //Inspectorから親オブジェクトとなるオブジェクトを取得
    public GameObject Parent;

    // Start is called before the first frame update
    void Start()
    {
      //Position(2, 0, 0), 回転せずに生成
      GameObject _prefabcube1 = Instantiate(PrefabCube, new Vector3(2, 0, 0), Quaternion.identity);
      //Position(0, -2, 0), x軸に関して30度, y軸に関して45度回転させて生成
      GameObject _prefabcube2 = Instantiate(PrefabCube, new Vector3(0, -2, 0), Quaternion.Euler(30, 45, 0));
      //Parentというオブジェクトの子オブジェクトとして生成
      GameObject _parfabcube3 = Instantiate(PrefabCube, Parent.transform);
    }
}

f:id:fineworks_fine:20220326152254p:plain

 Instantiate関数、Quaternionについての公式の説明は下記リンクからご覧いただけます。引数など参考になるかと思います。

docs.unity3d.com
docs.unity3d.com

Prefabをスクリプトから扱う際の注意点

 Prefab自身を変更したのか、インスタンス(実体)を変更したのかの違いを明確にしておきましょう。

Prefabをスクリプトから変更する

 次のスクリプトをGameObjectにアタッチして実行してみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeInstScript : MonoBehaviour
{
    public GameObject PrefabCube;

    // Start is called before the first frame update
    void Start()
    {
      //生成(1個目)
      GameObject _prefabcube1 = Instantiate(PrefabCube, new Vector3(-2, 0, 0), Quaternion.identity);
      //Prefabの書き換え
      PrefabCube.transform.localScale = new Vector3(1, 2, 1);
      //生成(2個目)
      GameObject _prefabcube2 = Instantiate(PrefabCube, new Vector3(2, 0, 0), Quaternion.identity);
    }
}

 実行すると次のようになります。

f:id:fineworks_fine:20220326153636p:plain

 2個目の生成の前にPrefabを書き換えたため、1個目と2個目で大きさが変わっていることがわかります。
 また、もう一回実行すると次のようになります。

 f:id:fineworks_fine:20220326153747p:plain
 1回目の実行で、すでにPrefabを書き換えているため、このような挙動になります。

インスタンススクリプトから変更する

 GameObjectにアタッチするスクリプトを次のように変えてみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeInstScript : MonoBehaviour
{
    public GameObject PrefabCube;

    // Start is called before the first frame update
    void Start()
    {
      //生成(1個目)
      GameObject _prefabcube1 = Instantiate(PrefabCube, new Vector3(-2, 0, 0), Quaternion.identity);
      //インスタンスのScaleを変更
      _prefabcube1.transform.localScale = new Vector3(1, 2, 1);
      //生成(2個目)
      GameObject _prefabcube2 = Instantiate(PrefabCube, new Vector3(2, 0, 0), Quaternion.identity);
    }
}

 実行すると、次のようになります。
f:id:fineworks_fine:20220326154649p:plain
 
 Prefabは変更していないので、2個目を生成するときは、Prefabのまま生成されます。また、何回実行しても、Prefabは変化していないため、実行結果は同じになります。

実験

 Prefab化しているCubeにRigidbodyを付け、次のようなスクリプトをGameObjectにアタッチして、実行した場合どのようになるでしょうか。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeInstScript : MonoBehaviour
{
    public GameObject PrefabCube;

    // Update is called once per frame
    void Update()
    {
      Instantiate(PrefabCube, Vector3.zero, Quaternion.identity);
    }
}

実行結果

 Updateに書かれているため、毎フレームに一個、Cubeが生成されています。Rigidbodyをつけているため、物理演算も働いています。そのため、Cube同士が反発しあって、このようになります。

最後に

 Prefabは敵の生成やシューティングゲームの玉などに使われます。使い方は無限にあるので、分かりにくくても使いこなせるようになることをお勧めします。