Calling RPC functions inside a UObject

I have often seem times where people want to call RPC functions inside a UObject that has an outer of AActor, for example a Weapon Actor, could have a FireMode UObject that wants to send RPCs. As long as the Weapon Actor is Owned by an actor that goes back to a PlayerController (for example the player pawn/character), then we can do RPC’s, issue is UObjects do not know how to route these RPC’s. Below i have a bit of code i have used to allow RPC’s to execute inside UObjects.

bool UMyObject::CallRemoteFunction(UFunction* Function, void* Parameters, struct FOutParmRec* OutParams, FFrame* Stack)
{
    if (AActor* OuterActor = Cast<AActor>(GetOuter()))
    {
        UNetDriver* NetDriver = OuterActor->GetNetDriver();
        if (NetDriver)
        {
            NetDriver->ProcessRemoteFunction(OuterActor, Function, Parameters, OutParams, Stack, this);
            return true;
        }
    }
    return false;
}

int32 UMyObject::GetFunctionCallspace(UFunction* Function, FFrame* Stack)
{
    if (AActor* OuterActor = Cast<AActor>(GetOuter()))
    {
        return OuterActor ->GetFunctionCallspace(Function, Stack);
    }

    return FunctionCallspace::Local;
}

So let us break this down a bit. CallRemoteFunction will be called when the RPC is fired, thing is we need to route this through an actor, which hopefully has an owning connection. We can not guarantee this, but what can we do?. If our outer is an Actor, we can then grab the NetDriver from that actor, and if that happens, we can then pass our remote function through that net driver.

The second bit, GetFunctionCallspace is the callspace in which we want to call the function, there is 3 possible callspaces, but we don’t want to determine that here if we have an outer actor, we can let that determine it, so we just pass it along. If we don’t have an outer Actor, then we know its local, and we can just return that.

With all that said and done, you should now be able to execute RPC’s from a UObject with an outer than ends up with an owning connection. Hope you find this useful.