How can i sync TMP_Text?

How can i sync TMP_Text?
35 Replies
kapa.ai
kapa.ai3w ago
Hi @CanyonsEcho. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To sync a TMP_Text (TextMesh Pro object) in NormalVR, you cannot directly sync the object as only primitives (int, float, Vector3, string, etc.) can be serialized. Instead, you should create a field for each property on the object that you’d like to sync. For example, if you want to sync the text content and color of a TMP_Text object, you would create separate fields for these properties and sync them individually. Here is the relevant information from the knowledge source (https://normcore.io/documentation/room/common-questions#when-i-try-to-sync-a-specific-object-to-the-datastore-i-get-an-error-that-says-it-cannot-be-serialized-whats-the-issue):
Only primitives (int, float, Vector3, string, etc.) can be serialized, so if you need to sync a specific kind of object like a TextMesh Pro object, you should create a field for each property on the object that you’d like to sync.
---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
how can i do that @Normcore Assistant how can i do that
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- To sync a TMP_Text object in NormalVR, you would need to create a custom RealtimeComponent that synchronizes the properties of the TMP_Text object that you want to sync. Here's a general outline of the steps you would need to follow: 1. Create a RealtimeModel subclass: This model will hold the data you want to sync. In this case, it could be the text content and color of the TMP_Text object. You would create a new script, say TMP_TextSyncModel.cs, and define the properties you want to sync in this model. 2. Create a RealtimeComponent subclass: This component will be responsible for syncing the state between the Unity scene and the model in the Normcore datastore. You would create another script, say TMP_TextSync.cs, and in this script, you would implement the logic to update the model when the TMP_Text object changes and vice versa. Here's a simplified example of what the TMP_TextSync.cs script might look like:
using UnityEngine;
using Normal.Realtime;
using TMPro;

public class TMP_TextSync : RealtimeComponent<TMP_TextSyncModel> {
private TMP_Text _text;

private void Awake() {
_text = GetComponent<TMP_Text>();
}

protected override void OnRealtimeModelReplaced(TMP_TextSyncModel previousModel, TMP_TextSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the TMP_Text object to match the current state of the model
_text.text = currentModel.text;
_text.color = new Color(currentModel.colorR, currentModel.colorG, currentModel.colorB, currentModel.colorA);
}
}
// Call this method to update the model when the TMP_Text object changes
public void UpdateModel() {
model.text = _text.text;
model.colorR = _text.color.r;
model.colorG = _text.color.g;
model.colorB = _text.color.b;
model.colorA = _text.color.a;
}
}
using UnityEngine;
using Normal.Realtime;
using TMPro;

public class TMP_TextSync : RealtimeComponent<TMP_TextSyncModel> {
private TMP_Text _text;

private void Awake() {
_text = GetComponent<TMP_Text>();
}

protected override void OnRealtimeModelReplaced(TMP_TextSyncModel previousModel, TMP_TextSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the TMP_Text object to match the current state of the model
_text.text = currentModel.text;
_text.color = new Color(currentModel.colorR, currentModel.colorG, currentModel.colorB, currentModel.colorA);
}
}
// Call this method to update the model when the TMP_Text object changes
public void UpdateModel() {
model.text = _text.text;
model.colorR = _text.color.r;
model.colorG = _text.color.g;
model.colorB = _text.color.b;
model.colorA = _text.color.a;
}
}
In this example, TMP_TextSyncModel would be a model that has properties for the text content and color of the TMP_Text object. Please note that this is a simplified example and you would need to add more code to handle registering and unregistering from events, as well as to handle syncing the state when the model changes. For more detailed information on how to create custom RealtimeComponents and RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
i only need to sync text @Normcore Assistant i only need to sync text
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- If you only need to sync the text content of a TMP_Text object, you can simplify the process. Here's how you can do it: 1. Create a RealtimeModel subclass: This model will hold the text content you want to sync. You would create a new script, say TMP_TextSyncModel.cs, and define the text property in this model.
[RealtimeModel]
public partial class TMP_TextSyncModel {
[RealtimeProperty(1, true)]
private string _text;
}
[RealtimeModel]
public partial class TMP_TextSyncModel {
[RealtimeProperty(1, true)]
private string _text;
}
2. Create a RealtimeComponent subclass: This component will be responsible for syncing the state between the Unity scene and the model in the Normcore datastore. You would create another script, say TMP_TextSync.cs, and in this script, you would implement the logic to update the model when the TMP_Text object changes and vice versa.
using UnityEngine;
using Normal.Realtime;
using TMPro;

