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

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

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

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

Unity

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

Q&A

解決済

2回答

2038閲覧

フェード処理を何度も呼び出したいがNullReferenceExceptionが出てしまう

haru325

総合スコア9

C#

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

Unity

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

0グッド

0クリップ

投稿2020/02/29 14:04

前提・実現したいこと

Unity初心者です。
ゲームのタイトル画面シーンでパネルにUIをまとめ、そのパネルをフェードで表示、非表示にするスクリプトを書きました。
こちら
https://teratail.com/questions/244118
の質問でいただいた回答のとおりにスクリプトを書き換え、ボタンでパネルを呼び出すたびに
フェードで出現するようにしました。
ところが、FadeManagerを各パネル(LoadGameパネル、Settingパネル、Aboutパネル)
にアタッチした直後はちゃんと動くのですが、別のシーンからタイトル画面シーンに遷移したり
Unityを再起動してタイトル画面シーンをPlayしようとすると、FadeManagerのSetAlpha ()部分で
エラーNullReferenceExceptionが出てしまいます。
エラーが出てからもう一度FadeManagerを各パネルにアタッチしなおすとエラーが消えるのですが
やはり別シーンから遷移・Unityの再起動をするとNullReferenceExceptionが出ます。

TitleSceneManagerのBackToMenu()からFadeManagerのResetAlpha()を呼び出して実行する際に
alfa=0;としたフェードカラーの設定が残ってしまっているのでは?と思うのですが
どうしたらいいかわかりません。
回答よろしくお願い申し上げます。

出ているエラー

NullReferenceException: Object reference not set to an instance of an object
FadeManager.SetAlpha () (at Assets/Scripts/FadeManager.cs:125)
FadeManager.ResetAlpha () (at Assets/Scripts/FadeManager.cs:162)
TitleSceneManager.BackToMenu () (at Assets/Scripts/TitleSceneManager.cs:88)
TitleSceneManager.Start () (at Assets/Scripts/TitleSceneManager.cs:34)

Unityのバージョン

