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

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

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

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

Unity

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

Q&A

解決済

2回答

341閲覧

【Unity】C# eventを用いたScriptの使い方をご教授願います。

nozomin_jp

総合スコア13

C#

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

Unity

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

0グッド

1クリップ

投稿2018/04/24 07:40

前提・実現したいこと

下記Scriptの実行方法をご教授願います。

発生している問題・エラーメッセージ

NullReferenceException

該当のソースコード

C#

1// ソースコード(1) 2// イベントを発行する側 3using System.Collections; 4using UnityEngine; 5 6// 10秒からカウントダウンをして値を通知する 7public class TimeCounter : MonoBehaviour 8{ 9 // イベントハンドラ 10 public delegate void TimerEventHandler(int time); 11 12 /// イベント 13 public event TimerEventHandler OnTimeChanged; 14 15 16 void Start() 17 { 18 StartCoroutine(TimerCoroutine()); 19 } 20 21 IEnumerator TimerCoroutine() 22 { 23 //10からカウントダウン 24 var time = 10; 25 while (time > 0) 26 { 27 time--; 28 //イベント通知 29 OnTimeChanged(time); 30 31 //1秒待つ 32 yield return new WaitForSeconds(1); 33 } 34 } 35}

C#

1// ソースコード(2) 2// イベントを受け取る側 3using UnityEngine; 4using UnityEngine.UI; 5 6public class TimerView : MonoBehaviour 7{ 8 // インスタンスはインスペクタビューから設定 9 [SerializeField] private TimeCounter timeCounter; 10 [SerializeField] private Text counterText; //uGUIのText 11 12 void Start() 13 { 14 //イベントを受けてuGUI Textを更新する 15 timeCounter.OnTimeChanged += time => 16 { 17 //現在のタイマ値をUIに反映する 18 counterText.text = time.ToString(); 19 }; 20 } 21}

試したこと

(1)空のゲームオブジェクトを作成し、ソースコード(1)をアタッチ
(2)さらに空のゲームオブジェクトを作成し、ソースコード(2)をアタッチ
(3)ヒエラルキービューからUI textを作成( Create → UI → text )
(4) (2)で作成したオブジェクトのSerializeFieldにインスペクタービューから(1)のオブジェクトと(3)のtextを接続

上記手順を踏んで実行した結果、NullReferenceExceptionが発生してしまい、意図した挙動となりませんでした。

補足情報(FW/ツールのバージョンなど)

Unity 2017.4.0f1

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

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

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

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

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

guest

回答2

0

ベストアンサー

見当違いだったら申し訳ないです。

最初にTimerCoroutine()が動いてOnTimeChanged(time);が呼ばれた段階では、まだTimerViewクラスのtimeCounter.OnTimeChangedに処理が登録されていないとかですかね・・・?

TimerViewクラスのStart関数をAwake関数にしてもダメですかね。。。

投稿2018/04/24 08:05

kakeiteiya

総合スコア252

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

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

nozomin_jp

2018/04/24 08:09

回答、ありがとうございます。 ご指摘頂いた箇所をAwake関数に変更したところ、動くことを確認しました。 ありがとうございました!
kakeiteiya

2018/04/24 08:14

よかったです!(^0^) Start関数より先にAwake関数が呼ばれる仕組みなので、 上記のような値の代入的なのはAwakeでやったほうがいいらしいです(値の取得系はAwakeではなくStartでやったほうがいいらしいです)
nozomin_jp

2018/04/24 08:44

なるほど!参考になります!
capra314cabra

2018/04/24 13:31 編集

この場合、Awakeに処理を書いても動きますが、イベントがどこからも登録されてない可能性を考えて呼び出す際は if(OnTimeChanged != null) OnTimeChanged(time); か OnTimeChanged?.Invoke(time); と呼ぶのが一般的です。 こうすればいつでもイベントを登録できます。 参考までにどうぞ。
guest

0

おそらくエラー文にどのゲームオベジェクトがNullなのか書いてあると思うのですが、どうでしょう

投稿2018/04/24 07:45

kakeiteiya

総合スコア252

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

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

nozomin_jp

2018/04/24 07:48

回答、ありがとうございます。 エラー文は下記の通りです。 ---- NullReferenceException: Object reference not set to an instance of an object TimeCounter+<TimerCoroutine>c__Iterator0.MoveNext () (at Assets/Scripts/TimeCounter.cs:34) UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17) UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) TimeCounter:Start() (at Assets/Scripts/TimeCounter.cs:23) --- 解決方法がわかりません...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問