Why the Realtime instantiated object is not always ready
I am trying to instantiate objects that have RigidBody and no custom Realtime components. If I have three objects usually at least one of them is missing the Model.
After Realtime.Instantiate call I try to call RequestOwnership but it fails with "Exception: This component doesn't have a model. Wait until the model is present before interacting with the ownership." error.
This does not happen everytime. Next time I launch the game the same object might work and then next time it doesn't. I have not found any pattern on this.
13 Replies
Hi @mhjort. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
The issue you're experiencing might be due to the timing of when you're checking the model property. If you're checking the model property inside of
Awake()
(or, for scene RealtimeViews, inside of Start()
), the model might not be ready yet.
To fix this, you should move the initialization logic inside of your OnRealtimeModelReplaced()
method if you're using RealtimeComponent<ModelType>
. If you're using the legacy RealtimeComponent
class, move the initialization logic into your model setter.
Also, it's important to note that the model is set by Realtime when you connect to the room. This will only fail if Realtime doesn't receive a reference to the RealtimeComponent. This can happen if the model was instantiated with Unity’s Instantiate API (Instantiate()
or GameObject.Instantiate()
) instead of Normcore’s Realtime.Instantiate()
. If you're passing a prefab reference instead of a prefab string, then you're using the wrong one. Make sure to call Realtime.Instantiate(prefabName)
.
If you’re dealing with a prefab, all views and components are initialized with their models. They will be ready to work with by the time Start()
is called on any script on the prefab. Awake()
must be called by Unity before Normcore can initialize any components on the game object. If you’re dealing with a RealtimeView that exists in a scene file, you’ll need to wait until realtime.connected == true
, or the didConnectToRoom
event has fired. RealtimeView uses Start()
internally to register with Realtime, and it’s possible your start method ran before RealtimeView.Start()
.
Sources:
- Why would a RealtimeComponent's model remain null? (https://normcore.io/documentation/realtime/common-questions#why-would-a-realtimecomponents-model-remain-null)
- Why do I get the error “This view doesn't have a model yet. Wait until the model is present before interacting with the ownership,” when interacting with RealtimeView? (https://normcore.io/documentation/realtime/common-questions#why-do-i-get-the-error-this-view-doesnt-have-a-model-yet-wait-until-the-model-is-present-before-interacting-with-the-ownership-when-interacting-with-realtimeview)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@553550237185212418> kapa.ai is still learning and improving, please let us know how it did by reacting below
I have no custom components. If I understand the documentation correctly
OnRealtimeModelReplaced
is relevant only with custom models.I don't know if this helps but I usually check if I'm connected to the room before I start instantiating
if you can make a small repo project it will help them debug
you can pass owned by client = true to InstantiateOptions so you don't need to request ownership
I am already passing the owned by client flag. This way RealtimeView is owned by the client but not the RealtimeTransform. I am trying to call RequestOwnership for the RealtimeTransform but that fails sometimes.
on a blank project I can spawn 100s of cubes and request ownership in the same frame so there's probably something else accessing the model before start
got any awake scripts?
normcore error messages could do with providing more information
Hmm.. I tested with some delay between spawns (they are not spawned in same frame anymore) and haven't seen any errors since then. Need to test more still.
In this case the objects that I spawn are vehicles and they are quite complex (they contain lots of components)
models become ready by start so I would check any awake scripts you have
I'll check that
From inspector I can see that in this failure case RealtimeView owner is Local Client but Realtime Transform owner is offline.
@mhjort does RealtimeTransform show up in the list of components on the RealtimeView? it sounds like potentially a bug with that component
are you trying to add RealtimeTransform via AddComponent by chance?
@Max I think I found the issue. We have almost one hundred vehicle objects objects that need RealtIme components. To avoid manual work I added Editor script that adds the components. However, Normcore does some magic (adds metadata) after those components are added in the editor. Apparently my editor script was not saving the prefabs correctly.
And then when ever I opened those assets in editor to see if the asset is ok the magic processing fixed the asset. So every time I inspected assets and then restarted the game it worked. For this reason it felt that sometimes things worked and sometimes not 😅
Also I learned a bit what was missing by opening prefabs with text editor. So I think I now understand roughly the metadata that is required for this to work.
BTW, are there any plans on supporting adding RealtimeTransform components in runtime? Our game platform is very dynamic and we need to run the same code both in single player and multiplayer context. For us it is a bit cumbersome to add Realtime components before hand.
One feature we have is that we generate 3D objects in the fly using AI and import them as game objects in runtime. This already works in single player context but I have no idea how to make that work in Normcore...
it’s on our list, but blocked on our serialization system refactor. that said, I’d recommend possibly creating a blank container prefab that has an RT on it, instantiate that separately and have a model that links it to your runtime imported game object