khoi
khoi2w ago

RealtimeComponent has been replaced with RealtimeComponent<TModel>

How do I upgrade RealtimeComponent? If I click the RealtimeComponent script that is marked as Deprecated it shows me Packages > Normcore > Normal.Realtime > 2019 > UnityEditor and opens the Normal.Realtime.dll. So I don't think I can edit this script? I followed all the instructions to install Normcore 2. I have the latest package in Package Manager (2.13.2 released 1/14/2025 in the My Registries and 2.12.0 from 10/12/24 in My Assets). My other Normcore scripts like RealtimeView and RealtimeTransform work fine. I am trying to add a RealtimeComponent to a prefab so that if I toggle activeSelf, it will toggle active on all clients. Is there a different way to do this?
No description
11 Replies
kapa.ai
kapa.ai2w ago
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 information provided in the knowledge sources, I can help you with upgrading from RealtimeComponent to RealtimeComponent<TModel> and achieving your goal of syncing the active state across clients. Here's how you can proceed: 1. Upgrading to RealtimeComponent<TModel>: The RealtimeComponent class has indeed been replaced with RealtimeComponent<TModel>. This is part of the changes introduced in Normcore 2. You're correct that you can't edit the deprecated script directly, as it's part of the Normcore package. 2. Creating a custom component: Instead of using the deprecated RealtimeComponent, you should create a new custom component that inherits from RealtimeComponent<TModel>. Here's how you can do it: First, create a new model for your component:
[RealtimeModel]
public partial class ActiveStateModel {
[RealtimeProperty(1, true)]
private bool _isActive;
}

[RealtimeModel]
public partial class ActiveStateModel {
[RealtimeProperty(1, true)]
private bool _isActive;
}

Then, create your custom component:
using Normal.Realtime;
using UnityEngine;

public class ActiveStateSync : RealtimeComponent<ActiveStateModel> {
protected override void OnRealtimeModelReplaced(ActiveStateModel previousModel, ActiveStateModel currentModel) {
if (previousModel != null) {
previousModel.isActiveDidChange -= ActiveStateChanged;
}
if (currentModel != null) {
currentModel.isActiveDidChange += ActiveStateChanged;
UpdateActiveState();
}
}

private void ActiveStateChanged(ActiveStateModel model, bool value) {
UpdateActiveState();
}

private void UpdateActiveState() {
gameObject.SetActive(model.isActive);
}

public void SetActive(bool active) {
model.isActive = active;
}
}

using Normal.Realtime;
using UnityEngine;

public class ActiveStateSync : RealtimeComponent<ActiveStateModel> {
protected override void OnRealtimeModelReplaced(ActiveStateModel previousModel, ActiveStateModel currentModel) {
if (previousModel != null) {
previousModel.isActiveDidChange -= ActiveStateChanged;
}
if (currentModel != null) {
currentModel.isActiveDidChange += ActiveStateChanged;
UpdateActiveState();
}
}

private void ActiveStateChanged(ActiveStateModel model, bool value) {
UpdateActiveState();
}

private void UpdateActiveState() {
gameObject.SetActive(model.isActive);
}

public void SetActive(bool active) {
model.isActive = active;
}
}

