Spawn Player for Multiplayer Top-Down

Hey guys,
I searching all over the web for a good answer.
How to propertly spawn a player character while possessing him with an AI controller, AND keep the corrent ownership of each player character.

I’m asking because I’m having some problem with my implementation.
I’m spawning a junky pawn as the default pawn, then in the player controller OnPossess event, calling a server function from the GameMode that actually call SpawnActor and everything.

After that, I’m setting the owner of the character to the player controller and then possessing with the AI Controller the character.

Each client is correctly controlled and it’s working fine. I can move with the client and server individually.
But I’m having some issues at different places when using RunOnOwningClient RPC.
Also for example, I have an Niagara effect when the character is ready to play - the server fire the effect once, the client fire it twice. But there’s only 2 characters visible.

So I can’t understand if that’s the correct way. Because a working code is fine, but the right code is better.

If anyone have any advices that would be great!

yeah if its possessed by AI then the client wont “own” it so you cant do runonclient events.

you could pass a player controller ref to the character and run the event through that

otherwise the way i do it is i have input commands on the controller that do server calls and the server tells the AI.

for the niagra effect you just need a server multicast. currently you’re spawning it on both server and client which is why the client gets two copies

So from my understanding, the server ownss the AI Controllers so I would need to call alot of Server RPC calls. Isn’t it going to be heavy? would it cause lags?

As for the effect, this is exactly what I’m talking about “Weird bugs”.
I do call RPC multicast. It’s RunOnServer → NetMulticast to Spawn Effect.

That what I cannot understand, there’s a paradigm change about the server and the owning client because it’s different now in my project.
But I can’t understand what exactly should I change.
I tried only Server RPC, tried non replicating, tried using has Auth and locally controlled.
No mather what I do it always fire twice (calling it from PlayerCharacter BP).
Although calling it from the PC directly do call it once for each which is good, but my question is why it’s like that?

If in the past Server → Multicast worked (for the effect for example), then what should it be now? Only the server? own client maybe through the PC?
This is so confusing, Epic.

ActorComponent are the most confusing to me. What used to work (RunOnOwningClient) doesn’t work now. For example, creating a widget on OwnClient RPC (called from Server first) from the AC, only works for the server.

so whats your setup with the AI pawn? if your doing input why need AI and if your doing AI why need input? as opposed to say aimoveto

actor components use their owner authority so you can run RPCs if they have permission.

how are you creating the niagra effect? if your spawning something its possible the spawn replicates which means you wont need a multicast

I’m using an AI controller to have AIMoveTo work. For a Top-Down game.
I need to have a PlayerController that isn’t possessed with the same pawn, so possessing with AIContorller solved the problem.

The niagara effect is in the character, I have a C++ which is the BasePlayerCharacter, with a UNiagaraSystem (the effect), this variable is replicated.
I’m spawning the character, then in begin play running some logic, and calling StartSpawnEffect with the niagara system that i’ve set.
The only way a successfully spawn the effect once for each player, is calling a SpawnSystem from the PlayerController as an Multicast event.

So ActorComponents, have the same server/client logic like a player pawn?

no performance problem on the ai then, you wont be inputting movements on tick or anything

no actor components have the same logic as the owner, so if its on the player pawn then yes but if its on the ai pawn then itll be considered server owned

the niagara could be because begin play runs on server/client maybe try a switch has auth before starting the effect? just guessing here as thats hard to visualize without code

Well, tried that here:

The result was it spawned only twice, one for each player, BUT only on the server.
The client didn’t saw the spawn effect.

This event is called on the BeginPlay of the character and the declaration also in the same BP characer.

Using OwningClient RPC with HasAuth: Not visible at all on both of them.
Using OwningClient RPC w/o HasAuth: Fire twice only the client see.

Using RunOnServer RPC with HasAuth: Once on the server, twice on the client.

Using Multicast RPC without HasAuth: The closest - Once for server (both can see), twice for client (both can see).

Then only place that works perfect is to call that same event just from the PC to the player character BP. without any RPC and NOT replicating the variable of the niagara system.

Edit:
Finally got it to work as I wanted. You were right, just calling HasAuth before starting the effect and that worked perfectly. Didn’t got it at the start, needed to learn a bit more.

About seperated actors, like an enemy for example.
A UserWidget is local owning client only.
In that case, I have a UserWidget component attached to the enemy character BP.
That user widget, visible when this enemy get damaged using the AnyDamage event which is only server.

So the result is that only the server can see that widget. But I want only the local player to see that widget.

The owner is the enemy character, which has it’s own AI controller of course. So how I supposed to display only to the local player?
At the end I would have every single code located on the PC which is owful.
The logic says that if it runs on the server, like native damage event, how does the clients show possible recieve that events also ?

I can’t figure out the logic that Epic decided to take with this replication rules. So confusing and some much work just to show or hide things.

well if you want everyone to see something then a multicast is fine but if you only want one player to see it then it does get tricky.

if you have ownership you can use ‘onlyownersee’ but in this case we dont since its AI owned.

the way i do it is to have a list of players you want to see it and send and PRC to the player client, so if only the ‘owner’ save a ref to the ownerplayercontroller on the actor