DJproject_備忘録_2

## 2024-10-31
- Unityからプレイヤーを引っ張ってきた。
    ```
    using UdonSharp;
    using UnityEngine;
    
    public class DebugPlayer : SuperPlayer
    {
        public bool DebugPlayerReset()
        {
            myName = "DebugPlayer";
    
            return true;
        }
    
        public override string ReturnMyName()
        {
            return "DebugPlayer";
        }
    
    
        public override string ExecuteMain()
        {
            Debug.Log("\n==== Debug ExecuteMain ==============================");
            
            // BallObjectのすべてのメンバ変数を出力
            Debug.Log($"nowSchedule: {typeConverterToolkit.Format2DArray(world.ball.nowSchedule)}"); // ちょっとまってね。これが一応今null参照してるってエラーが出てるの。でも、いったんコメアウトで、全体のエラーを確認しよう。
            Debug.Log($"nowScheduleStatus: {typeConverterToolkit.Format2DArray(world.ball.nowScheduleStatus)}");
            Debug.Log($"scheduleMode: {world.ball.scheduleMode}");
            Debug.Log($"indexOfSchedule: {world.ball.indexOfSchedule}");
            Debug.Log($"indexOfScheduleOfSchedule: {world.ball.indexOfScheduleOfSchedule}");
            Debug.Log($"nowCatchBallingPlayer: {world.ball.nowCatchBallingPlayer}");
            Debug.Log($"nextPlayerName: {world.ball.nextPlayerName}");
    
            Debug.Log("\n==== Debug ExecuteMain (END) ==============================\n");
    
            return "Completed";
        }
    
    }
    ```
    デバッグプレイヤーですね。
    これを基準にテンプレートを作ろう。
    ↓テンプレート
    ```
    using UdonSharp;
    using UnityEngine;
    
    public class TemplatePlayer : SuperPlayer
    {
        public bool TemplatePlayerReset()
        {
            myName = "TemplatePlayer";
    
            return true;
        }
    
        public override string ReturnMyName()
        {
            return "TemplatePlayer";
        }
    
    
        public override string ExecuteMain()
        {
    
            return "Completed";
        }
    
    }
    ```
    これを元に
    Python▶︎UdonSharpに変換していこう。
- 変換の続きをやろう。(InitFromQrcodePlayerからもう一度。)
    - InitFromQrcodePlayerの変換
        ```
        using UdonSharp;
        using UnityEngine;
        
        public class InitFromQrcodePlayer : SuperPlayer
        {
            private int data;
            private string mode;
        
            // 初期化メソッド
            public bool InitFromQrcodePlayerReset()
            {
                myName = "InitFromQrcodePlayer";
                data = 12345;
                mode = "numeric";
        
                return true;
            }
        
            public override string ReturnMyName()
            {
                return "InitFromQrcodePlayer";
            }
        
            public override string ExecuteMain()
            {
                Debug.Log($"{ReturnMyName()}が実行されました。");
        
                // データやモードを次のプロセスに持たせるための処理
                worldInstance.initFromQrcodePlayer = this;
        
                return "Completed";
            }
        }
        ```
        - 気をつけること
            - Unityでは、オブジェクトにアタッチすると、そのオブジェクトがインスタンスとして独立する為、非同期の振る舞いをする。そのため、インスタンスの更新は必要が無いこと
    (ExecuteMain()内で
     worldInstance.initFromQrcodePlayer = this;
     のようなコードは不要、ということ。)
            - myNameはnullで初期化しないこと(BallPassSchedulePatternをUdonSharp)
    - QRCodeModePlayerのU#化

## 2024-11-06
今日はQRCodeModePlayerのU#化なのですね、、

