I am currently working on a interaction system for a networked game and I have come to hit a snag - mostly due to the lack of knowledge with Netcode for entities, so I am hoping someone can clear my misconceptions, or guide me in the right direction.
Current Setup:
Use OverlapSphere to find all entities that the user can Interact with, and generate a list - that is then shown on a ui, the ui can pick a interaction to execute from this list.
The user can then select a interaction to execute.
The way I made that work is by using IEnabledComponent that when its true, gets caught in a system for that specific interaction.
Client System: This systems are currently running in SimulationGroup
if (physicsWorld.OverlapSphereCustom(intereactionCheckPosition, intereactionRadius, ref hitCollector, characterComponent.ValueRO.Interactables))
{
foreach (var hit in hitCollector.AllHits)
{
//Get Interaction Component
if (!SystemAPI.HasComponent<InteractionComponent>(hit.Entity))
continue;
var interactionComponent = SystemAPI.GetComponent<InteractionComponent>(hit.Entity);
var position = l2wComponentLookup[hit.Entity].Position;
interactions.Add(interactionComponent);
if (Input.GetKeyDown(KeyCode.F)) // This is to be changed by UI picker, since we can have a list of interactions
{
Debug.Log($"{interactionComponent.InteractionName}");
SystemAPI.SetComponentEnabled<InteractionComponent>(hit.Entity, true);
}
}
}
Somewhere else there is another system:
var ecb = new EntityCommandBuffer(Allocator.Temp);
foreach (var (powerInteraction, interaction, entity) in SystemAPI.Query<RefRO<PowerInteraction>, RefRO<InteractionComponent>>()
.WithAll<InteractionComponent>().WithEntityAccess())
{
var rpc = state.EntityManager.CreateEntity();
ecb.AddComponent(rpc, new SendRpcCommandRequest { });
ecb.AddComponent(rpc, new SendPowerInteractionRequest
{
Target = interaction.ValueRO.Entity // Entity this interactions applies to
});
ecb.SetComponentEnabled<InteractionComponent>(entity, false);
}
ecb.Playback(state.EntityManager);
And I have a Server System that listens to that RPC and executes the action. That works for simple actions, for example change GhostField value.
Problem
Problem is, how do I handle prediction on the client side? For example, lets say one interaction is to Kick a ball (rigidbody) around, I would like that the client does not need to wait for the round trip - so it would predict the interaction.
Is the idea, that the interaction system runs in the Predicted System Loop, and it applies the force on the client side, and the server will then hopefully do the same? This has the downside that Server Code and Client code would be slightly different, since the server uses RPC to trigger the action, and client will just straight up apply the force? - Is this even the case, or should the client not even apply the force at all?
How would I organize such a system?
There will be a large number of interactions - but they are low frequency, hence the RPC nature I tried.