3. Using the new component: Add this ActiveStateSync component to your prefab instead of the deprecated RealtimeComponent. When you want to toggle the active state, call SetActive(bool) on this component instead of directly setting gameObject.SetActive(). 4. Syncing across clients: With this setup, when you toggle the activeSelf state using the SetActive method of your ActiveStateSync component, it will automatically sync across all clients. This approach follows the new pattern for custom RealtimeComponent<TModel> classes in Normcore 2, as described in the Synchronizing Custom Data documentation. Remember to compile your model if you're using Unity 2019/2020. For Unity 2021+, the model code is automatically generated. If you need more detailed information about RealtimeComponent<TModel>, you can refer to the RealtimeComponent<TModel> API reference. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
khoi
khoiOP2w ago
@kapa.ai Ok. I implemented everything and there seem to be no errors. However, my object is still not being deactivated / activated when I call .GetComponent<ActiveStateSync>().SetActive(true)
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I understand you've implemented the ActiveStateSync component as suggested, but you're still experiencing issues with activating/deactivating the object across clients. Let's troubleshoot this issue based on the information available in our knowledge sources. 1. First, make sure you're using Realtime.Instantiate() instead of Unity's Instantiate() when creating your object. This is crucial for Normcore to properly set up the networking:
GameObject myObject = Realtime.Instantiate("My Object", ownedByClient: true);
GameObject myObject = Realtime.Instantiate("My Object", ownedByClient: true);
Source 2. Check if the RealtimeView component is properly set up on your prefab. The RealtimeView should list your ActiveStateSync component in its components list. If it doesn't appear there, try removing the component and re-adding it to your game object. Source 3. Ensure that you're not checking the model property inside of Awake() or Start(). Instead, move your initialization logic inside the OnRealtimeModelReplaced() method of your ActiveStateSync component. Source 4. Make sure you're connected to the room before trying to modify the state. You can check this using realtime.connected == true or wait for the didConnectToRoom event to fire. 5. Verify that the ownership of the object is set correctly. If the object is not owned by any client, you may need to request ownership before making changes:
ActiveStateSync activeStateSync = myObject.GetComponent<ActiveStateSync>();
activeStateSync.RequestOwnership();
activeStateSync.SetActive(true);
ActiveStateSync activeStateSync = myObject.GetComponent<ActiveStateSync>();
activeStateSync.RequestOwnership();
activeStateSync.SetActive(true);
Source 6. Double-check that your ActiveStateModel has the createMetaModel: true parameter set in its RealtimeModel attribute:
[RealtimeModel(createMetaModel: true)]
public partial class ActiveStateModel {
// ...
}
[RealtimeModel(createMetaModel: true)]
public partial class ActiveStateModel {
// ...
}
This is necessary for ownership to work properly. Source If you've verified all these points and the issue persists, it might be helpful to add some debug logging in your ActiveStateSync component to ensure that the SetActive method is being called and that the model is being updated correctly. If you're still encountering problems after these checks, you may want to reach out to the Normcore community on their Discord for more specific assistance. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
khoi
khoiOP2w ago
@kapa.ai can you read my file
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize, but I am not able to read any files or access any information outside of what has been provided to me in the knowledge sources. I am an AI assistant specifically tuned to answer questions about NormalVR based on the given documentation. If you have a question about NormalVR or its features, I'd be happy to try and answer it using the information available to me. Is there anything specific about NormalVR you would like to know? ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
khoi
khoiOP2w ago
@kapa.ai 1. I am using Realtime Instantiate. RealtimeView component shows the ActiveStateSync on my prefab. 2. RealtimeView shows the ActiveStateSync component in its components list. My logic is in OnRealtimeModelReplaced I spawn the prefab after didConnectToRoom fires. I am spawning it with ownedByClient true I added createMetaModel true Still not working. Here is my code. using System.Collections; using System.Collections.Generic; using UnityEngine; [RealtimeModel(createMetaModel: true)] public partial class ActiveStateModel { [RealtimeProperty(1, true, true)] private bool _isActive; } using UnityEngine; using Normal.Realtime; public class ActiveStateSync : RealtimeComponent<ActiveStateModel> { protected override void OnRealtimeModelReplaced(ActiveStateModel previousModel, ActiveStateModel currentModel) { if (previousModel != null) { previousModel.isActiveDidChange -= ActiveStateChanged; } if (currentModel != null) { if (currentModel.isFreshModel) currentModel.isActive = false; UpdateActiveState(); currentModel.isActiveDidChange += ActiveStateChanged; } } private void ActiveStateChanged(ActiveStateModel model, bool value) { UpdateActiveState(); } private void UpdateActiveState() { gameObject.SetActive(model.isActive); } public void SetActive(bool active) { model.isActive = active; } } private System.Collections.IEnumerator RespawnComboBagCoroutine() { GameObject newBag = Realtime.Instantiate("ComboBag112 Variant", ownedByClient: true); newBag.GetComponent<ActiveStateSync>().SetActive(false); yield return new WaitForSeconds(3f); newBag.GetComponent<ActiveStateSync>().SetActive(true); } Could there be an issue with calling the SetActive from an IEnumerator?
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on the code you've provided and the information from our knowledge sources, your implementation looks mostly correct. However, there are a few things we can check and potentially improve: 1. Coroutine Usage: Using an IEnumerator shouldn't be an issue by itself. However, make sure that the coroutine is actually running and not being stopped prematurely. 2. Ownership: You're instantiating the object with ownedByClient: true, which is correct. However, it's possible that ownership might be changing or not being set correctly. You can add a check to ensure the component is owned before setting the active state:
private System.Collections.IEnumerator RespawnComboBagCoroutine()
{
GameObject newBag = Realtime.Instantiate("ComboBag112 Variant", ownedByClient: true);
ActiveStateSync activeStateSync = newBag.GetComponent<ActiveStateSync>();

if (!activeStateSync.isOwnedLocallySelf)
{
activeStateSync.RequestOwnership();
}

activeStateSync.SetActive(false);

yield return new WaitForSeconds(3f);

if (activeStateSync.isOwnedLocallySelf)
{
activeStateSync.SetActive(true);
}
else
{
Debug.LogWarning("Failed to set active state: not owned locally");
}
}

