-
-
Notifications
You must be signed in to change notification settings - Fork 776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scene prefab instance invokes custom unspawn instead of deactivating in NetworkClient.DestroyObject #3574
Comments
You don't need to call RegisterPrefab on networked scene objects unless you want the custom unspawn to be invoked. Mirror picks up all networked scene objects automatically. Does that answer the question, or do you still think there's a bug? |
@MrGadget1024 The issue here is for mixed use prefabs. I have a prefab that is scene place sometimes, but other times I do dynamically spawn them. Say I have a Vehicle prefab players can drive. Sometimes it's placed by a level designer, other times I spawn it via code. If my project uses custom unspawning for dynamic objects (i.e. for pooling or some other purpose) then that custom unspawning is also called for scene placed objects (which breaks things). We've been running with a modification to just change the order in NetworkClient.DestroyObject such that sceneId is checked first before unspawnHandlers. This works fine for us, but I understand might not be right for thousands of other mirror projects. If you didn't want to make that change then this is might just be a restriction that could use a better error message. I.e. on scene load any prefabs that have custom unspawning registered could produce an error that explicit states that's not allowed ? We'd prefer the reordering change to NetworkClient.DestroyObject if possible! |
Show me your change, please. Here's the DestroyObject method as it exists today: static void DestroyObject(uint netId)
{
// Debug.Log($"NetworkClient.OnObjDestroy netId: {netId}");
if (spawned.TryGetValue(netId, out NetworkIdentity identity) && identity != null)
{
if (identity.isLocalPlayer)
identity.OnStopLocalPlayer();
identity.OnStopClient();
// custom unspawn handler for this prefab? (for prefab pools etc.)
if (InvokeUnSpawnHandler(identity.assetId, identity.gameObject))
{
// reset object after user's handler
identity.Reset();
}
// otherwise fall back to default Destroy
else if (identity.sceneId == 0)
{
// don't call reset before destroy so that values are still set in OnDestroy
GameObject.Destroy(identity.gameObject);
}
// scene object.. disable it in scene instead of destroying
else
{
identity.gameObject.SetActive(false);
spawnableObjects[identity.sceneId] = identity;
// reset for scene objects
identity.Reset();
}
// remove from dictionary no matter how it is unspawned
connection.owned.Remove(identity); // if any
spawned.Remove(netId);
}
//else Debug.LogWarning($"Did not find target for destroy message for {netId}");
} |
// !!! Changed ordering here to ensure scene objects are always cleaned up properly, even if we could spawn the same object at runtime via RegisterPrefab
// scene object.. disable it in scene instead of destroying
if (identity.sceneId != 0)
{
identity.gameObject.SetActive(false);
spawnableObjects[identity.sceneId] = identity;
// reset for scene objects
identity.Reset();
}
// custom unspawn handler for this prefab? (for prefab pools etc.)
else if (InvokeUnSpawnHandler(identity.assetId, identity.gameObject))
{
// reset object after user's handler
identity.Reset();
}
// otherwise fall back to default Destroy
else
{
// don't call reset before destroy so that values are still set in OnDestroy
GameObject.Destroy(identity.gameObject);
} |
With your change, are you getting any warnings like this? |
No we aren't seeing that. What's the stack? I didn't make it clear in my test instructions perhaps but i'm only calling RegisterPrefab once on the test cube prefab and I'm not including it in the NetworkManager spawnPrefabs list (that would be what I'd expect to generate that warning) Also fyi we are on 73.0 still so not sure if anything else has changed. |
Describe the bug
Prefabs placed in a scene, but also registered via RegisterPrefab will invoke the custom unspawn handler instead of being deactivated and added back to spawnableObjects and Reset.
[IMPORTANT] How can we reproduce the issue, step by step:
Spawn scene object not found for 7A7BE7168BCD866C. Make sure that client and server use exactly the same project.
Expected behavior
Would not expect scene objects to invoke custom unspawn handlers since they don't invoke custom spawn handlers.
Desktop (please complete the following information):
Additional Notes
It's also invalid to pass null to RegisterPrefab for the unspawn handler (so this can't be worked around easily)
The code causing this behavior also exists in DestroyAllClientObjects but I don't have a repro for an issue caused by it.
The text was updated successfully, but these errors were encountered: