Download

How to recognize, is current client the owner of this actor into a OnRep_- method?

ActorGun is spawned dynamicly.
By SetOwningPawn(..) the MyPawn is set as owner.
On every shot I call method (on Server), which changes property of ActorGun, named ‘LastShotInfo’.
This prop. is declared such way:


    UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_LastShotInfo, Category = "Shot")
    FLastShotInfo LastShotInfo;

FLastShotInfo here is the USTRUCT type name.

LastShotInfoinside AActorGun::GetLifetimeReplicatedProps(..) is added without any conditions:


    DOREPLIFETIME(AActorGun, LastShotInfo);

So, I expect, method OnRep_LastShotInfo(..) will be called on every relevant (e.g. located <= some distance) client every time the LastShotInfo property is changed.

This method I’ve defined such way:


void AActorGun::OnRep_LastShotInfo()
{
        PlayShot(); //! plays cosmetic

        if (Role == ROLE_AutonomousProxy) 
        {
            OnShot.Broadcast(); //! signal to current client UI to redraw some effects.
        }
}

I want the OnShot.Broadcast() to be called only on owning client to redraw UI only for player, who have did this shot
BUT! this broadcast is never called =(
Every time, I fall inside OnRep_LastShotInfo(..), the Role is == ROLE_SimulatedProxy.

Why is it so?
How can I separate unique logic for owner client only inside the OnRep_LastShotInfo() method?

You may try to check if GetOwner() of a weapon is your local PlayerController, assuming that SetOwningPawn also calls SetOwner(Pawn->GetOwner());

Well first of all you need a way to identify which specific instance of the weapon LastShotInfo represents. Otherwise you can’t figure out which player to notify at all. The best way to do this would be to add a condition to the Replication Struct, such as COND_OwnerOnly. Of course, that won’t work for the Server since that event will never fire there, it’ll only fire on clients.

Or, you can specify a weapon in LastShotInfo and compare it to *this when it arrives, to figure out if it’s for the local instance of the weapon or not. If it is, you can broadcast to the local player via this:



GetOwningPawn()->IsLocallyControlled()


However, you shouldn’t need to at that point anyway since you know who the weapon belongs to, you’ll have eliminated it. Then again, you are currently replicating LastShotInfo to everybody which may contain a lot of redundant data for other clients. If it does, split it up.

TheJamsh, thank you!
I can’t use COND_OwnerOnly for LastShotInfo , 'cos this prop. contains all necessary information for playing visual effects on all clients, who sees my pawn.
Do I understand correct?: comparing ptr to weapon with this will return true on all clients & server. It is needed only to find out, for which one of all weapons of all pawns on the level this concrete replicating LastShotInfo is relevant? If so, I think, I need not to do this check, 'cos OnRep_LastShotInfo(..) method is declared in this ActorGun (my weapon class), so identification of concrete weapon is done automaticaly.
Thank you very much for GetOwningPawn()->IsLocallyControlled() solution. It is exactly, what I was looking for!

PS: But I wonder, why if (Role == ROLE_AutonomousProxy) doesn’t work in expected by me way (doesn’t do the same)?

What it may be worth doing in that case is splitting up the LastShotInfo struct into information that’s relevant for all players, and information that’s relevant only for owner players and replicating them both separately with or without conditions. In the long run you’ll probably save bandwidth using that method. A good practice I’ve found for networking code is you can almost always trade a bit of extra code and potentially some CPU time for better Bandwidth usage, since that will almost always be your biggest optimization area.

What I meant above btw was you do the ‘this’ pointer comparison, then if that’s true you do the LocalPlayer check too. ‘This’ will indeed return true on clients and server, but it’ll isolate the actual instance of the weapon you’re referring too so the IsLocallyControlled() check becomes useful. Otherwise all of the weapons will do that bit of code inside regardless.