private System.Collections.IEnumerator RespawnComboBagCoroutine()
{
GameObject newBag = Realtime.Instantiate("ComboBag112 Variant", ownedByClient: true);
ActiveStateSync activeStateSync = newBag.GetComponent<ActiveStateSync>();

if (!activeStateSync.isOwnedLocallySelf)
{
activeStateSync.RequestOwnership();
}

activeStateSync.SetActive(false);

yield return new WaitForSeconds(3f);

if (activeStateSync.isOwnedLocallySelf)
{
activeStateSync.SetActive(true);
}
else
{
Debug.LogWarning("Failed to set active state: not owned locally");
}
}

3. Debug Logging: Add some debug logs to verify that your methods are being called and the model is being updated:
public class ActiveStateSync : RealtimeComponent<ActiveStateModel>
{
// ... other code ...

private void UpdateActiveState()
{
Debug.Log($"UpdateActiveState called. Setting active to: {model.isActive}");
gameObject.SetActive(model.isActive);
}
public void SetActive(bool active)
{
Debug.Log($"SetActive called with value: {active}");
model.isActive = active;
}
}

public class ActiveStateSync : RealtimeComponent<ActiveStateModel>
{
// ... other code ...

private void UpdateActiveState()
{
Debug.Log($"UpdateActiveState called. Setting active to: {model.isActive}");
gameObject.SetActive(model.isActive);
}
public void SetActive(bool active)
{
Debug.Log($"SetActive called with value: {active}");
model.isActive = active;
}
}

4. Room Connection: You mentioned that you're spawning the prefab after didConnectToRoom fires, which is correct. Just make sure that the connection hasn't been lost between when you connected and when you're trying to spawn the object. 5. Model Initialization: In your OnRealtimeModelReplaced method, you're setting the initial state to false for fresh models. Make sure this isn't conflicting with your intended initial state:
if (currentModel != null)
{
if (currentModel.isFreshModel)
{
Debug.Log("Fresh model detected. Setting initial state to false.");
currentModel.isActive = false;
}
UpdateActiveState();

currentModel.isActiveDidChange += ActiveStateChanged;
}

if (currentModel != null)
{
if (currentModel.isFreshModel)
{
Debug.Log("Fresh model detected. Setting initial state to false.");
currentModel.isActive = false;
}
UpdateActiveState();

currentModel.isActiveDidChange += ActiveStateChanged;
}

6. Timing: The 3-second delay in your coroutine might be causing issues if something is changing during that time. Try reducing the delay or removing it entirely for testing purposes. If after implementing these changes and adding debug logs you're still not seeing the expected behavior, you might want to check if there are any error messages in the Unity console or if the debug logs are showing unexpected values. If the issue persists, it could be related to how the RealtimeView is set up on your prefab or how the ActiveStateSync component is being initialized. In that case, you might need to double-check your prefab setup in the Unity editor. Source Source ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@412870643533479936> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?