ゲーム制作勉強中!あこがれだったプログラマーに今からなろう!

昔、あこがれていたプログラマー。今からでも勉強してみようと思い立ち、チャレンジ開始! 勉強メモや、悪戦苦闘な日々の記録です。

Unity経験者のGodotの遊び方:インスタンス化と実体化について


UnityGodotで共通する事として、GameObject(GodotではNode)はインスタンス化される必要があります。

ところが、このインスタンス化の概念が、UnityGodotでは少し異なる様です。
最初、すごく混乱させられたので、備忘録として簡単にまとめておきます。

Unityにおいて、ゲーム内で新しいGameObjectを生成する場合、

using UnityEngine;

public class InstansPrefab : MonoBehaviour
{
    public GameObject InstansPrefab; // Prefabを変数として指定

    private void Start()
    {
        // Prefabをインスタンス化
        var instansObject = Instantiate(InstansPrefab);
    }
}

これだけで、Prefabから新しいinstansObjectが生成され、ヒエラルキーウィンドウ上とゲーム画面上に表示されます。
もちろん、この段階で新しいGameObjectUpdate関数も動き始めます。

対して、Godotではと言いますと、

extends Node

var Instans_Prefab:PackedScene = preload("res://Scene/enemy.tscn")#Prefabを変数として指定
        
func _instans_prefab():
    #Prefabをインスタンス化?
    var Instans_Object=Instans_Prefab.instantiate()

一見、同じように見えます。
ですが、Godotでは、これだけではゲーム画面上には新しいInstans_Objectは表示されません。
そして、Unityでいうヒエラルキーウィンドウに当たるシーンドッグにも、この新しいInstans_Objectは表示されません。

試しに、色々と実験してみます。

   #先ほどのインスタンス化?の続き・・・

    #変数の内容を出力ウィンドウに表示してみる。
    print(Instans_Object)

    #オブジェクトにある初期設定用関数にアクセスできるか試してみる。
    Instans_Object._Set_Parameter(100.0,0) #初期設定用、今は仮に100.0と0を指定

    #オブジェクトの座標を出力ウィンドウに表示してみる。
    print(Instans_Object.position)

上記の処理はすべて成功します。
Instans_Objectは間違いなく生成され、どこかに存在している様です。

試しに、今度はInstans_Object_process関数printを追加してみます。

extends RigidBody2D
var Speed:float
var Color:int

func _Set_Parameter(speed:float,color:int) -> void:
    Speed=speed
    Color=color

func _process(delta):
    print("process test") #毎フレーム、"process test"を出力ウィンドウに表示させたい。

結果、このprintは処理されず、出力ウィンドウに表示してくれませんでした。

この2つの実験の結果から、Instans_Objectはどこかに存在して、その関数にアクセスする事もできますが、
_process関数が実行していない事が分かりました。

公式チュートリアルでは、練習として2Dと3Dの避けゲームを作成し、そこで、敵を大量に生成していたので、
もう一度、公式をじっくりと読んでみて、次の一文に気づきました。

メインシーン — Godot Engine (4.x)の日本語のドキュメント


Unityを触ってきた僕としては、シーン内で生成されたオブジェクトは、当然そのシーンに追加されるイメージでしたが
どうもGodotでは、そういう訳ではない様です。

Unityでいうシーンは、言うなれば、1つの世界の様なものだと僕はイメージしています。
特に意識する事なくヒエラルキーウィンドウ上でオブジェクトを作成し、
作成されたオブジェクトは、特に意識する事なくそのシーンに追加されます。

Godotにおいてのシーンとは、単純に(もしくは厳密に)ノードの集合体という意味が強いのかもしれません。
Godotの4大要素の一つにScene Tree(シーンツリー)がある事から、
Unityの様に「特に意識する事なく」ではなく、生成したシーンをScene Tree(シーンツリー)のどこに置くか
をきちんと指定しないと、実体として存在できない様です。

extends Node

var Instans_Prefab:PackedScene = preload("res://Scene/enemy.tscn")#Prefabを変数として指定
        
func _instans_prefab():
    
    var Instans_Object=Instans_Prefab.instantiate()
    add_child(Instans_Object)#生成したInstans_Objectを、このスクリプトがアタッチされたNodeの子に追加。

これで、ようやくシーンドッグとゲーム画面の両方にInstans_Objectが表示され、Instans_Object_process関数
も動き始めてくれました。

つまり、Godotにおいては、いわゆるインスタンス化と、シーンドッグ上に存在させる言わば「実体化」は異なる様です。
これを上手く使えば、色々と面白い仕組みを作る事ができるのかもしれませんね。