Alix Ollivier
Alix Ollivier2d ago

How can I sync a trail renderer?

I'd like to sync a trail renderer that's on my avatar, so that players can see each other's trails while flying. I know trail renderers are considered complex objects, so how would I sync them in Normcore? I don't necessarily need the exact same trail, just one that roughly correlates, because it's purely visual.
12 Replies
kapa.ai
kapa.ai2d ago
Hi @Alix Ollivier. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To synchronize a trail renderer for avatars in Normcore, you can use a custom RealtimeComponent to sync the key points of the trail. While we don't have direct information about syncing trail renderers specifically, we can adapt the approach used for brush strokes in a multiplayer drawing app, which is conceptually similar. Here's a high-level approach you could take: 1. Create a custom RealtimeComponent and RealtimeModel to represent your trail. 2. In your RealtimeModel, use a RealtimeArray to store the positions of key points along the trail. 3. In your RealtimeComponent, update the model with new positions as the avatar moves. 4. On remote clients, use the synchronized positions to recreate a visually similar trail. Here's a simplified example based on the brush stroke synchronization from the Creating a Multiplayer Drawing App guide:
using UnityEngine;
using Normal.Realtime;
using Normal.Realtime.Serialization;

public class TrailSync : RealtimeComponent<TrailSyncModel> {
[SerializeField]
private TrailRenderer _trailRenderer;

protected override void OnRealtimeModelReplaced(TrailSyncModel previousModel, TrailSyncModel currentModel) {
if (previousModel != null) {
previousModel.trailPoints.modelAdded -= TrailPointAdded;
}

if (currentModel != null) {
if (currentModel.isFreshModel)
currentModel.trailPoints.Clear();

currentModel.trailPoints.modelAdded += TrailPointAdded;
}
}

private void TrailPointAdded(RealtimeArray<Vector3Model> trailPoints, Vector3Model trailPoint, bool remote) {
// Add trail point to the trail renderer
_trailRenderer.AddPosition(trailPoint.value);
}
public void AddTrailPoint(Vector3 position) {
model.trailPoints.Add(new Vector3Model(position));
}
}
using UnityEngine;
using Normal.Realtime;
using Normal.Realtime.Serialization;

public class TrailSync : RealtimeComponent<TrailSyncModel> {
[SerializeField]
private TrailRenderer _trailRenderer;

protected override void OnRealtimeModelReplaced(TrailSyncModel previousModel, TrailSyncModel currentModel) {
if (previousModel != null) {
previousModel.trailPoints.modelAdded -= TrailPointAdded;
}

if (currentModel != null) {
if (currentModel.isFreshModel)
currentModel.trailPoints.Clear();

currentModel.trailPoints.modelAdded += TrailPointAdded;
}
}

private void TrailPointAdded(RealtimeArray<Vector3Model> trailPoints, Vector3Model trailPoint, bool remote) {
// Add trail point to the trail renderer
_trailRenderer.AddPosition(trailPoint.value);
}
public void AddTrailPoint(Vector3 position) {
model.trailPoints.Add(new Vector3Model(position));
}
}
In this example, you would call AddTrailPoint() periodically as your avatar moves to add new points to the trail. The TrailPointAdded method will be called on all clients (including the local one) whenever a new point is added, updating the TrailRenderer. Remember to create a corresponding TrailSyncModel with a RealtimeArray<Vector3Model> trailPoints property. This approach gives you control over how frequently you update the trail, allowing you to balance between accuracy and network performance. You may need to adjust the frequency of updates and possibly interpolate between points on remote clients to achieve a smooth trail effect. For more detailed information on creating custom RealtimeComponents and Models, refer to the Synchronizing Custom Data guide. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2d ago
<@185325614775926784> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mechabit
Mechabit2d ago
that's overly complicated, just sync a color property and set the avatar trail color when the model changes
Mechabit
Mechabit2d ago
Synchronizing Custom Data | Normcore Documenation
In this guide, I’m going to walk you through how to synchronize custom data in your Unity application using custom realtime components.
Mechabit
Mechabit2d ago
and where it says
private void UpdateMeshRendererColor() {
// Get the color from the model and set it on the mesh renderer.
_meshRenderer.material.color = model.color;
}
private void UpdateMeshRendererColor() {
// Get the color from the model and set it on the mesh renderer.
_meshRenderer.material.color = model.color;
}
replace with trailRenderer.startColor = model.color;
Alix Ollivier
Alix OllivierOP2d ago
I have the color property synced, but I don't see the trail itself for some reason.
Mechabit
Mechabit2d ago
lets see the avatar prefab
Alix Ollivier
Alix OllivierOP2d ago
I know that Normcore won't sync things like renderers because they're too complicated, my guess is that it just won't sync my trail renderer?
No description
Mechabit
Mechabit2d ago
and you see that object move when the player moves?
Alix Ollivier
Alix OllivierOP2d ago
I see the object move when the player moves, I see the arms move according to the arms of the player, but I don't see the trail.
Mechabit
Mechabit2d ago
and it's got the emitting box ticked? normcore wont turn off a trail renderer and it emits based on position so it doesn't need anything special to work I'd check it's the same prefab being used also look in the editor while it's playing to see if the trail mesh is there could be it's only not visible in the headset
Alix Ollivier
Alix OllivierOP2d ago
It was the emitting box. In the editor, emitting is on, but when I start a game in my Quest, I click on the Quest player from my Unity Editor and the emitting is off. I guess there's a setting somewhere that's disabling it when the game starts. Not sure why...

Did you find this page helpful?