We used to replicate FAmmoCapacityFragment for all entities and relied on that to update player's ammo HUD but that approach was very inefficient as really only the player needs to know about their own soldier's FAmmoCapacityFragment. So we disabled replication of FAmmoCapacityFragment. To replicate more efficiently I'm thinking of the following approach but open to other ideas:
[x] In AProjectM_PlayerController add a replicated UPROPERTY FAmmoCapacityFragment PlayerAmmoCapacityFragment. Make it protected and add a public getter FAmmoCapacityFragment* GetPlayerAmmoCapacityFragment().
[x] In AProjectM_PlayerController::Tick, call GetCurrentHumanCharacter() and if it's not null, set PlayerAmmoCapacityFragment = FMassUtils::GetFragmentForActor<FAmmoCapacityFragment>(CurrentHumanCharacter). Note this is not very efficient but as long as we have a small number of human players per server (which we will for a while) it's fine.
[x] In UMassWeaponBlueprintLibrary::GetAmmoCapacityFragmentForActor we should check if we're on client net mode, and if so we should check if the Actor is the player's human character. You can figure this out by: World->GetFirstPlayerController<AProjectM_PlayerController>()->GetCurrentHumanCharacter() == Actor. If that's true, it means we're trying to get the player's ammo capacity fragment on the client, which isn't replicated. So we should read it from the player controller instead: PlayerController->GetPlayerAmmoCapacityFragment().
[x] To verify, in client net mode shoot the player's weapon and confirm it correctly updates the ammo HUD.
[x] Verify in standalone net mode we still update ammo HUD correctly.
[x] Verify in Network Profiler we don't replicate the PlayerAmmoCapacityFragment property on PlayerController when we're not shooting.
We used to replicate FAmmoCapacityFragment for all entities and relied on that to update player's ammo HUD but that approach was very inefficient as really only the player needs to know about their own soldier's FAmmoCapacityFragment. So we disabled replication of FAmmoCapacityFragment. To replicate more efficiently I'm thinking of the following approach but open to other ideas:
FAmmoCapacityFragment PlayerAmmoCapacityFragment
. Make it protected and add a public getterFAmmoCapacityFragment* GetPlayerAmmoCapacityFragment()
.GetCurrentHumanCharacter()
and if it's not null, setPlayerAmmoCapacityFragment = FMassUtils::GetFragmentForActor<FAmmoCapacityFragment>(CurrentHumanCharacter)
. Note this is not very efficient but as long as we have a small number of human players per server (which we will for a while) it's fine.World->GetFirstPlayerController<AProjectM_PlayerController>()->GetCurrentHumanCharacter() == Actor
. If that's true, it means we're trying to get the player's ammo capacity fragment on the client, which isn't replicated. So we should read it from the player controller instead:PlayerController->GetPlayerAmmoCapacityFragment()
.