public class TMP_TextSync : RealtimeComponent<TMP_TextSyncModel> {
private TMP_Text _text;

private void Awake() {
_text = GetComponent<TMP_Text>();
}

protected override void OnRealtimeModelReplaced(TMP_TextSyncModel previousModel, TMP_TextSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the TMP_Text object to match the current state of the model
_text.text = currentModel.text;
}
}

// Call this method to update the model when the TMP_Text object changes
public void UpdateModel() {
model.text = _text.text;
}
}
using UnityEngine;
using Normal.Realtime;
using TMPro;

public class TMP_TextSync : RealtimeComponent<TMP_TextSyncModel> {
private TMP_Text _text;

private void Awake() {
_text = GetComponent<TMP_Text>();
}

protected override void OnRealtimeModelReplaced(TMP_TextSyncModel previousModel, TMP_TextSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the TMP_Text object to match the current state of the model
_text.text = currentModel.text;
}
}

// Call this method to update the model when the TMP_Text object changes
public void UpdateModel() {
model.text = _text.text;
}
}
In this example, TMP_TextSyncModel is a model that has a property for the text content of the TMP_Text object. Please note that this is a simplified example and you would need to add more code to handle registering and unregistering from events, as well as to handle syncing the state when the model changes. For more detailed information on how to create custom RealtimeComponents and RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
where do i attach these scripts? @Normcore Assistant
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The TMP_TextSync.cs script should be attached to the GameObject that has the TMP_Text component you want to sync. This is because the script uses GetComponent<TMP_Text>() to get a reference to the TMP_Text component in its Awake() method. The TMP_TextSyncModel.cs script doesn't need to be attached to a GameObject. It's a model class that's used by Normcore to sync data, so you just need to create the script and Normcore will use it automatically when you use the TMP_TextSync component. Here are the steps: 1. Create a new script in your Unity project, name it TMP_TextSyncModel.cs, and paste the code for the TMP_TextSyncModel class into it. 2. Create another new script, name it TMP_TextSync.cs, and paste the code for the TMP_TextSync class into it. 3. In the Unity editor, select the GameObject that has the TMP_Text component you want to sync. 4. In the Inspector, click on the "Add Component" button. 5. In the search box that appears, type TMP_TextSync and select it to add it to the GameObject. Now, whenever you want to sync the text content of the TMP_Text component, you can call the UpdateModel() method on the TMP_TextSync component. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
@Normcore Assistant can i sync a standard cube or something using realtimeview and realtimetransform if its disabled and i use a script to enable it?
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- No, you cannot sync a standard cube or any other GameObject using RealtimeView if it's disabled. As per the Normcore documentation (https://normcore.io/documentation/realtime/common-questions#can-i-disable-realtimeview), Scene RealtimeViews register with Realtime in Start(). If they are disabled, they will never register: Realtime will neither initialize them nor connect them to the datastore. Instead, you can use a custom RealtimeComponent to enable/disable child game objects, scripts, or renderers directly. For synchronizing a GameObject like a standard cube, you can use the RealtimeTransform component. Here's how you can do it: 1. Create an empty scene. Add a Realtime component to an empty game object and configure the appKey so it can connect. 2. Create a Cube game object in the scene and add a RealtimeTransform component to it. 3. Export a build, and open it next to the editor. Hit Play in Unity. 4. Click the "Request Ownership" button on the RealtimeTransform inspector (not the RealtimeView inspector). 5. Drag the cube around in the scene and watch how it updates on the build automatically. You can find more details in the Normcore documentation (https://normcore.io/documentation/realtime#synchronizing-a-gameobject). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
how can i do that @Normcore Assistant
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- To enable or disable a GameObject using a custom RealtimeComponent, you would need to create a RealtimeModel that has a boolean property to represent whether the GameObject is enabled or not, and a RealtimeComponent that syncs the state of the GameObject with this model. Here's a simplified example of how you can do it: 1. Create a RealtimeModel subclass: This model will hold the enabled state of the GameObject. You would create a new script, say GameObjectSyncModel.cs, and define the enabled property in this model.
[RealtimeModel]
public partial class GameObjectSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled;
}
[RealtimeModel]
public partial class GameObjectSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled;
}
2. Create a RealtimeComponent subclass: This component will be responsible for syncing the state between the Unity scene and the model in the Normcore datastore. You would create another script, say GameObjectSync.cs, and in this script, you would implement the logic to update the model when the GameObject's state changes and vice versa.
using UnityEngine;
using Normal.Realtime;

public class GameObjectSync : RealtimeComponent<GameObjectSyncModel> {
protected override void OnRealtimeModelReplaced(GameObjectSyncModel previousModel, GameObjectSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the GameObject to match the current state of the model
gameObject.SetActive(currentModel.enabled);
}
}

