(Question) NetCode How to Identify Local Player

Hello,

I am fairly new to the data oriented approach and I have been watching all the available tutorials and looking at the DOTS example project. But I am still having trouble understanding all the concepts of it.

How would you go about identifying which of the entities with LocalPlayer data component is the player for that connection? Basically if I wanted to do specific logic to it such as coloring its mesh a different color.

I have this code that spawns the network players,

[UpdateInGroup(typeof(ClientSimulationSystemGroup))]
public class GoInGameClientSystem : ComponentSystem {
    protected override void OnCreate() {
    }

    protected override void OnUpdate() {
        Entities.WithNone<NetworkStreamInGame>().ForEach((Entity ent, ref NetworkIdComponent id) => {
            PostUpdateCommands.AddComponent<NetworkStreamInGame>(ent);
            var req = PostUpdateCommands.CreateEntity();
            PostUpdateCommands.AddComponent<GoInGameRequest>(req);
            PostUpdateCommands.AddComponent(req, new SendRpcCommandRequestComponent { TargetConnection = ent });
        });
    }
}

[UpdateInGroup(typeof(ServerSimulationSystemGroup))]
public class GoInGameServerSystem : ComponentSystem {
    protected override void OnUpdate() {
        Entities.WithNone<SendRpcCommandRequestComponent>().ForEach((Entity reqEnt, ref GoInGameRequest req, ref ReceiveRpcCommandRequestComponent reqSrc) => {
            PostUpdateCommands.AddComponent<NetworkStreamInGame>(reqSrc.SourceConnection);
            UnityEngine.Debug.Log(String.Format("Server setting connection {0} to in game", EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value));
            var ghostCollection = GetSingleton<GhostPrefabCollectionComponent>();
            var ghostId = ShooterGhostSerializerCollection.FindGhostType<PlayerSnapshotData>();
            var prefab = EntityManager.GetBuffer<GhostPrefabBuffer>(ghostCollection.serverPrefabs)[ghostId].Value;
            var player = EntityManager.Instantiate(prefab);

            EntityManager.SetComponentData(player, new LocalPlayer {
                PlayerId = EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value,
                playerEntity = player
            });
            PostUpdateCommands.AddBuffer<MovementInput>(player);

            PostUpdateCommands.SetComponent(reqSrc.SourceConnection, new CommandTargetComponent { targetEntity = player });

            PostUpdateCommands.DestroyEntity(reqEnt);
        });
    }
}
EntityManager.SetComponentData(player, new LocalPlayer {
    PlayerId = EntityManager.GetComponentData<NetworkIdComponent>(reqSrc.SourceConnection).Value,
    playerEntity = player
});

That basically spawned a character with your network ID. With that network ID, you can now reference it in your code with something like this:

[UpdateInGroup(typeof(ClientSimulationSystemGroup))]
public class YourSystem : SystemBase
{
    protected override void OnUpdate()
    {
        // Should define RequireSingletonForUpdate<NetworkIdComponent>() in OnCreate
        var localPlayerId = this.GetSingleton<NetworkIdComponent>().Value;

        this.Dependency = Entities.ForEach((Entity entity, in LocalPlayer localPlayer) =>
        {
            if (localPlayer.Identifier == localPlayerId)
            {
                // do your player specific thing
            }
        }).Schedule(this.Dependency);
    }
}
1 Like

Oh I see! Thank you very much!

Im not familiar with Dots Netcode, but I think this case can be handled by the normal Data oriented design Which is adding a CD Tag LocalPlayer for your local Player Entity.
This way you can easly access that specific entity and prevent useless iterations and verifications, Specially if you have a lot of players.

1 Like