Can I spawn a prefab with RealtimeView on it, and then immediately remove the RealtimeView?
I basically have a prefab that I want to mostly spawn with Normal.Realtime.Instantiate. Except for ONE case where I'd like to just spawn them locally with GameObject.Instantiate. There are a TON of variants, so I really do NOT want to make a separate set of prefabs without the RealtimeView on it.
Is this allowed? Just instantly removing the components after GameObject.Instantiate?
12 Replies
Hi @khoi. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Based on the available knowledge sources, it is not recommended to remove a
Removing
RealtimeView
component at runtime after instantiating a prefab, whether you use Normal.Realtime.Instantiate
or GameObject.Instantiate
. Normcore relies on the metadata present in the prefab at the time of instantiation to correctly wire up all RealtimeView
and RealtimeComponent
instances across clients. Removing these components at runtime is not a supported workflow and may lead to desynchronization or errors.
Specifically:
- Normcore does not support adding or removing RealtimeComponents at runtime. The system uses metadata on the prefab to connect components on all clients, and this metadata is set up at build time, not dynamically (Common Questions).
- If you instantiate a prefab with GameObject.Instantiate
(i.e., locally, not networked), the RealtimeView
and its components will not be connected to the Normcore datastore, but simply removing the component after instantiation is not documented as a supported or safe operation.
- The recommended approach is to maintain separate prefabs for networked and non-networked use cases, even though this may be inconvenient with many variants. There is no mention in the documentation of a supported workflow for dynamically stripping out RealtimeView
components after instantiation.
Summary:Removing
RealtimeView
or RealtimeComponent
at runtime is not supported by Normcore and may cause issues. The knowledge sources do not provide a safe or recommended way to do this, and you should avoid it if possible. If you need to instantiate prefabs locally without networking, consider maintaining separate prefab variants or using a prefab loader that conditionally strips components before instantiation (outside of Normcore's workflow), but this is not covered or guaranteed by the official documentation.
If you need more flexibility, you might consider using a custom prefab loading system, but again, this is not directly supported for the purpose of removing core Normcore components at runtime (Common Questions).
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Worth a shot, as long as you use GameObject.Instantiate so the view doesn’t get a model or register with Realtime I think it would be fine
Ok. Seems to have worked.
Separately @kapa.ai why is the scale of my object not changing here?
GameObject handObject = Normal.Realtime.Realtime.Instantiate(
toSpawn.name,
new Realtime.InstantiateOptions()
);
handObject.transform.SetParent(handToUse == Hand.Left ? HandAnchorLeft : HandAnchorRight);
handObject.transform.localPosition = Vector3.zero;
handObject.transform.localRotation = Quaternion.identity;
handObject.transform.localScale *= 100; // scale up since armature is 0.01
My prefab local scale is 0.3, 0.3, 0.3 and it stays the same even after I call *= 100?
Let me check the knowledge base for you again. One moment! :books:
----------------------
The likely reason your object's scale is not changing after calling
If not, your local changes will be overwritten by the value in the datastore. 2. Is
If so, the scale is being synchronized and you must update it through the model as the owner. 3. When are you setting the scale?
If you set the scale before ownership is established or before the model is ready, it may be overwritten when the model syncs. Recommended solution:
- Ensure you have ownership of the
RealtimeTransform
RealtimeComponent lifecycle If you need more specific help, please provide details about whether your prefab has a
handObject.transform.localScale *= 100;
is because the prefab you are instantiating has a RealtimeTransform component on it. When a RealtimeTransform
is present, it synchronizes the transform (including position, rotation, and scale) across the network, and will override any local changes you make to the transform if you are not the owner, or if the model's value is being set elsewhere.
From the documentation:
RealtimeTransform will monitor the GameObject and synchronize the transform or rigidbody state to a model in the datastore.Additionally, the
...
In order to move an object with a RealtimeTransform component, your client needs to be the owner of the RealtimeTransform component
...
All other clients follow along with the owner's copy of the transform or rigidbody. This means that in order to move an object with a RealtimeTransform component on it, you must be the owner of the RealtimeTransform component.
RealtimeTransform
syncScale
property on RealtimeTransform
determines whether scale is synchronized. If it is enabled, the scale will be set from the model, not from your local assignment, unless you are the owner and update the model accordingly.
What you should check:
1. Are you the owner of the RealtimeTransform?If not, your local changes will be overwritten by the value in the datastore. 2. Is
syncScale
enabled on the RealtimeTransform?If so, the scale is being synchronized and you must update it through the model as the owner. 3. When are you setting the scale?
If you set the scale before ownership is established or before the model is ready, it may be overwritten when the model syncs. Recommended solution:
- Ensure you have ownership of the
RealtimeTransform
before setting the scale.
- Set the scale after ownership is confirmed.
- If you want to set the initial scale, consider doing it in the OnRealtimeModelReplaced()
method of a custom RealtimeComponent
, or immediately after confirming ownership.
Reference:RealtimeTransform
RealtimeComponent lifecycle If you need more specific help, please provide details about whether your prefab has a
RealtimeTransform
and whether you are requesting ownership before setting the scale.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai that worked!
However, the new local scale is 3000 instead of 100 * 0.3 which should be 30. Is there some weird matrix math operational order going on?
GameObject handObject = Normal.Realtime.Realtime.Instantiate(
toSpawn.name,
new Realtime.InstantiateOptions()
);
handObject.GetComponent<RealtimeTransform>().RequestOwnership();
handObject.transform.SetParent(handToUse == Hand.Left ? HandAnchorLeft : HandAnchorRight);
handObject.transform.localPosition = Vector3.zero;
handObject.transform.localRotation = Quaternion.identity;
handObject.transform.localScale *= 100; // scale up since armature is 0.01
Let me check the knowledge base for you again. One moment! :books:
----------------------
The knowledge sources do not explicitly mention any special matrix math or operational order that would cause the local scale to become 3000 instead of 30 when using
Set the parent before setting the local scale to ensure you are scaling relative to the correct parent transform: This approach avoids compounding scale changes due to transform hierarchy. If you continue to see unexpected results, double-check the scale of the parent objects and the order of operations. If you need more detailed troubleshooting, the knowledge sources do not provide further specifics on this scenario. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
handObject.transform.localScale *= 100;
after instantiating a prefab with a RealtimeTransform
component and requesting ownership.
However, based on the documented behavior of RealtimeTransform
, it is important to note:
- RealtimeTransform
synchronizes the transform state, including scale, across the network if syncScale
is enabled.
- If you set the parent after scaling, and the parent has a non-default scale, the child's local scale may be affected by the parent's scale due to how Unity's transform hierarchy works.
- The documentation does not specify any Normcore-specific behavior that would multiply the scale multiple times, but it does warn that transform hierarchy and synchronization order can cause unexpected results if not managed carefully, especially with nested transforms and networked synchronization (RealtimeTransform Extra Notes).
Possible causes (based on Unity and Normcore behavior):
- If the parent (HandAnchorLeft
or HandAnchorRight
) has a local scale that is not (1,1,1), setting the child’s local scale after parenting will multiply the child’s scale by the parent’s scale.
- If you set the scale before parenting, and then parent the object, Unity will recalculate the local scale to maintain the same world scale, which can result in unexpected values if the parent is scaled.
Recommendation:Set the parent before setting the local scale to ensure you are scaling relative to the correct parent transform: This approach avoids compounding scale changes due to transform hierarchy. If you continue to see unexpected results, double-check the scale of the parent objects and the order of operations. If you need more detailed troubleshooting, the knowledge sources do not provide further specifics on this scenario. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
ok seems like i just needed to not multiply since Realtime.Instantiate instantiates it THEN parents it, where as GameObject.Instantiate(x, parent) instantiates it AS a child
okay it seems like calling .SetParent does not run on all clients @kapa.ai how do I do this?
Let me check the knowledge base for you again. One moment! :books:
----------------------
You're correct—calling
-
.SetParent()
in Unity only affects the local client and is not synchronized across the network by Normcore. According to the documentation, Normcore does not synchronize parent-child relationships between GameObjects. This means that if you set the parent of a GameObject on one client, it will not automatically update on other clients. The docs specifically state:
We generally recommend that you don't [reparent a game object with a RealtimeView or RealtimeComponent on it]. Normcore will not synchronize parent relationships between objects. And if the new parent gets destroyed, it will take the RealtimeView and its components with it. This can result in desyncs between your clients.Common Questions – RealtimeView The recommended approach is to avoid reparenting networked objects. Instead, you can synchronize the position and rotation of the object to match a "target" (such as a hand anchor) using a script, rather than changing the parent. This gives the same visual effect without causing desyncs or relying on unsupported features. For more details and workarounds, see the RealtimeTransform extra notes. Summary:
Tip: If you need this functionality, check out some of the suggestions at the bottom of the RealtimeTransform extra notes page.
-
.SetParent()
is not networked by Normcore.
- Parent-child relationships are not synchronized.
- Use position/rotation synchronization to visually attach objects instead.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.