Hey, I’m attempting to create a typical character selection screen where the only local player sees the character they’ve selected. I need these to be replicated for other reasons so only spawning them locally is not an option. However I’m having trouble figuring out how to hide the actors on all other clients except the local one.
What I’ve got so far:
Player clicks the Character Icon in the UI and the selected character class is sent to the player controller.
At this point each players character appears on every other players screen all on top of eachother.
I read the way to do it is by using actor ownership, but I’m not entirely sure how I’m supposed to link the spawned actors to each player controller, when they are all spawned on the server
It results in all the characters becoming invisible on the server, and nowhere else.
I guess my question is, in a setup like this, how would I link each player controller as owner of their spawned actor? Or simply are there better ways of doing this?
The problem you’re having here, is that by design not all properties get replicated. If you do something like hide a mesh component, that will only happen on the machine where that code executed.
I believe, however, that there is a flag on every actor bOnlyRelevantToOwner, which will cause that actor only to replicate to the owning client of that actor, which is probably what you want. Set that on the server and the actor won’t get replicated to non-owning clients of that actor.
It’s been a while since I’ve used Listen Server (I normally work on games that use Dedicated Server), so I’m not 100% sure what that will do for the host’s view of the world, you might need to still set bOnlyOwnerSee on the host so that they don’t see actors. Try it first without that and see what happens.
Just to be complete, another way to do this, potentially, is with Replication Graph. It should be possible to temporarily stop an actor from being spatially replicated, and have them replicated to specific connections only. But honestly, I really wouldn’t mess with that unless you really know what you’re doing. It’s overkill for this situation. Though it’s worth mentioning if you’re basing your game on ShooterGame, that ShooterGame uses ReplicationGraph by default (I think), which will stop bOnlyOwnerSee from working if I remember correctly.
Thanks for the reply,
Unfortunately OnlyRelevantToOwner stops the Actors from replicating alltogether which is a problem for me because I need them to be referenced by other clients.
My main issue is that I don’t understand how I can link each Actor to the player they belong to. How do I make a certain player owner of their respective actor when they are all spawned on the server?
I might have stumbled on to something here, but when attaching the spawned Actor to the player controller that spawned it, it kind of works. The clients show only the Actors they are supposed to but then the server is still showing all of them…
Where the local PlayerID is compared to the PlayerID of the client who selected a character, then I just hide/show the actors based on if they are the same client or not
Firstly, that when you say you’re spawning the character, you’re just changing the pawn class of that player and respawning their pawn. (Which gets you all the ownership stuff for free without having to do anything). If you’re just spawning an actor manually, and want that actor to be considered to be owned by a particular player, then that actor needs to be ultimately owned by that player’s PlayerController (Call SetOwner). The object doesn’t need to be directly owned by the PlayerController (It can be owned by an object that is itself owned by the PlayerController), but the chain of ownership ultimately has to end with a PlayerController.
I also assumed that another player’s selected character doesn’t really matter to other clients, hence the relevancy suggestion. Generally speaking, if you want a player to know information about another player, the PlayerState is the place to store that.
With regard to uniquely identifying players, unless you have some kind of platform-specific ID for that player (like the ID of their Steam or Epic account), it’s probably better to use the PlayerState. If you use that player’s name, then you’ll likely run into issues further down the road if you want to allow players to change their name in game. (Players could also potentially break the mapping using the setname console command). For GetPlayerState to work on a Pawn though, you’d probably have to use the normal pawn spawning flow, or call SetPlayerState on the Pawn (on the server, so it’s authoritative)