かさたな日記

主にUnityを使った制作記録。書いてる人は初心者です。一緒に頑張ろう。

sceneUnloadedが呼ばれちゃう現象の調査

# 昨日からの調査の追記です。

うーむ、どうやらEditorOnlyModeは関係ないみたいだ。
また、起動時のみに発生するというわけでもなさそう。
#
発生はエディタ上のみっぽい。
#
エディタでプレイモード起動中にインスペクタの表示を切り替えると
つまりOdinを適用した別のオブジェクトを選択すると発生するみたい。

今のプロジェクトではシーン切替時にオブジェクトプールの掃除を
割り込ませているのでちょっと厄介。。。

根本的な解決になってないけどこれで対処しておこう。
5.6のときは発生しなかったから2017のみの現象なのかな。

void OnSceneUnloaded(Scene scene)
    {
        //現在のシーンでなければスキップ
        if (scene.name != SceneManager.GetActiveScene().name) { return; }

        CleanPool();
        Debug.Log("BulletMgr.cs:バレットのプールをクリアしました。");
    }


# 更に追記
どうもこれが原因の一つみたい。

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]

このattributeをつけたメソッドはゲーム起動時、Awake()の前に呼ばれます。
また、シーン上に配置されていなくても、プロジェクト内にあれば呼ばれます。

この勝手に読んでくれる機能がなかなかに便利で、
ボクはこれを使ってマネージャを自動生成したりデータベースを読んだりしてるのですが
どうもそのタイミングでsceneUnloadedにイベント登録しているのがまずかったみたいです。

このマネージャはシングルトンになっているし、
素直にインスタンス取得ルーチン内で生成させよう。。。

ちょっと雑記

うっかりプロジェクトを壊してしまったのは痛手だったけど
色々と構造の見直しとブラッシュアップができたので結果オーライとしておこう。

UI系統が設定ファイルから一括で色指定ができるようになりました。
色以外もフォントなども設定できます。
これでプレファブを1個ずつ調整する作業から逃れることができる!
スポイトで色を拾ってこなくても済む!

もっとも、ウィンドウの画像を変える場合は
見ながら位置とかの微調整が必要なんだけどね。


ユニット用のクラスが分割されてたのも統合しました。
ファイル数が減ってスッキリはしたけど
.csの中身は当然ながら行数が増えている。。。
ステータスからスキル、ドロップアイテム、
各種モーション値の設定から、視界、接触判定とその補正まで入れて
大体1400 行(多分2、3割はコメントとかsummryとかattributeとか)。
ちょっと大きいかもね。。。

かと言ってコンポーネントで分割してると
結局、本体になるやつを参照しに行かないといけないし、
ファイル数は増えるし、個々にアタッチする手間は増えるし、
どっちがいいのか微妙なところ。

ドロップアイテムとかはデータベース作ったほうがいいとは思ってます。

以上。
今日はただの日記でした。


# 追記:
支援イラストの1枚や2枚は送らせてもらおうかな


# 追記メモ
ツイッターに書いたけど忘れそうなのでこにもメモ。

OdinのEditorOnlyModeをEnableにしておくと
プレイ起動時にsceneUnLoadedが呼ばれることがある。
おそらくEditor上だけの現象。
また必ず実行されるわけではない。体感30%くらい。
何故か2回呼ばれている。
詳しいことは調査中。

自分用Unityメモ:アニメーションの終了を待つ

AnimatorStateInfo を使用することで、
再生中のアニメーションの情報を得ることができます。
AnimatorStateInfo.Length でアニメーションの再生時間がわかるので
それを使ってモーション待ちが出来たりします。

//プロパティで読み取り専用にするよ
private bool m_isMotion;
public bool IsMotion{
    get{ return m_isMotion; }
}

//モーション開始と一緒に呼ぶコルーチン
IEnumerator AttackMotionCoroutine()
{
        //ホントはAnimatorは先に取得しておいた方が良いです
        Animator myAnimator = GetComponent<Animator>();
        m_isMotion = true;
      
            //遷移を待つ
            float transitionTime = 0;
            while (myAnimator.IsInTransition(0))
            {
                transitionTime += Time.deltaTime;
                yield return 0;
            }
            //念のためアニメーションのステートをUpdate
            //無いと遷移前ステートを取得しちゃうことがあります。。。
            myAnimator.Update(0);

            //モーション時間分だけ待つ
            AnimatorStateInfo stateInfo = myAnimator.GetCurrentAnimatorStateInfo(0);
            yield return new WaitForSeconds(stateInfo.length - transitionTime);
        
        m_isMotion = false;
    }

ただ、割と横着な方法なので
モーションごとにインターバル設定した方が
確実性はあると思います。。。