並使用這個函數取代原來的Lambda表達式,一切即回復正常。
一點總結
其實這個坑的問題就在於匿名函數本身。在首次加載時,匿名方法能得到正常加到Delegate中,也能正常卸載,也能正常使用;再次加載時,匿名方法雖然也可以正常通過EventCenter加到delegate中,但是匿名方法中指定的gameObject卻無法正常訪問,得出MissingReferenceError。
雖然AddListener和RemoveListener時所使用的lambda表達式都是同樣的內容,但是在compiler看來,它們卻是兩個不同的函數。在.NET中,匿名函數的指針地址是隨機分配的,我在OnDestroy()時的RemoveListener其實只是移除了一個相同函數體的匿名函數,並不能清除原來被添加的那個匿名函數,除非我直接Clear掉整個委托。
那既然移除事件失敗了,當我重新加載場景時,場景中的所有物體也會被銷毀然後重新生成。但事件中心中的事件指向仍然是銷毀之前的物體,理所當然地,當我嘗試觸發事件時,自然會報出MissingReferenceError錯誤。
這也是lambda表達式與一般函數的不同之處,前者更多像是一個臨時的函數,它們基本是不會被重新被調用到的或者找到它們的位置的;而後者更多像是注冊了一個地址一樣,我們可以隨時根據名字找到這個函數的位置。