Save to send APawn* over RPC?


I can declare a function

UFUNCTION(Server, Reliable)
virtual void ServerSendPawn(APawn* Pawn);

and then send a specific pawn from the client to the server. This seems to work, but is it safe to do this? What will happen e.g. if that pawn was already removed on the server but the client did not receive that update yet? Will the server receive a nullptr?

What about performance? Is this internally only using the guid or does it use more bandwidth than just sending an actor id and then find that actor by id on the server?

Background: I want to tell the server which pawn is the current target of my player when he initiates an attack.

Yes, UObject pointers are safe to send over the network in most cases. Under the hood engine indeed does send only network GUID reference. So if the object will be destroyed on server by the time it receives the RPC, the pointer received will either be nullptr, or IsValid() for that object (that you definitely should check before using it) will return false, if the object still exists, but is pending to be killed (garbage collected)

Thanks for the clarification and the info on IsValid()! I will make sure to use it.

Hey I see IsValid() does not exist on the Actor in C++. Were you refering to IsPendingKill?

IsValid() is not a function of Actor, it is a engine function declared in CoreUObject module.

You call it like this:

void SendPawnToServer(APawn* Pawn)
     If (IsValid(Pawn))
         // Do your thing
1 Like

Replicated objects are safe to send references across the network, via replication or RPC. Other than replicated objects, you can reference things that meet the requirement IsNameStableForNetworking which is a UObject function in C++ that checks whether an object basically has a stable enough path name to be network referenced. Static elements of a map for instance typically have stable names which allow you to reference them via network.

If you do advanced programming with custom UObjects and such, it’s helpful to do some debug logging at least to catch circumstances where you expect to network a reference to something that returns false from IsNameStableForNetworking. If you are working with components specifically, use IsSupportedForNetworking(), which checks the replicate flag and IsNameStableForNetworking.

For situations where you have custom UObject derived classes, these can still be networked referenced provided you replicate the objects via your components ReplicateSubobjects, and those objects are effectively children of your replicated component, giving them a stable name for their lifetime.

For instance, in my UInventoryComponent, I have a custom UGameItemInstance : public UObject set of classes that network the details of inventory items. These are replicated via my UInventoryComponent::ReplicateSubobjects, and when items are added to the inventory, these item instance classes use NewObject with the inventory component as their Outer.

If you drop an object, and thereby need to move that item instance to another actor or whatever, you can’t just assign that reference into the new inventory component, you need to relocate the object to a child of the new object/inventory component. I use DuplicateObject, though you can also theoretically use UObject::Rename to give the object a new outer parent reference.