DJProject_備忘録_3

## 2024-11-11
オリジナルデザインパターン
BallPassSchedulePatternにおいての
Playerにおいて、
PythonのPlayer
をUdonSharpのPlayerに変換する例

---
### Python
```
import os, sys
sys.path.append("../..")
from Players_CommonPlayers.SuperPlayerDir.SuperPlayer import SuperPlayer

class QRCodeModePlayer(SuperPlayer):
    def __init__(self):
        super().__init__()  # スーパークラスの初期化メソッドを呼び出す
        self.my_name = None  # プレイヤー名をNoneで初期化
        self.mode_indicator = None  # モード指示子を保持する変数を初期化
    
    def return_my_name(self):
        return "QRCodeModePlayer"

    def set_mode(self, mode_type):
        """
        モードタイプを受け取って、それに応じたモード指示子を設定する。
        mode_type: str ( "numeric", "alphanumeric", "byte", "kanji" )
        """
        if mode_type == "numeric":
            self.mode_indicator = "0001"
        elif mode_type == "alphanumeric":
            self.mode_indicator = "0010"
        elif mode_type == "byte":
            self.mode_indicator = "0100"
        elif mode_type == "kanji":
            self.mode_indicator = "1000"
        else:
            raise ValueError("Invalid mode_type. Choose from: numeric, alphanumeric, byte, kanji.")
    
    def main(self):
        """
        メインの処理をここで行う。QRコードのモード指示子を設定して、次に渡す準備をする。
        """
        
        """ 初期化 """
        #モードを選択
        self.set_mode(self.one_time_world_instance.initFromQrcodePlayer.mode)
        
        if self.mode_indicator is None:
            raise ValueError("Mode indicator is not set. Please call set_mode before executing main.")
        
        # self.one_time_world_instance にモード情報を渡す
        self.one_time_world_instance.qRCodeModePlayer = self  # 自身のインスタンスをworldに登録

        return "Completed"


```

---
### UdonSharp
```
using UdonSharp;
using UnityEngine;

public class QRCodeModePlayer : SuperPlayer
{
    public PreviousPlayer previousPlayer; // アタッチ
    public string ModeStr;
    public string ModeBitStr; // モード指示子を保持する変数

    public bool QRCodeModePlayerReset()
    {
        myName = "QRCodeModePlayer";
        modeIndicator = null; // 初期化時にモード指示子をnullに設定

        return true;
    }

    public override string ReturnMyName()
    {
        return "QRCodeModePlayer";
    }

    public void SetMode(string modeType)
    {
        /*
         * モードタイプを受け取って、それに応じたモード指示子を設定する
         * modeType: "numeric", "alphanumeric", "byte", "kanji"
         */
        if (modeType == "numeric")
        {
            modeIndicator = "0001";
        }
        else if (modeType == "alphanumeric")
        {
            modeIndicator = "0010";
        }
        else if (modeType == "byte")
        {
            modeIndicator = "0100";
        }
        else if (modeType == "kanji")
        {
            modeIndicator = "1000";
        }
        else
        {
            Debug.LogError("Invalid modeType. Choose from: numeric, alphanumeric, byte, kanji.");
        }
    }

    public override string ExecuteMain()
    {
        /*
         * メインの処理: QRコードのモード指示子を設定して、次のプロセスに渡す準備をする
         */

        // モード設定を行う
        this.ModeStr = previousPlayer.mode;
        this.ModeBitStr = this.Setmode(this.ModeStr);

        return "Completed";
    }
}
```

### PythonからUdonSharpへの変換の注意点

1. **インスタンス管理の違い**
   - Pythonでは、`self.one_time_world_instance.qRCodeModePlayer = self` のように、`world`インスタンスのメンバとしてプレイヤーインスタンスを保持する。
   - UdonSharpでは、Unityのオブジェクト自体がインスタンスとして動作するため、`world`の自身の保持は不要。Unity内でのアタッチがインスタンス化の役割を果たす。
   そのため、次のような…
   ```
        modeIndicator = oneTimeWorldInstance.qRCodeModePlayer.modeIndicator;
        charCount = oneTimeWorldInstance.initFromQrcodePlayer.data.Length; // 文字数を取得

   ```
   …実装ではなく、
   次のように…
   ```
        modeIndicator = this.qRCodeModePlayer.modeIndicator;
        charCount = this.initFromQrcodePlayer.data.Length; // 文字数を取得

   
   ```
   …クラス変数にアタッチしたオブジェクトインスタンス変数から直接アクセスする形をとるとする。

2. **メソッドの命名と構造**
   - Pythonでは`main`メソッドが主な処理を担うが、UdonSharpでは`ExecuteMain`などに変更し、`public override`を使って継承されたメソッドを上書きする形に。
   - `__init__`のようなコンストラクタは`QRCodeModePlayerReset`などの名前のメソッドとして実装(末尾に Reset 必須)して、変数の初期化を行う。

3. **エラーハンドリングの方法**
   - Pythonでは`raise ValueError`でエラーを投げるが、UdonSharpでは`Debug.LogError`を使ってエラーメッセージを表示する。

4. **型とアクセス修飾子**
   - UdonSharpでは、型指定（例: `public string ModeStr`）が必須で、変数のアクセス範囲を決めるアクセス修飾子 (`public`, `private`) を指定する必要がある。

5. **データ保持と変数の初期化**
   - `self.mode_indicator`のようなPythonのインスタンス変数は、UdonSharpでは`ModeBitStr`など、明示的に`public string`として宣言する。
   - 初期化は別メソッドで行い、例えば`QRCodeModePlayerReset`で初期化するようにする。
   - 他のプレイヤーに使いたいメソッドや変数があれば、クラス変数の場所にアタッチする形で実装をする。
   - *Reset()メソッドの戻り値は、必ずTrueとする。