質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

492閲覧

ScriptExecutionOrderで変えたスクリプトの実行順が、単一シーン環境と複数シーン環境で違いが出てしまう件について

ko_yu

総合スコア18

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2022/05/26 06:24

単一のシーンからマルチシーンのゲーム構成に移行しようとテスト中、以下の手順で問題が起きました。
・新たにManagerSceneを作り、デバッグ用のシーンに加算ロード。
・エディタ上でデバッグシーン配置済のSoundPlayer2D(BGM再生オブジェクト)をManagerシーンに移動
・ゲーム実行をするとNullエラーが出てしまう

■SoundPlayer2Dスクリプト

C#

1public class SoundPlayer2D : MonoBehaviour 2{ 3 [SerializeField]private SoundData soundData; //ScriptableObjectをアタッチ 4 private AudioSource audioSource; 5 6 private void OnEnable() { soundData.RegisterListener(this); } // このオブジェクトがEnableになるとSoundDataに自身を登録 7 private void OnDisable() { soundData.UnregisterListener(this); } // Disableになると削除 8 9 10 public void BGMPlay(AudioClip audioClip) 11 { 12 Debug.Log("audioSourceは→" + audioSource); 13 audioSource.clip = audioClip; 14 Debug.Log("audioClipは→"+audioClip); 15 audioSource.Play(); 16 } 17 18 public void SEPlay(AudioClip audioClip) 19 { 20 audioSource.PlayOneShot(audioClip); 21 } 22 23 void Start() 24 { 25 audioSource = this.GetComponent<AudioSource>(); 26 Debug.Log("this.ゲットコンポネント:audioSourceは→" + audioSource); 27 } 28}

エラースクショ
調べてみると、SoundPlayer2DのStart()で自身のAudioSourceをGetComponetしてキャッシュする前に、SceneManagerというシーン開始直後の処理を行うスクリプトのStart()に記述されたBGM機能呼び出しが先に行われ、キャッシュ前のAudioSourceを用いて音楽を再生しようとしていたためnullエラーが出ているようです。

スクリプト実行順
しかし、SceneManagerのスクリプト実行順はScriptExecutionOrderによってこのように一番最後に呼ばれるように設定してあります。また、別シーンのオブジェクトはインスペクタアタッチ経由での参照はできないと聞いたので、必要な参照はScriptableObjectを通しています。

SoundPlayer2Dオブジェクトをデバッグシーンに戻してから実行するとエラーはなく、加算ロード用のシーンに配置して実行するとエラーが起きてしまいます。
ScriptExecutionOrderの設定は複数のシーンに跨がらないのでしょうか?
この辺りの詳しい仕様を知りたいです。
また上記の自分のUnityの仕様に対する認識に誤りがあれば教えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

調べていくうちに今回の質問の内容に直接言及された検証を見かけたため自己解決致しました。
https://qiita.com/hibiki8229/items/335978e65273a87e8d69

原因としてはやはりマルチシーン環境だとScriptExecutionOrderは単一シーン環境と挙動が変わるようで、アクティブなシーンのスクリプトが優先されるようです。アクティブシーンのスクリプトを実行し終えてから加算シーンのスクリプト実行に移るため、上記機能のスクリプト実行順は再生中のシーン全てにまたがって適用されるわけではないようです。
開発段階では作成中のシーンのテストをする際、都度ManagerSceneから遷移しては手間がかかるため自動で読み込んでいましたが、アクティブなシーンはあくまで作成中のシーンのためNullエラーが出たようです。

マルチシーンはスクリプトの実行順管理の難度が上がるので、なるべくスクリプト実行順に左右されないプログラムを組んでいく必要があるなと思いました

投稿2022/05/26 19:26

ko_yu

総合スコア18

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

上記のサイトを見る限り、同一フレーム であれば質問者さんの言うとおりだと思います。

…であれば、同一フレームでないのでは?
シーンが別れているような書き方をされていますが、それによってシーンごとに開始するタイミングがずれてしまっているとか、確証はないけど屁理屈であればいくらでもつけられると思います。

とりあえず、Debug.LogTime.frameCountの値も表示してみて、同一フレームかどうか、確認されてはいかがですか。


と一旦答えておきますが、

cs

1 void Start() 2 { 3 audioSource = this.GetComponent<AudioSource>(); 4 Debug.Log("this.ゲットコンポネント:audioSourceは→" + audioSource); 5 }

私だったら、このような処理はAwakeでやっちゃいます。

投稿2022/05/26 15:16

katsuko

総合スコア3462

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko_yu

2022/05/26 19:40

調べてみたところ同一フレームでした。Awakeに書くことでエラー回避ができるのは既に確認しているのですが、 Awakeに書けば動くからとりあえずそれでヨシ、では後々困りそうなのでScriptExecutionOrderの詳しい仕様が知りたかったため質問させて頂きましたが、なんとか解決に至ることができました
katsuko

2022/05/26 23:43

いいんじゃないでしょうか。 私も大変参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問