Unity协程中引用的成员字段变为NULL的问题排查
Unity协程中成员字段变为null的问题分析
第一段代码可以正常运行:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; class Enemy { public string enemyName = "Default Enemy Name"; TestGameObject_002 monoBehaviour = null; public Enemy(TestGameObject_002 monoBehaviour) { } } public class TestGameObject_002 : MonoBehaviour { Enemy enemy = null; void Start() { enemy = new Enemy(this); StartCoroutine(TestCoroutine()); } public IEnumerator TestCoroutine() { if(enemy != null) Debug.Log("TestGameObject_002.TestCoroutine(), enemy is not null"); else Debug.Log("TestGameObject_002.TestCoroutine(), enemy is null"); Debug.Log("TestGameObject_002.enemy.enemyName = " + enemy.enemyName); yield return null; } }
但第二段代码会导致enemy变为null,协程引用的成员字段出现异常:
using System.Collections; using System.Collections; using UnityEngine; using UnityEngine.Events; class Enemy { public string enemyName = "Default Enemy Name"; TestGameObject_002 monoBehaviour = null; public Enemy(TestGameObject_002 monoBehaviour) { this.monoBehaviour = monoBehaviour; monoBehaviour.StartCoroutine(monoBehaviour.TestCoroutine()); } } public class TestGameObject_002 : MonoBehaviour { Enemy enemy = null; void Start() { enemy = new Enemy(this); } public IEnumerator TestCoroutine() { //yield return null; if(enemy != null) Debug.Log("TestGameObject_002.TestCoroutine(), enemy is not null"); else Debug.Log("TestGameObject_002.TestCoroutine(), enemy is null"); Debug.Log("TestGameObject_002.enemy.enemyName = " + enemy.enemyName); yield return null; } }
问题原因
核心是变量赋值顺序和协程执行机制导致的:
- 在第二段代码中,
TestGameObject_002.Start()里执行enemy = new Enemy(this)时,会先调用Enemy的构造函数。 - 构造函数内直接启动协程,协程的迭代器会立即执行到第一个
yield之前的代码。 - 但此时
TestGameObject_002的enemy字段还没完成赋值——new Enemy(this)的构造逻辑还在执行中,enemy = ...的赋值要等构造函数完全结束后才会生效。 - 所以协程执行时,
enemy还是初始的null,触发空引用问题。 - 如果在协程开头添加
yield return null,会把协程的执行推迟到下一帧,此时enemy已经完成赋值,就能正常运行。
内容的提问来源于stack exchange,提问作者papyrus
相关产品推荐
相关产品推荐

