UdonSharpでAwakeすな

- [結論](#結論)
- [事象](#事象)
- [事象の確認結果](#事象の確認結果)
    - [VRChat SDK使用時のUnityEditor](#vrchat-sdk使用時のunityeditor)
    - [VRChat SDK未使用の通常のUnityEditor](#vrchat-sdk未使用の通常のunityeditor)
- [事象の検証手順](#事象の検証手順)
  - [～AwakeとOnEnableやStartでのTestInitVariables.cs のTransform.Positionの取得動作の違いについて～](#awakeとonenableやstartでのgameobjecttest-init-variables-のtransformpositionの取得動作の違いについて)
- [Appendix:イベントの実行順序](#appendixイベントの実行順序)

## 結論

- Awakeは使用せず、OnEnableメソッド以降で行う
    - 理由: Awake内で変数への代入や関数(例: Debug.Log)の実行はできるが、変数への格納情報はAwake外までは保存されない
        - → Monobehaviourと動作が異なるため、意図しないバグの原因になりかねない

<a id="anchor2"></a>
## 事象

- 変数の初期化処理をAwakeで行っても、変数に指定した初期値が保存されていなかった

**開発環境**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/dc18ddcd-05d2-4424-9bc0-f1d6f7d51397.png)

<a id="anchor3"></a>
## 事象の確認結果

先に結果を提示しておく。

<a id="anchor4"></a>
### VRChat SDK使用時のUnityEditor
- Awake時でawakePos変数をLogを表示すると`(0,2.605f,0)`だが、Update内で同じ変数awakePosを表示すると**Awake時と異なり**`(0,0,0)`になっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/154c3d3a-6554-42bc-b2ee-9150de63290b.png)

<a id="anchor5"></a>
### VRChat SDK未使用の通常のUnityEditor
- Awake時でawakePos変数をLogを表示すると`(0,2.61f,0)`で、Update内で同じ変数awakePosを表示してもAwake時と**同様に**`(0,2.61f,0)`になっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/df83eb28-69e1-4017-b632-54179e9e3101.png)

<a id="anchor6"></a>
## 事象の検証手順

<a id="anchor7"></a>
### ～AwakeとOnEnableやStartでのGameObject`Test Init Variables` のTransform.Positionの取得動作の違いについて～

**VRChat SDKを使用時のUnityでの動作確認**

1.  Udonsharpスクリプト `TestInitVariables.cs` を作成し、空のGameObject`Test Init Variables`にアタッチする。
    - `Test Init Variables` の座標は今回`(0,2.605f,0)`のようにインスペクターで指定する

```csharp:TestInitVariables.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class TestInitVariables : UdonSharpBehaviour
{
    private Vector3 enablePos;
    private Vector3 startPos;
    private Vector3 awakePos;
    private bool hasCalledAwakeLog = false;
    private bool hasCalledEnableLog = false;
    private bool hasCalledStartLog = false;
    private void Awake()
    {
        awakePos = transform.position; // (0,2.605f,0)
        Debug.Log("AwakePos in Awake: " + awakePos); // AwakePos in Awake: (0,2.605,0)
    }
    private void OnEnable()
    {
        enablePos = transform.position; // (0,2.605f,0)
        Debug.Log("EnablePos in OnEnable: " + enablePos); // EnablePos in OnEnable: (0,2.605,0)
    }
    private void Start()
    {
        startPos = transform.position;// (0,2.605f,0)
        Debug.Log("StartPos in Start: " + startPos);// StartPos in Start: (0,2.605,0)
    }

    private void Update()
    {
        if (!hasCalledAwakeLog) { Debug.Log("AwakePos in Update: " + awakePos); hasCalledAwakeLog = true; } // AwakePos in Update: (0,0,0)
        if (!hasCalledEnableLog) { Debug.Log("EnablePos in Update: " + enablePos); hasCalledEnableLog = true; } // EnablePos in Update: (0,2.605,0)
        if (!hasCalledStartLog) { Debug.Log("StartPos in Update: " + startPos); hasCalledStartLog = true; } // StartPos in Update: (0,2.605,0)
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/261c93b8-3c9e-4c8d-bde9-e30dde4653ea.png)

2.Unityエディタ上でPlayすることでUdonSimulatorを実行し、表示されるログを確認する
**VRChat SDK使用時のUnityEditor**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/154c3d3a-6554-42bc-b2ee-9150de63290b.png)

**VRChat SDK未使用の通常のUnityでの動作確認**

1. **VRChat SDK使用時と同様** Udonsharpスクリプト `TestInitVariables.cs` を作成し、空のGameObject`Test Init Variables`にアタッチする。
    - ※ただしVRChat SDKは使用しないため、`TestInitVariables.cs` の**スクリプトの継承元をMonoBehaviourに直しておくこと**。
    - `Test Init Variables` の座標は今回`(0,2.605f,0)`のようにインスペクターで指定する

```cs:TestInitVariables
using UnityEngine; // ← UdonSharpBehaviour用のusingは削除する

public class TestInitVariables : MonoBehaviour // ← Monobehaviourになおす
{
    private Vector3 enablePos;
    private Vector3 startPos;
    private Vector3 awakePos;
    private bool hasCalledAwakeLog = false;
    private bool hasCalledEnableLog = false;
    private bool hasCalledStartLog = false;
    private void Awake()
    {
        awakePos = transform.position; // (0,2.605f,0)
        Debug.Log("AwakePos in Awake: " + awakePos); // AwakePos in Awake: (0,2.605,0)
    }
    private void OnEnable()
    {
        enablePos = transform.position; // (0,2.605f,0)
        Debug.Log("EnablePos in OnEnable: " + enablePos); // EnablePos in OnEnable: (0,2.605,0)
    }
    private void Start()
    {
        startPos = transform.position;// (0,2.605f,0)
        Debug.Log("StartPos in Start: " + startPos);// StartPos in Start: (0,2.605,0)
    }

    private void Update()
    {
        if (!hasCalledAwakeLog) { Debug.Log("AwakePos in Update: " + awakePos); hasCalledAwakeLog = true; } // AwakePos in Update: (0,0,0)
        if (!hasCalledEnableLog) { Debug.Log("EnablePos in Update: " + enablePos); hasCalledEnableLog = true; } // EnablePos in Update: (0,2.605,0)
        if (!hasCalledStartLog) { Debug.Log("StartPos in Update: " + startPos); hasCalledStartLog = true; } // StartPos in Update: (0,2.605,0)
    }
}
```

2.Unityエディタ上でPlayし、表示されるログを確認する
**VRChat SDK未使用の通常のUnity**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/df83eb28-69e1-4017-b632-54179e9e3101.png)


## Appendix:イベントの実行順序
引用元にも記載されているが、ここにすべてのイベントが表示されているわけではないらし

- 引用元: [Event Execution Order](https://creators.vrchat.com/worlds/udon/event-execution-order/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771228/6cff37e4-bc84-442c-a975-fc2adea5cee7.png)