2019.3.1f1

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; //パネルのイメージを操作するのに必要 5using UnityEngine.SceneManagement; 6 7public class TitleSceneManager : MonoBehaviour 8{ 9 //4つのPanelを格納する変数 10 //インスペクターウィンドウからゲームオブジェクトを設定する 11 [SerializeField] GameObject titleMenuPanel; //TitleMenuパネル 12 [SerializeField] GameObject loadGamePanel; //LoadGameパネル 13 [SerializeField] GameObject settingPanel; //Settingパネル 14 [SerializeField] GameObject aboutPanel; //Aboutパネル 15 16 FadeManager fadeLoad; //LoadGameパネルをフェードで出現させるためのオブジェクト 17 FadeManager fadeSetting;//Settingパネル 18 FadeManager fadeAbout; //Aboutパネル 19 20 21 22 23 24 // Start is called before the first frame update 25 void Start() 26 { 27 28 fadeLoad = GameObject.Find("Panel_LoadGame").GetComponent<FadeManager>(); //newが使えないらしいのでこうやってFadeManagerを読み込むよ 29 fadeSetting = GameObject.Find("Panel_Setting").GetComponent<FadeManager>(); 30 fadeAbout= GameObject.Find("Panel_About").GetComponent<FadeManager>(); 31 32 33 //BackToMenuメソッドを呼び出す 34 BackToMenu(); 35 36 } 37 38 // Update is called once per frame 39 void Update() 40 { 41 42 43 } 44 45 //TitleMenuパネルでLoadGameボタンが押されたときの処理 46 public void SelectLoadGameDescription() 47 { 48 titleMenuPanel.SetActive(false); 49 loadGamePanel.SetActive(true); 50 51 fadeLoad.isFadeOutHalf = true; //フェードで半透明のパネルを出現させるフラグ 52 53 54 } 55 56 57 //TitleMenuパネルでSettingボタンが押されたときの処理 58 public void SelectSettingDescription() 59 { 60 titleMenuPanel.SetActive(false); 61 settingPanel.SetActive(true); 62 63 fadeSetting.isFadeOutHalf = true; //フェードで半透明のパネルを出現させるフラグ 64 } 65 66 //TitleMenuパネルでAboutボタンが押されたときの処理 67 public void SelectAboutDescription() 68 { 69 titleMenuPanel.SetActive(false); 70 aboutPanel.SetActive(true); 71 72 fadeAbout.isFadeOutHalf = true; //フェードで半透明のパネルを出現させるフラグ 73 } 74 75 76 //TitleMenuパネル以外の3つのパネルでBackボタンが押されたときの処理 77 public void BackToMenu() 78 { 79 80 81 titleMenuPanel.SetActive(true); 82 loadGamePanel.SetActive(false); 83 settingPanel.SetActive(false); 84 aboutPanel.SetActive(false); 85 86 87 // 処理を追加 88 fadeLoad.ResetAlpha(); 89 fadeSetting.ResetAlpha(); 90 fadeAbout.ResetAlpha(); 91 92 } 93}

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; //パネルのイメージを操作するのに必要 5using UnityEngine.SceneManagement; 6 7public class FadeManager : MonoBehaviour 8{ 9 float fadeSpeed = 0.005f; //透明度が変わるスピードを管理 10 float red, green, blue, alfa; //パネルの色、不透明度を管理 11 12 public bool isFadeOut = false; //フェードアウト処理の開始、完了を管理するフラグ 13 public bool isFadeIn = false; //フェードイン処理の開始、完了を管理するフラグ 14 15 public bool isFadeOutHalf = false; //半分フェードアウト処理の開始、完了を管理するフラグ 16 17 18 private float stepTime; // 経過時間カウント用 19 20 public string sceneName = null; //シーンの名前 21 22 23 24 25 26 27 Image fadeImage; //透明度を変更するパネルのイメージ 28 29 void Start() 30 { 31 fadeImage = GetComponent<Image>(); 32 red = fadeImage.color.r; 33 green = fadeImage.color.g; 34 blue = fadeImage.color.b; 35 alfa = fadeImage.color.a; 36 37 38 39 stepTime = 0.0f; // 経過時間初期化 40 41 sceneName = SceneManager.GetActiveScene().name; 42 43 } 44 45 void Update() 46 { 47 48 if (isFadeIn) 49 { 50 StartFadeIn(); 51 } 52 53 if (sceneName == "CasLogoScene"|| sceneName == "AttentionScene"|| sceneName == "WarningScene") 54 { 55 // 経過時間をカウント 56 stepTime += Time.deltaTime; 57 58 SetIsFadeOut(); 59 60 if (isFadeOut) 61 { 62 StartFadeOut(); 63 64 if (isFadeOut == false) 65 { 66 ChangeSceneName(); 67 68 SceneManager.LoadScene(sceneName); 69 } 70 } 71 } 72 73 74 if (isFadeOutHalf) 75 { 76 StartFadeOutHalf(); 77 } 78 79 if (isFadeOut) 80 { 81 StartFadeOut(); 82 } 83 84 85 } 86 87 public void StartFadeIn() 88 { 89 alfa -= fadeSpeed; //a)不透明度を徐々に下げる 90 SetAlpha(); //b)変更した不透明度パネルに反映する 91 if (alfa <= 0) 92 { //c)完全に透明になったら処理を抜ける 93 isFadeIn = false; 94 fadeImage.enabled = false; //d)パネルの表示をオフにする 95 } 96 } 97 98 public void StartFadeOut() 99 { 100 fadeImage.enabled = true; // a)パネルの表示をオンにする 101 alfa += fadeSpeed; // b)不透明度を徐々にあげる 102 SetAlpha(); // c)変更した透明度をパネルに反映する 103 if (alfa >= 1) 104 { // d)完全に不透明になったら処理を抜ける 105 isFadeOut = false; 106 } 107 } 108 109 public void StartFadeOutHalf() 110 { 111 Debug.Log(alfa); 112 fadeImage.enabled = true; // a)パネルの表示をオンにする 113 alfa += fadeSpeed; // b)不透明度を徐々にあげる 114 SetAlpha(); // c)変更した透明度をパネルに反映する 115 if (alfa >= 0.5f) 116 { 117 isFadeOutHalf = false; 118 119 120 } 121 } 122 123 void SetAlpha() 124 { 125 fadeImage.color = new Color(red, green, blue, alfa); 126 } 127 128 129 void SetIsFadeOut() 130 { 131 132 if (Input.GetMouseButtonDown(0) || Input.GetKeyDown("return") || stepTime >= 10.0f) //左クリックかエンターキー押下か10秒経つかで変数isFadeOutをtrueにする 133 { 134 isFadeOut = true; 135 } 136 137 138 } 139 140 void ChangeSceneName() 141 { 142 switch (sceneName) 143 { 144 case "CasLogoScene": 145 sceneName = "AttentionScene"; 146 break; 147 148 case "AttentionScene": 149 sceneName = "WarningScene"; 150 break; 151 152 case "WarningScene": 153 sceneName = "TitleScene"; 154 break; 155 156 } 157 } 158 159 public void ResetAlpha() 160 { 161 alfa = 0.0f; 162 SetAlpha(); 163 } 164 165 166} 167

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

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

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

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

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

guest

回答2

0

自己解決

こちらを参考にスクリプトを組み直し、Canvas Groupを利用して
UIをまとめてフェードできるようにしました。
https://kan-kikuchi.hatenablog.com/entry/CanvasFader

スクリプトを載せておきます。

C#

