【Unity】端末でも確認出来るAssertウインドウ

DEVELOP, Unity

Unity 標準で使えるDebug.Assertは論理エラーを弾くのにとても便利なものです。

【Unity】Assertを活用してデバッグ効率を上げよう | KAZUPON研究室

以前こちらでお話しましたが、僕がプロジェクトでAssert を仕込む時は少し拡張したものを使っています。

目次

ソースコード

using UnityEngine;
using UnityEngine.Events;
namespace mira
{
	class AssertWindow : MonoBehaviour
	{
		public enum MenuEvent
		{
			Continue,
			ReStart,
			Report,
		}
		[System.Serializable]
		public class OnPressMenu : UnityEvent<MenuEvent> { }
		/// <summary>
		/// UI Event 
		/// </summary>
		[SerializeField]
		private OnPressMenu m_OnPressMenu = new OnPressMenu();
		public OnPressMenu onPressMenu
		{
			get { return m_OnPressMenu; }
		}
		private string m_message = string.Empty;
		private Vector2 scrollPosition = Vector2.zero;
		
		private void Init(string _message)
		{
			m_message = _message;
		}
		private void OnContinue()
		{
			onPressMenu.Invoke(MenuEvent.Continue);
			GameObject.Destroy(this.gameObject);
		}
		private void OnRestart()
		{
			onPressMenu.Invoke(MenuEvent.ReStart);
		}
		private void OnReport()
		{
			onPressMenu.Invoke(MenuEvent.Report);
		}
		public static AssertWindow Create( string _message )
		{
			var prefab = new GameObject("AssertWindow", typeof(AssertWindow));
			var instance = Instantiate(prefab);
			AssertWindow component = instance.GetComponent<AssertWindow>();
			component.Init(_message);
			return component;
		}
		
		private void OnGUI ()
		{
			float scale = (Screen.width > Screen.height) ? Screen.width  / 720f : Screen.height / 720f;
			GUIUtility.ScaleAroundPivot(new Vector2(scale, scale), Vector2.zero);
			var centeredStyle = new GUIStyle(GUI.skin.label);
			centeredStyle.alignment = TextAnchor.UpperCenter;
			GUILayout.BeginArea(new Rect(0, 0, Screen.width / scale, Screen.height / scale));
			GUILayout.BeginVertical (GUI.skin.box);
			{
				GUILayout.Label ("Assert");
				GUILayout.BeginHorizontal (GUI.skin.box);
				{
					if( GUILayout.Button("Continue") )
					{
						OnContinue();
					}
					if( GUILayout.Button("Restart") ) 
					{
						OnRestart();
					}
					if( GUILayout.Button("report") ) 
					{
						OnReport();
					}
				}
				GUILayout.EndHorizontal ();
				scrollPosition = GUILayout.BeginScrollView (scrollPosition);
				GUILayout.Label ( $"{m_message}" );
				GUILayout.EndScrollView ();
			}
			GUILayout.EndVertical ();
			GUILayout.EndArea();
			GUI.matrix = Matrix4x4.identity;
		}
	}
}

using UnityEngine;
using UnityEngine.Events;
using System.Diagnostics;
namespace mira
{
    /// <summary>
    /// 例外検知機能。
    /// </summary>
    public static class Assert
    {
        static AssertWindow s_assertWindow_ = null;
        [Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD")]
        public static void Check(object obj, string _message)
        {
            Check(obj != null, _message);
        }
        [Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD")]
        public static void Check(bool isComparison, string _message)
        {
            if (!isComparison)
            {
                UnityEngine.Debug.Assert(isComparison, _message);
            }
        }
        public static void LogMessageCallBack(
            string condition,
            string stackTrace,
            LogType type,
            UnityAction _onContinue = null,
            UnityAction _onRestart = null,
            UnityAction _onReport = null)
        {
            switch (type)
            {
                case LogType.Assert:
                case LogType.Exception:
                    if(s_assertWindow_ == null)
                    {
                        s_assertWindow_ = AssertWindow.Create(condition + "\n" + stackTrace);
                        s_assertWindow_.onPressMenu.AddListener((_t)=>
                        {
                            switch (_t)
                            {
                                case AssertWindow.MenuEvent.Continue:
                                {
                                    _onContinue.Invoke();
                                    break;
                                }
                                case AssertWindow.MenuEvent.ReStart:
                                {
                                    _onRestart.Invoke();
                                    break;
                                }
                                case AssertWindow.MenuEvent.Report:
                                {
                                    _onReport.Invoke();
                                    break;
                                }
                            }
                        });
                    }
                    break;
            }
        }
    }
}

使い方

using UnityEngine;
public class Example : MonoBehaviour
{
	void Start()
	{
		mira.Assert.Check(false, "アサートテスト!!!!!!!");
	}
 
#if DEVELOPMENT_BUILD || UNITY_EDITOR
	public static void LogMessageCallBack(
		string _condition,
		string _stackTrace,
		LogType _type)
	{
		mira.Assert.LogMessageCallBack(
			_condition,
			_stackTrace,
			_type,
			_onContinue:()=>
			{
				// コンティニュー
			},
			_onRestart: () =>
			{
				// 再起動
			},
			_onReport: () =>
			{
				// エラーレポート送信など
			}
			);
	}
	private void OnEnable()
	{
		Application.logMessageReceived += LogMessageCallBack;
	}
	private void OnDisable()
	{
		Application.logMessageReceived -= LogMessageCallBack;
	}
#endif
}

結果

通常のAssert ではコンソールウインドウに表示されるだけですが、こちらはゲーム画面に表示されます。こちらですと実機でエラーを確認することが容易なため「実機でエラー発生したけど、発生場所が分からない」の様な面倒な出来事も回避できるためおすすめです。

Posted by kazupon