// Call this method to update the model when the GameObject's state changes
public void UpdateModel() {
model.enabled = gameObject.activeSelf;
}
}
using UnityEngine;
using Normal.Realtime;

public class GameObjectSync : RealtimeComponent<GameObjectSyncModel> {
protected override void OnRealtimeModelReplaced(GameObjectSyncModel previousModel, GameObjectSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the GameObject to match the current state of the model
gameObject.SetActive(currentModel.enabled);
}
}

// Call this method to update the model when the GameObject's state changes
public void UpdateModel() {
model.enabled = gameObject.activeSelf;
}
}
In this example, GameObjectSyncModel is a model that has a property for the enabled state of the GameObject. Please note that this is a simplified example and you would need to add more code to handle registering and unregistering from events, as well as to handle syncing the state when the model changes. For more detailed information on how to create custom RealtimeComponents and RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
@Normcore Assistant what if instead of disabling the object, it turns off the mesh renderer, will realtimetransform work now
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, turning off the Mesh Renderer of a GameObject will not affect the functionality of RealtimeTransform. The RealtimeTransform component synchronizes the position, rotation, and scale of a GameObject, and it doesn't matter whether the Mesh Renderer is enabled or not. If you want to synchronize the enabled state of the Mesh Renderer, you can create a custom RealtimeComponent similar to the one in the previous example, but instead of calling gameObject.SetActive(), you would get a reference to the Mesh Renderer component and call meshRenderer.enabled = currentModel.enabled; to enable or disable the Mesh Renderer based on the model. Here's a simplified example:
using UnityEngine;
using Normal.Realtime;

public class MeshRendererSync : RealtimeComponent<MeshRendererSyncModel> {
private MeshRenderer _meshRenderer;

private void Awake() {
_meshRenderer = GetComponent<MeshRenderer>();
}

protected override void OnRealtimeModelReplaced(MeshRendererSyncModel previousModel, MeshRendererSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the Mesh Renderer to match the current state of the model
_meshRenderer.enabled = currentModel.enabled;
}
}

// Call this method to update the model when the Mesh Renderer's state changes
public void UpdateModel() {
model.enabled = _meshRenderer.enabled;
}
}
using UnityEngine;
using Normal.Realtime;

public class MeshRendererSync : RealtimeComponent<MeshRendererSyncModel> {
private MeshRenderer _meshRenderer;

private void Awake() {
_meshRenderer = GetComponent<MeshRenderer>();
}

protected override void OnRealtimeModelReplaced(MeshRendererSyncModel previousModel, MeshRendererSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
}

if (currentModel != null) {
// Register for events and update the Mesh Renderer to match the current state of the model
_meshRenderer.enabled = currentModel.enabled;
}
}

// Call this method to update the model when the Mesh Renderer's state changes
public void UpdateModel() {
model.enabled = _meshRenderer.enabled;
}
}
In this example, MeshRendererSyncModel would be a model that has a boolean property for the enabled state of the Mesh Renderer. Please note that this is a simplified example and you would need to add more code to handle registering and unregistering from events, as well as to handle syncing the state when the model changes. For more detailed information on how to create custom RealtimeComponents and RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
send me the mesh renderer sync model @Normcore Assistant
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Sure, here's a simple example of a MeshRendererSyncModel class that has a boolean property for the enabled state of the Mesh Renderer:
using Normal.Realtime.Serialization;

[RealtimeModel]
public partial class MeshRendererSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled;
}
using Normal.Realtime.Serialization;

