#multiplayer
1 messages · Page 112 of 1
The only thing I've thought of that is really useful for game mode is that it can be excluded from client builds in games that will be running exclusively on dedicated servers that you don't distribute, so if you have some logic or values that you don't want to distribute, you could put it in the game modes and exclude them from the packaging - obviously not all game modes can be excluded, you'd still need at least one for the player to start the game up, but you wouldn't have to include ones that you don't want distributed as they'll be running on your servers.
Everything other than handling players joining and spawning their default pawn could technically be handled by any other actor, it's all a matter of how you want to handle the communication to those actors and whether or not you want to have a somewhat easy access to the actor holding the values (ie. Get Game Mode/Get Game State)
Thanks @sinful tree things are slowly clicking together tonight, I'm sure it will all make more sense once I start putting more of it into practice, certainly a bit of a mentality shift compared to single player experiences.
How can I teleport a player to a specific spawn location, so for example p1 always spawn in the same location as well as p2
This is for a round system
Why not spawn them at that specific spawn location to begin with rather than teleport them there?
If you're doing something like Restart Player, you could use "Restart Player at Start Location" and select the appropriate actor to use for the start location, or "Restart Player at Transform" and feed in a location directly.
I'd like to do this too
So that the player always spawns in a certain spawnpoint depending on the player number
Gamemode::ChooseStartLocation or something like that
just override it and put your logic in there
What's more performant in terms of networking? 50 different actors each with a single component, or 10 actors each with 5 components?
So get gamemode then cast, then start location?
@unkempt tiger no idea but there is a network profiler tool available which might give you the answer https://docs.unrealengine.com/5.2/en-US/using-the-network-profiler-in-unreal-engine/
it looks like AActor::OnPossessed is server side, is APlayerController::OnPossess also server side only? what would be a good way to implement client side logic at the same time?
Pretty sure OnPossess on player controller runs on client too. Nope
There's also ReceiveControllerChanged on Pawns.
just used beginPlay, which is working atleast for now, saw on the network compendium it occurs on both client & server
Run as seperate processes
Max Step Height on the CMC set too low?
Server can smoothly step on. And the weird things is I can step on the right buildings but not the left buildings.
I think it is related to the bp generated instanced mesh
The room bp is copied from the sample project in market place
Is the Actor that this Mesh is in replicated?
Now I don't rotate it , I just size -1 it . I can step on it now.
no , it's not replicated
Sure. I can try
Iirc there are some issues for the CMC to figure out the Base you are on if the actor has some generated/spawned mesh and isn't marked as replicated. But this is just a shot in the dark
no, set it to replicated not work. but size -1 work.
The first room was rotated. The second room set x to -1.
You mean the generated instanced static mesh component should all set to replicated?
Hm no I think the actor is enough
Hm
Your log says it can't resolve the base actor
Which usually means the Actor you are standing on and the component of it have trouble syncing between server and client
A mesh placed into the level for example works fine but if you runtime spawn it it might not be able to resolve
You could try marking the component as replicated but I don't think that helps :/
Yes I tried, it does not help.
My current understanding of how to make rpcs is to make a custom event, call it from another custom event so the client gets around the wall stopping clients modifying servers and calling that event from the keybind, input, whatever. Is this wrong or right? What improves upon this?
Not entirely sure about what you are describing here
Making RPCS
You make an RPC in BPs by making a Custom Event and setting it to the type of RPC you want
Not sure about the rest of your message
Yes for server to client
But what is the usual way people make client to server
Yeah, there are some rules around this
Client Input > Run On Server RPC > Server does things based on client input.
Which you can read about in the Compendium that is pinned
I was unsure if it was still recent or if the systems were changed
is net load on client checked?
Any events marked as "Run On Server" can technically be called at any time by a client on an actor that they are owner of. It's like you're opening the door for a client to call to the server to do something and is a requirement in order for the client to request the server to do something. So, to prevent cheating, you want to limit the number of Run On Server events as best you can, don't have Run On Server events call other Run On Server events (this can allow players to skip part of your process), limit the amount of data that you accept from a player (ie. Your events can have inputs, just don't let the client fully dictate all the data, the server can figure some of it out on its own) and validate on the server if the client should be performing the action in the first place. Some events should never be allowed to be called from a client, like a "Kill Actor" event that passes an actor reference that then calls a "Destroy Actor" node on the server.
maybe try unchecking it if is and make that mesh replicated
I cant get problem pls help
If just host join server nothing happens but if join anybody other it gives error
add, update players names and update level selection give error
Hey people, would anyone be able to answer a question about replicated timelines and how costly they are in terms of network usage?
sorry let me rephrase that,
How costly are replicated timelines?
Not very
Downside is they update constantly and are quite jittery
Not completely unusable though
Actually saying that, I think the playback is actually ok
yeah i havent noticed any iddues with playback
Yeah, the timeline doesn't apply the replicated position until start/end so it's alright really.
im mostly concerned with the potential problems that could be caused by lots of doors in a level being updated simultaneously
ahh thats what i thought it might be
Should be fine to be honest. A combination of a low net update raw and/or dormancy would be fine for a fair few doors
Literally just did a door thing last week, I didn't use timelines though - I have a "state" and a server timestamp the door entered that state.
yeah that was another way i was considering
Our doors are pretty simply though, just simple rotation/translation animations from curves
mine are super debug atm, just rotating the z axis of the mesh dependent on the output float track from the timeline
yeah, similar to what I'm doing, just no timeline.
im guessing seeing as they only update at start/end they use some form of prediction to work out the space in between?
Yeah, relevancy is a problem for us especially with doors with long opening times etc, so the animation fast-forwards a bit depending on the timestamp
Relatively simple setup though:
{
// NB: This will fail to resolve a timestamp if GameState has not yet replicated, so we also call this from BeginPlay() where it *is* garaunteed to be valid.
const float* TimeSinceStateChanged = DoorState.ServerTimeSince(GetWorld()).GetPtrOrNull();
if (TimeSinceStateChanged != nullptr)
{
const FName UnpackedState = NetIndexToState(DoorState.GetState());
if (DoorState.GetTimestamp() <= 1.f)
{
// "Default" state
DoorController->SetStateImmediatte(UnpackedState);
}
else
{
// Avoid fast-forwarding within small time discrepancies
static const float SkipFastForwardThreshold = 0.75f;
if (FMath::Abs(*TimeSinceStateChanged) <= SkipFastForwardThreshold)
{
DoorController->SetState(UnpackedState);
}
else
{
DoorController->SetState(UnpackedState, FMath::Max(0.f, *TimeSinceStateChanged));
}
}
}
}```
SetState takes the state + some base time offset to fast-forward to through the curve based on how long it's been.
Or it the door opened like 30 minutes ago and only just became relevant for you, it'd be in the right state.
Each state specifies the "time" the curve needs to be at for the door to be in said state
Some collision shenanigans.. quite straightforward though
thanks for the help i appreciate it
Oh this relies on GameStateBase::ServerWorldTimeSeconds btw - which is not the greatest clock but totally viable for simple stuff like this
Hey Guy's any one have idea how can i Terminated the AWS Gamelift Game session i looked for every where but can't find how to stop the session can some one help it's import to me.
Can anybody help me about it
you will need to do that with a class that isnt destroyed when leaving
here another things about it
I have done some similar work. I have an energy shield which has an activation and deactivation function. I use timeline to set the opacity of the material of the shield. but client visual effect is always lagging, and start from the middle.
i use multicast function to trigger the timeline.
Does net relevancy also extend to components? E.g can there be an actor with component A thats considered net relevant, and component B thats not considered net relevant? Or is the concept of net relevancy apply to actors alone?
sounds like your triggering off the timeline from the server on the clients. mine runs the timeline on server and replicates to the client
On UWorldSubsystem::ShouldCreateSubsystem(), how can you know that the game is running server or client side?
@blissful talon With great difficulty:
https://github.com/TheJamsh/UnrealSnippets/tree/main/Code/World Subsystem
James you're on fire today with these code snippets of you, thanks indeed! ❤
Only applies to actors
So components will have the same net relevancy status of its owner actor
Oh, awesome, thank you!
Is there a way to easily see how many players the server is expecting after a seamless travel? (So the game waits for all of those players to do X before starting) I currently have a super janky sollution with an options string and getting player states before the travel but I feel like I remember seeing something native.
i suppose i could override PostSeamlessTravel and get the old controller array to wait for them to load. This might be the best way of doing it, though i still feel like I remember an easier way. Anyways, i suppose ive solved it myself, but if anyone has any pointers it would be much appreciated!
Guys, I'm wondering something.
I am doing RunOnServer and adding 1 to an Integer variable. The Replicated of this variable is true.
Shouldn't this action take place on the Server that creates the host? But this +1 operation is done on whoever is performing that action (for example the Client). So what is the difference between this action and Multicast?
@woven bramble Where are you performing that RPC?
I thiiiiink there is some value for traveling players in general
C++ of course
Character BP
A possessed Character BP?
And what function triggers the RPC?
In theory, what you wrote is not correct. If the Client triggers the RPC in its own Character, then the Server will execute it
So the +1 is not happenign on whoever performed the action, but on the server side of things
Might need to see code to understand the issue.
But in general the reason you pass stuff to the server and let it replicate is because it keeps state. A new joiner, or someone that enters relevancy gets updated to that state. That doesn't happen in a multicast.
I assume you'd need to utilize:
APlayerController::HasClientLoadedCurrentWorld() and FSeamlessTravelHandler& SeamlessTravelHandler = GEngine->SeamlessTravelHandlerForWorld(CurWorld); which has SeamlessTravelHandler.IsInTransition() for the Server
In general, the Server will via GameMode and the Clients via RPC call HandlSeamlessTravelplayer on the GameMode
So you could just count in there?
Yes, It's possessed Character BP.
Pressing a key, I add +1 to the variable that is Integer (Replicated true) after running RunOnServer.
Then I bind a function to the text on the screen in the widget, cast to Character_BP and add this integer to the text.
When I press the key, +1 is only reflected on the Client screen.
There is no change in the server screen.
(Print String says "Server: 1" on both screens)
My current way of counting clients in sending an rpc when on rep player state gives them a valid PS. I find this gives me the best timing as latency is baked in with the rpc. I just need a good way of knowing how many players I should be waiting for. Getting the number of player controllers right before PostSeamlessTravel is called seems to be the best, but testing seamless travel is a pain without a packaged build and two steam accounts (the editor seamless travel functionality seems broken)
I can confirm it works as expected with one player
Show the whole code please
Everything that is involved from key press up until the UI
Editor has no SeamlessTravel enabled, but you can try it with that console variable. Might crash though
You don't need to package though, you can start standalone
Can also test on one PC if you don't need steam
Just test it with SubsystemNULl fwiw
Yeah thats what I was referring to
oh yeah youre totally right
But counting how many you expect on POST SeamlessTravel sounds weird
is there an easy way to change the subsytem?
If you don't have steam active, it should probably fall back to null
Just kill the app :D
smart, thank you!
FWorldDelegates::OnSeamlessTravelTransition.Broadcast(CurrentWorld);
This is a thing
void AGameMode::PostSeamlessTravel()
{
if (GameSession)
{
GameSession->PostSeamlessTravel();
}
// We have to make a copy of the controller list, since the code after this will destroy
// and create new controllers in the world's list
TArray<AController*> OldControllerList;
for (auto It = GetWorld()->GetControllerIterator(); It; ++It)
{
OldControllerList.Add(It->Get());
}
// handle players that are already loaded
for( AController* Controller : OldControllerList )
{
this is the snippet, i assume the player controllers in the old list are the previous ones
That triggers on server and client I guess
Yeah
But I feel like setting that earlier might be safer
yeah, its still a little janky
oh there's literally a NumTravellingPlayers int
i suppose I could override the iteration and plug my custom functionality into it
IT'S IN AGamemode doesn't it mean it's by default will be called by server since server owns the gamemode and clients just replicates it . correct me if I am wrong?
That's a strange int I gotta say
Gets incremented in places where I would expect it to be decremented
Honestly
Just listen to the delegate
Save how many controllers are there
And that's it
The delegaete gets called by the SeamlessTravelHandler right before verything dies
yeah im going to go with that, seems to be the cleanest. Thank you
fyi in 5.2 it's in World.cpp:7113
game mode is a server only actor, its not replicated. Im not sure what you mean
I mean the game mode logic is executes on server thread and after the gamemode is set then it goes to client gameinstance and clients set their gamemode by copying the Server GameMode actor on their respectiive gameinstance
Is it correct since client has no authority over game mode, so the gamemode will be replicated
When I press the M key (in the client), 1 decreases from Integer on the client's screen. (No change in server.)
When I press the M key (in the server), 1 decreases from Integer on the server's screen. (No change in client.)
This is exactly what I want, but I'm very curious as to why. Shouldn't this only be on the Server screen when I press the M key?
Having a look soon, doing something else atm
You really need to name your variables better
Why is Magazine a replicated variable, widgets don't replicate
When you press M, it changes the integer serverside for that instance of the character, which then gets replicated out to clients.
Your widget is fetching player character 0 which I think is always the local player's character. Don't rely on that though, it's gross. The widget should just have a stored ref to the character it cares about.
Probably not even a ref
Server's widget only shows server's character's integer.
Client's widget only shows client's character's integer
Pressing the button on either only changes the integer for their character.
We setup our widgets with proper callbacks to when the PlayerCharacter replicates possessed :D
But that's beside the point
And yeah, what Adriel said
Thank you <3
@dark edge can you help me about it? Anybody cant solve it until morning
@shrewd ginkgo Please don't ping people directly for help,
Your issue looks like you are using PlayerControllers to reference specific players in a network game
PlayerControllers are only valid locally or on the Server. A given player can't access other player's PlayerController
You are supposed to use the PlayerState of a Player
Cause that one is replicated to everyone
A list of PlayerStates can be found on the GameState in the PlayerArray
Sorry adriel help me about many thing, thats why I want help from him
Also suggestion to (re)read the Network Compendium that is pinned to this channel, cause this is basics
Ty
- When we do RunOnServer > Set Variable (Replicated), the Server processes the action and replicates it to the clients. This only changes the variable of the person who triggered the action. (Actually the variable is 1 but it is replicates specific to the Clients.)
- When we do RunOnServer > Multicast, we will show the action we changed on the other clients. (So we also run them)
- When we do RunOnServer > RunOnOwningClient, we only run that action on the client running that action.
If these statements are correct, I don't understand the difference between 1 and 3.
1 should replicate to all clients, unless you have non-standard replication condition
What is "non-standard replication condition"?
Buddy, the variable is replicating fine in 1. you are displaying only the local player's variable in the widget
The other players are only looking at their own character
That one does not have the variable incremented
- and 3. and fundamentally different
Yes, I took the direct character as a reference in the widget, this was a mistake, thanks.
I ask these 3 questions off-topic. I don't understand the difference between 1 and 3
-
Run On Server -> Set Replicated Variable: If done in the Character, this will cause the Variable to replicate to all Clients. Any Client who has a reference to that specific Character will see the change. This also counts for players who come into relevancy range later or join the server after this happened
-
Run On Server -> Multicast: If done in the Character, this will cause all currently relevant Players to receive the Multicast in that specific Character. Everyone outside of relevancy range or players who are joining late, won't get this event. If the Variable is set via the Multicast is not marked as replicated, it's not going to be changed for those out of relevancy players and late joiners
-
Run On Server -> Run On Owning Client: If done in the Character, this will cause the Local Player Only (not even the Server unless it's his Character) to run the Event and no one else. The variable will only be set locally and no one will see the change despite that player.
I think the difference is exactly here. 1. "Any Client who has a reference to that specific Character will see the change."
3. "The variable will only be set locally and no one will see the change despite that player.""
I copied what you wrote and took notes. Thanks a lot.
Has anyone seen this crash before? seems like a bug in SteamSockets plugin
Hate spoilers
i saw that one before... iirc the RedpointEOSNetDriver was the culprit, and it was fixed
Can't believe you revealed the spoiler 😭
I'm trying to spawn duplicated pickups when a player kills an enemy. I want each player to have their own pickups (similar to loot in Diablo, where each player has their own set of pickups).
I have a BasePickup actor, which has replication turned off, and I have a multicast function to spawn the actor on each client, and I see the pickups spawn, but when 1 player picks them up, they disappear for every player.
I've been googling but can't seem to find anything for this specific use-case, has anyone done this? Or have any ideas of what I might be missing?
Oh wait, I'm dumb, the OnComponentOverlap was firing for both clients, adding a IsLocallyControlled check allows the pickup actions (destroying the actor) to propagate to the other clients
You're best to use replicated actors, but you need to override IsNetRelevantFor and make it so the item is only relevant to the owner which you can set to the player that owns that specific drop.
As for the pick up logic you'd check if its the owner that is the one performing the pick up and if so, then let them collect it.
I tried that, but now I'm realizing I never enabled replication, just changed the IsNetRelevantFor, Let me try that, since my IsLocallyControlled check, technically worked for destroying the actor, but if I run over the spot that it still exists on the server it picks it up again and again and again.... 🙂
That worked perfectly, thank you!
So just provide true if realviewer = actors owner
Why exactly is it required to use a source build of UE to compile a dedicated server? Is it for some optimization reasons that are excluded in the compiled binaries of the engine or something?
the engine binaries + debug symbols are huge
and there are many many builds
so launcher version comes with limited number of targets, or it would take 250GB
Hi. need help.
Got a widget added to a playerBP
want to have the floatinghealthbar replicate its progress to the other clients
how can i do that?
on standalone everthing is perfectly working
working with the GAS and all attributes should be replicated to the server. but 1 client works as intended. the other doesnt update the health bar
it fails? ( it used to work before ) [ADVANCED SESSION PLUGIN]
I added the "run under one process" to the multiplayer menu dropdown so you can toggle it on/off easier/quicker during testing. The PR is here (on the likely assumption Epic wont merge this in, but if you are running a source copy you can add it if you want it): https://github.com/EpicGames/UnrealEngine/pull/10800
Not that it's quicker, but also brings peeps attention to it such that they're aware that it's a more reliable way of testing. Cool one, thanks!
yeah - its one of those important toggles hidden out of sight, out of mind
Anything network related should just have it's own toolbar menu
Still a lot of stuff hidden
is it possible to first join a session, then join another session from that session if that makes sense
i want players to group up, and then join a larger session with more players
@stoic lake Yes and no
Depends a bit on the Subsystem you use
The Grouping up is usually done via Party Session and Beacons (C++ only) and you still won't be able to have both session active at the same time
Ok so I've put my dedicated server on a vps, what do I do to start it?
It's Debian btw.
Could anyone show me how to do this in bp?
Think there was a FindPlayerStart or something similar in the gamemode you can override to implement your custom logic (or just use the player start indexes), I dont have the engine rn to check :x
The Player Start Tag
Is there a way to get the player's player number (for example p1 p2) then set the according spawnpoint
Why are you doing this not in the game mode?
It's called from the gamemode inside the character bp
What is it supposed to do, respawn / restart?
Yeah but I need player 1 to respawn at the 1 spawnpoint and 2 at the 2 spawnpoint
Just call restart player it'll be like when the game started up
You already have the code to put the players where they gotta go. Don't reinvent the wheel.
I don't though
This is the part im stuck on
GameMode has functions to override
stuff like "Choose player start" or whatever
No but like how can I get what number the player is from inside the player character
I'm having trouble finding that and getting the right spawnpoint
I'd find the playerstate in the playerstate array
What would it look like?
Has anyone had any success remotely connecting to an EC2 instance in GameLift using SDK version 5.0?
The CLI command get-instance-access is no longer available for this version of the SDK, and it used to return the Username for connecting. It says to use get-compute-access instead
You should be doing all of this in the gamemode
but from the pawn, you want to get YOUR playerstate
not player state 0
then loop through the player array to find YOUR index
that's your player number
What number are we even talking about?
Nothing controls the spawn points tbh
I mean sure you could use the array index, but if someone leaves the array is gonna shrink
You should just override the Find or ChoosePlayerStart function
It'll give you the Player that is being restarted
I think UE has a build in system for saved playerstarts
It will remember the spawn point and use it again next time
I think for that it's important to override choose and not findplayerstart
Idk what you are posting there
Override the function in the GameMode
This is not how you override a function
Open you GameMode. Go to the Functions on the left, hover the tab and press on override
Yop
You can get the PlayerState from the Player pin
And fwiw get the index via the GameState PlayerArray
Idk where you store your PlayerStarts or how you identify the first PlayerStart, but that's what would need to be used there to return the correct PlayerStart
I don't have anything setup
Only 2 spawnpoints with one tagged "1" and another tagged "2"
theres only two players
Well the naive first try is to use GetAllActorsOfClass for the PlayerStart class and then choosing the one you want
The array you get there is in no particular order though
So if they are tagged you still need to expect 1 to be in the second slot
If you have 2 starts they can be in either order
It can be that it's reverse
You will have to loop the two entries and check which one is the first one via the tags
Fwiw you can also make your own PlayerStart child BP and give it an actual integer variable
Well given you wanted to use the index of the entry
You would call Find or whatever it's called on the array
That wants a PlayerState and gives you its index, or -1 if not found
find item?
Check if it returns an index
Yop
That's 0 or 1 if found (if you have two players)
Now you can use that together with the GetAllActorsOfClass for your PlayerStart to get the matching one
But again the GetAllActorsOfClass returned array follows no guaranteed order iirc.
Like this?
Hello, I'm trying to do seamless travel, and it works fine, however mid transition I get a bunch of ensures due to GC. Does anyone know whether I need to fix them or should it be that way?
[2023.08.26-17.28.44:612][608]LogLoad: Error: Some previously active worlds or related objects were not cleaned up by garbage collection!
[2023.08.26-17.28.44:613][608]LogLoad: Error: Once a world has become active, it cannot be reused and must be destroyed and reloaded.
[2023.08.26-17.28.44:613][608]LogLoad: Error: Dumping reference chains:
[2023.08.26-17.28.44:616][608]LogLoad: Beginning reference chain search...
[2023.08.26-17.28.44:616][608]LogLoad: - World /TowerDefenseCore/Maps/L_TowerDefense_Lobby.L_TowerDefense_Lobby
[2023.08.26-17.28.45:004][608]LogLoad: Error: Printing reference chains leading to World /TowerDefenseCore/Maps/L_TowerDefense_Lobby.L_TowerDefense_Lobby:
after that it prints like a few hundreds of lines of references, and then, at some point, it gives a bunch of these https://pastebin.com/8SVEpwV7
I said about 3 times now that the array will not be in the correct order. You have to check which of the entries is indeed the one you call first
But this won't change mid game right?
So say it's in the wrong order at the start it wont keep changing the order?
In that case it doesnt really matter
I just need it so the players don't spawn in the same place basically
You then need to loop over the actors of class and match one up to the integer. Probably make a subclass of PlayerStart and add an int to it
or use a tag if you want but idk how you'd go from tag to int for the comparison
Loop over the get?
Could I also just use the default playerstart and add the int
add it how
Inside of it
by making a subclass with an int variable?
That's what I'd do
I need to make the variable instance editable and exposed and with a value of 0 then 1 for the other right?
no
Foreach over OutActors to find the one whos int matches the Find result, return that one
The get actors of class will return that array in a probably random order
Find off of array element?
Get Actors of Class -> Foreach -> Body -> check if element.integeryoumade = the int from the Find -> True -> return element
Body?
Loop body?
yes
do you understand what you're trying to do here
you're trying to find the PlayerStart whos int matches the int returned by finding the playerstate in the player array
im kinda lost
How am I getting the Player num variable which is inside the player spawn
In my mind I would get that from the get all actors of class
Get Actors of Class is an array - it's a list of items, and in this case it's a list of PlayerStarts.
You want to loop through that list of PlayerStarts and check the Player Num variable == to the found number.
What you have right now is you're getting the list, getting the PlayerStart at the array index of the found number, putting that into another array and starting to loop through that.
I can't get the player num from the array element
Disconnect everything from the loop
First thing that should be connected is the array from the Get Actors of Class.
Ok
If you've done that, you should be able to get the PlayerNum from the Array Element on the loop.
Yes
Because you didn't disconnect everything from the loop like I said.
Now connect the array up.
The thing is, the loop is using a "Wildcard" input, and the first thing you connect to it, sets its type.
It retains it so long as something remains connected to the loop.
So if it doesn't have the right class type, you won't be able to access the right variables and functions.
The out actors doesnt change the variable type of the for each
great
I see what you mean
now check if Element.Integer = the result of that Find
that's your SUBCLASS of player start with an integer in it right?
from array element?
yes
You also want to connect the Array Element to the Return Value output.
That way if it does match, you're returning that playerstart within the array to use as the start location for that player.
ah nevermind my bad the spawns were too close to the ground
Is there a way to respawn the player but keep the stats etc?
Probably
All right so I'm working on a multiplayer UI and I think I'm close, what I want is for a sort of multiplayer UI like this but where every player sees their own name at the bottom and everyone else's name around the "table"
So basically I have a text slot for the local player and then every other slot is in an array called Remote Slots, and I iterate through the player array and check if it's the local player, then fill in the rest into the remote slots. The delay is there hard coded just to wait for everyone to connect.
Right now the issue is that Players can only see their own name and the hosts name, but not other clients. Yet the slots where their would be a player name do appear blank, so they know a player is supposed to be there. This means to me that it's probably a replication issue with the player name and client's not being able to see other player names, I just don't know what exactly the issue is. I set each player name as a replicated variable in the playerstate and it gets its index from the Gamemode OnPostLogin
Image 1: Gamemode
Image 2: Playerstate
What I'm wondering is if it's something where I need like a RepNotify or something or some change in the Main UI widget, I just have no clue
Have BeginPlay of PlayerState tell the UI to refresh
Every time a playerstate shows up it'll holler at UI to do its thing
I think that'll do it but I know there's some weirdness with PlayerState (the first begin play might be a false start) but just make your UI code able to handle that and you'll be golden
Okay that sounds perfect
When you say UI refresh is that a specifically named thing or do I just tell it to run the code again
I'd first make the update function and call it every 1 second, make sure it works.
Then just change to calling it when a PlayerState shows up
and optionally when anything that'd be displayed gets OnRepped like Ready status
YourMainUIWidget.Update -> update all the things
Is any way to test audio on multiplayer?
Show me the ways Datura ❤️
Okay so that does update the UI but the main issue is still that client's can't seem to access each other's names
so they just come back blank
set replicated variables on server
Here's the general pattern
Client wants to change something
Input -> Run on Server Event (passing over the info)
RoSE -> change a replicated variable (now everyone has it)
ohhh that might be the issue
Adriel do u know how test audio?
I'd just fire up in standalone not PIE
PIE multiplayer audio can get goofy
I don't mean packaged
launch game
you can do that from editor or right click uproject file
Hey there... got a big problem with a floating widget and multiplayer replication.
Working with GAS (attributes are replicated)
added a widget component on the playerClass.
Handled Init and update for a healthbar on the player state.
Now everything is working fine in a standalone.
when i start as client with 2 or more players:
Client 1 is working correctly. all widgets healthbars are working.
all the other Clients: No widgets are initialized. Only widgets with defaults is showing.
What can be wrong?
Begin Play of PlayerState isn't great for clients as clients have a non-replicated playerstate to start with and the replicated version comes down and replaces their local copy but doesn't trigger Begin Play again, so the reference and values at begin play aren't correct for owning clients.
You can override OnRep_PlayerState in the controller for owning clients. Other clients other than the owner should be able to use Begin Play just fine.
oh yeah that's it
how the hell does it NOT trigger beginPlay?
is it like a reverse tear-off situation?
Why is it even there in the first place >_<
C++ only right?
Err, what? Pretty sure this isn't true for anything. Player states are purely spawned by the server.
You don't have one until it replicates.
The game state is the only thing that has any guarantees about ordering because BeginPlay literally cannot be called until the game state replicates.
PlayerState isn't special.
so i can only solve the problem in cpp?
Overriding OnRep_PlayerState is indeed the "right" way to know when you have been given a player state, assuming that's what you want to know.
BeginPlay on a player state should work fine, but there's no guarantee about when it'll be called which may be your underlying issue (also it'll be called even for remote players since clients can see other clients' player states)
Like this for the owner?
Or I guess that but in the controller instead of the playerstate
hmm got my AbilitySystem on the player state. got my widget on the player.
now i have to get them together on the controller for updating the widget
How do I override OnRep_PlayerState?
How do I get a player which is not yourself with a loop?
so essentially the other player
there is a list of player states on the game state
Yeah
got the solution 😄 added a 4 secs delay after beginplay on playerstate
spend so many hours for that
you don't need to cast for that, fyi
Looking at the code, I stand corrected...
It's been a while since I was having similar problems of my own and I do recall that my reference to PlayerStates that were used on BeginPlay of the PlayerState seemed to go bad, but that could also be my own faulty memory.
how'd I get the other player?
like = not self
?
compare each player with the local player...?
there's no "loop over everyone except the local player", you just loop over everyone and check if they're local or not.
ok so i'll check if local
In C++.
🙃
No, that'll throw errors as you're trying to access the controller of a playerstate.
If that's supposed to be for other clients, then player controller can be null for them.
Better
That can still throw errors if the pawn isn't within relevancy.
Also not required to cast your gamestate there if all you're doing is retrieving the player array.
Get Game State > Get Player Array
Got it
What would I do with teams, make p0 p1 on have team 1 member team 2 member variables? (not coding this just wondering)
Is this a bind within a widget?
Depends really
yes
Hm the scores are wrong
When i'm setting the variables, is this correctly replicated?
Why are you doing that on the client
set replicated variables on the server
Player state doesnt auto replicate?
Everything works well now, just need to figure out how to spawn the player back at their correct spawn
Can I just multicast from the server for every player to update their UI whenever a playerstate is created?
you are setting the variable ON THE CLIENT
That variable will not replicate.
You need to set it ON THE SERVER
What if multicast hits before playerstate does?
idk 😵💫
If you need a hack set a replicated bool in PlayerState at BeginPlay on server and use the onrep from that I think.
love a good hack
Nothing "Auto Replicates".
Replication is always Server -> Clients, so any values you want others to see needs to be set on the server.
Replicated variables go from the server to the clients.
The only way to get data from a client to the server is through a Run On Server Event in an actor the client owns (PlayerController, Pawn, PlayerState I think)
Hi, I'm having an issue where my client and server registering hits becomes out of sync with each other, my Caretaker class can throw axes which when it hits a StudentBase class character it applies damage but sometimes the client player wont register being hit by the axe but the server has registered it being hit which then leads to the client saying it has a different health value to what the server says it should have, any ideas how its hitting on one but not the other and how I can fix it?
On BP_Caretaker I'm spawning the axe, on BP_ThrowingAxe is where it registers what the axe hits and on BP_StudentBase is where damage is applied
Hi there, I'm working on setting up dedicated servers using SteamCore PRO. In their tutorial they mention they use Steam Dedicated Servers, however they also say that you should have a remote hosting service. Can someone explain to me how exactly this works and how these 2 tie together? Would I just put my dedicated server file on playfab for example and then the servers show up on the steam browser?
I would say have the server manage damage and hit reg and replicate a variable to the client's. You can use a switch has authority on your on hit that way only the servers on hit event will play
I tried putting a has authority on the OnComponentHit event but it caused the clients to have some wierd behaviour, they wouldn't see the axe hitting the other player, when i removed it again it started hitting the player again on the clients screen
Is there anything like APlayerState::CopyProperties() for APlayerController? I'm trying to save some data that would be persistent across worlds, and always valid regardless. What I mean that is that in the PS case to actually get the old data to the new one you have to wait it to call CopyProperies, which for me is too late (I'm using Game Feature System which dispatches things during PreInitialization, which takes place before CopyProperties).
Why not store that data in the PlayerState?
As I said, the CopyProperties is called too late for me, so I'm looking for something else
Hmm, I seem to have a problem with repnotify. In my game mode (on the server), I am calling an custom even which casts to my game state, and then changes a value which is set to repnotify. I am then changing the value of the replicated variable and in the repnotify function I am printing a string. The string never fires.
Put in some breakpoints and see where your logic halts.
It halts at the onrepnotify function. I have a print string directly inside the function and it never prints.
First image is the game mode, second image is the updateplayerlist event in the game state, and third is the event notify. Everything prints except the last print in the on rep notify. (The one that says made it to the repnotify)
And here's my logic for updating the variable I am passing into the custom event.
No, it was done because of the 'remove item' node.
It wasn't removing the item fast enough so it was sending the variable through with the item still in it.
I suppose I could put the delay on the route after the remove, but I just stuck it there so it was consistent in both actions. (add and remove)
I'm not playing in editor, I'm playing standalone. Both postlogin/logout are in the gamemode, which is only available on the server so the authority is the one getting it. The prints I am putting in place on the game mode are only printing on the client that acts as the server.
hmm.. I just got the repnotify on this playthrough.
I wouldn't, that's why the prints are in the game state (which is available to the clients), and in the repnotify function.
You can't replicate player controllers.
Also, completely unnecessary. The GameState contains a PlayerArray which is a locally generated array of PlayerStates present in the game.
If server needs the list of player controllers, it can get the PlayerArray and get the controllers from it.
If clients need to know about the list of players, they can read the PlayerArray and read from that.
Clients (and Server) can use BeginPlay of the PlayerState to know when a player joins and EndPlay when they exit.
Originally, the repnotify was connected to the player array (which was promoted to a variable) on the game state, but that was empty when I was printing it.
Does the PlayerState variable automatically get updated on each client when a player leaves/joins, or does that manually need to be updated per client?
Which playerstate variable? You mean the PlayerArray?
Its updated automatically.
PlayerControllers don't replicate to other clients anyway
void APlayerState::PostInitializeComponents()
{
Super::PostInitializeComponents();
UWorld* World = GetWorld();
AGameStateBase* GameStateBase = World->GetGameState();
// register this PlayerState with the game state
if (GameStateBase != nullptr )
{
GameStateBase->AddPlayerState(this);
}
void APlayerState::Destroyed()
{
UWorld* World = GetWorld();
if (World->GetGameState() != nullptr)
{
World->GetGameState()->RemovePlayerState(this);
}
void AGameStateBase::AddPlayerState(APlayerState* PlayerState)
{
// Determine whether it should go in the active or inactive list
if (!PlayerState->IsInactive())
{
// make sure no duplicates
PlayerArray.AddUnique(PlayerState);
}
}
And of course opposite with RemovePlayerState
Okay, so then I can use the playerstate class and the begin play and end play events to update the local clients playerlist widget then instead of doing it through the server?
Yep
wtf... why has every video I've watched use the game mode and postlogin and on logout events to do it..
Couldn't answer that. Just need to keep in mind that Begin Play of PlayerState doesn't mean all the data that you need to properly display the player info is there, though the playerstate reference can be kept and used as a valid reference to bind to event dispatchers which could be called from OnReps.
All I need is player name. (for now)
why is my multiplayer lan only? a little concerning since I cant find much about it online. it works fine for my two pcs
Did you do any port forwarding on your router or are using sessions?
Thank you Datura and V-Monologues. What you did helped and my player list is now working.
I did the whole steam setup
used an alt steam account and it connected to a server started on my other pc
Are you using app id 480 ?
yeah
No. You can playtest once you buy your own AppID
I was actually thinking about setting up the steam page at some point. its just part of that right?
Alls I know about them is that they're supposed to be a good way to replicate big arrays.
Hey everyone 😄 If I want to spawn a map through the game-mode when the game starts, should I call the game-state to spawn it, or what is the best workflow to spawn an actor?
Currently I just spawn it on the game-mode only and I set the blueprint to have the replicate option ticked. This works decently but is that the best method?
It doesn't specifically matter really. So long as your map blueprints are replicated they can be spawned from anywhere, so then it's a matter of organization and keeping track of the spawned map actors.
Oh okay. I kind of thought that but wanted to get some opinions from people who know more in case I was wrong 😆 Thanks!
It must be the plugin that is causing replication issues then not the implementation
Now if you wanted to save bandwidth.... You could technically have a "seed" system that you then have both the server and client spawn on their own when the client receives the seed.
It requires a bit more finagaling in C++ to ensure the actors and their components are named appropriately so they can be made netaddressable, but it can work.
Unfortunately I am only a blueprint developer at the moment lol. I hope to learn C++ eventually but for now I am just trying to learn UE overall and dive into programming after
I was considering doing that seed method as well, I might give it a try
If I have a Main Menu level where I can create a joinable session and search for existing sessions, if I want to create another menu that's basically a lobby menu where you can see players as they join, ready up, then the host can launch into a gameplay level, is the lobby menu a separate level from the main menu level?
or is there a way I can do the lobby menu in the same main menu level
So you want to boot up the game and be able to host or join from there?
Right so boot up into main menu, click Play, then you get the server browser where you can find games to join or create your own
when you choose to create your own, you set the game settings and hit create, then you get into a lobby menu
Join and Create will involve a map load
Unless you do a trick we're doing where booting up the game opens it as listen server by default
because we don't want hard loads
If we are talking Overwatch/Fortnite kind of lobbies, then they are done using beacons and party sessions via c++
gotcha, yeah I was thinking more just like
cod black ops 1 zombies lobbies
like this kind of thing
It doesnt have anything to do with network then
Overlaps are hanfled by local physics engines
ok, but still overlapping should be done
Actor is replicated
if server overlaping Actor
then nothing print from server
only from client
Actor being replicated doesnt mean it exists on server if you say , spawned it locally on client
is spawned from server
I spawn Actors only on server side
Actors are replicated
server and client see actor
but overlaping works only on client side
even if the server collides with the actor
Then your server instance setup the collisions wrong
ok, but how can i fix it ;p
I'm a little bit confused about the persistent Data Compendium. It says:
There are three ways in which a non-seamless travel must occur:
When loading a map for the first time
If a player open the game and open a lobby level for other player to join. Since game map isn't loaded, so the server take other players to the game map should always be non-seamless travel. Is that right?
hi. if i have a replicated variable in my gamestate, will it be replicated on begin play for the client when he joins the server?
yes
thx!
When I replicate a UMyDataAsset* DataAsset, how is it actually replicated? Via a string for the class name? Or is it more optimized than that?
i need to update actor location with timer and on client it looks weird.... target location replicates
No, by that reasoning, every map a play travels to (no matter how) will be non seamless and that's wrong. Keep reading till you reach the note beneath
Loading a map for the first time (main menu for example), not every map for the first time. I made sure to clarify that, glad i could help
First time it's by path name, then a net guid is assigned and starts being used
awesome
what will be better: creating a manager that will manage all actors on and with the map, updating the location of these actors using Event Tick and Server World Time? or for each actor separately?
i must use event tikc or timer, and i don't know what is better.... 1 Tick in manager what have all actors references and for each what is there update World Location or each actor have 1 Tick and updates the locations itself
Are corrections while colliding with objects in the game normal?
heyy guys, can you help?
i have a material which uses Camera Position Node and some scalar parameters to control that camera, so, im trying to test it with multiplayer, do i need to replicate camera position or scalar parameters? because when second player spawns, the camera position from 1st player is not working anymore
or maybe exist something else to use instead of Camera Position Node to make that material look in 1 direction but not where character camera is located?
Hello all, i just joined this disc because im trying to understand/fix a problem. I managed to get the issue "fixed", but I don't think it's being done in a way thats optimal.
What is the best way to ask lengthier complex questions? just type it all out? or make a thread? I also took a few pictures of my various blueprints if theyre needed
TLDR, im working on a multiplayer RPG game and just trying to replicate damage from a player shooting a bow+arrow at other players. However in the current set up, the server character can take damage and have their health UI updated properly, but the Client characters do not have their health UI updated at all, even though it seems like their health does drop and they can reach zero. Although its weird that they can reach zero and "die", but the server character actually reaches zero and plays its death ragdoll.
When I try to debug with a bunch of print strings I can see the health values get initially set, but then the clients dont get updated afterwards, even though I can see the server properly applying the damage with each arrow shot.
Btw, sorry for the incoming wall of text. I just wanted to describe the issue thoroughly instead of leaving parts out.
In my set up, the arrow projectile has the ApplyDamage event.
Then, on the Character_BP i have the Event AnyDamage, which feeds into a custom function called TakeDamage, that is being called from an actor component called PlayerStatsComponent (this is just an actor component that stores a struct called PlayerStatsStruct that contains all of the player stats. Health, Stamina, Mana, etc etc, as well as all of the getter and setter functions)
The TakeDamage function just takes in the incoming damage, multiplies by -1, and then passes it into a function called SetPrimaryStatValue. This function ends with setting the PlayerStatsStruct variable equal to itself to make sure it updates.
The PlayerStatsStruct is set to be a RepNotify, and inside the OnRep function, I call an event dispatcher named OnPlayerStatsStructUpdated. Inside the UI widget, I have it bound to this OnPlayerStatsStructUpdated event dispatcher.
It’s basically just supposed to update the health text widget every time the PlayerStatsStruct is updated, but for some reason the clients don’t get the value updated – it seems like the clients’ UI isn’t calling the EventDispatcher, even though using a print string inside the OnRep function I can see it triggering.
The only way I was able to get my set up to work “properly as it should” was by going to the Character_BP→Event AnyDamage and running it through a Multicast RPC first which then triggers the TakeDamage function.
This doesn’t seem optimal long-term, and in my head the setup RepNotify should work without the Multicast RPC
Trace down your logic to figure out where it's breaking
Temporarily use a replicated float to see if it's the struct
well i traced it down pretty thoroughly last night, the data itself seems to get replicated fine, i can especially see it in stamina (i have a basic dodge roll set up that uses -20 stamina, and then the stamina regenerates) and i can see that get updated properly on all players
ive basically traced it down to the way the AnyDamage function is doing.... something
i use the timer to change the location of the actor on the map and on the server it is smooth and on the client this actor twitches
someone can help?
for Homing Target Component
I would suggest just using the ProjectileMovementComponent and its homing feature
And then calling SetInterpolatedComponent on it on BeginPlay or so
Given you have the Actor with a collision comp on root and a mesh comp as child of that
@half umbra
Cause that component already does some smoothing
Not sure if it needs more though
Hi. I have a campfire actor, and when interacted with it spawn an particle emitter. It works fine with multicast, but when new players join, it isn't spawned for them.
What's the best approach to this?
I was thinking of using a repnotify, however, that's only spawning on the server, and not the clients.
Is it possible to call the multicast from the repnotify, or something like that?
Thanks in advance.
Matias
You use an OnRep. The OnRep function can turn the particle effect on and off based on the value of the variable. If it's not displaying on clients, then you probably haven't marked the actor as replicated.
No multicast required.
Thanks! I just tried it again, and this time it worked.. Replicates were on, so not sure what went wrong last time I tried. It's late.. 🙈
Thank you very much for taking the time to help. Means a lot! ☺️
Have a great evening!
Hey everyone! When a client joins a server, what's common practice for passing values that were on that client into the joined server?
For example if I set a weapon skin in the game main menu, and then join a server, how can I reference that data? I'm not sure what to store it on and how to fetch it. For example if I store the selected skin on the Player Controller, then when they join a new server the PC changes and loses all values right? Where should these types of things be stored and how can they be transferred on join?
I would save it on the gameinstance, and then on postlogin, I'd request the client to get those values.
Okay I haven't looked into gameinstance too much. I will try and learn about how it works! Thank you for the suggestion 😄
Can the server auto access client gameinstances? Like to show the whole server the skin the client has? Or will I need to send that info to the server from the client with an RPC
GameInstance never gets destroyed, and is only accessible from the client.
You need to make a client only call to get the data, as the server does not have access to the clients GameInstances.
Cool sounds good. So I would have the client player call the gameinstance to get skins, and then I could multicast when I set the skin so it changes for all clients? Does that sound accurate or should I do something else
Not how I would do it though, as multicast only affects people nearby. And if other people join after the multicast, then they won't see the change.
Let's say you have a material variable on the GameInstance, then you make a client event in the pawn that gets that material. Then you create another event but for server, which have a material input, and call it with the clients material as input.
The server call then sets a material variable in the pawn, which is a repnotify. Inside the RepNotify function, you set the mesh, or whater you want, with that material.
That's how I would go about it, but it really depends on what your goal is.
Hope this helps ☺️
Oh yeah I forgot that about multicast. I haven't needed it much yet for what I've worked on. I will do it that way then. Thank you so much!
A RepNotify is great for when something changes permanently, like materials, weapon equip, etc..
No worries! Hope you get it working ☺️
since it works on lan, should it logically work with me and my friend using hamachi somehow?
Not with app id 480
Im confused how it works between my two pcs in the first place in that case then
What is hamachi ?
Oh. I've never used that before. I'd imagine it's because it's only a simulated network not an actual one. Do you have is lan checked ?
no, not been using lan servers, but Ive been saying that because it only seems to detect lan
I'd imagine it could work if they're VPN'd in as then their network traffic should be appearing as if it is on the LAN - so long as it's all configured to properly route whatever Unreal needs through the VPN connection. I don't know what would be required for any of it, but it's a sound idea.
if you don't run in standalone, it usually defaults to IpNetDriver
which usually uses IPs directly
Would you mind if I DM you a couple questions real quick? Or I can post here. Just having a few small hiccups with this implementation
Post here! Other people can answer 😛
Haha okay. I'll post it in a second after I try one last thing. I might have it 🙂
I guess my main question is, if I am testing multiplayer through the editor, do all players use the same game instance?
No. Each client has their own, even with Run Under One Process enabled.
Okay thank you for the info!
I got it, thank you everyone 😄
have you ended up using NetImgUI? When I search on this discord about it, only you + @hollow eagle have mention it once, and its never come up again.
It seems very useful, but no one seems to be talking about it?
netimgui is great, but you're not going to see many people here talking about it because quite frankly there aren't that many people doing work where it'd be useful. And by that I mean that most people here are hobbyists working on some solo project.
Where netimgui would be useful is for use with consoles (where you want to be able to control aspects of the game while testing on a remote devkit) and when testing with multiple computers for a multiplayer game.
Hell, imgui itself doesn't get talked about that much because it's somewhat of a niche
yeah, fair enough. I'm thinking for dedicated server debugging specifically would be my use case
although multiple computers sound good too
combined with this: https://github.com/guitarfreak/PropertyWatcher
I guess that'd work, not really something I've thought of using it for. I have used imgui on clients that displays information coming from the server, however (via normal replication, not netimgui)
but how do you debug a server issue when testing multiplayer? or you just run it as a listen server and view the output?
just run it locally and attach a debugger?
build console commands?
use the "run separate server" option in PIE and inspect the server's world in the editor?
lots of options
yep yep
Hello , in unreal engine 5 i can't connect my client (packaged one) to my dedicated server (packaged as well) , i followed all step from UE4 but not working, however when i use command console as the UE5 dedicated server guide it's working perfectly , my blue print seems like it's not working (i tried without port aswell) . How can i do to make my client connect instantly at the server (my client from the packaged project) . I didn't miss any step , setted all project settings (server default maps etc..)
@woven basin @hollow eagle The only thing I would use it for is for like an external cheat tool. So that I can modify the game from a second window instead of some UMG cheat window.
It might also make sense to use to debug BPs values runtime when not playing PIE, cause you can't really attach Editor to a standalone or packaged game. Not sure that would work though.
Main reason it never came up again is that I don't have the time on any project to actually set this up
Use the ExecuteConsoleCommand node with open 127.0.0.1:7777 instead
Can you please tell me which version of Windows Server is better to setup on hosting?
Hi, I know this has been asked before but it's difficult getting a definitive answer - what is the best approach for a simple multiplayer game using pixel-streaming? e.g. if we're hosting at AWS.
We just need 2 instances - in this case, is it possible for one instance to host a session and the other instance to join via IP (or another method)?
Note I've read the documentation here, but as far as I'm aware the matchmaking server is essentially just finding a free instance for any users joining, it's not actually doing any multiplayer stuff: https://docs.unrealengine.com/5.1/en-US/hosting-and-networking-guide-for-pixel-streaming-in-unreal-engine/#multiplefullstackswithmatchmaking
Hey guys, simple question :
Have actor lets say its a weapon that have some VFX on spawn, since noone owns it from the start how can i correctly decide to spawn the VFX only to locally controlled player? Is creating like a huge box collider and bind on begin overlap to check if other actor is locally controlled is a good idea or maybe there is a better way, thanks for any answer!
Why not set an owner? Box overlap idea sounds horrible.
In any case, the object has to have some way of knowing who the "locally controlled player" is
but its not owned by anyone yet, its just a spawned weapon with some particles on it. It will be owned if someone pickup it but not at the begining.
sorry for those neebish questions im kinda new in multiplayer maybe im missing something important
So when do you want the VFX to occur?
on spawn
I don't understand your problem
how to specify VFX effect to show on only Locally Controlled Player if actor doesnt have an owner
your question doesn't make any sense
maybe you want SWITCH HAS AUTHORITY
or "ISDEDICATEDSERVER"
hmm i probably overthink the stuff anyway thanks for help
...so if it is not owned by anyone - then your question "only to the locally controlled player" makes no sense, since no locally controlled player owns it.
either it shows to everyone, or the actor who controls it
You could spawn VFX in BeginPlay as a non-replicated animation I guess - that is then showing it for everyone on spawn
@woven basin ye i have hard times to wrap my head around how multiplayer works thats why i asked question that may have no sense
Does anybody know where I can set timeout for removing player from a game in case it closes the game or client crash? For now Player State stays on server, but for too long.
there is an event on GameMode i think its for that kind of situation
wich runs first the gamemode or the controller ?
hi, Multicast not working on AI Component, why? If AI get damage, then call to Run On Server >>> Multicast
Multicast run only on server, but should run on everyone
someone can help?
AI is Replicated and Component
i want Run Multicast in Component what is attached to Replicated AI
Do you mean AIController?
By clicking a button in the widget, I add 1 to an Integer in GameState. This is a vote system that both sides can see.
While the system works fine on the server, the client cannot add +1 in any way. What could be the reason?
@woven bramble Back to the Compendium you go!
- ServerRPC in non-Client owned Actor
- Multicast for State is wrong, the replicated Variable is enough
If this isn't clear, read the Compendium again, especially Ownership and RPCs
I read it from the beginning 2 days ago.
I think I understand some things incompletely.
Press Button > Run On Server > Cast To GameState
There is no 1 logical reason why this process does not work.
Multicast was optional. So I just added it. I don't know why run on server and replicated variable not working
@woven bramble GameState is not owned by the Client that tries the ServerRPC
That's the main "logical reason" :P
The RPC is dropped
Ah, I didn't evne see that
You are also using an RPC in the Widget
Widgets aren't even replicated, they can't run RPCs
So that's point number 3.
The first problem is you're trying to do an RPC inside a widget. That can't happen.
The run on server event needs to be in your PlayerController or Pawn or PlayerState
no, my custom component
and this component is replicated
What actor is that component inside, and is that actor replicated?
is it inside the AI Pawn or AIController
inside AI Pawn i have Actor Component
AI Pawn and Actor Component are replicated
and i want run multicast in Actor Component
if i run it from server, then only server print string
but should all
because it is mulitcast ;p
Show your code, that sounds like it should work
The Compendium has this information for GameState "Additionally, it is replicated for all clients, so everyone can access it. "
But here you said.
"GameState is not owned by the Client that tries the ServerRPC"
What you mean is, "The Client cannot initialize a GameState that it does not own. But it can access variables in the GameState that have been initialized by the Server"?
For example, Server has changed the variable, Client can see this variable.
But Client cannot change this variable.
The only way to break this is to do it in PlayerController / Pawn. Is this correct?
Yeah
These aren't the only two options
But they would work
Any Actor that is owned by the Client who needs to use an RPC can be used
But PlayerController, Pawn/Character (Possessed) or PlayerState are the base ones you can use
The RPC would be in them
Then you can access the GameState and set the Variable which then replicates just fine without Multicast.
So you should NOT have a ServerRPC in the Widget, nor in the GameState.
@woven bramble
It was very clear, thank you so much.
ok if i set Damage to Multicast then is ok, but why?
can someone explain to me?
is Event Any Damage being called on the server?
That should work assuming everything else is set up correctly
I'd first make sure that the component is replicated, try have it BeginPlay -> switch on authority -> set a replicated variable
and see if it's actually replicated
still not working, if i call to not replicated Event
(Damage)
when I think I understand multiplayer in unreal engine, after a while it turns out that I don't 😄
ok, then can someone explain to me why it doesn't work?
as if multicast doesn't work if call directly from component
What does Begin Play -> delay -> multicast do in the component?
Hi. im having an issue with my health widget being updated after applying damage for the client, i have a throwing axe actor that when it hits a character will send a message to the Apply Damage interface function which calls a damage event on the StudentBase character class that was hit by the axe which calls a OnHealthChanged delegate, which then calls for the HUD to update the widget.. the issue i'm having it that for some reason the Update Health event that is bound on the HUD class is being called twice every time the StudentBase class is hit if they're the client but called only once when the server is the StudentBase class?
The other issue is that the HUD updates the health correctly for the server but when the client is hit by the axe the first time it does call the UpdateHealth event because the print statement prints twice, but the number still stays at 100, when the client is then hit a second time the health widget will update and go down to 80, but the correct health is actually 60 because the axe does 20 damage. Any ideas on how i can get this working properly?
if i set 5 sec delay, then call on Client and Server
Did you switch on HasAuthority?
Spawn Effect
nope, wait
same
Put a print string on every step from the hit to the end of the multicast and see where it breaks
ok
The system works flawlessly, I wanted to thank you again.
By the way, I initialized a Replicated variable in GameState normally. Why didn't we make this event RunOnServer? (RunOnServer > Replicated variable would be perfect I think?)
Quick question if anyone has an answer for it.
When an actor of a class is spawned by a blueprint event called by the server and an instigator is set, is the instigator field replicated?
Not sure what you mean
Yeah, but only if the actual Object you pass in is replicated too
Thank you so much!
Hi, everyplayers have kkkk on the head
when i pick up a helmet it changed the KKK into KING to the player whick interacted with the helmet
but when i play on the real game server the variable doesn't change any idea?
i'm using text render
Hello , my friend got this issue when he tries to connect to my dedicated server in unreal engine 5 : the match you are trying to join is running an incompatible version of the game , he is trying to join me from the editor, if someone know what is exaclty causing that , and if its to complicated to fix it , Can someone explain me how to bypass this by editing source code
Because i dont want to be forced to have the exact same version each time he wants to connect to my server
(we should have the same version tho, because im up to date with his branch)
might be an editor thing? have you tried from a packaged build?
I love this game
The thing is that my friend doesnt have a good connection, the packaged build is working
using Unreliable instead of reliable will make the network packets smaller?
yeah my too i'm working on my first map since 15 days join my discord and check all screen
original map and mod
idk about smaller but it'll make it not clog up your pipe if it's something that will be garbage data anyways in half a second
You'd use unreliable to send aim direction because if you miss one, well, another one is coming down the pipe a frame later
hey guys im trying to Figure out why this is not working.... Im Trying to a "lobby list" when a player joins add that player to the list for both players etc, but its not displaying the Name of the player and its removing it from the "server" and moves it to the client only
so I thought I solved it and I didn't so, how do I go about attaching the fp meshe's weapon to the tp mesh or do I need to use 2 components for that (1 for fp and 1 for tp)? how do most games solve that?
anyone got time to help me :/?
As usual, you need to post the relevant code, otherwise no one can help
Thanks )
yeah, but i dont wanna spam untill someone "got time" ...
just fills the chat otherwise..
https://blueprintue.com/blueprint/l7jt9r10/
https://blueprintue.com/blueprint/qpea-8nb/
https://blueprintue.com/blueprint/9171a2dg/
ill just do this
so using "custom controller / game mode" this is all the code basicly for it
anyone :/ ?
Looks pretty wild. I think you might want to rethink that setup
Your best bet is to get the PlayerArray from the GameState when you create the Widget.
And on top of that, in the BeginPlay of your PlayerState, also add an entry. Ensure you aren't adding an entry for a given PlayerState twice and that's kinda it
The name part is cut loose from that. You can use the PlayerName of the PlayerState for now in a binding
If you want to change that to the name from the GameInstance, then you can use the PlayerController BeginPlay, locked to IsLocalPlayerController, to send an RPC with the Name. In the RPC you can then get the GameMode and call ChangeName iirc.
Then will adjust the PlayerArray PlayerName.
Anyone know if there's a way to make a replicated actor, but specify exactly which clients it gets replicated to?
I'm working on a lobby system where players can host and join lobbies. I have a main menu level and a lobby level, how do I allow players to enter their username on the main menu and then when they join a lobby have their name populate the player slots in the lobby?
You would use a game instance to persist the player name variable throughout the different levels. When you load into the lobby, you would then pull that variable locally and send it to the other clients to update their UI. The game mode has a post login in event that gives you a player controller, you could call an on client event in the player controller that fetches the game instance variable to pass it to a server event that then calls a multicast with the new players data. Each individual client would then add that to their player array and then display the new infoinformation. There's an old ue tutorial on multiplayer lobbies that does it this way.
is it this one?
https://www.youtube.com/watch?v=abmzWUWxy1U&list=PLZlv_N0_O1gYqSlbGQVKsRg6fpxWndZqZ&ab_channel=UnrealEngine
In this video we take a look at the finished project and step through each of the features that will be covered in this series. We show our functional Main Menu and its options, a lobby where players can chat with one another and select their characters for the game, some server options such as changing the map or match time as well as the abili...
That's a 2 parter. Name to savegame, and savegame to server (you can also use game instance but it's pretty much the same)
Name Widget:
OnEnter -> get GameInstance -> update whatever name field, optionally do some savegame stuff
On Joining a Server
PlayerController or PlayerState:
Begin play -> locally controlled? -> fetch name data from GameInstance or SaveGame or wherever it is locally -> Pass it to Server in RunOnServerEvent
Server can now set the replicated name variable in PlayerState
So if I'm understanding correctly, every player will have their own GameInstance in a standalone version of the game, and it seems like one use for it is basically for environment variable-esque type stuff?
like holdingon to local variables through level swaps and stuff?
Yes GameInstance is what persists from startup to exit
When you join a server, it's the only framework object that's still around from your previous level (main menu or whatever)
Just remember it can't hold actor references across level loads.
luckily this particular game will have no actor references to keep consistent, but I will keep that in mind for sure
okay super cool
so I'm here
how would I now pass it to the server?
I know I need to do a run on server custom event
but do I pass it to the gamemode?
or iirc clients cant do anything involving the gamemode
You'd need to use a "Run On Server" event on a client owned actor.
So if this is the controller, that should be fine to do it here.
Once running on the server, you can set the variable wherever you like. Seeing as it's a player name, you may want to store it on the PlayerState.
so something like this?
this is in the player controller
Okay so before for testing purposes I was just assigning "Player n" as the playername in the gamemode based on what order each player joined
so I want to basically replace that implementation with the new variable I just set
That looks ifne
Yes, but here the problem is that you're using the controller. Controller doesn't replicate to everyone so you're then setting the value in a replicated variable that'll only go back to the player that sent it in the first place.
better?
Better 🙂
:D
You could just skip the playercontroller in all this and do it direct from PlayerState right?
other than the weird playerstate false start stuff
okay so the question is now just actually populating the UI with the names
I'd start with a binding
BindingFunction -> ???? -> get playerstate corrosponding to this widget -> get name -> set text
So apparently I was mistaken about that kinda stuff. PlayerState is replicated, it doesn't actually have a local copy of itself.
OnRep_PlayerState is still a good way to know when the playerstate is available in the PlayerController/Character, but otherwise, Begin Play on PlayerState on the owning client works just fine.
It must've been how I was setting some references somewhere previously that made me think this, but after reviewing the code, if NetMode == NM_Client no PlayerState is created locally, only the replicated version comes down.
How would I use Begin Play on a playerstate to also have other people's UI update when a new player joins?
You'd want to probably call an event dispatcher on the gamestate that your UI could bind to.
If you bind then you don't gotta worry about it
But you can OnRep on Name
Begin Play of Playerstate > get GameState > Call OnPlayerJoined (with ref to the joining playerstate)
UI > On Construct > Get GameState > Bind to OnPlayerJoined > UpdateUIForJoiningPlayerFunction
From there, you may want your UI to bind to any other event dispatchers you'd have on the playerstate, like one that you'd probably call on the OnRep of the name.
PlayerState:
Begin Play -> tell the HUD to add a widget for this player or go through GameState which would somehow else end up with a widget being created and knowing about this PlayerState
OnRep_Name -> call NameChangedDispatcher which the widget has bound to
Something like that maybe.
Okay so this is my playerstate beginplay:
and then in my UI on construct I have:
and my ui is basically a bunch of text boxes that are variables for the player slots
so in the UpdatePlayerList event can I just start populating names?
You want that OnPlayerJoined event dispatcher to have a PlayerState reference input so your UI can know which PlayerState joined.
The UpdatePlayerList can then read values or bind to event dispatchers on that playerstate.
Or create specific widgets for each playerstate as it joins (and they too could bind to the playerstate if you pass in a playerstate ref to them)
Hi! How can I replicate this? 😦 dont work
Unarmed variable also set to replciate and nothing
so would something like this work?
and it's kind of a rhetorical question because it didn't work lol
but basically I have all the text for the slots and each time a player joins I'm trying to set the text of the next slot to the player's name
The problem may be because your Player's Name hasn't replicated by the time the BeginPlay of the PlayerState has started on the client that triggers your UI update.
Like, does the name go blank? Do you see any activity?
No activity, just stays default
Don't multicast when you need to know the value of a replicated variable. Set the variable as a "RepNotify" variable, and use the OnRep function to perform what you need.
could probably be a lot of things, gonna dig around with some print statements
Could even be that your GameState hasn't replicated by the time the widget is created.
okay so I put a print string right on beginplay of my menu controller
and it didn't print
even though it's set here
But how can I call it in repnotify?
that set class is connected to begin play
same with my playerstate
hmm, no beginplays are printing anything in the lobby
RepNotify on Unarmed variable instead
But what do I put in renotify function?
So basicly it looks liek this, then I need to promote In class to varaible and set it as RepNotify?
But then how do I replicate it in repnotify? What do I call there?
The repnotify would fire when Unarmed is replicated. That's when you want to fire Link Anim Class Layers, right?
why is none of my beginplay logic running 😭
Either play isn't beginning or the blueprints aren't in the world
It really doesn't mater, all I need that Link anim class replicates then I change them for anim BP. Currently it shows only on owning client and for rest is in A pose
first off make sure it's actually replicating
Begin Play wasn't happening, I just called a custom event on the player controller from the gamemode and put my beginplay logic there and it worked
wtf
LETS GOOOO
ehhh didnt completely work lol, when a client joins the client does not see anyone's name and the host sees an empty name
but it's a start
Umm.. try restarting the editor? Begin Plays should be firing o_o
o.O
tried, same issue
literally no idea
Did you just create your custom game state?
yeah
It's probably the wrong parent class. Is it based off of GameState or GameStateBase?
GameState
And what about your game mode? GameMode or GameModeBase?
Okay, fixed that lol
now onto the actual issue which was my replication or passing of variables or something
Okay so I fixed the host view of the client's name by adding a .2 second delay
but the client connecting cannot see their own name in the lobby or the hosts name
so on construct could I get the player array from the gamestate and populate it like that?
nope
maybe when a new player joins add their playerstate to a replicated array and populate it from there
hmm that didnt work either
.2 second delay is not a fix. Again, the issue there is that you're trying to pull the name before it is replicated. You can use the playerstate reference provided to bind to additional event dispatchers that you could call during OnReps of variables that need to be displayed in UI.
right
like this?
You want it so that every time someone updates their name they use the last slot and increment the counter?
You probably want to create a widget specifically for that playerstate and insert it into the playerlist.
I want the players to fill up slots 1-8 incrementally
That widget can then maintain itself based on that playerstate.
I've got it so that for the host it looks like this
but for the client they just see waiting for player
And again, that may be because your gamestate isn't replicated by the time you construct your widget. Check with some print strings in your widget to see if your cast to your gamestate failed on the client.
Don't construct your widget until gamestate begin play fires.
brilliant
silly issue here. when the client character dies, i enable ragdoll, and then after a few seconds i want to disable the ragdoll so it stops simulating physics but doesnt destroy the actor. on the server player, the dead skeletal mesh disappears when i re-disable physics, but it doesnt disappear on the client player lol. any ideas?
I'm currently constructing the widget from the gamemodes Event Handle Starting New Player and calling an RPC to the client to create the UI
I think I saw that in a tutorial today
so how do I make sure the gamestate begin play fires if that's how im initializing the ui
You have the Begin Play of the GameState to know when it arrives on a client.
This may seem dumb but I'm actually not sure how to use Begin Play of the GameState to get the UI to initialize
Begin Play > Create widget
and for owning player?
That's optional I believe, and mostly meant for local co-op.
so where would I call the event dispatcher to then update the UI?
I have it bound to the game state and then an additional binding to the player reference that's passed through
but before, I initiated that first dispatcher from the playerstates beginplay, hence the issue with the gamestate not being initialized
Welcome to race conditions.
Any widget that is about a specific player should be its own self-contained UI that takes in a reference to a PlayerState and manage itself. So when you create it you feed in the PlayerState reference it should use, and it can bind to whatever dispatchers it needs.
Your main UI relies on the gamestate, so you create it when GameState begins play. As you're also using the GameState in OnConstruct of this main UI you can also check for any PlayerStates that may have already fired their Begin Play by doing a "Get Player Array" on the GameState. You can loop through them and create the PlayerState specific widgets I mention above and on their OnConstruct they can bind to events on their respective PlayerStates.
So now that's handling all PlayerStates that have already Begin Play, so now you just need to know about the other ones that are joining later. You've already accomplished this by having an event dispatcher you're calling in the GameState when a PlayerState Begin Play fires. This event dispatcher can do the same thing as what you're doing in the loop - creating a specific widget for the PlayerState that joined.
animating trees are expensive for network game?
damn
time to take a break and go to the gym while I digest that lol
thank you so much for your time as always 🙏
Yea I cant make it work lol, It jsut dont replicate
If I set manually in anim Bp it replicates, but cant make it replicate in character BP on begin play
this replciates on client 1 but not on client 2 lol
Don't mutlicast the change.
Use OnRep.
Set the OnRep variable on the server.
Have the OnRep function call to Link Anim Layers and feed in the class.
Both clients jsut stay in A pose
ah nvm
If I set default to non it works
Make sense lol, I had already value I want to change to as def, so norep never gets called right?
All good now, thanks
Correct. Normally only if the value is changed will the OnRep Fire. Glad you got it working 🙂
Learned something new, thank you for help!
does a server complete a multicast before continuing on its execution path?
if its a reliable one does it make sure everyone has received it and then execute the next thing?
actually i thought of a better way
Yes and no - the server will immediately perform the multicast event (on the server), clients will execute it whenever they receive the packet
but the server won't block until clients have executed or anything
For an actor using dormancy, is there any way for the client to call an event when it's left relevancy range?
The reason i'd like to do this is because i want this actor to stay in the world when it leaves relevancy. Dormancy is the most direct way to do this, afaik. But then you lose the ability to know when something has left relevancy, meanwhile relevancy still matters to whether or not replications happen on the dormant actor (when you push a net update).
Edit: hmmm, well i fixed my problem in this case by working around it such that the actor didn't need a "relevancy ended cleanup" step at all. But that's not always possible, so suggestions on alternatives would be nice
I've made a Sound Cue for with a random node that is giving different sounds when multicast
How do I make it play the same sound for everyone?
Don't use a random node and either feed some multicast random value into the cue (if that's a thing) or multicast a random cue
Thank you, I'm going to try feeding the cue with a paramater from server
Relevancy is handled by the Server, there is no way for the Client to know that the Actor was out of relevancy range because all it sees is the Actor Channel being removed, which causes its deletion.
What are you trying to achieve here specifically?
Okay so my takeaways:
-Create main UI on gamestate's beginplay
-Specific player UI components should be their own widget
-Do you feed it in by setting the owning player to the player in question?
-Get the player array in the Event Construct of the main UI and loop through them to create the player widgets
-Set an event dispatcher on playerstate beginplay that you call in Gamestate
This makes sense. I was trying to clean up some logic from running forever once it pulled out of relevancy range. I solved it by changing the structure of the actor's logic so that an event to stop it even if it got interrupted midway through wasn't needed.
It was kind of complicated because it involved a state machine where some of the states had to tick to check for a couple things. In this case, i was lucky that only the server actually needed to keep ticking during that specific state, so clients just don't tick during that state so there's no worry of a dormant, irrelevent actor ticking forever, long past when the server has ended and sent out a stop rpc or variable.
I suppose in this case i could have range checked the distance to the player camera every tick, and compared it to the net cull distance..
-Do you feed it in by setting the owning player to the player in question?
No. You create a PlayerState variable on the widget and feed in a reference to the PlayerState that should be associated to it.
-Get the player array in the Event Construct of the main UI and loop through them to create the player widgets
This will get any current playerstates that exist that may have already executed their Begin Play before the widget is created. You may want to create a Map variable of type PlayerState > PlayerWidget so you can verify if there is a widget created for a player already and add references to the player's widget to this map when it is created.
-Set an event dispatcher on playerstate beginplay that you call in Gamestate
No. You call an event dispatcher in the gamestate when a playerstate's beginplay starts. It should pass through a reference to the playerstate that called the begin play (basically passing a reference to self to the call). This will be used in your UI to then handle any players that join after the widget is created.
No. You create a PlayerState variable on the widget and feed in a reference to the PlayerState that should be associated to it.
Like this?
This will get any current playerstates that exist that may have already executed their Begin Play before the widget is created. You may want to create a Map variable of type PlayerState > PlayerWidget so you can verify if there is a widget created for a player already and add references to the player's widget to this map when it is created.
Something like this?
I guess in total I have it like this so far
You can make the Player variable "Expose on Spawn" and "Instance Editable" this will make it so you can feed it directly into the widget creation node (you may need to refresh the node to see it).
You want to create the widget when the Player Joins, not when the name changes.
Otherwise yep, Getting there.
Within the Player widget you can both read the current player name and also bind for when the name changes.
Ahh okay let me make those adjustments
so something like this
with playerslot blueprint like this?
Yep. That's looking alright. Missing a connection from the Return Value to the Add Child here.
hell yeah
Okay I need to make that map now
Something like this?
