为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
Smart猫小萌 2023-04-16 10:01:14
我试图让我的 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");    }    ...}这是最佳实践,还是有更好的方法在游戏启动前验证基本参数?
查看完整描述

1 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

不是真的在编译时,但如果你想在每次在 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


查看完整回答
反对 回复 2023-04-16
  • 1 回答
  • 0 关注
  • 204 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信