使用AR Foundation开发AR游戏遇EventManager空引用异常求助
问题描述
我正在使用AR Foundation开发一款AR游戏,运行时先出现UIManager.Update()中的NullReferenceException: Object reference not set to an instance of an object错误,通过在场景中引用对象解决后,又出现EventManager.TriggerEvent方法中的同类型空引用异常,以下是EventManager的相关代码:
private static EventManager eventManager; public static EventManager instance { get { if (!eventManager) { eventManager = FindObjectOfType(typeof(EventManager)) as EventManager; if (!eventManager) { Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene."); } else { eventManager.Init(); } } return eventManager; } } void Init() { if (eventDictionary == null) { eventDictionary = new Dictionary<string, Action<Dictionary<string, object>>>(); } } public static void StartListening(string eventName, Action<Dictionary<string, object>> listener) { Action<Dictionary<string, object>> thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { // Add the called function to the action thisEvent += listener; // Renew the dictionary with the action instance.eventDictionary[eventName] = thisEvent; } else { thisEvent += listener; instance.eventDictionary.Add(eventName, thisEvent); } } public static void StopListening(string eventName, Action<Dictionary<string, object>> listener) { if (eventManager == null) return; Action<Dictionary<string, object>> thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent -= listener; instance.eventDictionary[eventName] = thisEvent; } } public static void TriggerEvent(string eventName, Dictionary<string, object> message) { Action<Dictionary<string, object>> thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent.Invoke(message); } }
解决办法
1. 修复TriggerEvent中的空引用
空引用的核心原因是:当某个事件的所有监听器都被移除后,字典中该事件对应的Action会变成null,此时调用thisEvent.Invoke(message)就会触发异常。
修改TriggerEvent方法,使用空条件运算符(?.)确保只有在thisEvent不为空时才调用Invoke:
public static void TriggerEvent(string eventName, Dictionary<string, object> message) { Action<Dictionary<string, object>> thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent?.Invoke(message); // 仅当thisEvent非空时执行调用 } }
2. 清理字典中的空事件条目
为了避免字典中留存null的Action,修改StopListening方法,当移除最后一个监听器后,直接将该事件从字典中删除:
public static void StopListening(string eventName, Action<Dictionary<string, object>> listener) { if (eventManager == null) return; Action<Dictionary<string, object>> thisEvent = null; if (instance.eventDictionary.TryGetValue(eventName, out thisEvent)) { thisEvent -= listener; if (thisEvent == null) { instance.eventDictionary.Remove(eventName); // 移除空事件条目 } else { instance.eventDictionary[eventName] = thisEvent; } } }
3. 额外检查事项
- 确保场景中存在且仅存在一个挂载了
EventManager脚本的激活状态GameObject(单例模式要求)。 - 检查调用
TriggerEvent时传入的message参数是否为null(如果你的监听器依赖该参数非空,需提前判空或确保传入有效值)。
内容的提问来源于stack exchange,提问作者safae
相关产品推荐
相关产品推荐