1using UnityEngine; 2using System; 3using System.Collections; 4using System.Collections.Generic; 5 6[RequireComponent(typeof(CanvasGroup))] 7 8public class CanvasFader : MonoBehaviour 9{ 10 //フェード用のキャンバス 11 private CanvasGroup _canvasGroup; 12 13 //フェードの状態 14 private enum FadeState 15 { 16 None, FadeIn, FadeOut 17 } 18 private FadeState _fadeState = FadeState.None; 19 20 //フェード時間 21 [SerializeField] 22 private float _duration; 23 24 //タイムスケールを無視するか 25 [SerializeField] 26 private bool _ignoreTimeScale = true; 27 28 //フェード終了後のコールバック 29 private Action _onFinished = null; 30 31 //================================================================================= 32 //更新 33 //================================================================================= 34 35 private void Update() 36 { 37 if (_fadeState == FadeState.None) 38 { 39 return; 40 } 41 42 float fadeSpeed = 1f / _duration; 43 if (_ignoreTimeScale) 44 { 45 fadeSpeed *= Time.unscaledDeltaTime; 46 } 47 else 48 { 49 fadeSpeed *= Time.deltaTime; 50 } 51 52 _canvasGroup.alpha += fadeSpeed * (_fadeState == FadeState.FadeIn ? 1f : -1f); 53 54 //フェード終了判定 55 if (_canvasGroup.alpha > 0 && _canvasGroup.alpha < 1) 56 { 57 return; 58 } 59 60 if (_onFinished != null) 61 { 62 _onFinished(); 63 } 64 65 _fadeState = FadeState.None; 66 this.enabled = false; 67 } 68 69 //================================================================================= 70 //開始 71 //================================================================================= 72 73 /// <summary> 74 /// 対象のオブジェクトのフェードを開始する 75 /// </summary> 76 public static CanvasFader Begin(GameObject target, bool isFadeOut, float duration, bool ignoreTimeScale = true, Action onFinished = null) 77 { 78 CanvasFader canvasFader = target.GetComponent<CanvasFader>(); 79 if (canvasFader == null) 80 { 81 canvasFader = target.AddComponent<CanvasFader>(); 82 } 83 84 canvasFader.Play(isFadeOut, duration, ignoreTimeScale, onFinished); 85 86 return canvasFader; 87 } 88 89 /// <summary> 90 /// フェードを開始する 91 /// </summary> 92 public void Play(bool isFadeOut, float duration, bool ignoreTimeScale = true, Action onFinished = null) 93 { 94 this.enabled = true; 95 96 if (_canvasGroup == null) 97 { 98 _canvasGroup = GetComponent<CanvasGroup>(); 99 } 100 101 _canvasGroup.alpha = isFadeOut ? 1 : 0; 102 _fadeState = isFadeOut ? FadeState.FadeOut : FadeState.FadeIn; 103 104 _duration = duration; 105 _ignoreTimeScale = ignoreTimeScale; 106 _onFinished = onFinished; 107 } 108 109} 110

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using UnityEngine.SceneManagement; 6 7public class TitleSceneManager : MonoBehaviour 8{ 9 //キャンバスを格納する変数 10 //インスペクターウィンドウからゲームオブジェクトを設定する 11 [SerializeField] GameObject titleMenuCanvas; //TitleMenuキャンバス 12 [SerializeField] GameObject loadGameCanvas; //LoadGameキャンバス 13 14 GameObject canvasFaderLoad; //Loadキャンバス 15 16 // Start is called before the first frame update 17 void Start() 18 { 19 canvasFaderLoad = GameObject.Find("CanvasFader1"); 20 21 loadGameCanvas.SetActive(false); 22 } 23 24 // Update is called once per frame 25 void Update() 26 { 27 } 28 29 //TitleMenuパネルでLoadGameボタンが押されたときの処理 30 public void SelectLoadGameDescription() 31 { 32 titleMenuCanvas.SetActive(false); 33 loadGameCanvas.SetActive(true); 34 35 CanvasFader.Begin(target: canvasFaderLoad, isFadeOut: false, duration: 0.2f, ignoreTimeScale: true, onFinished: OnFinished); 36 } 37 38 39 //Backボタン押下でLoadGameキャンバスのフェードアウト後に呼び出されるメッソッド 40 private void OnFinishedLoadBack() 41 { 42 loadGameCanvas.SetActive(false); 43 titleMenuCanvas.SetActive(true); 44 45 } 46 47 48 //フェード後に呼び出されるメッソッド 49 private void OnFinished() 50 { 51 52 } 53 54 //LoadGame画面のBackボタン 55 public void LoadBack() 56 { 57 CanvasFader.Begin(target: canvasFaderLoad, isFadeOut: true, duration: 0.2f, ignoreTimeScale: true, onFinished: OnFinishedLoadBack); 58 59 60 } 61} 62

投稿2020/03/01 08:10

haru325

総合スコア9

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

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

0

FadeManagerを各パネルにアタッチした後にシーンを保存していますか?
アタッチ後にメニューバーの「File」->「Save」かキーボードのCtrl+Sでシーンを保存しないとアタッチした設定が保存されません。

投稿2020/02/29 21:03

kawa0x0A

総合スコア271

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

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

haru325

2020/03/01 07:56

すみません、なぜかそれでもダメでしたが別の方法で思い通りの動作をさせることに 成功しました……! おそらくは教えていただいた方法を試しているつもりでどこかで私が間違えていたのだと 思います。 教えていただいて誠にありがとうございました、そしてお手数をおかけして 申し訳ございませんでした……。 また機会がありましたらご教授いただければ幸いです。 本当にありがとうございました!
kawa0x0A

2020/03/01 08:53

解決できたならよかったです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問