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; }
ただ、割と横着な方法なので
モーションごとにインターバル設定した方が
確実性はあると思います。。。