RPC from actor which is owned by player controller

Hey guys,

I need your help. I can’t quite get my head wrapped around the whole replication thing, so please bear with me.

I have created an actor which inherits directly from AActor. Let’s call it node. The node is an actor which has already been placed in the map and has bReplicates and bNetLoadOnClient set to true.
The node has the following methods defined:

node.h

UFUNCTION(BlueprintCallable, Category = "Node")
void DoStuff(APawn* character);

UFUNCTION(Reliable, Server, WithValidation)
void ServerDoStuff(APawn* character);
virtual void ServerDoStuff_Implementation(APawn* character);
virtual bool ServerDoStuff_Validate(APawn* character);

the node implements the following:

node.cpp

void ANode::DoStuff(APawn* character){
    if (Role != ROLE_Authority)
    {
        ServerDoStuff(character);
    }
    else if(Role == ROLE_Authority){
        SetOwner(character);
        //spawn another actor which replicates
        SetOwner(nullptr);
    }
}

void ANode::ServerDoStuff_Implementation(APawn* character) {
    DoStuff(character);
}

bool ANode::ServerDoStuff_Validate(APawn* character) {
    return true;
}

Now the thing is, when I trigger the execution of that code on the server. everything works just fine. A new actor will be spawned on the server which replicates to the client.

If I call the code from a client, DoStuff will be called and the code branches correctly into ServerDoStuff, however nothing will be called after that. I set breakpoints into ServerDoStuff_Implementation, ServerDoStuff_Validate and DoStuff but the code in there will never be called.

The APawn Pointer is a “this” reference from within the executing character which inherits directly from ACharacter. Might that be an issue?

character.cpp

node->DoStuff(this);

At first I did not set the owner, which resulted in a console message which told me that the RPC will be ignored since no owner has been set. Now that I have set the owner, no more errors or messages are displayed. Just nothing happens.

If I change the method to “Multicast” all methods will be called and executed as expected. But I don’t want a multicast here, since the client would create its own instance of the spawned actor, right?

Any idea as to why nothing happens, or what I did wrong?

Thanks for your help!

Cheers
Edregol

Hi,

I have had actually ran into this problem myself.

Your problem here is that as Server RPCs will only be run if it is called from the “Owning client”, whereas Multicast will run on the client even if it’s not the owning client. I’m sure you’ve found this out. But, you are setting the owner if Role == ROLE_Authority, but if you call DoStuff not with ROLE_Authority, it won’t run the if statement code for setting owner. The problem then is that you can’t set the owner from the client, because it doesn’t have authority.

Solution

If your “node” variable is a “private” variable, meaning only one character have reference to it, then all you have to do is to attach the actor to your actor in the constructor, thus having your character owning it.

However, if your “node” is a public Actor that all clients can use, then it is very messy. Basically you need the RPC functions inside your character class (or I prefer the playercontroller class because it has less things). Then when you call Node->DoStuff(Player) on the client, the Node will call Player->ServerDoStuff(…), which then calls the Node’s DoStuff, but this time the call will be on the server.

I hope this helps, if you don’t understand my explanation then I can give a few examples.

: )

1 Like

Thank you!
That makes sense. However is kinda counter intuitive to transfer the logic from the node into the player controller to call RPCs on the server to call the node’s method on the server side, to then replicate stuff to the client again.
I bet you can tell my node is a “public” actor. :smiley:
I was hoping there is another “cleaner” way to accomplish what I wanted to do.

However, thank you for your clarification!

Cheers,
Edregol