(Godot c#)AddChildするときは、そのシーンでやれ

AddChildでハマった。

なんとも初歩的なことだ。

タイトルにある通り、AddChildをするときは、つけたいシーンにあるスクリプトでやったほうが混乱が少ない。

全く関係ないスクリプトで hoge.AddChild(xxxx);なんてやりだしたらエラーが出る確率があがる。

素直に、this.AddChild(xxx)と書けるようにやるべきだ。

なんかエラーが出てしまうと、あれこれ考えて深みに入るが、ちょっとでも複雑そうなことはやめたほうがいいだろう。

という教訓。(ただの寝不足だったのかもしれない)

Godot4.3 C# | シグナルをGeminiに習った日

ずっと気になっていたシグナル。どうやらunirxに近いものを感じた。

ボタンを押したりする時に必要になりそうなので、とりあえず腰を据えて学んでみた。

とはいえ1時間ぐらいかな。

少しでも気になったところをAIに聞き倒して理解を深めた。

一回覚えたらずっと使えるというのが良いところ。


using Godot;

public partial class MyButton_1 : Button
{
    // シグナルの定義
    [Signal]
    public delegate void button_testEventHandler();

    public override void _Ready()
    {
        // ボタンが押されたときの処理
        Pressed += OnButtonPressed; // Godot組み込みのPressedシグナルに接続
    }

    private void OnButtonPressed()
    {
        // カスタムシグナルを発行
     //EmitSignalを呼び出す事に通知するので、何回でも発行して良い。(個人的メモ)

        EmitSignal(nameof(button_test)); // シグナルの名前を変更
    }
}

using Godot;

public partial class Main1 : Node
{
    private Label _myLabel;
    private MyButton_1 _myButton;

    public override void _Ready()
    {
        // ノードの取得
        _myLabel = GetNode<Label>("myLabel");
        _myButton = GetNode<MyButton_1>("koko");

        if (_myLabel == null || _myButton == null)
        {
            GD.PrintErr("Label or Button not found!");
            return;
        }

        // シグナルの接続
		_myButton.button_test += OnMyButtonPressed;
    }

    private void OnMyButtonPressed()
    {
        // ラベルのテキストを変更
        _myLabel.Text = "Button Pressaaaaed!";
    }
}

//受信型は送信側のことを考えなくて良い。
//どのクラスからでもシグナルに接続すると受信できる。

学んだこと

・コードのみで実装可能

・シグナル名は変更できない (Pressedなど)

・xxx_xxxxEventHandlerを必ずつける必要がある
(button_testEventHandler)

・1つのクラスに複数のシグナルをつけることができる。

・ノードにあるものでシグナルをする。

なんとかわかりそう。あとは何度か実際に試していくだけ

Godot4.3 C# | AddChild後に.Nameはどうだろう

以下、初心者の意見です。

「AddChild」というよく使う関数がある。

これを実行する前にシーンに名前をつけることもできるし、後からつけることも可能だ。

個人的には名前や位置などを調整してからAddChildを実行していたが、どうやら逆の方がしっくりくる。

というのも、先に名前をつけておくとシーンに「@Sprite2D@x」というようなシーンが作られることが多かったからだ。これがなんとも気持ち悪い。AIに聞いてみると、「内部的には名前は変わっているので問題ない」と言っている。

しかし、見た目は重要。今のところAddChildをしてから.Nameで名前を変更するとうまくいっている。

もちろんそれでも100%うまくいっているわけではない。「@Sprite2D@x」というようなシーンは作られることがあるが、ゲームを進めていくと消えていく。

ということで、「AddChild」を使う時は、AddChildをしてから名前を変更するという手があるということをシェア。(あまりにマニアックでどっちでもいいと思っているけど)

Godot 画像を表示させるシンプルな方法

using Godot;
using System;

public partial class Field : Node2D
{
	[Export] private Texture2D[] _textures = new Texture2D[8];
	public override void _Ready()
	{
		LoadAndDisplayImages();
	}
	private void LoadAndDisplayImages()
    {
		for (int i = 0; i < _textures.Length; i++)
		{
			var sprite        = new Sprite2D();
			sprite.Position   = new Vector2(50 + 200 * i, 250);
			sprite.Texture    = _textures[i];
		
			AddChild(sprite);	
		}
	}
	
}

ChatGPTが生成したコード。

Godot上で_texturesに画像をアタッチしておく。

メモ。

Godot+R3のマウス操作

動作確認をして学習している。

せっかく学んだことをそのままにしておくと忘れるのでメモ。


using R3;
Observable.EveryUpdate()
	  .Where(_ =>Input.IsActionPressed("click_DOWN"))
            .Subscribe(_ => GD.Print("GetMouseButtonDown"))
            .AddTo(this);

click_DOWNの部分は、任意で設定したもの。
「プロジェクト>インプットマップ」で作れる(下)

click_DOWNという文字列はおかしいとは思うが、テストでやっているのでご愛嬌。

作りたいゲームがあればどういう機能が必要なのかを考えて、1つずつテストしていく。

頭の中で分からないことがなくなれば実際に作り出せばいい。

今の時点ではよく分からないことが多いので、検索したりAIに聞いたりしてまとめている。

(結構楽しい☺️)

Visual Studio CodeのアクティビティバーにGitHub Copilot Chatのアイコンを表示させる

有料だったので、あまりGitHub Copilot には興味はなかったのだが、無料になったということで早速インストールしてみた。

***

インストールは簡単に終わったものの、アイコンが出ない。

それ以外の機能は使えている。

githubにログインもできている。

おかしい。

・・・。

謎にアイコンが表示されないので30分ぐらい悩んだ結果、出すことに成功したので、やり方をシェア。

ずっとこんな状態だった。(上)

ショートカットキーで一応チャットは開けるし動作も確認できている。
しかし、使い方を教えてくれているwebサイトにはアイコンが表示されているので私も表示したい。

解決

上の画像は、ショートカットキーなどでGitHub Copilot Chatを開いたときの上段メニューである。

ここにチャットのアイコンがあったので、これをドラックしてアクティビティバーに移動したらアイコンが移動できた。

終わり。

(超基本)他のゲームオブジェクトにアタッチしているスクリプトの変数を外部から変更する方法

XXX_SCRIPT game_obj = GameObject.Find("MOTO_GameObject").GetComponent<XXX_SCRIPT>();
game_obj.functionX(); //雰囲気こんな感じか

//Find系は、AwakeやStartで1回だけやらないと負荷がかかるので注意。

unityを触るのが久しぶりすぎて超基本的なことを忘れていた。

「なんか変だなあ」と思いながら結構ゲーム自体は作れてしまったので不思議。

現在は、全てGetComponentに置き換えて、基本的に1つのゲームオブジェクトには1つのスクリプト。あるいは関連するスクリプトしかないようにしている。外部からどうしても変更したい場合は、GetComponentで取得して変更するとうまくいった。

誤ち

別のゲームオブジェクトを複数画面に表示させて、同じスクリプトをアタッチしていたところ、謎の状態となってしまった。
(AwakeでDebug.Logを書いたら同じログが3回も表示していた)

正解

基本的にスクリプトは1つだけアタッチさせて、外部からGetComponentでアクセスしていじる。

この記事の1番の上に書いたように、「GetComponent<XXX_SCRIPT>();」で探して利用すると良い。

いろいろなゲームオブジェクトにアタッチしておくと全て初期化されるので(だよね?)、データの更新など意味がなくなる。staticやらシングルトンにすると良いと思うがそれは基本的にやらない方がいい。

結局1本ゲームを作るとなると1から全て学ぶ必要があるんだよね。

滑らかにオブジェクトを移動させるには?

float fallSpeed = 1.0f;
gameObject.transform.Translate(Vector2.down * fallSpeed * Time.deltaTime);

テトリスのようなゲームでオブジェクトを自然に落下させるにはこんな感じにすると良い。

1マスずつずらしていくとなんかカクカクした感じになるのが個人的に苦手なんでね。

Observable.EveryUpdate()
.Subscribe(_ => Down_Block());

R3も使って、Updateをする感じも忘れずに。

いろいろ試してみたけどGeminiが教えてくれた。

ミソは、「fallSpeed * Time.deltaTime」これ。

すーっとオブジェクトが移動するのがなんとも気持ちいい。

R3 ダブルクリック

unirxではなくR3を使うのでメモ

using R3;
var DoubleClickStream = 
            Observable
                .EveryUpdate()
                .Where(_ => Input.GetMouseButtonDown(0))
                .TimeInterval()
                .Select(t => t.Interval.TotalMilliseconds)
                .Chunk(2, 1)
                .Where(list => list[0] >  250d)
                .Where(list => list[1] <= 250d)
                .Subscribe(_ => { Debug.Log("double click");
                //ここに関数を書いたりしてテストに使える
                
                 });

引用元はこちら 下

using UnityEngine.Poolな件

早速、ゲーム開発をしている。

今回はusing UnityEngine.Poolの話をする。

ブログ自体のタイトルにしているが「Unity6」でやっている。(次からの記事はわざわざ書かないようにしたい)

とりあえずコード

// プールを新規作成

var newPool = new ObjectPool<GameObject>(
 createFunc: () => Instantiate(prefab),
 actionOnGet: obj => obj.SetActive(true),
 actionOnRelease: obj => obj.SetActive(false),
 actionOnDestroy: obj => Destroy(obj),
 maxSize: maxSize
);

メインとなるのはこのコード。

無名関数を使うととてもシンプルになる。

公式に書いてあるのだが、

https://docs.unity3d.com/ja/2021.2/ScriptReference/Pool.ObjectPool_1.html

GETとReleaseが標準publicで定義しているので、そのまま呼び出せる。

上のコードは私が四苦八苦検索して調べたものではなく、ChatGPTが書いたもの。

実際自分でビルドして思った通りの動作になればOKというスタイルだ。

他にも、シングルトンにする方法もChatGPTが教えてくれて実際のコードにはシングルトンで書いている。

あまり記事が長くなると書く私も読む方もしんどいので、ここで終わりにする。

言いたいことまとめ

1、ChatGPTが便利

2、オブジェクトプールは使うべき

3、マニュアルを読め

4、unirxではなくR3を使い出していてオブジェクトプールがないらしい

以上