[RealtimeModel]
public partial class MeshRendererSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled;
}
This model class uses the [RealtimeModel] attribute to indicate that it's a model class for Normcore, and the [RealtimeProperty] attribute to indicate that the _enabled field is a property that should be synced. The 1 is the unique identifier for the property, and true indicates that the property should be synced reliably. Please note that this is a simplified example and you might need to add more properties or methods depending on your specific use case. For more detailed information on how to create custom RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtime-model). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
@Normcore Assistant why does it automatically enable
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The reason it automatically enables is because of the default value of the _enabled field in the MeshRendererSyncModel. When a new instance of MeshRendererSyncModel is created, the _enabled field is initialized to its default value, which is false for a boolean. However, in the Normcore model synchronization system, a property is only synced when its value changes. So if the initial value of _enabled is false, and you set it to false again, it won't be synced because the value didn't change. To solve this issue, you can initialize the _enabled field to true in the MeshRendererSyncModel. This way, when you set it to false, it will be considered a change and will be synced. Here's how you can do it:
[RealtimeModel]
public partial class MeshRendererSyncModel {
private bool _enabled = true;

[RealtimeProperty(1, true)]
private bool enabled {
get { return _enabled; }
set {
if (_enabled == value) return;
_enabled = value;
}
}
}
[RealtimeModel]
public partial class MeshRendererSyncModel {
private bool _enabled = true;

[RealtimeProperty(1, true)]
private bool enabled {
get { return _enabled; }
set {
if (_enabled == value) return;
_enabled = value;
}
}
}
In this example, the _enabled field is initialized to true, and the enabled property only updates _enabled if the new value is different from the current value. Please note that this is a simplified example and you might need to add more code depending on your specific use case. For more detailed information on how to create custom RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtime-model). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
@Normcore Assistant Severity Code Description Project File Line Suppression State Error (active) CS0592 Attribute 'RealtimeProperty' is not valid on this declaration type. It is only valid on 'field' declarations. Assembly-CSharp C:\Users\CanyonsEcho\Stinky-Project\Assets\Scripts\Networking Sync\MeshRendererSyncModel.cs 6
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The error message is indicating that the RealtimeProperty attribute is not valid on a property declaration. It is only valid on field declarations. In the Normcore system, the RealtimeProperty attribute should be applied to fields, not properties. So you should change your enabled property back to a field. Here's how you can do it:
[RealtimeModel]
public partial class MeshRendererSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled = true;
}
[RealtimeModel]
public partial class MeshRendererSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled = true;
}
In this example, _enabled is a field (not a property), and it's marked with the RealtimeProperty attribute, which tells Normcore to sync its value. For more detailed information on how to create custom RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtime-model). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
@Normcore Assistant im using the game object one but it automatically enables every gameobject with it
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- If every GameObject with the custom RealtimeComponent is automatically being enabled, it's likely because the initial state of the _enabled field in your GameObjectSyncModel is set to true. When a new instance of GameObjectSyncModel is created, the _enabled field is initialized to its default value. If this value is true, all GameObjects with the GameObjectSync component will be enabled when they are created. To fix this, you can initialize the _enabled field to false in the GameObjectSyncModel. This way, GameObjects will be disabled by default when they are created. Here's how you can do it:
[RealtimeModel]
public partial class GameObjectSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled = false;
}
[RealtimeModel]
public partial class GameObjectSyncModel {
[RealtimeProperty(1, true)]
private bool _enabled = false;
}
In this example, the _enabled field is initialized to false, so GameObjects will be disabled by default when they are created. Please note that this is a simplified example and you might need to add more code depending on your specific use case. For more detailed information on how to create custom RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtime-model). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below
[MPPL] Canyons
how about i make i enable from a different script in my game @Normcore Assistant
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can certainly control the enabled state of the GameObject from a different script in your game. You would need to get a reference to the GameObjectSync component and call its UpdateModel() method after changing the enabled state of the GameObject. Here's a simplified example of how you can do it:
using UnityEngine;
using Normal.Realtime;

public class MyGameScript : MonoBehaviour {
private GameObjectSync _gameObjectSync;

private void Awake() {
// Get a reference to the GameObjectSync component
_gameObjectSync = GetComponent<GameObjectSync>();
}

public void EnableGameObject() {
// Enable the GameObject
gameObject.SetActive(true);

// Update the model to sync the new state
_gameObjectSync.UpdateModel();
}

public void DisableGameObject() {
// Disable the GameObject
gameObject.SetActive(false);

// Update the model to sync the new state
_gameObjectSync.UpdateModel();
}
}
using UnityEngine;
using Normal.Realtime;

public class MyGameScript : MonoBehaviour {
private GameObjectSync _gameObjectSync;

private void Awake() {
// Get a reference to the GameObjectSync component
_gameObjectSync = GetComponent<GameObjectSync>();
}

public void EnableGameObject() {
// Enable the GameObject
gameObject.SetActive(true);

// Update the model to sync the new state
_gameObjectSync.UpdateModel();
}

public void DisableGameObject() {
// Disable the GameObject
gameObject.SetActive(false);

// Update the model to sync the new state
_gameObjectSync.UpdateModel();
}
}
In this example, MyGameScript is a script that controls the enabled state of the GameObject. It gets a reference to the GameObjectSync component in its Awake() method, and it has two methods EnableGameObject() and DisableGameObject() that change the enabled state of the GameObject and then call UpdateModel() on the GameObjectSync component to sync the new state. Please note that this is a simplified example and you might need to add more code depending on your specific use case. For more detailed information on how to create custom RealtimeComponents and RealtimeModels, you can refer to the Normcore documentation (https://normcore.io/documentation/realtime/synchronizing-custom-data). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@1170785024254169139> kapa.ai is still learning and improving, please let us know how it did by reacting below