如何检查 Unity Inspector 空参数和不正确值的脚本

我试图让我的 Unity 游戏代码尽可能健壮,理想情况下我希望能够在游戏启动之前抛出异常,例如在编译时,如果 Unity Inspector 参数丢失或不正确(例如 null或超出范围)。


Attributes目前我正在使用和UnityEngine.Assertionson的组合Awake()来检查空引用或不正确的值;在游戏启动时抛出异常(而不是在执行过程中的意外点),例如:


public class PlayerMovement : MonoBehaviour

{

    [SerializeField]

    [Tooltip("Rigidbody of the Player.")]

    private Rigidbody playerRigidBody;


    [SerializeField]

    [Tooltip("Forward force of the Player.")]

    [Range(100f, 50000f)]

    private float forwardForce = 6000f;


    [SerializeField]

    [Tooltip("Sideways force of the Player.")]

    [Range(10f, 1000f)]

    private float sidewaysForce = 120f;


    private GameManager gameManager;


    void Awake()

    {

        // Cache essential references

        gameManager = GameObject.FindGameObjectWithTag("GameManager").GetComponent<GameManager>();


        // Assert that all required references are present and correct

        UnityEngine.Assertions.Assert.IsNotNull(gameManager, "Member \"gameManager\" is required.");

        UnityEngine.Assertions.Assert.IsNotNull(playerRigidBody, "Member \"Rigidbody\" is required.");

        //UnityEngine.Assertions.Assert.IsTrue(ForwardForce > 100, "\"ForwardForce\" must be greater than 100");

        //UnityEngine.Assertions.Assert.IsTrue(SidewaysForce > 10, "\"SidewaysForce\" must be greater than 10");

    }


    ...

}

这是最佳实践,还是有更好的方法在游戏启动前验证基本参数?


Smart猫小萌
浏览 205回答 1
1回答

皈依舞

不是真的在编译时,但如果你想在每次在 Unity 中打开项目时进行检查,重新编译代码或加载新场景,你可以使用[InitializeOnLoad]and SceneManager.sceneLoaded。首先有一个像这样的界面public interface INullReferenceChecker{    void CheckReferences();}然后在eg里面有一个全局编辑器脚本Assets/Editor/RunNullChecks.cs(重要的是那个是放在Editor后面的所以去掉)[InitializeOnLoad]public class RunNullChecks{    public static RunNullChecks    {        // first of all also add a callback so it gets re-run everytime you switch a scene        // removing it first makes sure it is only added once        EditorSceneManager.sceneOpened -= Run;        EditorSceneManager.sceneOpened += Run;        Run();    }    private static void Run(Scene scene, LoadSceneMode mode)    {        Run();    }    public static void Run()    {        // here it depends a bit on your needs        // you either can check only stuff in the Scene like        var nullCheckers = FindObjectsOfType<INullReferenceChecker>();        // this gets only active and enabled components!        // or you could include all prefabs, ScriptableObjects using        //var nullCheckers = Resources.FindObjectsOfTypeAll<INullReferenceChecker>();        // and then let them do whatever they implemented        foreach(var tester in nullCheckers)        {            tester.CheckReferences();        }    }}那么你会有public class PlayerMovement : MonoBehaviour, INullReferenceChecker{    ...    public override void CheckReferences()    {        UnityEngine.Assertions.Assert.IsNotNull(gameManager, "Member \"gameManager\" is required.");        UnityEngine.Assertions.Assert.IsNotNull(playerRigidBody, "Member \"Rigidbody\" is required.");        // you could also simply go for        if(!gameManager) Debug.LogErrorFormat(this, "Member \"{0}\" is required.", nameof(gameManager));        if(!playerRigidBody) Debug.LogErrorFormat(this, "Member \"{0}\" is required.", nameof(playerRigidBody));    }}另一种选择也可能是使用[ExecuteInEditMode]属性。这使得Awake每次打开项目/加载场景/向场景添加新组件时调用的方法Update每次更改场景中的内容时都会调用方法然而,您可能会禁用某些代码块,例如Update检查Application.IsPlaying和/或Application.isEditor。
打开App,查看更多内容
随时随地看视频慕课网APP