Unity销毁Button后EventSystem访问已销毁对象引发异常求助
问题核心是:点击按钮销毁时,光标可能仍停留在按钮上,EventSystem的pointerEnter等指针状态引用了已销毁对象,后续每帧处理指针移动时尝试访问其transform导致空引用错误,阻塞其他UI交互。
以下是几种无需延迟销毁的优雅解决方案:
方案1:手动清理EventSystem的指针引用
直接找到当前InputSystemUIInputModule,重置指向待销毁按钮的所有指针状态,从根源切断EventSystem对已销毁对象的引用:
public void makeProgram(int i, Button button) { // 清理EventSystem中关联当前按钮的指针数据 var inputModule = EventSystem.current.currentInputModule as InputSystemUIInputModule; if (inputModule != null) { foreach (var pointer in inputModule.pointers) { var eventData = inputModule.GetExtendedPointerEventData(pointer.id); if (eventData.pointerEnter == button.gameObject) { eventData.pointerEnter = null; eventData.pointerPress = null; eventData.lastPointerPress = null; } } } // 原有创建逻辑 GameObject obj = Instantiate(ProgramObject, programHolder); var programComp = obj.GetComponent<Program>(); programs.Add(programComp); programComp.gameManager = this; obj.GetComponent<RectTransform>().localPosition = button.transform.localPosition; Destroy(button.gameObject); }
方案2:先禁用按钮再销毁
通过禁用按钮的交互性和激活状态,让EventSystem自动忽略该对象,避免后续指针事件关联:
public void makeProgram(int i, Button button) { // 先禁用按钮,让EventSystem不再将其视为可交互目标 button.interactable = false; button.gameObject.SetActive(false); // 原有创建逻辑 GameObject obj = Instantiate(ProgramObject, programHolder); var programComp = obj.GetComponent<Program>(); programs.Add(programComp); programComp.gameManager = this; obj.GetComponent<RectTransform>().localPosition = button.transform.localPosition; // 可立即销毁,无需延迟 Destroy(button.gameObject); }
方案3:清空当前选中对象(针对按钮被选中的场景)
如果按钮处于EventSystem的选中状态,强制清空选中对象,避免残留引用:
public void makeProgram(int i, Button button) { // 若当前按钮是选中状态,清空选择 if (EventSystem.current.currentSelectedGameObject == button.gameObject) { EventSystem.current.SetSelectedGameObject(null); } // 原有创建逻辑 GameObject obj = Instantiate(ProgramObject, programHolder); var programComp = obj.GetComponent<Program>(); programs.Add(programComp); programComp.gameManager = this; obj.GetComponent<RectTransform>().localPosition = button.transform.localPosition; Destroy(button.gameObject); }
推荐实践
优先结合方案1+方案2,既手动清理指针引用,又通过禁用按钮让EventSystem主动放弃关联,能彻底避免空引用问题,且无需依赖延迟销毁的妥协方案。
内容的提问来源于stack exchange,提问作者Liambro64
相关产品推荐
相关产品推荐