## 2024-11-08
- QRCodeModePlayerのU#化
    - GPTに記事を読み込ませ、「このようにU#に変換して」と頼む
    作らせた。しかし恐らく変数の取得が異なってると思うのでしっかり見て調整する。
        - オブジェクトをアタッチする描き方を忘れた
            - クラス変数として、オブジェクトインスタンスを格納しなければならない。
            なので、
            ```
            using UdonSharp;
            using UnityEngine;
            
            public class QRCodeModePlayer : SuperPlayer
            {
                ✨
            
                public bool QRCodeModePlayerReset()
                {
                    myName = "QRCodeModePlayer";
                    modeIndicator = null; // 初期化時にモード指示子をnullに設定
            
                    return true;
                }

            ```
            ✨️の部分に、オブジェクトインスタンスをアタッチする必要がある。
            1つ前のプレイヤーをここにアタッチするので、次のようになる。
            ```
            using UdonSharp;
            using UnityEngine;
            
            public class QRCodeModePlayer : SuperPlayer
            {
                public SuperPlayer previousPlayer; // 1つ前のプレイヤーを保持するオブジェクトインスタンスを宣言
            
                private string modeIndicator; // モード指示子を保持する変数
            
                public bool QRCodeModePlayerReset()
                {
                    myName = "QRCodeModePlayer";
                    modeIndicator = null; // 初期化時にモード指示子をnullに設定
            
                    return true;
                }

            ```
            ここで、Masarinaのようなpythonしか出来ない動的言語ユーザーは、Udonhaviorを継承したSuperPlayerを継承したPreviousPlayerをアタッチしたUnityオブジェクト(自動的にインスタンス化されて…)を、QRCodeModePlayerオブジェクト(仮)に、アタッチするために、ココのQRCodeModePlayerのクラス変数として定義する！
            と、頭を巡る訳ですが…。
            浮かぶ疑問は、
            ```
            public PreviousPlayer previousPlayer; // 1つ前のプレイヤーを保持するオブジェクトインスタンスを宣言
            ```
            じゃなくて、
            ```
            public SuperPlayer previousPlayer; // 1つ前のプレイヤーを保持するオブジェクトインスタンスを宣言
            ```
            なの…？という点です。解消しなきゃ。
            - SuperPlayerにしないと、SuperPlayerのメソッドが使えないんだってさ。
            SuperPlayerを継承してるpreviousPlayerなのに、typeにPreviousPlayerを指定してもSuperPlayerのメソッドが使用できないの？
        - これについては複雑な現実があるみたい。
            - PythonとU#を比較するようにまとめてみる。
            簡単に言うと、
                - Pythonでは、
                継承クラスの継承クラスのメソッドを
                呼び出すことが出来る。
                - U#では
                1つ前の継承クラスのメソッドまでしか
                呼び出せない。
                つまり、継承クラスの継承クラスのメソッドは呼び出せない。
                しかし、C#では、継承クラスの継承クラスを呼び出すことができる。

                さて。これは厳密に言えば違う。### U#も継承クラスの継承クラスを呼び出すことが出来る。

                この可笑しい話は、次の事実で「あ、そっか！」となる。
                - UdonSharpでは var が使えない
                
                
            あそっかぁ！
            C#では
            ```
            public var previousPlayer;
            ```
            と定義し、
            ```
            previousPlayer.method()
            ```
            としてメソッドを実行した場合、
            継承クラスのメソッド、
            または継承クラスの継承クラスのメソッドを指定しても、動的にC#アプリケーションが「method()はどこの継承クラスのメソッドかなぁー？」って検索して実行してくれる。だから、いくら継承クラスの層が深くても大丈夫。
            でもUdonSharpではVRCHAT側が「var使えないようにしちゃった(´>∀<｀)ゝ」って言ってるからvarが使えない。
            しかし、C#でも同じだが、型を指定すれば、その型のメソッドを使えるようになる。
            さらにしかし、
            ```
            public SuperPlayer previousPlayer;
            ```
            として定義したpreviousPlayerにPreviousPlayerをアタッチさせたオブジェクトをアタッチしたとしても、SuperPlayerのメソッドしか使えないのだそう。
            なので。PreviousPlayerのメソッドや引数を使いたければ、
            ```
            public PreviousPlayer previousPlayer;
            ```
            とするべきなのだそう。

            SuperPlayerのメソッドもPreviousPlayerのメソッドも両方使いたければ…
            ```
            public SuperPlayer previousPlayersSuperPlayer;
            public PreviousPlayer previousPlayer; 
            
            ```
            というように、2つクラス変数を用意しなければならないということなのか、、。

            以上から、今回はpreviousPlayerに用があるので
            ```
            using UdonSharp;
            using UnityEngine;
            
            public class QRCodeModePlayer : SuperPlayer
            {
                public PreviousPlayer previousPlayer; // 1つ前のプレイヤーを保持するオブジェクトインスタンスを宣言
            
                private string modeIndicator; // モード指示子を保持する変数
            
                public bool QRCodeModePlayerReset()
                {
                    myName = "QRCodeModePlayer";
                    modeIndicator = null; // 初期化時にモード指示子をnullに設定
            
                    return true;
                }

            ```
            とすることにした。