UnityTest调用静态Utils类报错:TypeInitializationException问题求助
问题原因与解决方法
错误原因
System.TypeInitializationException 是因为静态类的静态字段初始化失败导致的:
- 当你第一次访问
Utils的任何成员(比如测试代码里的Utils.CHARACTER),.NET 会自动执行静态字段的初始化逻辑。 - 你的
EPSILON字段依赖GameObject.Find(CHARACTER)获取场景对象,但此时场景可能还未加载完成(测试代码中先触发了Utils的初始化,再完成场景加载),GameObject.Find返回null,访问null.transform抛出NullReferenceException,最终引发类型初始化异常。
解决方案
方案1:懒加载依赖场景的字段
用静态属性代替字段,延迟初始化逻辑到场景加载完成后第一次访问时执行:
public class Utils { public static string CHARACTER = "Ball"; private static float? _epsilon; public static float EPSILON { get { if (!_epsilon.HasValue) { var characterObj = GameObject.Find(CHARACTER); if (characterObj == null) { throw new InvalidOperationException($"无法找到名为 {CHARACTER} 的游戏对象,无法初始化 EPSILON"); } _epsilon = characterObj.transform.localScale.x / 2f; } return _epsilon.Value; } } public static float DIRECTION_UPDATE_TIME = 0.1f; }
方案2:拆分常量与动态逻辑
把不依赖场景的常量(如CHARACTER、DIRECTION_UPDATE_TIME)和需要动态计算的逻辑(如EPSILON)分开,用方法获取动态值:
public class Utils { public const string CHARACTER = "Ball"; public const float DIRECTION_UPDATE_TIME = 0.1f; public static float GetEpsilon() { var characterObj = GameObject.Find(CHARACTER); if (characterObj == null) { throw new InvalidOperationException($"无法找到名为 {CHARACTER} 的游戏对象"); } return characterObj.transform.localScale.x / 2f; } }
测试代码中在场景加载完成后调用 Utils.GetEpsilon() 即可。
方案3:确保场景加载完成后再访问Utils
调整测试代码,等待场景完全加载后再访问Utils,避免提前触发静态初始化:
[UnityTest] public IEnumerator test_MoveDirectionIsPossibleOnBorders() { // 异步加载场景并等待完成 AsyncOperation loadOperation = SceneManager.LoadSceneAsync("TestScene_1Enemy_Static"); yield return loadOperation; // 此时场景已加载,访问Utils不会因找不到对象报错 GameObject character_go = GameObject.Find(Utils.CHARACTER); CharacterBehavior character = character_go.GetComponent<CharacterBehavior>(); bool moved = character.updateDirection(Direction.Right); Assert.Equals(moved, true); yield return new WaitForSeconds(Utils.DIRECTION_UPDATE_TIME); }
内容的提问来源于stack exchange,提问作者Julexe
相关产品推荐
相关产品推荐

