Unityでチュートリアルを作りたい
解決したいこと
interfaceのITutorialTaskを取得したい
例)
Unityでチュートリアルを作成している際、interfaceで定義されているITutorialTask taskがnullになってしまいます。
UnityもC#も初心者で途方に暮れています。
解決方法を教えてください。
発生している問題・エラー
NullReferenceException: Object reference not set to an instance of an object
TutorialManager+<SetCurrentTask>d__10.MoveNext () (at Assets/TutorialManager.cs:100)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <f712b1dc50b4468388b9c5f95d0d0eaf>:0)
該当するソースコード
TutorialManager.cs
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// ゲーム上のチュートリアルを管理するマネージャクラス
/// </summary>
public class TutorialManager : MonoBehaviour
{
// チュートリアル用UI
protected RectTransform tutorialTextArea;
protected Text TutorialTitle;
protected Text TutorialText;
// チュートリアルタスク
protected ITutorialTask currentTask;
protected List<ITutorialTask> tutorialTask;
// チュートリアル表示フラグ
private bool isEnabled;
// チュートリアルタスクの条件を満たした際の遷移用フラグ
private bool task_executed = false;
// チュートリアル表示時のUI移動距離
private float fade_pos_x = 350;
void Start()
{
// チュートリアル表示用UIのインスタンス取得
tutorialTextArea = GameObject.Find("TutorialTextArea").GetComponent<RectTransform>();
TutorialTitle = tutorialTextArea.Find("Title").GetComponent<Text>();
TutorialText = tutorialTextArea.Find("Text").GetComponentInChildren<Text>();
// チュートリアルの一覧
tutorialTask = new List<ITutorialTask>()
{
new MovementTask(),
new AttackTask(),
};
// 最初のチュートリアルを設定
StartCoroutine(SetCurrentTask(tutorialTask.First()));
isEnabled = true;
}
void Update()
{
// チュートリアルが存在し実行されていない場合に処理
if (currentTask != null && !task_executed)
{
// 現在のチュートリアルが実行されたか判定
if (currentTask.CheckTask())
{
task_executed = true;
DOVirtual.DelayedCall(currentTask.GetTransitionTime(), () => {
iTween.MoveTo(tutorialTextArea.gameObject, iTween.Hash(
"position", tutorialTextArea.transform.position + new Vector3(fade_pos_x, 0, 0),
"time", 1f
));
tutorialTask.RemoveAt(0);
var nextTask = tutorialTask.FirstOrDefault();
if (nextTask != null)
{
StartCoroutine(SetCurrentTask(nextTask, 1f));
}
});
}
}
if (Input.GetButtonDown("Help"))
{
SwitchEnabled();
}
}
/// <summary>
/// 新しいチュートリアルタスクを設定する
/// </summary>
/// <param name="task"></param>
/// <param name="time"></param>
/// <returns></returns>
protected IEnumerator SetCurrentTask(ITutorialTask task, float time = 0)
{
// timeが指定されている場合は待機
yield return new WaitForSeconds(time);
currentTask = task;
task_executed = false;
// UIにタイトルと説明文を設定
TutorialTitle.text = task.GetTitle();
TutorialText.text = task.GetText();
// チュートリアルタスク設定時用の関数を実行
task.OnTaskSetting();
iTween.MoveTo(tutorialTextArea.gameObject, iTween.Hash(
"position", tutorialTextArea.transform.position - new Vector3(fade_pos_x, 0, 0),
"time", 1f
));
}
/// <summary>
/// チュートリアルの有効・無効の切り替え
/// </summary>
protected void SwitchEnabled()
{
isEnabled = !isEnabled;
// UIの表示切り替え
float alpha = isEnabled ? 1f : 0;
tutorialTextArea.GetComponent<CanvasGroup>().alpha = alpha;
}
}
ITutorialTas.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface ITutorialTask
{
/// <summary>
/// チュートリアルのタイトルを取得する
/// </summary>
/// <returns></returns>
string GetTitle();
/// <summary>
/// 説明文を取得する
/// </summary>
/// <returns></returns>
string GetText();
/// <summary>
/// チュートリアルタスクが設定された際に実行される
/// </summary>
void OnTaskSetting();
/// <summary>
/// チュートリアルが達成されたか判定する
/// </summary>
/// <returns></returns>
bool CheckTask();
/// <summary>
/// 達成後に次のタスクへ遷移するまでの時間(秒)
/// </summary>
/// <returns></returns>
float GetTransitionTime();
}
自分で試したこと
https://gomafrontier.com/unity/2183
上記のWebサイトをそのまま実現したいです。
質問なのですが、interfaceのC#スクリプトはGamaObjectにアタッチする必要がありますか?Assetsのところにあればいいのですか?
空のUIオブジェクトを作成するには、Create EmptyをCanvasに設置すればいいのですか?