#multiplayer
1 messages · Page 239 of 1
yeah, i run these tests locally
as seen here
main viewport is listenserver
the other 2 windows are client
open level with ?listen argument
2nd client has a slight delay with updating the playerlist
like 1 second or so
both connect to 127.0.0.1
PlayerState's default net updated rate is low, that might be the reason for that and the null elements inside array (which is not a total fix to increment it, you can't know (I guess?) when the array itself and the objects inside the array will be replicated)
yea i thought its just timing and server stuff like i mentioned
https://www.reddit.com/r/unrealengine/comments/18cymdz/player_state_update_is_delayed_on_client/
found some more info
doesn't the gamestate class have an array of playerstates clients can access? i'd use that instead of making my own imo
Hi there, when I'm running a new Unreal multiplayer project in PIE with 2 windows (from main menu with "Host" button), both windows create a server when clicking "Host" in just one of the windows. I'm using a custom OnlineSubsystem as per Sneaky Kitty's video series.
Would someone know the reason for this happening, and how I can possibly fix it?
Yop.
This is because the Array replicates before the actual PlayerState actor replicates.
That's a pretty normal thing. Can happen with all Actors.
Especially if you call a Multicast at the same time.
That's what OnRep is for, and even in there you gotta check if the entry is valid. OnRep will call multiple times in that regard.
What are the Multiplayer settings in the Editor?
Editor preferences:
Do you spot something weird?
"Play as Listen Server" is wrong.
That starts the players connected already.
If you start in the Main Menu you need to "Play as Standalone".
I have tried that - same problem 😅
But it's good to know
both windows create a server when clicking "Host" in just one of the windows
That's more or less impossible. Especially if you play as standalone.
I also get OnlineSubsystem::OnCreateSessionComplete logged two times
Then breakpoint it and see where the 2 calls come from
maybe it's a config file error then, or the "hosting player num" SessionInterface->CreateSession(0, TEXT("My Session"), Settings);
The SessionName param should not be changed btw
Use NAME_GameSession for that.
The actual Server Name, if you want one to show up in the server list, has to be done via SessionSettings.
I will try those things. Thank you!
thanks for clarifying that Cedric
question, wouldnt using the original Playerstate array provided by Epic eliminate that issue like Omnicide suggested? or there is no difference still?
I mean, kinda. The native array is filled locally and not actively replicated. the PlayerState add themselves (and the GameState checks for all of them once).
But if they are sending a Multicast at a point that the PlayerState haven't replicated yet, it will just result in a similar situation.
Well, they being you apparently. Didn't check the name.
Would I also use NAME_GameSession as in this when joining: SessionInterface->JoinSession(0, NAME_GameSession, SearchResults[0]); ?
What you should/could do is, instead of doing a Multicast and shitty delays, is to rely on functions that already tell you if something is valid.
Either you make your own RepNotify PlayerState array, and use the RepNotify to update the UI (still check valid on the entries), or you use the PlayerState's BeginPlay and EndPlay functions to know that a new PlayerState "joined" and update the UI from there. Those two functions will call on everyone anyway.
Yes. There is one other type used by Steam, the PartySession, but you use that usually with Beacons and not normal gameplay.
Wait PartySession is for Steam only?
No, but Steam does use that
Idk, you would need to read the docs
Hmm okay. Also I remembered my problem is NetDriver related (I guess?) rather than the sessions, players are able to do session operations from both steam and egs (with PartySessions)
Hello. There is a multiplayer jump code in the picture. When I test the game, there is lag. How can I reduce the lag?
God.. I was apparently still using SteamNetDriver while giving it connection string I resolve from EOS session..
Is there a specific reason of not using the ACharacter::Jump?
The character is a ball character with physical properties. jump() has no effect.
Is there no place in Actor class where an authority Actor could send an RPC to its freshly "spawned" alterego when a new client joins the game?
Is it moving unrelated of it's capsule parent?
I've been researching for 3 days but couldn't find the solution.
Well there are possible solutions according to what you are trying to do, is BeginPlay itself with non auth filter and/or OnRep properties not useful?
Well you are not predicting the Jump at all.
ServerRPC -> Multicast is a full RoundTripTime before the Impulse is added.
On top of that, doing it like this, or generally using Physics in Multiplayer, will always be shite. You don't have any proper prediction or reconciliation.
Also is Character the best parent for this kind of a thing?
I want to say CMC could interfere with stuff
Doesn't matter anymore at that point. If not using the CMC then Pawn would be enough
CMC turns itself off if you enable Physics
Oh okay, didn't know that
Can you show an example image for node connection?
No, Physics + Multiplayer isn't solvable that easily, especially not in BPs.
Either stick to the CMC and its prediction and fake the physics, or live with the corrections.
Only other thing you can do is to apply the Impulse locally first and then skip the IsLocallyControlled pawn in the Multicast.
But that will only remove the input lag, rest is still gonna suffer
OnRep is called after replication so it's not applicable.
If there was a way to completely override replication using RPCs instead (typically for data the size above replication but below RPC) that'd be interesting, but that's not a thing in Unreal AFAIK.
On PostLogin in the GameMode I can probably do whatever I want from server, it's just weird to do.
BeginPlay might indeed be a solution, to have the new client yell at the server that it's now there. I'll check that.
Overall, it's just weird it does not exist.
https://store.steampowered.com/app/3202400/Ball_Race_Party/ I am developing this game. I wanted to add jumping for multiplayer mode.
Physics-Based Fun: Experience the thrill of realistic physics with a fun twist. Competition and Strategy: A perfect mix of luck and skill-based gameplay. Variety and Excitement: From challenging single-player levels to entertaining multiplayer modes, there’s something for everyone!Join the world of Ball Race Party now! The finish line a...
$3.99
OnRep is called after replication so it's not applicable.
How else could you interact with a proxy before it replicates though 🤔
Thank you for your help. I don't know what to do. I also asked chatgpt but I couldn't find a solution.
is player input replicated or used for replication in anyway by default by the engine?
My example for OnRep was for in case if you wanted to send data with your RPC. If there is no data then there is no need for server instance to do anything, you can just do what you want in client BeginPlay
thinking about gutting parts of the input system in the engine and want to know if it would break any future attempt at multiplayer
I want to say input is handled entirely locally, but I don't have any information to prove that
My answer remains the same. Check "Bang On Balls". That is also using the CMC and not Physics.
I don't have much coding knowledge. I'm researching how I can do it.
no worries. figured Id ask and save myself diving through code if it was already obvious to some people here.
I do want to send data using the RPC. It's just that onRep kind of implies that data is replicated through built in smart replication (which would fail in my case) and not using RPCs.
I guess I could do a dummy property that is the proxy of the true data I want "replicated through RPCs".
I don't follow on smart replication and replicated through RPCs
Replicated variables are the reliable way of syncing data between server and clients
Can you send me the node connection as an image?
If you have a bigish array, like for example 5k int vectors, you can send it fully over one RPC, but it's way too big for basic built-in replication.
Because of that, in theory you can still "replicate" it by exchanging RPCs at the right time instead of the built-in logic.
I am running into issues trying to wire up a ui widget on the client that needs multiple items replicated before it can initialize the default values. The only way I see around this right now is by keeping a series of flags and after each onRep, attempting to wire up the UI, which then checks for each flag before firing, like
OnRep_A { AFlag = true; TryUINow}
OnRep_B { AFlag = true; TryUINow} etc
TryUINow {
If (AFlag && BFlag && CFflag)
SafelySetupUI();
}
But this seems so awful. Is this the way people do it when dealing with client side code?
That's more or less the way. There is no global callback to when all your "items" have replicated, unless those items/properties are trivial types, which is not the case, they gotta be Actors/Objects.
A more clean way would probably be to have one unified OnRep for all of them, and then inside the OnRep you check pointer validity for all of them
Thanks, I will stop beating myself up over it then. Would the unified way be through a struct?
A struct can work, or just really separate properties. You know that different properties can have shared OnRep, right? Something that people tend to think is impossible 😄
That is new to me.
Figured. Up to you really. Also even if you use a struct, the OnRep would be called multiple times, per item replicating
So it's not just one call and done.
Also, a food for thought, if the types were trivial types as I said before then you can use PostNetInit if their owning actor is created from replication as a global callback that would guarantee you that all of them got replicated. In this case your replicated properties would be item tags (GameplayTags) rather than items, and then you just recreate the items locally on client... but then they would not have replication support ofc... something that you can bypass though to support replication is to use a replication manager adhoc actor
A really cool article in pins goes over that (the network manager one, regardless whether u end up using it or not, it's cool to know)
Do know the title of that article? (they are not trivial, btw)
This one, also the whole site is a must read really
also darn a lot pins in there since the last time i looked :P
yeah I figured they are not trivial, so it will involve a lot of work, so ez mode is to go the route of using OnRep and check for pointer validity
Thanks for the help. I can see where this might be a trickier corner of multplayer dev in UE.
Hello everyone, I’m stuck on a replication issue that seems quite simple, but I can't figure out where the error is.
Basically, I have an event (Spawn_Task_1) (inside BP_ThirdPersonCharacter) that is set to "Run on Server". In this event, a Blueprint Actor (BP_Task_1) is spawned on the server, and the newly created object is stored in a specific variable (LastTask1Created). Then, an array inside BP_Task_1 is modified.
Now:
- The BP_Task_1 blueprint is replicated.
- The array inside it is replicated.
- The variable LastTask1Created is replicated.
However, I’m experiencing the following issues:
- If I call the Spawn_Task_1 event from the server, BP_Task_1 is correctly spawned on both the server and the client, but when I check the value of LastTask1Created on the client, the variable is empty (while it is correctly updated on the server).
- If I call the event from the client, BP_Task_1 is correctly spawned on both the server and the client, but when I check the value of LastTask1Created on the server, the variable is empty (while it is correctly updated on the client).
Calling a server RPC from server or an owning client shouldn't change the result, both should run the logic on the server as it is
How/where do you check your variable to see if it's set or not?
Thank you very much for your help ❤️ I check it with the following code. I run it locally on both client and server to see if the variable is correctly updated on both of them
Is this inside your character BP too?
Well most probably, variable seems to be it's own variable
I'm assuming you're testing with listen server and 2 players, there are 2 characters on each client, the owned character (which runs the input event you use for test) and the other player's character
When you trigger the server event from your client, server creates your actor and sets the variable, on the client's character. But when you press your input button on server, it's trying to read the value from server's owning character (which hasn't run anything). And the opposite applies, when you trigger the server RPC from the server itself, it's running on the character owned by the server. And when you press your input button on your client, it tries to check the value of the client's character. But the logic run on the server's character
Just for the purpose of the test, you might want to use GetAllActorsOfClass (or whatever it's named) with class type being your character so you get both character's on the current player and then check both of character's variable. One should be set and the other should be null/invalid/not set
You can check if a character is the one you own with IsLocallyControlled node to put more context/information to your debug log
In short, the instance of character your code runs and you check the value of are different
Hmm I might be wrong about keyboard input events only running on owned character though 🤔
But it should be something similar considering you do see your actor is spawning on both server and client (hence it's working on the server on both cases and should be setting the variable). So I believe you're just checking the wrong character
You're absolutely right my friend! thank you a lot for your support ❤️ So now my spontaneous question is: If I wanted a variable to be accessible by all characters, I would have to set it in each character, right? Or is there a better way to store a variable in a place that is directly accessible to all players? I hope I was clear
It kind of depends on what you're trying to achieve. If every player should have their own different tasks then it can be logical to store it in a player owned actor like character as you do it. If it's a common task for all players, then it's more logical to store it in GameState (there is only one instance of GameState), as it's purpose is (kind of) to hold variables that should be accessible to all players with the context of game related stuff
Yes, the tasks are the same for all players and moreover they can collaborate to solve them, so I think GameState is definitely the right solution for me (I suppose). I'm gonna try, thank you very much 🙂
hmmm, is it normal that BeginPlay is being called first and then OnRep functions?
Nope, can also happen other way round
Which is really fun if the OnRep has something that silently fails if the actor hasn't begun play yet
How could I cull actors specifically for clients that are closer/further from them, and what would be the best way to do this
Right now I have a sphere trace that is on the ThirdPersonCharacter which checks every .1 seconds but its 30000 radius so it takes a pretty big hit on the clients performance
To not render them or to not replicate them?
So is it guaranteed that OnRep will be called first before BeginPlay?
There is NetCullDistanceSquared to cut the replication when something is far away from a client
And for rendering it should be already doing automatically but I'm not sure what kind of configurations are there to customize it
Which is not so much #multiplayer related
Yeah i'll ask in rendering
Both are possibilities, there isn't any certainty which one will be called first
I didn't know OnRep first BeginPlay then was a possibility though
That's the way I was omitting the initial rep, just checking if !ActorHasBegunPlay
And now in another case BeginPlay is first than OnRep
Would NetCullDistance squared be for each specific client for ex: if one player is near an actor that is replicating but another player is very far away it would still send replication to the close actor opposed to the furthest one?
Yup it's per client, except for listen server since it's the server
I have these building objects (similar to the game Rust) i'm trying to optimize if a player is far away from the object, and a player is close but destroys the building object and the net cull distance is set to close. Would I just run Force Net Update when the player gets close to the building object so it'll update its destruction?
I mean if something is destroyed when the player is not there and goes to the location afterwards, should they see it getting destructed?
im trying to create a simple way to destroy ism's and im curious if there is a better way to go about this lol , it works fine and seems to have no issues but as you can see i resorted to having to loop through the possible isms in this bp (which is a large building) ** on true i break the loop and remove that instance *
no but it wouldn't need to be updated? (I am using 0 net update frequency on the building objects)
After destruction tho i'm using force net update
Does 0 frequency prevent actor's destruction from clients too? 🤔
If an actor is out of the net cull distance they are (or should be with default settings) destroyed already
When they get relevant again, they get spawned again
I don't know how 0 frequency would affect that behavior
I see, ty
I have a replicated ptr to an Actor, which may or may not replicate to a client.
So when I replicate a ptr to Actor which is not currently replicating a client, and after 5 seconds the Actor starts replicating, does it call OnRep of the ptr?
how would i go on bout spawning ISMs or HISMs and make sure they remain for late joiners, seems like when i spawn them on server they dont appear for clients?
Is it a constant set of entities?
yea
it wont change dynamically but think of it as a set biome for the play session. so its static to that level at that match
Probably having replicated TArray of transforms should do the trick.
So in your actor with ISM comp create a replicated TArray<FTransform> , replicate it with COND_InitialOnly so it's sent with the inital bunch.
On begin play or OnRep (I would go with onrep, just to be sure you got it with the inital bunch, it might be possible large enough array might take longer to arrive) . So OnRep you add instances to the ISM comp based on the replicated transforms.
Should work fine
If you set it on server after the begin play, don't use the COND_InitialOnly
ah damn i thought this could work but just seemed weird of a solution. so now every client would spawn their own meshes right
what would this do?
You are basically saying to the engine - Replicate it once at the start and don't worry about it, it's not gonna change, so it doesn't check for changes.
yeah well its not gonna change irrespectively its gonna be once filled an array of transforms isnt it?
Is there a way to restart match properly without reopening the level with RestartGame? After I end it its state is stuck in WaitingPostEnd and I don't know how to get it to ReadyToStartMatch again
Well, if it's for example an array of trees and someone destroys one of the trees, you could remove that tranform from the array to "destory" it on clients. So the engine (by default) checks for changes of all replicated properites.
i dont have any tree removal or such, just static meshes around as foliage so i think i can set that condition in?
Hello I have a dumb question, why if I change the GameState within the GameMode with "MyGameState" (before it was "GameStateBase"), when I run the game it doesn't spawn the BP_ThirdPersonChar on EventBegin?
Don't set it for now, if you find polling to be the bottleneck then optimise. It is good optimisation to keep in mind, but you should be good with the defaults.
i see, thanks a lot! i usually get anxious bout keeping things optimized but yeah Thanks!
wdym doesnt spawn it on event begin?
It get's a bit complicated if you want to avoid reloading the level. AGameModeBase::ResetLevel() is useful as it calls A->Reset(); on every actor and resets itself.
I mean that when I run the game, it doesnt spawn the BP_ThirPersonChar at the beginning of the run
While if I set it to GameStateBase again it works fine
And if I try to find GameStateBase within the content browser I dont find it, probably cause it is a C++ class
And I dont find any reference to the BP to use with possess within MyGameState
you gotta right click and new blueprint and then below in AllClasses you have GameStateBase you can chose it and make your own game state inheriting from it
I would recommend going for GameState over GameStateBase as a parent class.
yea it has more functionality^
altho ive never used it dont you have to set the match to start ?
i think thats their issue
Yep, MyGameState is a GameState, cause I read on the web that it fits better to multiplayer
Wdym? Is it an option within the GameState?
Just changing GameState shouldn't change the spawning of pawns, unless something went really wrong.
Wanna share the code for MyGameState?
Actually there's not a code, I just changed it in the BP_GameMode
Is MyGameState a BP with parent class GameState?
Yes
That shouldn't change much, any errors/warnings in logs?
ive been through the same thing, im sure its cause the match hasnt started by default or smth like that
No errors/warnings in log
(I'm running on a listen-server with 2 players if it matters)
Ok also in standalone it goes the same way
What do you mean with "the match hasn't started"?
afaik GameState has a match start or smth like that, however idk since i dont use it. thats whats prolly handling your pawn not spawning in.
since i have my own MatchStart and MatchEnd system and i use GameStateBase so i wouldnt know much
Thanks, that's what I'm trying to implement, but I can't get the match state to ReadyToStart again - after resetting it's in the WaitingPostMatch
Any reason why not call void AGameMode::SetMatchState(FName NewState) manually after the reset?
SetMatchState(MatchState::WaitingToStart);
I'm not familiar with cpp, unfortunately) And it looks like this is not exposed in BP
Yeah, going outside the intended way (reloading the map) will often require some CPP
I do a roguelike with a lightweight visuals so I'm exploring the possibility to shorten load time as much as I can. And that means trying to play the whole game in one level
What does a reset entail?
restartplayer is a thing
I already have the setup with PlayerState copying properties on travel and it works, but there's a thing that I want to get rid of that's driving me nuts - this loading phase that is not covered by the loading screen. I know it sounds like a crutch, but it really sticks out and breaks the flow of getting into the game
Not sure I got what you mean. Reset will rebuild the dungeon and get PlayerState and GameState to defaults. But I can't get the game mode to change state. If that's not crucial than I guess I can live with GameMode being forever in this state after player's death
You don't need to use the built in gamemode states
Is your game multiplayer?
if you're just BP only just use GameModeBase and GameStateBase and put your own state management in there
2p co-op with a listen server
and the game state doesn't actually manage the state, the game mode does
I can still use GameMode's start/end/reset, right? Or if I use RestartPlayer and other manual flow events then I don't need these?
Sure, I didn't state otherwise
Can you please point me to an extensive read on what's happening on StartMatch/EndMatch etc.? If these are just triggering other events like StartPlayer then I would rather do these manually and get better controll of the overall flow
You might want to try reading the source, even though you are doing BP only, it is the most "in-depth" docs UE has and is relatively well commented.
https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Engine/Private/GameMode.cpp#L186
Yeah, thanks but when it comes to dealing with code syntax my brain just shuts off )
I don't often recommend it, but shoving it to GPT asking for line by line interpretation or summary might be good alternative.
Thanks. Already tried it, the result was 50/50 info and BS
In fact all I need for now is to fill in the missing link - how to get the game started without using StartMatch. I already handle the OnPostLogin events to generate client dungeons, but as I reparent to GameModeBase the flow stops there obviousely
I looked for it but it seems to not exist within the GameMode, but thank you anyway for your support ❤️
wait i dont understand, did you find what was wrong or?
Nope, I tried several things but I still dont understand how the GameState is connected to the initial spawn of the BP_ThirdPersonCharacter
i sadly dont know but i faced similar stuff when i used gamestate, hope you find something though. all the best
game state is initialized in game mode
it's hard to follow
look at game mode base, it's less complicated
Random guess would be that you are mixing Base and non-Base versions of GameMode and GameState
Both need to be GameXYZ or GameXYZBase. No mixing allowed.
If your GameMode is a GameModeBase child and had GameStateBase in the GameState Class before and you now made a Blueprint of GameState and set it as the class, then you mixed Base with non-Base.
That proofs it
If you want to swap to GameState instead of GameStateBase then you also need to reparent the BP GameMode from GameModeBase to GameMode
Anyone have any tips for using WithNetDeltaSerializer/NetDeltaSerialize(FNetDeltaSerializeInfo & DeltaParams)
I want to control some packing but I also don't want to send the entire struct every time. I can't seem to find much on this besides FFastArraySerializer using it
Hmm, I see class FNetFastTArrayBaseState : public INetDeltaBaseState, It looks like I store some base stuff here I want to use to compare states when trying to serialize
(the Interface struct, not the child, thats just an example)
Seems like a real pita tbh
Yesterday I asked about RepNotifies that are called after BeginPlay, it turns out that can be two cases and it breaks my "omit initial replication" for objects like buttons for state-ful replication when button i s pressed - sound should be also played. I do not wanna to play that sound on initial replication so I simply used:
if (!HasActorBegunPlay())
return;
but when BeginPlay is called first it will not work. How can I workaround this?
Okay, what are you trying to achieve?
You don't want to replicate the initial value of whatever that OnRep is for?
Oh, you want to not play a sound on initial replication. But what is initially replicated for a button like object?
Is it a bPressed boolean? Wouldn't that be false initially?
Is it a sound that is called when the button is pressed (like the active pressing of it)?
In that case I am replicating "TimePressed" which is used to check if button can be pressed again in ceratin delay to limit "bruteforce pressing" or whatever to call it
Okay, where does the sound come into play?
in OnRep_TimePressed
So you use that OnRep_TimePressed to also play the sound?
Is that a sound meant to be played when the button is actively pressed?
I'm mainly asking because maybe you are using an OnRep for a sound that is not "state".
only to play the sound. Sound is meant to be played when button will actually do the action
Right, keep in mind:
- OnRep/RepNotify -> State
- RPC -> One Time Action
E.g.
- OnRep/RepNotify -> Turn on/off a looping sound
- RPC -> Play a sound once
Using an OnRep to play a sound once might just be wrong, and that's why it gives you so much headache.
eh, I am trying to not use that evil netmulticasts 🙃
Why evil?
What if you press the button and I'm not close to the button.
And you press it 10 times and it gets locked.
And then I come into relevancy range
And get the TimePressed replicated with 10
Why would I need to hear the sound?
I wasn't there when it was pressed.
This is what a Multicast would be used for imo.
You wouldn't play an explosion sound when bExploded is true on a barrel.
this is what I was doing in the beginning
Even if you solve the initial sound, which you could by checking if TimePressed is != 0
You'd still run into the issue for late joiners and people coming into relevancy.
You are right, I forgot about relevancy
RepNotifies shouldn't be used for one time actions like this, at least in most cases.
I'm actually surprised that I have to write this, cause usually people need the explanation the other way round lol.
Try to keep your State to RepNotifies or replicated variables in general, and your one time actions to RPCs. Unreliables ones.
If you want to predict the button press then try to identify who pressed the button in the RPC and skip them.
If the button isn't locally controlled or something like this, send a pointer to the person that pressed the button and compare it locally.
If you aren't predicting anyway then it shouldn't matter. Multicast away.
Your initial question about OnRep and BeginPlay is valid though.
But for other reasons.
Man I'm writing too many single messages, but I'm not really awake yet, sorry :D
no problem
I'm glad you are full time dev(propably?) and you still have time and willing to help/learn people here
guys, is there any standard pseudo random numbers generators to be synced on client/server? I have game that is heavily relies on server rolling dice, thus it cannot be predicted on clients so I was thinking about something like this
Like maybe have a server sending out random numbers list for clients to pick up from. so they are in sync.
You want to use something like a stream where they all share the same seed and then as you increment the stream and "roll" random numbers it will all be determinisic and in sync
Something like squirrel noise is good but unreal has has FRandStream if you dont care about it being good
Oh, that is how it works. Thank you.
I have my own implementation that was done in like a day and has some custom nodes for better BP usability but its also not hard to just implement yourself https://github.com/itsBaffled/BFSquirrel
my squirrel wasn't cmake ready, I will be happy to check yours 🙂
Not sure if mine is "cmake ready" whatever that means (like stricter flags or what)
actually it's amazing. I should be able to predict anything. since my game doesn't mess with character positions at all. smoooooth gameplay
Is there a proper way to change ownership of a simulated actor at runtime? Im getting some weird location mismatch when the owner switches
is there any caveats I should be aware of on this path? like you read it and chuckle about naive noob dev? 
Not really, it just takes a seed and index and does some fancy bit shifting to get a psuedo random number
As long as the seed and index are the same then the output value will be the same
but it's still a struggle to keep index in sync :/
Seed would be shared between all clients and the index would be advanced locally on each client after generating a number
maybe make it time dependant?
Foo shoots a weapon this increments foos index and the RPC is sent to the server with Foos index, so they can generate the same outcome, otherwise you can make the server be only one who can decide what the index is and if the client is wrong or server disagrees it would send back their index so and tell foo they never shot
Oh, client sends index it used. Nice.
We get to do polls now?
Just trying to gather opinions
this looks like you are just trying to gauge interest in a product
My Product Isn't Even Half Finished, I'm actually trying to know if people would want such product or not so I don't waste my time working on it, but If I wanna promote I won't do it here, don't worry I've read the server rules.
Ah I remembered. Isn't it that when it actors becomes revelant it is just spawning like when the game starts? BeginPlay will be called when it becames revelant. Am I right? So the !HasActorBegunPlay() should do the job here as well.
I agree with Cedric on state vs events but to help a little, AActors have a CreationTime that you can use to query against the world seconds to know if its a relevancy related thing
good to know
but theoretically my initial rep omit would work either right? in relevancy case 😂
The order of OnRep vs BeginPlay is still not given.
If BeginPlay calls first you are back at your problem.
yeah
Well you should get onreps before beginplay, assuming it's the initial packet
You've also got things like Pre/PostNetReceive, PostNetInit etc. Those will def call before beginplay does even if the world has already begun play
that's important information also, thanks
Sure, and your Burst Counter, fwiw, has some code to better solve this either way, but I still think a one time sound should not be done via the RepNotify.
I already explained why I did it this way. My first thoughts was right but then I remembered the stuff everyone keeps repeating over and over - don't use multicasts.
Honestly I do so little with BeginPlay for this reason 😄
I always thought it was the other way around, wasn't it considered not safe to call RPCs in BeginPlay because it might not have properly replicating at the moment? So PostNetInit could be waited for such cases. Am I halucinating or mixing stuff?
PostNetInit is client-only
everyone keeps repeating over and over - don't use multicasts.
But this is strange to me. Who is everyone and when does it get repeated over and over? Where did you get that from?
Everything in the freaking Engine is meant to the be used, as long as you aren't using it wrong.
Multicasts are totally fine and viable to be used if what you want to do is send a one time event to "everyone".
ye multicast definitely has a place
So is it a thing for client instances to wait and be sure the connection is properly ready before doing anything multiplayer/network related?
What keeps me up at night is how maddening complex small replication setups can get just due to having to handle State and one time events.
I definietly should stop watching dumb tutorials
Problem is: How do you figure that out?
Also is there any difference between world placed actors vs the ones spawned on runtime?
I'm not sure whether it fires for actors which are already in-world, but it does fire as soon as the actor is spawned via replication
And for an actor which wakes from dormancy I believe also
It being the PostNetInit here?
ye
The shitty thing with this is: When I worked on The Ascent (I think) we had some cosmetics stuff that was controlled by a RepNotify State (as it should be).
But the stuff that was being called there was silently failing if ActorHasBegunPlay returned false somewhere internally.
So I ended up blocking the OnRep at the start with that condition and calling the OnRep by hand on BeginPlay.
I never really had to do that again I think, so I'm not even sure anymore where the problem was.
Some color on a material or so maybe.
I just remember using the old match state system (that still exists btw) and actually using the warmup/pre match start flow, and actors wouldn't begin play until the match state actually went to in progress, so I just learned really early on do try not to rely on begin play
It's funny how all that stuff still exists but it's basically ignored now 😄
Yeah I think I still use that for a Client's project that is round based with warmup etc.
yeah
If you basically want to mimic exactly what UT/gears did.. it's still workable
if a little jank
And I even ran into that issue when updating it from 4.27 to 5.4 or 5.5, where the CameraActor wasn't registering itself to my Manager properly, cause I was doing it on BeginPlay, and the round didn't start yet.
Not sure if that was a bug before the update and I just never noticed.
Probably though.
Yeah, it's actually sad how well that works.
What would be nice though, is if component initialization was post-replicated properties being read in 
but nooooo
WidgetComponent has one of those shady HasBegunPlay things
But it's rare that someone would OnRep a WidgetClass.
void UWidgetComponent::SetWidgetClass(TSubclassOf<UUserWidget> InWidgetClass)
{
if (WidgetClass != InWidgetClass)
{
WidgetClass = InWidgetClass;
if (FSlateApplication::IsInitialized())
{
if (HasBegunPlay() && !GetWorld()->bIsTearingDown)
Does FFastArraySerializer still not preserve order of TArrays? I can't find recent doc about it. If that is fixed it's great.
Order isn't guaranteed no
If you want an order, add an index inside the item struct
It's not "fixed" because it's not meant to, just FYI. Not actually considered a bug
Nevermind, that was a rather dumb mistake - I reparanted the game mode to GameModeBase and left game state's parent as GameState, not GameStateBase. That lead to character freezing after spawn and not proceeding further after OnPossess
Can anyone please share your best practices on how to make the spectator's screen black starting from frame 1? Or disable spectator at all so the players see only black screen or widget until they are spawned as a pawn
Not sure if there is a better approach but I personally make the controller PostInitializeComponents function set its camera manager to black
PlayerCameraManager->SetManualCameraFade(1.0, FLinearColor::Black, false);
and then after I have possessed and made sure everything has been setup on the client I then begin fading it in
pretty sure I do something similar also
Thanks. By any chance is there a BP counterpart of it?
They are blueprint callable, just get access to the camera manager from the controller
Not sure about timing though since post initialize isn't exposed to BP. To be honest I'm the last person to ask about BP, I try stay clear of 🍝 land
Yeah, I meant the PostInitializeComponents timing. Thanks again, will dig into that, I completely forgot about the camera manager
Could always do something scary like go into cpp land and make a BlueprintImplementableEvent that is called from your actors PostInitializeComponents, will be a good learning experience if you have never done it before
I'm from Kyiv, we have a slightly different definition of "scary" around here. Thanks for suggestion and for daily dose of BP despise, but these days it's an issue for me - my brain shuts off when I see cpp syntax. I understand how everything works and I try to follow all the oop best practices and overall keep things neat and clean, but as soon as I see code that I can't perceive into something visual-ish my mind goes "Yep, lets sort it into the nice bin marked "unrecognizeable trash" here"
ah shit, yeah that sucks, definitely scarier.
I think you could do it though, everything is unfamiliar and seen as "unrecognizable trash" until you learn it and understand, I just think BP is severely limiting in what you can use it for (this is a prime example rn), I think if you gave yourself some credit and took a few days to learn the basics before using it with unreal you'd be shocked at how nice it is to work with (I am bias though) but if youre set in your ways of BP then so be it, there are lots of BP only devs out there. I just feel a whole new dimension becomes available when you arent limited to BP graphs 
I could not agree more - I feel these limits all the time, that's why I've already cleared some time to start the cpp course next month. I mean I'm not hopeless, after all I did some custom nodes for my RootMotionSource and array sorting needs, but these were 99% copypasting and 1% of understanding. The issue is not in the core, it's just I trip over the little things in syntax and I and up doing it in BPs. But the more I get into custom stuff the more I need things at least exposed to BP
I promise all you need is godbolt compiler/any IDE and learncpp.com to master the basics. A course might help if you want to be hand held a little but I wouldn't pay for anything.
When I began I just went through a good amount of these videos The cherno and learncpp and it got me most of the way, the rest is just pushing yourself to learn how something works if you dont know it. All this is to say is its not that difficult to get started, its just a bit of time
But I'm glad to hear you have plans to learn it. We're always active in #cpp and #programmer-hangout so if you have any questions or anything we'll always be able to help out
Thanks for the links, I'll check 'em out. I heard all cool kids are doing cpp so I guess 40 is the right time for me to start as well
60 is the right time but 40 will do I suppose 
I'd give +1 for Cherno for extra and simple examples on top of the written material. His way of explaining things and speaking is very clear and understandable to me as a non native english speaker. I use his code review series as a podcast/watch material while eating to pickup common practices that I might not be aware of
Sold
Can someone remind me why i should not run non-cosmetic logic from anim notifies?
I remember reading something about it
Can you give an example
I've heard low frame rates make it inconsistent but I personally cannot verify that.
Also you can usually cancel one montage by activating another so if you don't plan for it correctly it may not be what you want
I can verify that (verify is a big word I don't want to use) had some issues similar to what you mention, like anim notifies not getting triggered with low frame rates (~30fps). It doesn't do any checks to see if there was any notify skipped if there is a jump on the animation time by default. It's possible to enable it by setting MontageTickType to BranchingPoint instead of the default Queued value though
Not sure if this is what you mention but there is this conversation that I remember about anim notifies #cpp message
I feel like there was something else, but that conversation is making a really good point, thanks
I am using anim notify for my tracing
begin and end always called no matter the fps
depends on what you want to do with it, I don't see why it's not okay to use anim notify
I most deffinitly have lots of important logic in anim notify
motion warping. tracing, etc.
In APlayerController on BeginPlay on client, is IsLocalController() always accurate? I want to use it to spawn a widget.
I used IsLocalPlayerController for all my HUD related things, seems to work pretty decent
How would I measure/record simulated bandwidth usage when running 2 clients with one as a listen server?
I'd like to compare before/after a few sets of changes
(not a multiplayer programmer) BUT maybe point you in a general direction in the meantime "network insights". Not sure what it does but it sounds relevant
tyty!
Hi, im trying to update my steam SDK, ive downloaded the newest one (1.61) put the stuff in the folders and updated the Steamworks.build.cs file but its still loading the old one? Is there another way i need to tell the engine which one to use?
What is the best place for client/server events when a player joins? I was considering AddPlayerState in the GameState but if there is a better spot I'm all ears
I assume that's a custom Engine?
PlayerController BeginPlay for example?
But I guess that's too late if you don't instantly start play.
Wont work for clients
You want it for ALL clients?
The PlayerState yeah. BeginPlay would have the downside of needing play to begin first. So if you delay that it wouldn't work.
Yes, IE for a leader board I need to repopulate it and add information about the connected client
If you can use C++, maybe PostInitProperties or so
But would need to make sure the UWorld is a GameWorld in there
Sounds good
Can also have ayour own replicated Array in the GameState and add the PlayerStates to that and use an OnRep to update the leaderboard.
Yeah that could work, is TArray ordering promised to be the same, I assume it is, its just FastArrays that aren't
Yop
appreciate itt
wdym? If you mean source build project then na its through the launcher
I don't think you can modify that without a source build.
Modifying Steamworks.build.cs would require Steamworks to be rebuilt.
oh really? i swear ive had to do this before to set up multiplayer ages ago tho lol i was following this - https://dev.epicgames.com/documentation/en-us/unreal-engine/online-subsystem-steam-interface-in-unreal-engine - unless im blind that doesn't mention source build or rebuilding Steamworks.build.cs, just makes it sound like you change the version number and save lol
Speaking of chatGPT - am I missing something or this info is outdated? I can't find this node anywhere
IsEditor is not a node. It's a C++ function. It's not exposed by default. ChatGPT sucks as always.
Yeah, I though so. Is there any way at all in BP to know if we're running in editor?
Kinda sure, no. You'd need to add a small function via a function library.
Thanks. By any chance is there a solution I can use as a cheat sheet for it maybe?
As in something you can use to make that C++ code?
More of a general guide for dummies on how to expose things like that properly
Hm, don't think so.
You usually create a new C++ class of type UBlueprintFunctionLibrary.
And then you add static BlueprintCallable functions to it.
I already have one with a couple of utility functions. Guess I'm off digging how to add this particular one
E.g.
// Some Copyright notice.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "SomeFunctionLibrary.generated.h"
UCLASS()
class USomeFunctionLibrary : public UBlueprintFunctionLibrary
{
public:
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"))
static bool IsEditorWorld(UObject* WorldContextObject);
};
Written just here, so can have typos and stuff.
Thanks, that's a good start
Can potentially also do it without the WorldContextObject.
You can do return GEngine->IsEditor();, but not sure if there are any implications.
No, it actually is better in my case for several reasons
With the WorldContextObject you would do:
bool USomeFunctionLibrary::IsEditorWorld(UObject* WorldContextObject)
{
const UWorld* const World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject);
if (!IsValid(World))
{
return false;
}
return World->IsPlayInEditor();
}
Thanks. I'm off educating myself on the subject
The IsValid check is redundant I guess, cause the Getter of the World is the Checked one and that will freak out if the World is invalid.
One more thing - what will be the 100% surefire way to define remote client and server side client on the client running listen server? I could not get it to work properly with all the checks available, must've missed something
Usually you check the NetMode
On the remote client it's pretty simple, in the dediserver scheme as well. But I could not find the correct way to define players locally on the listen server
IsLocallyControlled and HasAuthority combo is how I would do that
That was my call too, but it didn't work for some reason. If you say it's a working scheme than it's probably my implementation
If I'm not mistaken on the listen server both players have the authority, that's why it didn't work
Not 100% sure, but technically yes and no - yes like in it's on the same machine, no like in it's not the same engine instance
If you are checking for actors in the server, ofc it would have authority over the actor
The listen server is still a server, but it's running next to the client, no?
Same machine would imply local multiplayer
They do, but only one will be locally controlled
wdym by running next to the client?
listen server is the host player
running its own instance in it's machine
a client will run their own instance
I could be stepping onto BS territory, but it's another game instance, not the one that client is running?
Unless it's Local multiplayer (e.g split screen)
Then everyone run their own instance
picture me as the host (listen server). I run my own Game.exe
where you run your own game.exe
In local multiplayer, there would only be one instance being run
In my test they were both and I thought it was pretty logical) Okay, then it's my implementation I have to check
This would be a dedicated server, whether it runs on the same or a different machine than any client
You mean both are authority? ofc you are checking as the server
the server have the authority of those actors
as for the isLocallyControlled, it will only pass on the actor that the server is controlling
A listen server has authority over all networked actors (same with dedicated servers) but it wont be locally controlling all actors, only the local ULocalPlayer to that instance will be considered LocallyControlled
Thanks. I will tripplecheck my setup then
Yeah, thought that too, but doubted myself
more than checking the setup, try to understand what it actually does and the context
probably good time to read the pinned materials
"It is always a good idea. But not in this case" (c)
you know those nodes are covered in the pinned material right? read exi's compedium and wizard tips and trick.
what's not a good idea is asking chatGpt here
but you do you
Your answers confirmed that I got it right the first time. And when that didn't work I began to question whether I got the overall authority thing right. But my bet would still be on the realization, not the principle behind it
Yep
Thanks for letting me, really appreciate it
das what we're for 
Locally control checks if the actor is controlled by a local controller or not
so you won't get 2 true here, ever since character can only be possesed by 1 controller at a time
And this is for HasAuthority check
notice it's all true on server because server have authority over the actors
while it will fall false on clients
Is there a way to quit a specific PIE window instance without ending the game for all? Similar to how you can join late
I did it with a QuitGame from console if I recall it right
Just tried, quitgame isnt a command, I know quit itself doesnt work though it will end it for all instances
I did pretty much the same and it din't work as expected. And until I don't rule out the "pretty much" part I don't see how I can proceed with it
Sorry for misleading, I did it with the node in my UI
yeah that would just call the console command quit
I'm asking if I could quit a specific window but keep the other two active
that also terminate all instances
Not closing the PIE window but there is disconnect command. Also a complementary reconnect to simulate a reconnection after disconnecting
Guess I tested this only on the standalone, not PIE
Yeah thats not bad, gets me closer but I am still on the hunt 
all good
What in the name of waifu am I looking at
How can you avoid network saturation when a big TArray gets replicated when player joins? Is there some way to send parts over several frames?
It would have to be pretty massive for you to hit that limit but in any case this might be helpful https://vorixo.github.io/devtricks/data-stream/
Hoooow big is big?
Like, worst case is about 5K of a 6 bytes struct. 24KB in total.
Which sounds like not much, but I can have quite a few actors that can trigger that.
During gameplay everything is alright, thank to FFastArraySerializer. But damn the joining is tough
yeah, I mean in property replication terms that's gigantic
I'll try to do some custom RPC based replication. Or perhaps I could use mass.
If it has to be a UPROP, not much you can do really
24KB I think fit into a single reliable RPC, so that should be doable. Just mean I don't replicate it, I have to send all edits through rpcs.
And somehow find a way to send data to new clients post login. Of course there is no post login on actors themselves... sigh
Last time i saw someone needing to send a lot of data was when we had Client based SaveGames on The Ascent that had to be sent to the Server upon joining
I think that was done by splitting it into multiple smaller RPCs that just send a byte array that gets plugged together on the other side or so
Ok funny behavior, and need some enlightement.
I've got a Property, no matter the type. Let's said a int.
it's replicated.
In some conditions, with bUseNetOwnerRelevancy Checked, if i change this property from a (what i seem) a static function call, the change isn't replicated, i need to catch ->ForceNetUpdate() to catch it.
Any code examples for that?
ReplicatedActorCtor :
bNetUseOwnerRelevancy = true;
//From Static
PointerOfReplicatedActor->ReplicatedVariable++; // np replication
PointerOfReplicatedActor->FunctionThatIncrementReplicatedVariable++; // no Replication
PointerOfReplicatedActor->ReplicatedVariable++;
PointerOfReplicatedActor->ForceNetUpdate(); // Replicate
//From non static
PointerOfReplicatedActor->ReplicatedVariable++; // Replicate```
Basically.
Didn't push the test so far after.
The function is also called from an UI, on NativePaint, Maybe it happen before net have compared previous value ? but if it was the case, the next compare round should catch it, that why i'm a bit confuse.
our game splits the initial sending of enemy data into smaller groups each sent as an RPC and just maintains non-replicated arrays on server and client, synced via an array of updates that is filled out every time the actor replicates
you do run into issues with initializing things in order, waiting til all data has been received before interacting with anything in the array, etc.
we have between 4-10k enemies at a time so using fastarray replication doesn't really work
or at least last time i tried it, it wouldnt let me replicate that many structs at a time to a joining client
Does anyone know a solution to this issue when switching ownership during runtime on a simulated actor?
Is that ball a Pawn?
staticmeshactor
to be accurate I should have swapped the green and blue during the second stage. Because the rubberband only happens on other clients. The new owner sees it smoothly
So you have an independent StaticMeshActor rolling along the floor.
Is that using any kinda of physics or ProjectileMovementComponent or so to be moved?
I'm not sure why setting the Owner would have an impact without any other code interacting with that.
im using smooth sync plugin to have physics client auth. When the owner switches that new client is now controlling the replicated transforms
here's a more accurate professional illustration lol
Puh, never used that. Was Client 2 owner before that?
Or are you saying Ownership changes from Client 1 to Client 2
xD Drawing isn't helping much haha
Yes, Client 1 was the last owner, client 2 becomes the new owner
that sounds painful as heck
ya'll need Δcompression and custom transport fr
And Client 1 gets the correction?
Yes
That would make sense then, because Client1 was forward predicting, so its Location of the Ball was ahead of the Server.
While the Location of the ball on Client2 was 1/2 Client1_RTT + 1/2 Client2_RTT behind.
Once the Owner changes, the local Location of the ball for Client2 becomes the new truth, which is a past version of Client1's Location. Once that new information goes to Server and back to Client1, it will get the new Location, which is in the past.
It would be easier to understand this if you put all 3 views below each other.
ah, gotcha. Just made more sense to me that way
yes exactly, so thats what I was thinking too, but I have no idea how to fix this.
This is how it looks like at some Timestamp X when Client1 is the Owner.
If you would have all 3 PCs next to each other and see their screens.
Now if Client2 becomes the Owner, this would reverse.
If you would want Client1 to not get a Correction, you'd need to teleport Client2's ball into the future, so that the replicated location later down the line aligns with the green ball on Client1. That's not really possible and also quite the correction for Client2.
hmm I would think since client 2 is the new authority/truth even the server would be behind equal to client 1
You could teleprot Client2 to the location of Client1, then Client1 would get corrected to Client2's location in theory.
But if you just accept Client2's location, then I would assume that the red ball goes 1/2 Client2 RTT backwards, and green another 1/2 Client1 RTT.
And you get your correction.
In other words, you can't really avoid this.
damn thats what I thought lol
the downside to client auth
would trimming down extrapolation/interpolation help at all?
Low ping and and a higher threshold for teleporting so that it smooths this out more could help.
But you'll notice it either way I guess.
Yeah, I mean it's not often that someone switches Owner in the middle of movement.
You can try hiding it somehow, but I don't know what your game is about and why this is even possible.
game is using physics pretty heavily in weird ways.
not smart enough to write out a prediction or resimulation script even know its a thing in 5.4.4
kicking a ball using physics is basically what im trying to accomplish in this scenario passing between two players
How big is an empty TArray<ESomeEnum> as part of a replicated struct?
Will it just not send anything over the network if it's empty and only changes from the default struct state will replicate?
You where right and it worked perfectly! Thank you very much for your support ❤️
Did you turned off built in movement replication if you are using smooth sync?
yes
Does Chaos destruction replicate if I mark replicate movement for an actor?
proabably, but the issue will be stability when multiple players interact with the physics
you will have to do some work yeah
have you tested?
maybe the fact that it broke is, but I very much doubt the movement of the individual pieces is
Good morning everyone 🙂 In the screenshot, you can see BP_Task_1. The goal is as follows: when a client (or the server) clicks on a square, the color of that square should change on all clients (and the server).
So, what I thought of doing is enabling replication on BP_Task_1 and all its components, then changing the color using a Run On Server event. I've seen this method work in other cases (like when spawning a BP_Actor), but in this case, I don't understand why it's not working.
PS: If I call the RunOnServer event and immediately after that a Multicast event, the colors update correctly. However, the problem is that the event is then called once for each client, and I'm not sure how correct that is, considering that replication is already updating everything on all clients (although only certain things, apparently) based on what happens on the server.
Thanks a lot to anyone who can help 🙏 ❤️
- Replicating Components is very often not needed. It allows Variable Replication and RPCs to go through them (Server/ClientRPCs only if they are owned by the Client), but most of the built-in ones don't have anything to replicate.
- Color is changed via a DynamicMaterial having its Color Param changed (usually), or the whole Material being swapped out.
- Neither of the two is replicated, so you can "un-replicate" the Components again.
- Using a Multicast works, cause now you are replicating the change, but a Multicast is wrong because the Color is a STATE change.
- Use a RepNotify Variable with the STATE data you want to sync between everyone. E.g. the Color itself. If you need to replicate more than 1 variable at once, make a Struct and replicate that.
- In the OnRep_YourVariable function that gets created due to marking the YourVariable as RepNotify, grab the Variable and set the Color in whatever way you ended up implementing the color change (e.g. set the Dynamic Material param or assign the Material).
- Bonus Point: ServerRPCs and ClientRPCs (not MulticastRPCs) only work on Actors that are owned by a Client. Specifically the ServerRPC will be dropped if the Client that calls it isn't the Owner of the Actor. If you need multiple different Clients to communicate with the replicated Actor via RPCs, then you are in need of a proper Interaction System that usually routes its ServerRPCs through the PlayerController or PlayerCharacter, or a replicated Component on them.
I've been having some replication issues with general movement where all movement works fine when the client is near the server player, but the client desyncs a bunch when far from the server. is this some sort of culling problem, or could my replication code be off?
if anyone could help me i would much appreciate it, and pls ping if you need more info.
are you using the CMC
i have no idea what that is
oh yes
Try setting bAlwaysRelevant on your character for testing purposes
I'm assuming you're using listen server
@thin stratus @pallid mesa I'm kind of stuck at 99% completion for my partial client authority solution
Routing:
Server >> SendClientAdjustment() ➜ ServerSendMoveResponse() ➜ ServerFillResponseData() + MoveResponsePacked_ServerSend() >> Client
>> ClientMoveResponsePacked() ➜ ClientHandleMoveResponse()
When granting client authority, the server assume's the client's location (up to a limit, and has an alpha representing how much it assumed, but that doesn't matter atm)
But the server always sends the client it's location, which in this case is the client's own location but latency seconds in the past
However, when calling Super::ClientHandleMoveResponse(MoveResponse); the client overwrites it's own location with the location received from server
So I handle it like this:
// Cache the old location because the server will apply our own past authoritative location when calling Super!
FVector OldLocation = UpdatedComponent->GetComponentLocation();
Super::ClientHandleMoveResponse(MoveResponse);
FVector NewLocation = UpdatedComponent->GetComponentLocation();
// Clamp the location to the server's authoritative location based on the authority alpha
const FVector ClampedLocation = FMath::Lerp<FVector>(OldLocation, NewLocation, 1.f - ClientAuthData->Alpha);
UpdatedComponent->SetWorldLocation(ClampedLocation, false);
So the above 'issue' is fully handled. It works as expected.
Except then ClientUpdatePositionAfterServerUpdate() further overwrites what I just did to prevent ClientHandleMoveResponse() from overwriting it. ClientUpdatePositionAfterServerUpdate() is called from TickComponent()
I can prevent this from happening by setting ClientData->bUpdatePosition = false;, but then it doesn't get updates for anything being applied in OnClientCorrectionReceived()
ClientHandleMoveResponse() ➜ ClientAdjustPosition_Implementation() ➜ OnClientCorrectionReceived()
So I'm at a loss of how I'm meant to prevent the location being overwritten while still allowing everything else to be sent through
I can push this if it helps
hey, if I have an actor set to DORM_DormantAll, lets say its a door, and It gets interacted with and I call FlushNetDormancy and I update the value, all current clients see it updated but new connections see the old behaviour (or at least its not calling the OnRep for the variable that was updated). what should I do in this case
Hi does anyone have any info on how to setup the newtork prediction plugin to work with chaos cars or have any other fix to stop the jittering apart from smooth sync? :(
I can see someone else also asked this on the forums but no response 6 years later https://forums.unrealengine.com/t/late-connection-and-dormant-actors-replication/445893
Hello. Suppose that we have an actor that is initally dormant. We change some replicated variable on it and make a dormancy flush. Then some client connects to server. Will the client receive that changed replicated variable even if this actor is initally dormant for him? And if not, what to do in such case?
Imagine in fornite you interact with a chest and its in an opened/used state, they surely have those dormant so what am I missing
okay im really lost now, I have an actor placed in the level with a replicated value. If I update that value and a client joins late they dont see that new value? The actor has
bReplicates = true; in the constructor. What is going on...
What value? I don't remember having an issue where the late joiners don't get the replicated variable updated.
omfg
Its because I set the actor hidden after it played its animation. hidden actors dont replicate I suppose
Yeah they don't 🐱
is that some how common knowledge and I missed it or is it something everyone is supposed to figure out
what a waste of time over the dumbest thing.. like what If I had some kind of network manager with no representation, why does SetActorHiddenInGame dictate replication... so weird in my opinion
yeah, epic is playing sick games here by assuming...
bool AActor::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const
{
if (bAlwaysRelevant || IsOwnedBy(ViewTarget) || IsOwnedBy(RealViewer) || this == ViewTarget || ViewTarget == GetInstigator())
{
return true;
}
else if (bNetUseOwnerRelevancy && Owner)
{
return Owner->IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation);
}
else if (bOnlyRelevantToOwner)
{
return false;
}
else if (RootComponent && RootComponent->GetAttachParent() && RootComponent->GetAttachParent()->GetOwner() && (Cast<USkeletalMeshComponent>(RootComponent->GetAttachParent()) || (RootComponent->GetAttachParent()->GetOwner() == Owner)))
{
return RootComponent->GetAttachParent()->GetOwner()->IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation);
}
else if(IsHidden() && (!RootComponent || !RootComponent->IsCollisionEnabled())) // <<<<<<< Here was my issue I think
{
return false;
}
i wont forget it next time, ill tell you that much
Said network manager would probably be marked as AlwaysRelevant or similar.
yeah but still my point stands, its a bit of a gotcha
sorry I didn't want to distract from your question
No its fine don't worry about that 😄
100%
That question is so technically involved that I need a coffee first anyway haha
the server assume's the client's location
"Assume" as in forward predict or do you mean like accepting it as truth?
But the server always sends the client it's location, which in this case is the client's own location but latency seconds in the past
Right, that's what the SavedMoves are for (usually), so that a correction doesn't cause the Client to teleport all the way back.
However, when calling Super::ClientHandleMoveResponse(MoveResponse); the client overwrites it's own location with the location received from server
Eh. That's weird.
Actually, why does the Server send a MoveResponse that isn't just an Ack anyway?
Ah okay, you want everything else to come through, hm. Not sure that makes sense to me actually.
Accept as truth up to a certain limit (distance)
Applies client's location to itself
Yeah I guess.
Hm, but why is that all happening anyway? If you enable ClientAuth, the Server shouldn't cause a Correction.
See ServerMoveHandleClientError
Right, lemme open Rider.
And in particular ServerShouldGrantClientPositionAuthority
So you want to give the Client Position Authority, but not as strong as the default one?
Just up to a larger threshold?
Wouldn't it make more sense to just increase that threshold on the Server so it doesn't even send the correction?
I'm probably just a bit confused at the start of trying to understand this.
The default one = ServerShouldUseAuthoritativePosition?
That prevents it sending anything whatsoever, it is named poorly, its not just position
But it sounds strange to me that you want ClientAuth (in whatever shape or form) but at the same time you get correctiosn send?
OK so let me walk you through it
Well, yes, right, because the CMC, by default, only checks Location.
So if you want to, e.g., compare Stamina and still correct based on that, then you get your problem.
And now you want to get rid of the Client applying the Location, but keep the correct Stamina etc.
I'll think about it a bit and look at the Tick function.
Don't want to keep you awake much longer.
Can talk in 8-10 hours about it. Then it's evening here and you should be refreshed :D
In ServerMoveHandleClientError it checks if a Snare is going to be applied
If so it calls InitClientAuth which adds to ClientAuthStack.Stack
Then calls ServerShouldGrantClientPositionAuthority()
If it should grant authority, it applies the client's location to itself
// If the client is not within the maximum allowable distance, accept the client position, but only partially
if (LocDiff.Size() >= Params->MaxClientAuthDistance)
{
// Accept only a portion of the client's location
ClientAuthData->Alpha = Params->MaxClientAuthDistance / LocDiff.Size();
ClientLoc = FMath::Lerp<FVector>(ServerLoc, ClientLoc, ClientAuthData->Alpha);
LocDiff = ServerLoc - ClientLoc;
}
else
{
// Accept full client location
ClientAuthData->Alpha = 1.f;
}
if (ServerShouldGrantClientPositionAuthority(ClientLoc))
{
// Apply client authoritative position directly -- Subsequent moves will resolve overlapping conditions
UpdatedComponent->SetWorldLocation(ClientLoc, false);
}
The stack is sent to the client also
Its received in ClientHandleMoveResponse()
But now that the server has assumed the client's location, it sends the client's location back to itself, latency seconds in the past
And the client tries to apply this location to itself, and basically gets an even more severe desync as a result
So it parses the stack that it received from the server to learn that it has location authority, and shouldn't apply the server's location, because it will be it's own in the past
That's what this is doing
The problem is that, immediately on the next tick, unless bUpdatePosition is set to false, it is going to overwrite it
But if bUpdatePosition is false it can't apply Stamina etc. either 😐
I need it to apply Stamina etc. but not the location
So the solution is either: Apply Stamina and anything else that isn't location, or prevent it applying location while client has authority, or revamp the whole thing so this isn't a factor if its possible, I doubt it 😄
Woops, got sidetracked into #blueprint .
But a Client that receives any kind of correction would replay its local moves, right? So the correction wouldn't be that big anyway?
Assuming the Server continues simulation with the partially accepted Location, and then client setting that locally and replaying its moves that were send to the Server, it shouldn't cause any further corrections, as thye are aligned again then.
Let me record a video
I'll show you with and without ClientData->bUpdatePosition = false;
First with (working as intended except it won't be updating Stamina)
Second without (desync because bUpdatePosition causes it to overwrite the applied location from the SetWorldLocation that follows Super::ClientHandleMoveResponse)
I have a 4 day weekend so not a big deal 😄
If you grab the tmp-dev branch you have this stuff setup
So why are you actually getting a correction in the second one? Cause you Sprint and the Snare doen't allow that?
So the Stamina usage of Sprint is mis-predicted?
The stuff that happens in TickComponent is the replaying of the local moves.
The debug 100 Stamina in your screen aren't updating. So what is actually triggering the correction then?
Like, why is the Server sending a correction in that specific example?
I assume you predict the Snare locally, and since it's a Snare that happens due to the Overlap, this should be all in sync anyway. Server and Client would enter the Snare at the same CMC timestamp.
The example of running into something that applies a Movement change is imo not even something that needs special care.
I don't sprint there at all
The correction is the client applying it's own location the server sent back latency seconds in the past
Yeah, but why is the Server sending it back?
Or rather, why is the Server sending it back in form of a Correction?
Dunno 😐 Server applies client's location to itself and server sends its location, not sure why
What is the Condition for the Correction here
But you are getting a Correction and you shouldn't.
First video - sprinting through it without setting bUpdatePosition to false -- desync but no stamina issue
Second video - set to false -- no desync but stamina gets out of sync because it isn't being applied
The snare is sent via a correction
Nah coz its usually from a damage event
Think of warrior hamstring from WoW
Right, cause the Overlap wouldn#t cause that issue otherwise.
The overlap would work fine with a local predicted, the 'slow' is literally a local predicted snare
Okay, but that's all still somewhat normal. The Server will creat a ClientAdjustment.
But in this case the overlap is doing an auth check and its not predicted
Just for testing
The Client will apply the Server Location and then replay its local Moves.
If you don't apply the Server Location, it will still replay the Moves.
Which is what happens in the TickComponent function.
Yeah so its replaying the moves where the location gets overwritten, right?
That's what I'm not sure how to handle
Well, kinda
Can I pass this new location into the local moves, to overwrite them
In theory the Client is supposed to be at a Location that is now "correct" and replaying the newer Moves makes sure that all Input given that isn't processed by the Server yet is re-applied based on the new "Start Location".
If you don't update the Location at all, then the Client will apply its Moves to the current Location.
So you'd basically move more than you want.
If you apply the Server Location and that is not the same as teh Location you had in that frame, then you have a normal correction.
If you want this to remain smooth you'd need to make sure that the Client sets its local Location to the Location it had in that frame.
Hmm
Then replaying the moves would result in exactly the location it has right now.
No there is no such thing. The SavedMove is used to replay the Input basically.
The SavedMoves are in fact buggy in theory.
An example:
- The Client moves straight forward, forever.
- Another Client applies a Stun to to the Client that lasts 0.2 Seconds.
- The Server applies that Stun and replicates it to the Client.
Now at this point, the Client receives the corrected Location, as it wasn't meant to move in a Frame it did, and it will reapply the SavedMoves.
The problem that comes up is that the Client doesn't know how long it is stunned for.
The SavedMoves only have the Input, so it will try to move again and get corrected again.
The Client would need to know, in its SavedMove, that it is Stunned. But SavedMoves are created based on current local information and the Client wasn's stunned when it recorded them.
So in theory, one would need to go over the SavedMoves and update them to reflect the actual Server data.
That's what Overwatch does at least, and you can see that in their Video about the NetCode.
Timestamped
Does putting the client auth stack into the saved move help? Just not sure what to do with it from there
Hmm I'll watch that tomorrow
The part shows that the stun coming from the Server updates the client buffer.
Aka our SavedMoves. He also goes on to say that the Client KNOWS how long they are stunned, so they are fully synced up.
Now, you don't need to plug this information into the SavedMoves fwiw. As long as the Client has all the information locally to know that it is stunned in Timestamp X it can replay the moves and get the Information from whatever holds the Stun information.
That's also a reason why GAS + CMC is such a shit show.
But for your specific issue, I think all you need to do is change the code that applies the Location Correction to only apply the Location of the Server for Frame X if it's a Location correction, and otherwise apply the Client's Location of that frame.
Or even better, let the Server send the Client the Client location and not the Server's.
So it basically comes down to finding where it's getting overwritten in tick component as a result of that bool and handling it there
ServerData->PendingAdjustment.NewLoc = RelativeLocation;
}
else
{
ServerData->PendingAdjustment.NewLoc = CharacterOwner->GetBasedMovement().Location;
This is in ServerMoveHandleClientError
Or there is more a bit up
But the PendingAdjustment.NewLoc is the thing you could just set to the Location the Client told you.
Then when the Adjustment reaches the Client, you allow it to override the local Location.
Cause replaying the Saved Moves will bring it back to the right location anyway.
Oh so I can just throw this in here
Is that your code?
I think your problem is just that the Server sends the Wrong Location back.
It's totally fine for the Server to send a Location back when the Snare hits.
But that Location must be the one that is "correct".
Idk where that code is now. Don#t have the repo open at the same time.
But assuming the Client send you Location XYZ in Frame X.
If Snare hit in Frame X, the Server has to send back XYZ to the Client.
Otherwise, when overriding the Client location later down the line, the replaying of the Moves will put you elsewhere.
If the Server in Frame X has a different Location then what the Client sent, but the Location is allowed, then you can't send back the Server Location.
Or well, you can, but you'd need to do the same check locally and see if the Client location of Frame X (not the current one!) is within the threadshold. If it is, you apply the Frame X Location, otherwise you apply the Server Location.
But it might be easier to just fille the NewLoc with the Client's Location if it's in the Threshold.
I updated it to this, and maybe I'm misunderstanding what you said but I thought that would do it 😐
I really do gotta go to bed tho 😄
Yeah in theory that should do it.
You'd need to further debug why the Locations don't align.
Hello, is it possible to run a packaged dedicated server and join with an editor client? And is it possible to do it the other way around, e.g. have a dedicated server running in the editor, and join it with a packaged client?
pretty sure you can do the first thing, pretty sure you cant do the second thing
Overall, you shouldn't do either.
Even if you manage to, I don't think this generally leads to a good thing. PIE is just way too "special".
does anyone know how to handle steam kick widget for the client.
I checked gameinstance->Event NetworkError but dont think thats what i need since correct reason is not there
using advanced steam sessions
how should I call the OnRep_ function to listen server with the old value before replication?
Should it be executed before changing the actual variable and pass into param var before change?
like:
OnRep_SomeVar(foobar);
foobar = 5
``` ?
Yes
Does steam have a kick functionality?
I only know kicking from the UE side of things
If i want to have a replicated variable that contains information hidden from other players, should i store it on the PlayerController or on the PlayerState with a OwnerOnly Repcondition?
const Type OldValue = CurrentValue;
CurrentValue = NewValue;
OnRep_Value(OldValue);
+- Mark Dirty Push Model sfuff
not using push model
Both is fine, depends on the data
Right, you should though fwiw
OnRep stuff stays the same though
but should I then mark all vars as dirty or can I use replication system in the old way as well?
a reference to another player's playerstate specifically. I'll store it on the playerstate then, thank you!
Specified per property in the GetLifetimeReplicatedProps method
Ah okey
In theory you just wrap all places you set or change your property with a function so you can place the OnRep and the mark dirty stuff there
Then it's in more or less one place
I didn't dive into it but - why should I use it?
Without it the engine polls every frame if the property changed. That's expensive
With it you tell it when the value changed
ah I get it
so I think it will be worth, but for now I do not have any problems with bandwidth
It's not a bandwidth thing
It's a CPU/GameThread thing
The engine spends time on figuring out if the properties changed. That's time lost for things that you want to do with gameplay
got it
yea it has one. i did follow Ryan Laley's tutorial instead. the approach with using options string and opening level with custom string option worked for me
trying to get the invite friend to session work now instead because for some reason its not working when using invite friends overlay
looks like its not working at all.
I need a sanity check. For guns, I’m doing client side hit detection. For rockets and other slow projectiles, I’m spawning them both on the client and the server and then syncing up the client version so it’s in real time. The problem is, I’m doing client side movement via physics so when client B tries to run over client A, it hits a brick wall because A is being interpolated to B. Is there a better way of doing this?
On that topic, is there a way to spawn a projectile on the client without having to wait for the server to confirm, then interpolate that server-side projectile when the server-side one has been spawned?
If a component ForceNetUpdate on it's owner, does it also force component's replicated property to replicates ?
Yes have a look at how unreal tournament 4 does it
hello , i think its rubber banding or what , but my client car facing some jittering issue , but heres magic when i switch on PhysicReplicationMode to interpolation then all works good
but when i packaged my game and test on steam server it start showing same jitter effect , PhysicReplication done not work on package build ( packaging in developement mode )
is there any solution guys
here is video regarding issue i am facing
They use a projectile movement component, whereas I’m trying to do it all via physics
Is your game PVP?
Yep
One option I’ve seen is to create a global list of projectiles that keeps track of everything, but that doesn’t seem very elegant or performant.
Or I could spawn a dummy projectile and simply despawn it when the ping comes back saying the server projectile has been spawned.
I haven't seen how games deal with physics interactions in a pvp setting other than rocket league but I do think it is quite tricky
Hi does anyone have any info on how to setup the newtork prediction plugin to work with chaos cars or have any other fix to stop the jittering apart from smooth sync?
Is there any way to get a String out of a Unique Net Id?
I want to put a value pairing into key storage, but it seems like the UniqueNetId is an opaque pointer where I don't know what it's pointing at.
I'm assuming that's because it's the front for a variety of different interface contracts?
Hey guys, quick question, does anyone have any resources deailing with GAS and Seamless ServerTravel speciically, are there any gotchas to watch out for with ASCs and ServerTravel for Lobbies of players, either with dedicated servers or listen server Sessions
There should be ToString method?
Don't have editor to check rn but pretty sure there is.
That's what I was expecting [Image 1].
Digging through the definition of FUniqueNetId in CoreOnline.h has a lot of comments referring to opaque data.
[Image 2] It does have a few String returning options which Im betting are overloaded for specific platforms
I'm figuring out how I can use it for my purposes.
Did you try to break this struct first and then get to string the variables the struct holds?
Hey guys, I have a game like Rust. Where there is a lot of individual building pieces (actors) I have their net update frequency to 0 and i only force net update after damage, destruction, etc. I also have them set to Always Relevant but I fear this setting is taking up a lot of bandwith on servers with a mass amount of buildings, how can I disable Always Relevant and still have builds load in/out for client and updated correctly?
Hello, I have a sit on kayak mechanic, but when my character sits down, the client or server sees it as incorrectly seated. These are my codes for sitting on the kayak and this is how it looks when I sit down. Where do I need to replicate in these codes?
This is what it looks like when you sit down
Use OnRep variables for the state of things. When the actor becomes relevant for a client, the OnReps can trigger whatever changes you need to have it displayed correctly. The only thing this wouldn't handle right is if you wanted to have buildings visible outside of relevancy range... in which case you may want to rethink using individual actors for every building.
How about for spawning in the buildings, say someone joins the server far away from a building then runs towards it. How will the server know to show it to the client?
That's what relevancy handles with replicated actors. The server would automatically tell the client to spawn the actor... When the client moves far enough away, relevancy drops, and the client is told to destroy the actor on their end.
How would I handle this relevancy?
For some context, these are my replication settings for my building object actor atm, whenever it is destroyed/damaged I just call force net update
It's handled automatically so long as you have IsAlwaysRelevant unchecked. You can then specify the relevancy range which is a squared value, so if you wanted something visible to a client at 10000 units away, you'd need to enter 100000000 for the value.
There is also a function you can override in C++ called IsNetRelevantFor which can allow you to have your own conditions.
I just disabled AlwaysRelevant and then spawned far away from the builds walked towards the builds and they won't load in.
As far as I know, yes, but not for every situation. For example we usually don't use repnotify for urgent, one-time updates.
I think if you have the netupdatefrequency at 0 then relevancy probably isn't checked either...You could probably keep the update frequency to a high value like 5 or 10 seconds and use ForceNetUpdate as you want. I'd imagine this would limit the CPU time required for each actor pretty low since it doesn't have to keep updating everything... And OnReps should function just the same - they'll check if they need to be pushed when you force them or one of the built in timed updates occur.
Ah I see I was just wondering... wouldn't update frequency at 5 or 10 for every single building actor cause a ton of bandwith / cpu usage with 1000+ building actors? Or is Always Relevant more detrimental to performance?
I think that's more of a "you need to profile it" kind of deal...
AlwaysRelevant can be bad (but not always!) if you have a NetupdateFrequency every frame and yea, if you have a lot of those actors. If you're using individual actors to make up parts of your buildings (effectively making each "building" dozens or hundreds of actors?) it may be time to consider using a single actor for a "building" and its "parts" (which can be actor components that add meshes and and the like and maintain the part's state that you can add at run time) to limit the amount of relevancy checks, updates required, etc that the server would need to do.
-@sinful tree Sorry about the ping- Do you have any idea where I should replicate in my blueprint? I don't understand what part I need to replicate.
It's not really answerable based on what you've shown here....
If this is something that is triggered by an input from the player, then you'd probably need that input to send an RPC to the server, the server determines the variables that would need to be used (like your CanSit bool) and set the state in a replicated OnRep variable. You'd then use the OnRep to adjust the visual state of things.
End result is always:
Server Sets Replciated Values
Client (and server) consumes those values to do visual things
Actually, the logic is like this in my system. The variable I call can sit controls the seating conditions. For example, when I jump to get out of the bot, I don't sit down again, I need to jump once more to sit down. If all conditions are met for me to sit on the boat, I run the “Check for and Enterboat” event. In that event, I transmit the information about which socket I will sit on to the enterboat function, and in that function, I use attach actor to actor and attach the player to the boat, close collision and make the “in boat” variable true. The in boat variable is also used in the animation blueprint, so when we sit on the boat, I make the character in a sitting position.
Event Tick runs on client and server. Your bool isn't replicated in that event. That means you're setting that boolean locally only if you are setting it anywhere.
So while you may set the value on the server, if it's not replicated, the client woudln't know about it. If you set it on the client, the server won't know about it.
Do I need to replicate the can sit boolean? Already if can sit is true, the event “Check for and enter boat” will work in local in both
If you're somehow doing it on both based on some wierd set up, then it may not be in sync since each side does their own thing with the actor. It's only through replicated properties and RPCs that anything gets communicated.
Actually I don't do any replication in this system, because I tried to do it a few times, but always the positions or the character's posture was buggy. So I don't really understand what I need to replicate
Think of it this way... The server should be the authority over what happens in the game, and it would replicate what should happen out to others. This means you generally want to use the server's point of view for interactions in the world, and it would use replicated variables for anything that anyone else in the game may need to know that they wouldn't already know. You use Client RPCs (sends an event to the owning client only using the Run On Client events) or Multicasts (sends it to everyone that has the actor relevant) if it's just a one-shot kind of thing that someone late joining the game wouldn't necessarily need to know about.
Clients can make requests to the server, and pass along information to it, and they can only communicate with the server, not other clients - only the server can communicate out to clients. This means you can have a client ask the server to sit in a boat, the server can do whatever needs to be checked (without necessarily having to replicate anything) and then set state (to then replicate things) or send an RPC back (to communicate something).
The values on either side can be different and that's why you may be witnessing some posture or position bugginess... You need to ensure that you're replicating anything that could potentially be different because it's calculated locally in some way and could be out of sync --- positions and rotations are definitely things that are usually out of sync between one instance of the game and another.
Ensuring a player is in a specific boat in a certain socket, would generally only require replicating a reference to the boat and the socket, and then ensuring the OnRep sets it up so the character is then in the right position, pose and disables any movement or controls that would augment the position or rotation of the character, and probably change some movement inputs and the like if it's locally controlled.
Thank you very much for the explanation. Yes, I understand much better now. But even though I do not replicate variables such as inBoat, socket name, canSit in any way, I see that both client and server are aware of it
It is probably coincidentally the same or it's getting replicated through something else
When I replicate variables such as CanSit and InBoat, I already get similar results. That's why I don't understand exactly what I need to replicate here
What exactly did you mean when you said "and then ensuring the OnRep sets it up so the character is then in the right position". Do you want me to send the character's position with Repnotify?
That's likely you doing something locally on both sides that may look like replication, but unless you're sending RPCs or marking variables as replicated, then it's generally not replication. There are some functions within Unreal that will automatically replicate things for you (usually when done on the server).
You utilize the OnRep to drive logic based on what you're replicating. So if you have a structure variable that contains the boat and the socket, you'd then set up the OnRep to use the boat reference and the socket to then locally get the boat, determine the position and rotation based on the defined socket, and set the player to be in the right spot and rotation, etc.
There are some things that may be done for you automatically if you do it on the server, but not everything.... Attachment for example, I think can happen on the server and it would replicate it down.
Thank you, I will try to do something based on the information you provided !
@sinful tree Are you familiar with RepGraphs at all?
Looking to buy a project on unreal engine store to study RPC's. Any suggestions. I bought one but it didnt replicate any data from the client. It just overrides the clients with the servers choices.
I never buy any plugin to get to know RPCs. Why not just read the pinned material dozens of times. It will eventually click.
All you have to do is practice what you learn.
If you can sync a ball color across the network, then do a random number. Then a door.
Once you can do those exercise, rpc should make perfect sense.
The shooter game and Lyra are free example projects from Epic that show good practices without it being a complete project
Aren't you optimistic of FAB products 😆
Cute graphics
Also, idk if that was said already, but Attachment is usually replicated by default.
If the Server attaches the Character it would be enough.
So you don't necessarily need to run the Logic on Tick on Clients.
But if you don't, then you'd need to replicate the rest of the variables you set.
Whiiiich in theory would be better anyway.
Thank you very much !
Thank you very much for your advice. Do you have any idea how to replicate what and how to replicate it to solve my problem exactly? I made a few attempts but it didn't work quite right
I'm actually not 100% sure atm what your issue is. I didn't fully read up on how far you got with the others trying to help you.
Oh
In theory you want to design your system like this:
- Ensure the Server is the one calling the code that figures out if the Player should enter the Boat (Branch with IsServer or SwitchHasAuthority if Standalone is a thing).
- Make sure any kind of "State" changes (
bIsInBoatis a State!) are replicated as variables.- If there are multiple properties set at the same time that should replicate together, put them into a Struct and use that.
- If the Client should do something based on that State, mark the variables as "RepNotify" and use the "OnRep_VariableName" function this generates to call methods.
- Example would be,
bIsInBoatcould be RepNotify and insideOnRep_bIsInBoatyou can then use the boolean to turn of the Collision and stop the Movement.
- Example would be,
Thank you very much. I appreciate it !
so i want to make a physics based sword fighting game in multiplayer meaning the weapons actually hit each other.
and was wondering how it would work in multiplayer and what way would be best to implement it
atm
i was thinking of implementing it on the cmc since it already has networking i can add on to
and i want to have the weapon interaction also have an effect on the movement anyways
so how to implement on the cmc?
add an extra capsulecomponent for the weapon (as a child of the main capsule)
add a location and rotation variable of the weapon to the cmc
so now what I'm not sure about
everything is from the perspective of client 1 unless stated otherwise
if client 1 hits client 2 so sword moves into another weapon they can just cast before moving and decide not to move
but if client 2 hits client 1, what does actually happen?
does the server get the info first and then just send a correction to the client hit?
and if so how does the server get the info?
because if the server version of the cmc is not actually moving how would it know its getting hit?
since the client 2 that would hit client 1 just casts beforehand and doesn't actually move into the weapon
I would really appreciate any insight/help or opinions on this
do actors have an event for when they go dormant
sadly no
I'll first say Unreal isn't really setup out of the box to do melee combat online. If you're trying to implement a server authoritative game (where the listen server has authority), you'll obviously need to have both characters simulating on the server side in sync. What you're going to run into is Unreal doesn't really maintain a synchronized clock between clients and the server with the classic CMC, so corrections on the client side are going to be very noticeable. I could give you suggestions on what to do, but it mostly revolves around not using the CMC at all and implementing your own character controller.
how would a client and server go about synching animations at the same place anyway
You could create a frame-rate independent clock that is synced between the server and client using a simple network clock syncing method. Then you'd just sync the animations to that clock.
lets assume I had a fixed tick clock all clients share, then what how do I sync the animations based off a time (like an AnimBP)
First, give up using animation state machines and stick with montages and animation sequences. Then you can control the animation playback directly.
but the seems infeasible for most cases, say I am walking and someone shoots my leg, how would that work with only sequences or montages
In what way? I'll tell you that every fighting game uses this method. If you need something like the state machine graph you could implement it on your own.
I believe you but i am thinking from a shooting game perspective. valorant or csgo for example.
Shouldn't be any different. If you know the time stamp of when an event occurs on one end, you just trigger that animation at the same time on the other using your shared clock. You may need to do something like a rollback + resim on the client/server though.
If you're curious about this, there is a pretty good GDC talk about Overwatch's networking model.
When this trigger is run this with multiple players, they all go to their own level(Same level, just different instance). How would i get it so the players go to the first level opened?
You would need to perform a ServerTravel, not an "OpenLevel" travel.
And you'll want to limit that to Authority (SwitchHasAuthority or potentially even just IsServer) as only the Server should call this.
ServerTravel is in BPs only available via ExecuteConsoleCommand node.
Where you can pass in ServerTravel <LevelName>. E.g. via an Append node.
thanks for taking the time to respond
and yh after looking into it further the cmc would indeed not be adequate like you said
any info on how to implement your own character controller?
im mostly worried about how to do the networking and rollback correctly without running into issues
would really appreciate something where i can start from even if it will be hard
Like this?
Don't forget the space behind ServerTravel
And please put a SwitchHasAuthority in front of it.
So Remote is for client and Authority is for server right?
Also, is there a way to only send the player that went through the trigger instead of all of them...
Kinda, yeah. Not 100%, cause a locally spawned Actor that isn't existing on the Server etc. would also return Authority for that Client that locally has that Actor.
if you want to 100% check for only Server you can use IsServer with a branch.
Nope, Unreal Engine has no support for that.
Once connected, everyone goes where the Server goes.
Hmm... Would adding this level as a sublevel fix that and allow for only the triggering player to move to the start of the sublevel?
Yes you could work with Streaming Levels. But keep in mind the Server would need to have all active that clients are in right now
And they are in fact still in the same level. Streaming Levels only really divide a bigger level into smaller ones. So they could see each other if they are in the same location or close to each other
What about sessions? Could you have the first user that goes into the trigger create and join Session1 - Set that as the current session for that trigger, then when second user triggers it, to go into Session1? I feel like it would be pretty resource intensive to have hundreds of sublevels running....
You can place the levels further apart but if they go to the same level they would see each other again
I would want them to see each other, so this would be fine.
Sessions are a different construct. They have nothing to do with Unreal Engine in theory
A session just holds information about the server that is hosting.
And is usually just some database entry that can be queried to get said information and potentially connect to the server
Making multiple sessions means you have multiple servers
Which means only people connect to a given server would be in the same level.
And it means you somehow have to handle communicating the servers.
Cause RPCs etc don't exist cross server
Ahh, so i don't want to make multiple sessions. So would the best way to be for me to have the main open world that players join, find doors to trigger a tp to other worlds that are the preloaded sublevels away from view. Each world would need to be its own sublevel though along with functions on the trigger to determine what door goes to what world. Am i thinking of that correctly?
Yes.
There is also a node to dynamically spawn a sublevel to a specific location/rotation but if you have a fixed set of levels than that would not be useful
I will look into that, My sublevels for the other worlds currently use a actor bp_generator that procedurally generates the land/actors/structors...etc around the bp_Generator. I have all the generator stuffs working along with variables i can modify to set certain things. Like the seed of that world. These aren't permanent worlds, rather they are opened until a condition is met then they close and trigger an event for the main world. Ill start with dynamically spawning in the sublevels of the worlds and go from there. Thanks again for all the help!
Why does my simple RPCs dont work client sided?
one sec lemme take a look
the Key is wrong. Its just "ServerName"
You can only call RPCs to the server if the client is set as the owner of that actor. Lights are also something that should probably be stately - use an OnRep variable rather than multicast.
likely need to pass in a boolean if the light is on or off
where are you calling the rpc from?
Character -> Interface -> Car
so its on a replicated pawn?
Yeah sure
and the car is replicated
yes
Do replicated BP vars automatically use the push model?
Asking because I'm wondering if I should lean towards CPP implementations instead to avoid the comparison overhead
No
Have you measured the comparison overhead and determined that it is your bottleneck?
I don't have a bottlneck, I'm a silly man doing premature optimization
Fair enough. Have a good day.

AGameModeBase::PostLogin is probably where you would want to handle late join logic
if you're correctly using replicated properties, you shouldnt have to sync anything
if you're using RPCs instead of replicated properties, you need to rethink some design
Ah, yea I just couldn't see other players
Even though it's experimental still you might want to look into the Mover 2.0 and Network Prediction plugins, which in principle should be much better for this kind of thing. If you're doing 1v1 it might just end up being easier to roll your own at the end of the day.
pretty sure basic rollback can be done with cmc just fine
it already does prediction
just store the transforms of bounding boxes for a given range of time
as far as I know it doesn't rollback/resim the whole world
In games where melee combat really depends on syncing up animations, you need to rollback everything
NPP only rolls back all simulations in FixedTick Mode. Independent only rolls back the current simulation that failed. And all simulation only means the ones of the player that fails, not ALL simulations.
So in the end this has the same "flaw". On top of that NPP and Mover are nothing I suggest leaning into at the moment. We use it heavily for the past 8 months on a bigger project, and we had to basically rewrite it to a point that it's so far ahead of whatever sits on uemain branch that we can't even properly merge stuff into it anymore.
Also NPP is terrible in its current iteration if you need something more complex. You can't properly communicate between two simulations, not even two of the same type.
The user probably might need their own setup.
Yeah I really only pointed it out as something to look into to find out where it's lacking. Honestly I'd heavily suggest anyone who's doing 1v1 competitive multiplayer just to implement their own simulation with rollbacks/resim. It's not too difficult.
Wasn't there some third party library for that kind of stuff?
I haven't heard of any that's really in a shippable state, but happy to be proven wrong.
I just don't see any general purpose rollback plugin being feasible unless they're heavily modifying existing systems, which are not really build for state restoration and resim.
Every game I know if that has shipped will such a scheme just runs their own game sim, and then they sync up the rest of the Unreal world to that game sim state.
GGPO is what I meant
I think
There might be plugins that integrate that into UE already
But it's open source by now. Not sure if there is any license requirement coming with it
GGPO is basically just the network transport layer + some code for sending/receiving inputs, triggering rollbacks, and running resims.
It doesn't do the work needed to integrate with Unreal itself
Yeah I'm aware
I think there are plugins that are just a wrapper around that library, but it's not doing the work of integrating with Unreal systems. Just the network side of things.
The network side of things is the thing that UE has no nice solution for in terms of rollback etc.
Despite CMC and NPP, which don't work well for fighting games I assume
when I set an actor dormant it closes the actor channel so when I wake it, it has to create a whole new one and send all its values that are replicated right?
basically Its not cheap is what I'm getting at is it, so what are better approaches for a reusable pool of actors that spawn every so often that I dont want them to waste time creating and destroying channels but not enough to want always around. Would I set its update frequency to like a really really low number then or should I modify its IsNetRelevant or what is the best approach here
is IsNetRelevantFor a server/auth only called function
this comment actually seems like its what MinNetUpdateFrequency is for, should I set this to something really like .0001 when i am not using the actor?
/** Used to determine what rate to throttle down to when replicated properties are changing infrequently */
UE_DEPRECATED(5.5, "Public access MinNetUpdateFrequency has been deprecated. Use SetMinNetUpdateFrequency() and GetMinNetUpdateFrequency() instead.")
UPROPERTY(Category=Replication, EditDefaultsOnly, BlueprintReadWrite, meta=(AllowPrivateAccess=true), BlueprintGetter=GetMinNetUpdateFrequency, BlueprintSetter=SetMinNetUpdateFrequency)
float MinNetUpdateFrequency;
IsNetRelevantFor is only called on the server yes
You'd want NetUpdateFrequency
You can set it to something like 0.1f
I would profile before you decide which way to go
Dormancy is generally a big performance gain, and the actors will still exist on clients with that
well here is my use case, imagine I have a pool of replicated coconut actors. When the player hits a tree a coconut can spawn an fall then they can interact and pick it up. I only want to replicate it when it spawns and stop after the player picks it up (which hides it and the server adds one to their inventory)
these actors are more like generic fruits which can change but you get the picture. I only need to replicate them a small amount of time but also if the player hits enough trees frequently that is a lot of actor channels being closed and opened if I use dormancy right
In theory yes, but I don't see it being as much of an issue as you think
I would profile it and optimize it if it shows up as an issue
Why are you pooling the actors btw?
it defeats the purpose of dormancy if I just keep making it dormant and awake
How many coconuts are we talking
because I dont want to create a new network actor over and over
its not the size of the pool but its use. You cant naively create an destroy these things when you dont need to with a smarter system in place
non networked game im sure it would be irrelevant
I'm asking because I'm wondering if you even need a pool in this scenario
a pool or array, it makes no difference, i only want to spawn these things once so all connections dont need to keep creating the new actors (which btw is a heavy network cost, just check the profiler like I have been)
im asking about the most efficient route for infrequently frequently used actors in a network context
infrequently updated on the map, net dormancy
do you have numbers? how heavy was it in your scenario
im not comfortable sharing screenshots but if you netprofile in unreal insights you can see how many bits are involved in network actor creation and setup for a new network actor, this isn't news to anyone who has sufficient networking experience
I'm not even asking for screenshots, I'm asking for the numbers you have in your scenario so I can understand better what you're doing
If you can't even answer basic questions nobody here is going to be able to help you outside of basic answers
i.e. net dormancy for actors already spawned, spawn actors when needed otherwise
I did answer your questions but its getting away from my original one, i am not sitting here explaining why pooling networked actors is good thing.
I simply wanted to ask someone with experience how i should handle actors who are replicated semi frequently, and I gave an explanation for my reasoning of not using dormancy and if there was a better approach
NetUpdateFrequency set to 0.1, same with MinUpdateFrequency or have that set to a lower value
ForceNetUpdate() whenever you need to replicate a change
Sounds like something you'd use a network manager for
The tree is the manager in this case, and give it a fast FastArray containing information of the coconuts it spawned
Let the clients read that array and spawn those coconuts locally
I was looking into it because I recall you used to be able to pause replication for specific actors without closing the channel but I see it was deprecated https://github.com/EpicGames/UnrealEngine/commit/22219eef19558d13f206f6afd00cad7917335f84
I'm curious why that was done
Out of curiosity, is there a way to rename a replicated UObject on the server without it being re-created on the clients?
When its outer changes that is
or does the engine already do that
just curious, sounds like clients wouldn't know about the outer change and would just assume it was two different objects
Wasn't there a pin for the online beacons in here or am I halucinating again? 🤔
Ah I guess I was thinking about the additional resources under Network Compendium (thanks eXi)
Yay I wasn't halucinating. Thanks again
There's not. If you rename it, it's a brand new object as far as network is concerned. I'm fairly sure renaming objects and changing their outers is generally not a good idea in MP.
When you consider things like relevancy there's probably little reason/benefit to support it anyway really
It wasn't that long ago that only actors were supported as the outers
yeaaah I wanted to be able to do stuff like moving inventories (UObjects with an array of FItemData inside them) without having to copy the data around
bummer
Hello, in my game players can carry others around, and drop them at any point in time they want. The way I do that is by attaching the other player character to a USceneComponent "ConductRoot" component that other player has in front of them, a bit to the right (X=40, Y=40, Z=0) relatively to capsule component center. This causes one little problem though: if a player releases another one in front of a wall, that other player might get stuck if the wall is not thick enough.
I know that there's UWorld::FindTeleportSpot() to find a valid teleport spot, and that it would fix problems when players try to put others in solid walls, but that doesn't help with thin doors, e.g. space where player is supposed to be in, but only if that door is open. I was thinking about not using ConductRoot location in FindTeleportSpot as is, but fire a trace towards that off the carrying player world position, and use the trace hit location (or trace end in case it didn't hit anything).
I'm not sure whether it's going to fix the problem, so before trying to implement that I wanted to ask whether anyone ran into a problem like this, and possible fixes to that.
Nevermind, it seems to work perfectly like this, even if the ConductRoot is at (X=200, Y=200, Z=0)
You could also use Overlap traces at the drop position to see if it would be hitting anything, it wont give you much info but a sweep would if you need that. You migh have issues with a line trace
Yeah, sweep should work better, that's for sure. As for the overlap, do you suggest to disallow player to release the other player in case there's something that they are overlapping with?
To be honest that's entirely dependent on your system, but, if you are planning to teleport the player to a given position when releasing them then I would make sure they are not overlapping things in the given space, perhaps figure out the spawn position but then go above it on the Z and sweep down, then wherever the sweep ends up (if its in an okay position for you) then I would spawn them there, if you have a generic line trace or drop position it wont account for uneven surfaces or if the capsule can truely fit.
Again, this is a little speculative on part but in generally you would want to ensure that mechanic doesn't break player experience so do all the tests and checks you can before releasing them
Got it, makes sense. I'll try to build something off of that. Thank you 😄
Im working on a similar thing and was gonna ask the same lol . It seems that renaming could work but I will need to test that part
Renaming works, the server isn't copying inventories around anymore
Also swapping from owner A to B might involve duplicating which seems expensive
But unfortunately the price is re-creating the inventory on the clients, so more bandwidth use
The inventory ?
Yeah, switching the outer on the server causes the inventory to be re-created on clients
Cause all the clients see is the inventory being removed from the previous outer, and a new subobject appearing on the new outer
Ohi plan was transferring an item individually
They don't know it's the same object
Yeah that’s a lot
Oh in my case I'm talking about inventories
The same principle should apply but it has to recreate the whole thing for sure
Think all the subobjects of the component
It will probably have to do a deep copy or something
I guess it depends on what sort of data they store
🤔 totally not sketchy
Hi, I have a -I think a basically- problem with Listen Servers Client side movements. I m using physics mesh composited pawns and interpolating nicely. At editor testing pushed ping and tested all good untill 110ms. But when I m trying to test for multiple computers ~with Steam connected on Development Package~ the clients movement is looking like restricting from server 🤔 Its like somethings trying to pulling client back. But interestingly this just being on online testing !!with 40ms!!.
I added the project skills and more too and all working perfectly but however I cant solve anytime this movement shits.. Help me please 😮💨
and the testing video, server is flowin but clients always like someone pullin clients pawns back
Could it not be done with the AddMovementInput function instead of using force? 🤔 Does it provide a different movement feeling?
I want to say not having prediction and only relying on SetActorLocation from server with RPCs (especially if they're reliable) send on tick like behavior could be the reason
But I'm not experienced with physics based movement (if this can be considered as one) or don't know what is the desire for that instead of using CMC
oh but I dont use characters, I usin pawn with physics movements
btw I tried before physics, a movemented character but sooo much jitter so I changed this is better for it but now still I have this problem
I feel like you could at least convert your server RPCs into one and make it unreliable
At least for this setup. But I'm still questioning if this is a correct proper setup
Alright, never mind we are all good.
hmmm did I get right, u says this bp code wrong? sending event to server and make movement there 🤔 @upbeat basin
Eh, I'm saying I feel like I don't know enough to say whether this is correct or wrong. But it feels off
Having 2 reliable RPCs on input's trigger won't help you for sure though
ohk then do u have any video or somethings to prefer to me. I checked lots of listen server videos but anybody doesnt show how should be movement
ohh but 2 rpc mean?
oh if u mean two event ServerEv and Opl? opl isnt a movement or something its just changing a var
I relied on custom CMCs so far, so unfortunately no
the ServerEv the all movement event
hmp but default events doesnt makes a replicated movement right? so
they re just says to client controller, do move
My consideration here is you're sending 2 reliable RPCs on trigger, which works like tick as long as you press the key (unless you configured it otherwise). That should create an overhead. You can first combine them into a single one (or just set your bool to true with CustomEv and use Opl to set it back to false) and make them unreliable since you're sending the input every frame. Even if an RPC is dropped, you could correct it on the next frame with the next RPC
Still not sure if it would solve your issue though but that's my bit that I can recommend
ohh I got u now but when I check the network profiler, the pawn is not sending tonns of by second soo lets just try. 