Unity跨脚本调用后GameObject数组长度获取异常问题
Unity跨脚本获取数组长度异常,int变量却正常
问题情况
在Unity项目中,尝试从BoidSpawnScript脚本获取自定义的GameObject[]数组并通过Global类静态变量共享使用,但始终获取到错误的数组长度(返回0)。同时获取同脚本中的NumberOfBoids变量却能得到正确值(应为2)。尝试延迟1秒调用测试函数避免Start()执行过早,无效,且已检查所有拼写无误。
相关代码
Global类与测试脚本代码
public class Global { // 要访问的数组 public static GameObject[] BoidsArray; // 测试用变量 public static int NumberOfBoids; } private void Awake() { Global.BoidsArray = GameObject.Find("Main Camera").GetComponent<BoidSpawnScript>().BoidsArray; Global.NumberOfBoids = GameObject.Find("Main Camera").GetComponent<BoidSpawnScript>().NumberOfBoids; } void test() { Debug.Log(Global.BoidsArray.Length); } // Start在第一帧更新前调用 void Start() { test(); }
BoidSpawnScript中填充数组的代码
BoidsArray = new GameObject[NumberOfBoids]; for (int i = 0; i < NumberOfBoids; i++) { float randomY = Random.Range( - cHeight / 2f, cHeight / 2f); float randomX = Random.Range( - cWidth / 2f, cWidth / 2f); Vector2 spawnPosition = new Vector2(randomX, randomY); GameObject newBoid = Instantiate(PhysicalBoid, spawnPosition, Quaternion.Euler(Vector3.forward * Random.Range(0f, 360f))); BoidsArray[i] = newBoid; }
原因分析
核心问题是脚本执行顺序不匹配以及引用类型的赋值时机错误:
NumberOfBoids是值类型(int),你在Awake()中直接赋值的是当时的数值副本,只要BoidSpawnScript在你赋值前已经将其设置为2,Global.NumberOfBoids就能拿到正确值。BoidsArray是引用类型(数组),你在Awake()中获取的是BoidSpawnScript当时的数组对象引用。如果BoidSpawnScript在你获取引用之后才执行BoidsArray = new GameObject[NumberOfBoids];(重新创建数组),那么Global.BoidsArray会一直指向最初的空数组(长度0),而BoidSpawnScript中的数组已经更新为新的对象。
解决方案
方案1:调整脚本执行顺序
在Unity编辑器中进入Edit > Project Settings > Script Execution Order,将BoidSpawnScript的执行优先级调到测试脚本之前,确保它在测试脚本的Awake()执行前完成数组的初始化与填充。
方案2:动态获取数组引用
不要在Awake()中缓存数组引用,而是在需要使用时再获取最新的数组对象:
void test() { var spawnScript = GameObject.Find("Main Camera").GetComponent<BoidSpawnScript>(); Global.BoidsArray = spawnScript.BoidsArray; Debug.Log(Global.BoidsArray.Length); }
方案3:使用事件通知机制
在BoidSpawnScript完成数组填充后触发事件,测试脚本监听事件再获取数组,确保时机正确:
- 在
BoidSpawnScript中添加事件:
public static event Action OnBoidsSpawned; // 填充完数组后调用此代码 OnBoidsSpawned?.Invoke();
- 在测试脚本中监听事件:
private void OnEnable() { BoidSpawnScript.OnBoidsSpawned += OnBoidsReady; } private void OnDisable() { BoidSpawnScript.OnBoidsSpawned -= OnBoidsReady; } void OnBoidsReady() { Global.BoidsArray = GameObject.Find("Main Camera").GetComponent<BoidSpawnScript>().BoidsArray; test(); }
方案4:检查BoidSpawnScript的数组初始化时机
确保BoidSpawnScript在Awake()生命周期函数内完成数组的初始化与填充,而不是在Start()或更晚的函数中执行,避免测试脚本提前获取到未初始化的数组。
内容的提问来源于stack exchange,提问作者Lando Bunion
相关产品推荐
相关产品推荐

