Fix: Prevent FriendsListToggle null reference after scene changes#1297
Fix: Prevent FriendsListToggle null reference after scene changes#1297JessTello wants to merge 8 commits into
Conversation
JessTello
commented
Jun 11, 2026
- Clear static Friends tab UI callbacks on scene unload to avoid retaining old listeners.
- Safely invoke Friends tab expand/collapse callbacks, skipping destroyed Unity targets.
- Guard optional UIFriendInteractionSource usage to prevent calls into missing or destroyed references during UI refresh.
- Clear static Friends tab UI callbacks on scene unload to avoid retaining old listeners. - Safely invoke Friends tab expand/collapse callbacks, skipping destroyed Unity targets. - Guard optional UIFriendInteractionSource usage to prevent calls into missing or destroyed references during UI refresh.
…friends-list-toggle-null-ref
|
|
||
| foreach (Action handler in action.GetInvocationList()) | ||
| { | ||
| if (handler.Target is UnityEngine.Object target && target == null) |
There was a problem hiding this comment.
Can we get a comment here on why is this needed? Why a handler could ever be null?
There was a problem hiding this comment.
This is the actually null check fix, the handler.Target became null because the GameObject have been destroyed when scene change (from "Lobbies" to other), and the action may still referencing that destroyed object here so NRE before the fix
and here cannot just directly if (handle.Target == null) because handle.Target just plain System.object and have to become a UnityEngine.Object to check the destroyed object as null here.
There was a problem hiding this comment.
So maybe there a bit context :
This fix is likely null check guard before Invoke a function, and remove the reference point found it became null (got destroyed elsewhere), that mean the subscribe/unsubscribe to this Action isn't clean up completed in some flow.
There was a problem hiding this comment.
So there's two options here I think:
- We remove this check and wherever we find that code isn't unsubscribing properly we fix that
- We add a comment to the code saying why this check exists (as Pong says due to the way that Unity marks GameObjects for destruction)
I'm leaning towards option 1, it leads to better code because you're aware of when an event hasn't been unsubscribed from properly
There was a problem hiding this comment.
I think that doable, I would check the unsubscribing logic where is missing as well check how bad is it, I remember I may noted when report to Apex before.
|
Finially fixed the add/remove listener in correct pair in OnEnable/OnDisable |
| // We add the listener to the Action first in OnEnable. Then, if StartsHidden = true, it will be set to Disabled to remove the listener. | ||
| UIActions.OnCollapseFriendsTab += EnableInterferingUIForFriendsTab; | ||
| UIActions.OnExpandFriendsTab += DisableInterferingUIForFriendsTab; | ||
|
|
||
| base.OnEnable(); |
There was a problem hiding this comment.
Does this work? Looking at the base class it looks like it will work when it's hidden at the start, but I didn't look into when it's shown later.
| // We add the listener to the Action first in OnEnable. Then, if StartsHidden = true, it will be set to Disabled to remove the listener. | |
| UIActions.OnCollapseFriendsTab += EnableInterferingUIForFriendsTab; | |
| UIActions.OnExpandFriendsTab += DisableInterferingUIForFriendsTab; | |
| base.OnEnable(); | |
| base.OnEnable(); | |
| if (!Hidden) | |
| { | |
| UIActions.OnCollapseFriendsTab += EnableInterferingUIForFriendsTab; | |
| UIActions.OnExpandFriendsTab += DisableInterferingUIForFriendsTab; | |
| } |
There was a problem hiding this comment.
Checking Hidden not work when It's shown, the flag update after SetActive(true), so I changed to the actually Unity activeSelf for that gameObject seem suitable for this case