Snapshot not sending child rotation for interpolated entity

Edit:

Resolved:

Solution:

overrides["Unity.Transforms.Rotation"].attribute.SendDataForChildEntity = true;

See source for more information:


Original post:


Goal:

I’m trying to present a ghost child entity (blue) of a client-interpolated ghost (red), but the server rotation data of the ghost child entity is not transferring to the client-side ghost child entity, despite the translation data of the ghost root entity transferring.

7576516--938653--upload_2021-10-15_21-53-46.png

The ghost has no ghost owner and is in interpolation-only mode; i.e. there is no prediction or player input involved.

7576516--938656--upload_2021-10-15_21-53-55.png

I’ve attached a minimal example .zip to this post. It’s based on https://github.com/Unity-Technologies/multiplayer/tree/master/sampleproject/Assets/Samples/NetCube

Here is a visualization of the goal:

Red: Ghost root entity
Blue: Ghost child entity

7576516--938647--2021-10-15 21-25-45-small.gif

Here is the current state of things:

7576516--938644--2021-10-15 21-25-45-no-rotation-small.gif

Here is the server update system:

using Unity.Entities;
using Unity.NetCode;
using Unity.Transforms;
using Unity.Mathematics;

[UpdateInWorld(UpdateInWorld.TargetWorld.Server)]
[UpdateInGroup(typeof(GhostSimulationSystemGroup))]
public class MoveCubeSystem : SystemBase
{
    protected override void OnCreate()
    {
    }

    protected override void OnUpdate()
    {
        float elapsedTime = (float)Time.ElapsedTime;

        Entities
            .ForEach((
                    Entity               entity,
                ref Translation          translation,
                ref MovableCubeComponent movableCubeComponent
                ) =>
        {
            // Translate cube (entity root) via time
            translation.Value.z += 0.05f * math.sin(elapsedTime * 2.5f);

            // Rotate child entity via time
            // NOTE: This data does not transfer to the client for some reason
            var childRotation = GetComponent<Rotation>(movableCubeComponent.ChildEntity);
            childRotation.Value = quaternion.Euler(0f, math.radians(movableCubeComponent.RotationSpeed * elapsedTime), 0f);
            SetComponent(movableCubeComponent.ChildEntity, childRotation);
        }).Run();
    }
}

To get the goal visualization video I ran this system on the client as well.

The Entities window in the Editor shows that the child’s rotation in the server world is updating while the child’s rotation in the client world is not, despite the translation of the root entity in each world updating. The child entity has a GhostChildEntityComponent.

7576516–938659–Interpolated-Child-Entity-Minimal-Example.zip (73.7 KB)

1 Like

Below are screenshots showing that there exists a non-zero rotation on the server, but a zero rotation on the client, despite the translations matching (in LocalToWorld):

ServerWorld:

ClientWorld0:

Correlation: I did not have this child-entity-not-updating problem for interpolated ghosts when I had a corresponding ghost-owner-predicted ghost in another client world and ran updates for it in the server’s GhostPredictionSystemGroup.

This looks interesting. Will try.

Edit: It worked.

Keep in mind IGhostDefaultOverridesModifier will be deprecated soon (or even removed in next version). So this is not a future-proof solution. What you should be doing is setting the flag in the component list of the prefab. If the checkboxes are greyed out, there’s a temporary fix somewhere on the forums. Even with that fix, you’ll need another fix from here:

to have the child override actually saved in the prefab. 0.6 buggy is enough that I regret using NetCode so soon.

1 Like