I spent all day yesterday working on replication for my game, and the more I learn about it, the more I absolutely despise it. Do I really have to send a bunch of requests to the player controller and have it interface back to the object for every single thing I need replicated? It seems not only tedious but also likely to bloat the player controller with countless server and multicast events. Plus, I’ll need to create interfaces for every type of thing I want to replicate. There has GOT to be a more efficient way to handle this—game development is already tedious enough. If anyone has any tips or pointers, I would greatly appreciate it.
For example, I’m struggling with actor spawning when the actor has an instance-editable variable exposed on spawn. How am I supposed to handle that without creating a specific event in the player controller to spawn the actor on the server and set its variable?
Any Actor and its Components that are Spawned by the Server and given the Owner of a specific Client allows that Client to call RunOnServer RPC’s on the Actor. This is how Pawns and Characters that are possessed allows the client to give move commands for example.
It doesn’t have to be a Pawn though it can be any Actor that has a specific Client as the Owner.
Generally you want to avoid Net Multicast in favor of OnRep Variables except for Sound or visual effects.
Can you give more details on what your exact implementation is and what’s causing the frustration? Certainly developing for MP comes with it’s only layer of complexity. Poor design can complicate it even further. It is true though that you will find yourself pushing functionality at some point into either the player controller or pawn as a means to reach the server from a client. That is not uncommon. While you can limit this with good design you can not completely do away with it.
As a simple example, consider an interaction system. Imagine you have a lot of different objects in the world you wish to interact with and none of them can be owned by the PC or pawn. You have no choice but to go through the PC/pawn in order to interact with said object. Now a poor design would be to have a different interaction function for each individual object type…or you can have a base interactable actor class which implements an “interact” interface function. You then could have a single server RPC in the PC/pawn to interact with any of your objects that inherit from the parent interactable actor class.
Yeah, thanks! So, I’ll need to create several custom events that run on the server in my player controller, which will then send interface messages back to the actor, right?
Really depends on your project. What I do in mine might not mesh well with yours.
I’m doing open world looter shooter. To loot items, open/close doors, work with elevators, enter vehicles etc I have a single input event that executes interact logic.
The client does a trace. If the hit returns a result it checks if that actor is interactable. If so it RPC’s the server to Interact. Server executes the same exact code. I use a branch to allow it to further step through logic. If the actor is interactable, determine its type (Gameplay Tag C++ implementation), then execute either a BP Interface call on the actor (Doors, lifts, elevators) or an actor component function (Enter vehicle, pickup item etc).
This maintains server authority in the game world and reduces code bloat.