#multiplayer
1 messages Β· Page 254 of 1
because server has copy of each client, if you call with HasAuthority(), the server will call this function if it exists on server
Basically I want something like this:
UFUNCTION(Server, WithValidation, BlueprintCallable)
void ServerPermissionFunction()
{
// Get the player state that was calling this function or something else.
APlayerState* PlayerState = // Not sure how :(
if (PlayerState.Permission == "Owner" || PlayerState.Permission == "Admin")
{
}
else if (PlayerState.Permission == "OtherPermission")
}
else if (PlayerState.Permission == "Client")
{
}
}
its the same thing, you just need to make UENum instead of using strings
But if I'm sending this as a parameter with the function, then a hacker can easily change that.
locally but not on server
FYI, this function currently lives on the GameState
But I call the function from a local player, and when this guy changes the argument, the server just gets that right?
for this you have WithValidation, and check if the condition match which you already know
But how can I get the PlayerState or something, to validate the client in WithValidate?
passing parameter of type target character, which will be the client calling this function
or even controller which you can directly access from the gamemode of the joined clients
Sorry I might be a bit dump but how do get the client?
void AGameState::ServerFunction_Implementation()
{
}
bool AGameState::ServerFunction_Validate()
{
// How do I get the calling client here?
return ;
}
without passing parameter
UFUNCTION(Server, WithValidation, BlueprintCallable)
void ServerPermissionFunction()
{
APlayerController* PlayerController = Cast<APlayerController>(GetController());
if (PlayerController)
{
APlayerState* PlayerState = PlayerController->GetPlayerState();
if (PlayerState)
{
if (PlayerState->HasPermission("Owner") || PlayerState->HasPermission("Admin"))
{
}
else if (PlayerState->HasPermission("OtherPermission"))
{
}
else if (PlayerState->HasPermission("Client"))
{
}
}
}
}
if you pass param, get controller from the passed character
Really so the server function will return a different controller dependent on who called it?
Yea but then I as player A could pass in player B to the function if I'm a hacker or do I misunderstand?
nah, you can't... your controller 0 is registerd to your character, if you passed another character your controller will failed
Ok cool, I didn't think GetController would return anything meaningful on the server. Thanks a lot! π
also getplayercontroller() should be used
it will return your controller
or getworld and controller 0
Thanks a lot! π
no issues happy coding
But controller 0 will be different for every player calling the server function?
for server it will be indexed, for each client it is controller 0
But if you player with index 5 on the server, are calling the server function, and then on the server GetController is called, it will return the controller of player with index 5 right?
controller is not replicated to other clients, they can't access your controller
but does the server know which player was calling the function?
server will read from their real controller yes
I'm confused now π
they can't change it
if they change it, they will be removed from the game since their controlled which is registered is different
so if player 3 calls the server function, get controller returns player 3 and if player 5 calls it returns player 5?
yes
ok, I still cant believe it, but it has to be like that then π
to make your life easy, just store an array of controller when they join/leave add remove to array
this way you can access any client controller easily
yes server can access all controllers, client can access only local controller
local and their owning controlelr on server
Yes but on the GameState I don't even have a get controller function
you have player array in gamestate which has controlelrs stored
but how do I know which client was calling the server function?
in each controller you can have method like this
UE_LOG(LogTemp, Log, TEXT("Client %s called ServerFunction."), *GetPlayerState()->GetPlayerName());
and call this method like this
for (APlayerState* PlayerState : GameState->PlayerArray)
{
if (PlayerState)
{
APlayerController* PlayerController = PlayerState->GetPlayerController();
if (PlayerController)
{
welcome
and happy coding to you! π
@glossy wigeon I didn't read all of it, but GameState can't have ServerRPCs to begin with
You call those on Client Owned Actors. If that's news to you then you need to learn the basics a bit more.
You can call ServerRPCs in e.g. the PlayerController or the PlayerState.
From which you then know who called it, cause these actors are usually somewhat relativ to the owner.
Yea I figured that so far, I'm now going with a ControllerComponent.
Also what if I understand correctly, getting the the controller inside the ServerRPC will then also return the calling controller on the server right?
Depends on what getting the controller means for you
If you call the RPC in the player controller, this will be the calling PC on the server. If the RPC is inside a component on the controller, then the same goes for the component. And getting the owner of that component then gives you the PC
It's all just a matter of having the RPC somewhere where you can get your PlayerController or PlayerState
Which is usually pretty straightforward
Yea so in my case it would be the ControllerComponent, that sounds like what I need! π
But I think I just needed to wrap my head around, that a RPC can only be called by someone owning it and that calling a RPC will also call said RPC on the "same" object on the server.
Hope at least I got that right π
Also thanks a lot for setting things straight and helping me understand them!
Did you read the Network Compendium?
hello, I need some help figuring out a stuttering issue with with multiplayer on the editor. I am getting quite a bit of lag and stuttering on my Listen server (editor) when its trying to replicate the client's player actor when hitting play in the editor. This does not happen in the default third person template project from unreal so I think its some setting I must have changed
can anyone point me to which setting to look into?
the movement of the listen server is replicating properly to the client with no lag or stutter
You mean the Animation of the Client on the ListenServer is stuttery even though the fps are fine?
Or does the whole actor lag? The Animation is ticked through the movement component. You'd need to enable smoothing for this if it's not on by default. And potentially ensure your client doesn't have low fps, e.g. When the window isn't focused.
I just enabled the fps to check on the editor ( which is my listen server) its seems to drop to like 3 fps when I am tabbed out to my other client
I guess unreal has a setting to reduce performance when the viewport is not focussed
ok I disabled "use less cpu when in background". now the movement is not stuttering anymore but the animation still is. I did find some threads online that in local server the animation only updates when it gets a network update. I guess that is the cause of this
When doing latency compensation, is there some kind of reliable clock with high precision I can use to sync using a timestamp in payload or should I instead use GetPing and approximate?
E.g replicating movement via sending a position, velocity and a timestamp so that the client can compensate for one way trip time by simulating those couple dozen msec
Which I think should cover 90% of βmoving in a straight lineβ cases
Why is Iris routing unreliable unicast rpcs to the reliable send queue, does it use it as an hybrid quueue?
im referring to, in 5.5.1
bool FNetObjectAttachmentSendQueue::Enqueue(TArrayView<const TRefCountPtr<FNetBlob>> Attachments)
{
const FNetBlobCreationInfo& CreationInfo = Attachments[0]->GetCreationInfo();
if (EnumHasAnyFlags(CreationInfo.Flags, ENetBlobFlags::Reliable | ENetBlobFlags::Ordered))
{
if (ReliableQueue == nullptr)
{
ReliableQueue = new FReliableSendQueue();
}
return ReliableQueue->Enqueue(Attachments);
}
else
{
const SIZE_T TotalCountNeeded = UnreliableQueue.Count() + Attachments.Num();
if (TotalCountNeeded > MaxUnreliableCount)
{
UE_LOG(LogIris, Verbose, TEXT("Dropping old RPCs due to too many unreliable attachments: %u max: %u"), UnreliableQueue.Count(), MaxUnreliableCount);
const SIZE_T PopCount = FPlatformMath::Min(TotalCountNeeded - MaxUnreliableCount, UnreliableQueue.Count());
UnreliableQueue.Pop(PopCount);
}
for (const TRefCountPtr<FNetBlob>& Attachment : Attachments)
{
UnreliableQueue.Enqueue(Attachment);
}
}
return true;
}
TRefCountPtr<UE::Net::Private::FNetRPC> UNetRPCHandler::CreateRPC(const UE::Net::FNetObjectReference& ObjectReference, const UFunction* Function, const void* Parameters) const
{
FNetBlobCreationInfo CreationInfo;
CreationInfo.Type = GetNetBlobType();
CreationInfo.Flags = ((Function->FunctionFlags & FUNC_NetReliable) != 0) ? UE::Net::ENetBlobFlags::Reliable : UE::Net::ENetBlobFlags::None;
// Unicast RPCs should be ordered with respect to other reliable and unicast RPCs.
if ((Function->FunctionFlags & FUNC_NetMulticast) == 0)
{
CreationInfo.Flags |= UE::Net::ENetBlobFlags::Ordered;
}
FNetRPC* RPC = FNetRPC::Create(ReplicationSystem, CreationInfo, ObjectReference, Function, Parameters);
return RPC;
}
```c
It seems that everything thats not multicast unreliable gets the ordered flag that pushes it into the reliable send queue?
Ok i probably shouldnt have been insane enough to look around experimental core system like Iris. Also Iris seem to have a placeholder send rate bandwidth limit of 150 000 bytes/s with net.Iris.ReplicationWriterMaxAllowedPacketsIfNotHugeObject, which default to 3. when running about 60 fps on client. its defined in FReplicationWriter::Write()
Does anyone by chance know if there is any know issues with common session subsystem with Steam on 5.5.4 . I seem to not be able to get clients to connect (match creation & match searching does work however). I have tried both Steam sockets and normal net drivers as well.
I'm looking into subsystems. My group wants to use Steams subsystem in unreal but we were suggested to use advanced sessions by a mentor at school. What's best? Could one enhance the other? Any tips would be helpful
Hello, π
Quick question: Is it normal for rotation to replicate without Replicate Movement being enabled? I thought it would stop replicating rotation if I disabled this option but it's still rotation on the client. π€
Any insight would be appreciated.
Cheers.
Ah yes, it's the relative rotation of the root component that replicates by default. I see. π
Tell your mentor to start suggesting CommonSessionSubsystem from Lyra.
The general note is that CommonSessionSubsystem is generic. It works with Steam, EOS, consoles, Null(Direct IP stuff), etc. And is much easier to handle than advanced session stuff. And it obviously doesn't tie your project only to Steam.
I'll look into it!ππ» Appreciate the feedback, the mentor is more of a blueprint/game design teacher and not c++ heavy end but appreciate the advice. I'll look into it tomorrow
You can use it entirely in BP by default. Above code is for singleplayer, but you can easily set that to online. And there are other options.
Wow that looks really simple, awesome!
guys, what is the best way to test disconnect/reconnect in dedicated server?
Why this isn't in the engine by default? Only Tim knows.
Cause then they would have to spend three days a year maintaining something actually useful. Much better to waste time on ALandscape upgrades that won't actually help much.
this just a check to see if im thinking of this correctly before i implement, but i want to allow players to modify their player stats / skills before they join the game*, like a "pregame lobby" but i'd need it to be with the server, so i figured i cant do this in the main menu, as this is just standalone, so when they join the server, i'd then just not spawn the charcter in world yet, and allow them to make any modifications to the allowed params and then when done, then they'd spawn at the location they choose, after modifying (if they choose to)
is this the correct thinking? again, my main thought is i need to do this in the actual server map and not the main menu (which, tbh, i'd rather let them do it locally , but i realize that wouldn't be security effective)
You can do either. The process is pretty much the same. The main menu only has the extra step of storing the data somewhere that persists level travel.
Without the main menu you would create a set of data and RPC it. Which would then trigger character creation spawn etc etc.
With main menu you would set the same data, store it somewhere, join game make the same RPC with the same outcome.
yes, nice this is what i figured, glad you could confirm. but if i were to do it in the main menu, i'd be effectively allowing the player some sort of ability to "cheat" given that they would be setting data locally, and then that data would go to the server but the server wouldn't know about it, so server would have to just trust that the client data was fairly inputted
specific example is i want to give the player a starting currency that they can use off the bat to customize their character's stats. this would be predeteremined amount per player (unless they are rejoining / have a save game already with more / less etc)
i just wouldn't want a player to use "more" than i would essnetially want
but i guess, i could od a check on the server to ensure that plyaer doesn't have more than i would expect , now that i think about it
The main menu part is identical to doing it in game. There is zero difference. You're accepting a set of data from the player. The server can still parse this data to determine if it's valid. You don't have to apply it blindly. Whether you do this in game or in the main menu makes no difference.
The singular way to avoid cheating in this case is to have a backend server where you pull the data from on the server, and even then the server needs to never be in the hands of a player and only ran on secure machines you host. This is assuming that you have a system where they save their progression and continue it when logging back in, etc.
perhaps i am overthinking it or i just have a bit to learn .. my remaining question is how would the player get access to server data if they were in the main menu? my assumptions were i would not be able to get say, a profile save game file from the server from the main menu unless it was locally stored, and then i would have to send that locally stored changed data back to the server when joining. i do now see how i could check to make sure this data is valid in whichever way i need to check once the player joins and that new data arrives
i'll probably do it in the server map vs the main menu, but only becuase i feel like i'd have more ability to control that data more. the client will always be the one locally choosing, but even the data that they see that they can change shouldb e controled by the server to begin with, and that's the part i feel would be hard to control via the main menu
ok, yea now that im thinking through it, i can definitely just have server variables that are ready to check whatever the client selected.. and as long as they are within the requirements i can valid it. will just need to lay it all out to see the flow to know for surely
There is a middle ground, fwiw, that you could utilize: Beacons.
Needs C++ though afaik
With Beacons you could connect to the Server, have RPCs going and data replicated, without actively leaving the MainMenu.
But it's true that the "cheater" side of things is the same in all cases. If you do it locally, the Client can create something outside the limits. You'd need to confirm that every value is "correct" within its limits. Money not too high, total allocated stats not too high, allocated points per stat not wrong, etc.
But you'd also need to do that similarly when having a connection, cause the Client is still telling the Server what they want to change. They might send the action of incrementing a stat instead of the final stat, but you still need to check if they can increment it or not.
You do need a minor bit of C++ to use beacons. But it's worth a note that you can create a base class for them that is blueprintable, and then you can make a few functions in a library that are BP Callable to spawn and manage your beacons. Past that it's basically just understanding that these actors can RPC and not replicate. I'm a little shocked that the info on them is kind of buried given how useful they could be and how easy they are to use.
We have stuff pinned in #online-subsystems
Hello hello,
I'm currently porting a Quest system from Single Player to Multiplayer and essentially for quests that require a shared amount of items I need to check all players inventories for those items and display it in the UI
I already have a fully replicating inventory system where the inventory is a Component in the controller
everything works properly, what I'm curious about is for all clients locally what is the most reliable way for me to get all controllers?
would it be registering them as they login/out? would it be simply getting all actors of the proper class?
I used the PlayerArray (Playerstates) but I don't think they replicate the owner ref
wait what am I saying, a Controller is only available between the server and owning client
Does this mean the only way for me to accomplish this is to hold the inventory in the PlayerState? Or have the server on inventory change callbacks update a replicated counter for items needed by quests π€
If you're wanting players to be able to read other player's inventories, then yes, you'd probably want your inventories attached to an always relevant actor like the playerstate.
The trouble with having a separate incremental counter comes when you have a player disconnect - do you want their contribution to still count towards the total? Is your quest system going to just keep a running tally regardless of what is in their inventory?
that's a good point, I wouldn't want to have a counter per player (which is techincally the inventory) so unless I do that I can't react to disconnects
well I guess I can just decrement on logout
I actually am going to ask the designers to consider first a quest system where you "Contribute" items
so the system doesn't have to count everything from all players
but we'll see, if that isn't an option I'll move the inventory to the PlayerState
You can still count them, just gotta do it when it makes sense. Count the items on item pickup, on item drop, and on join and leave.
It's a good idea to not have redundant information. Don't have a container of things and a separate int Count, just have the container, get the count when needed.
I might consider that yes, I already have callbacks in all the approptiate places apart from Login/Logout
hmm i definitely like the sound of Beacons, but my noob ways of not knowing cpp makes this again one of those moments i realize i should just learn it already lol
Yop
oooo, may just feel a bit more capable now
perhaps i'll give this a go
i do feel like i could trial and error my way into making some stuff, just wouldn't trust myself to fully cpp anything from scratch with my current knowledge
[2025.05.11-16.11.17:423][579]LogGameMode: FindPlayerStart: PATHS NOT DEFINED or NO PLAYERSTART with positive rating
semi unrelated, but i get this when i load into the server map, and i had a feeling something like this was happening, i mentioned this above how my character will "spawn" in the center of the map before going to the selected spawn location / where they last were when logging out, and im going to assume that this is the reason. i attempted the solution of adding a delay after things were loaded but that seemed to just delay that little spawn in glitch, as it happnes no matter what upon first spawn.
not super sure how exactly i should override that as the player starts wouldn't be relevant as i have spawn zones which random place you within that volume but im guessing i hsould handle that function so i dont get that , or just place a default player start somewhere, but still wouldnt' really know why the camera would even show that part of the map, as i don't have the lodading screen beign pulled down until after the character is fully loaded and should be in the chosen spawn location
Realistically I would just make a system for the moment that has a single point of accepting the data. Whether you choose to do this entirely on server through your own backend, allow client to send data before or after connecting is largely irrelevant at that point as any of the three ways can be interchanged with relative ease once you have a working model.
yea i feel that, i currently am just using save games, i had a SQL database working in a way that i thought would be the solution but it caused crashes due to the amount of data im retrieving at once, and honestly coulnd't figure out a solid solution to scale that as a working method. save games are honestly great i'm currently just having the server load that in when the player is registered in the game mode and the character is valid. it works but yea have just been thinking of ways to securely store certain data outside of save game files or a way to store those save game files seperately to have a server ensured copy. i've considered using IPFS for that actaully but i dont have a working way to send / retrieve that data without making something custom (there is a plugin, but only for windows and im on mac)
Hello,
Is it possible to have a different directional light (and sky atmosphere, etc.) between each client on the same level?
With the "switch has authority" feature in the level blueprints, it's possible to have a different directional light between the server and the client, but each client will have the same light.
Lights and atmosphere aren't replicated so it's all handled locally. If you want each client to have different settings for these things, then you need some way to differentiate what happens on each client otherwise they'll still execute any code you may have to change it the exact same way. An example would be to use random values - these would be generated locally and each client could potentially have different values.
Thanks for the reply, I didn't know light was managed locally.
The idea is that a client is teleported somewhere (fixed position) and their directional light changes, and the same thing happens for another client, but elsewhere and with a different directional light. The problem is that I can only change the directional light from the blueprint level, which therefore runs on each client, and I can't find a way to differentiate between clients or "cancel" the replication.
Hey guys, I have a little question. RPCs and Replication are only possible with Actors? Or is there somewhere a low level system which could be used?
I try to extend my plugin with multiplayer support. I have a GameInstanceSubsystem which contains data, and another GameInstaceSubsystem which reacts to the other and replicates the data if needed.
But do I really need to use Actos as middleman for the replication?
Built in replication happens through actors. Even making replicated UObjects requires them to be replicated through an Actor.
Hey sorry for the ping, but how did you get common session subsystem to work with steam? I have it setup in our project and it can create and find, but it can't join. I tried a quick test with advanced sessions as well and that works, but ideally would like to use this as we are already using a lot from the user subsystem part. (we are using 5.5.4)
I don't recall we did anything. Just the normal calls that are in BP already, setup your ini which you've clearly already done since you can search. π€ Though I do recall that @meager spade might have mentioned a bug with it around our latest version?
Yea it's quite odd since it always times out.
I can check if I have the latest, but I know it's from the latest version of the fab release. I didn't think the GitHub version was any different.
Am I understanding correctly that movement done by default character movement component are server authoritative and you can't really change that unless you're planning to develop your own replication from scratch?
Basically having the same issue as this guy: https://www.reddit.com/r/UnrealEngine5/comments/1ep3msb/jumping_on_moving_platforms/
The second a character steps on a moving objects jitter occurs
Except I don't see any difference when ticking the "server accepts client authoritative position" as suggested. It still seems as if the character's position is being corrected
I don't have issues with jumping on moving platform in multilayer
You will always get minor corrections but nothing that's game breaking especially with latency
It is client predictive and server authoritative. There is another setting "Ignore Client Movement Error Checks and Correction" but turning this on with the client authoritative position basically makes it so someone with a bit of know-how would be able to make their character teleport anywhere in the gameworld at any time.
Anyone know how to disable the black loading screen with the throbber in bottom right? It keeps clearning my loading screen widget and wont go away?
There is no loading screen implementation out of the box in unreal.
What ever you have is your own doing so we don't know what you actually do with it.
I am using SIK, so is it with them?
Make an EnvironmentActor that contains the atmosphere, sky light, sun light, etc
Then you can just get actor of class and tell it whatever you want
Like this
Does the PlayerArray in the gamestate maintain a list of all currently connected playerstates or all playerstates including players who disconnected?
All connected players
There is somewhere (i think GS/GM) where you have a "recently disconnected player array".
Each entry are removed after X seconds once added. Its used to pickup back data if people get dced
Bear in mind that the player array can also contain AI player states if you allowed them to spawn (in AIController iirc)
yeah I'd like to ensure players who return get their playerstate or its data back, but also im creating a set indexed replicated array of players because for the engine replay system with UI elements object refs get dereferenced while scrubbing and get set to null (likely an engine bug but the replay system is so old is anyone willing to fix?)
thats why im creating my own array
it would store all states even if disconnected
I think engine already handles assigning back the correct PS if disconnected player reconnects
Idk how tho
yeah thats fine but what i need is to be able to index the player states by something other than an object ref
Maybe it detects a connection/local player ID
i can do that via an array index if i dont shift elements in the array
Yeah i guess making your own array works
Or you have an player ID on your PSs, and to get your player you do a find by predicate
And you store the ID where you want
If you are using an online subsystem, you should have a unique id you can identify them with
yes tho this list needs to be replicated, for client and replay access
Why does your own array not work atm?
lol i was just asking about the PlayerArray variable. im in the middle of implementing my own array
Ag
Ah*
Yeah okay. I don't think the PlayerArray contains the Inactive PlayerStates. But I would need to double check.
I think they want a player array with connected and disconnected players
I know I had some issues a long time ago with my Lobby Kit
It doesnt, its another array
Where inactive players got added back to the player list
GS/GM
Yeah, but the PlayerArray is filled manually via BeginPlay iirc.
But maybe it's guarded by now. Been ages since I looked at that or had any problems
Minor corrections, you mean something like this is expected?
I assume it's cause the train is naturally a little further behind on the clients, due to natural latency
What should I look for?
look at the settings in GameNetworkManager
you set them in ini file
[/Script/Engine.GameNetworkManager]
TotalNetBandwidth=200000
MaxDynamicBandwidth=40000
MinDynamicBandwidth=20000
ClientAuthorativePosition=false
ClientErrorUpdateRateLimit=0.015f
MAXCLIENTUPDATEINTERVAL=0.35f
MaxClientForcedUpdateDuration=0.60f
ServerForcedUpdateHitchThreshold=0.150f
ServerForcedUpdateHitchCooldown=0.100f
MaxMoveDeltaTime=0.125f
ClientNetSendMoveDeltaTime=0.05
ClientNetSendMoveDeltaTimeThrottled=0.066
ClientNetSendMoveDeltaTimeStationary=0.0833
ClientNetSendMoveThrottleAtNetSpeed=10000
ClientNetSendMoveThrottleOverPlayerCount=24
bMovementTimeDiscrepancyDetection=true
bMovementTimeDiscrepancyResolution=true
MovementTimeDiscrepancyMaxTimeMargin=0.25f
MovementTimeDiscrepancyMinTimeMargin=-0.25f
MovementTimeDiscrepancyResolutionRate=1.0f
MovementTimeDiscrepancyDriftAllowance=0.10f
bMovementTimeDiscrepancyForceCorrectionsDuringResolution=true
ClientNetCamUpdateDeltaTime=0.066
BadPingThreshold=200
SeverePingThreshold=500
BadPacketLossThreshold=0.05
SeverePacketLossThreshold=0.15```
heres some settings i used in the past
Ty, I play around with them
Same jitter during movement (once again I think because the client lives somewhat in the past). Actually, isn't interpolation supposed to smooth out this jitter? Or is it not how it works?
As in, the character slides towards or averages it's position instead of instantly snapping?
well does it know its on that base?
cause there is a BasedMovement part of the code
OH ! i see what you mean, I didn't know you could add actors to the blueprint.
I'll try that out soon, thanks!
I think so, yeah
Relatively to the platform client stands where it believes it is
but yeah we had this issue on moving trains
Oh thank God I'm not the only one struggling with trains
one thing
your base might not be set right
like it does traces
to find what it should be standing on
one thing we also did was turn of replicate movement in the train (and its carriages)
Mine is moving along the spline by sampling it and manually positioning itself (both position and rotation). Trying to replicate just movement resulted in it going off track every now and then on clients, so right now both server and clients just simulate spline movement locally and only get corrected if divergence between server position and client position is too big
Naturally Iβve got replicate movement ticked off. Should it still be on even if the clients simulate independently?
Nvm I can't read you said turn it off not on 
Just did a couple checks, both movement base and movement base velocity seem to be in order both on client and server, so theoretically should replicate fine
if your carriages also have smoothing
then this could conflict with cmc smoothing
the server is ahead of the client (if the train moves on client)
when normally movement client is ahead of the server
Wait, is this supposed to be the case? Say train begins movement on server, velocity variable changes and gets replicated to clients, one way trip's around ~30msec. By the time clients receive velocity change rep and start to move the train, it's already been moved on the server, no?
So the server is always ahead by a tiny margin
Not with CMC because movement is predicted (can be even client auth iirc)
Also you cannot rely entirely on net timings, of course supporting more than 300 ping is usually not a thing, but it could happen that there are 100 or 200ms ping in bad scenarios
Not sure if relevant or would help you but there is a βstat based while jumpingβ variable in the character that you could try to set to see if that does anything
Yeah I'd prefer experience on 100-200 window to be at least tolerable
So what you're saying is that CMC movement is predicted but train movement isn't, which may cause all this mess?
Yes although I don't have experience with this kind of situations, it's my theoretical understanding of how networking works
Kaos is way more knowledgeable
Nice, exactly what I was looking for. I almost thought of implementing the thing myself
Now only the movement jitter left
Hypothetically, I can just implement prediction for train as well (offset along the spline by speed * approximate ping)
yeah tbh no clue what is the proper way to do it
But unsure whether it'll actually solve anything. Doubt you can get it close enough with latency approximations available
Changing tick group of CMC to "Post physics" seem to have solved the jitter. Not sure if a hack that's gonna bite me in the ass later
But hey it's smooth now
I actually have the following settings
But honestly I'm not sure if they're doing anything
Oh yeah, cranking it up I can definitely see it. Movement on the train is 100% smooth, getting on and off (thus changing base status) produces noticeable jitter due to lack of prediction on the train and getting worse as latency increases
So I'm thinking to throw some rudimentary prediction and see how it goes. Everything else just worksβ’οΈ
yeah great
Ty all for help
hoepfully somebody with more knowledge of this scenarios can give you more input
I mean, doubt there's much to it. You can't really reliably get accurate latency in a real scenario. Best bet is to just get average ping and compensate by it
Should cover most cases where the thing isn't actively breaking
Or accelerating. But even then it's probably possible to waste a bit of bandwidth and send acceleration alongside head position and velocity
high ping players gonna lag, not too much around that
Yeah that's just how it be. Still won't hurt to predict a little
Or at least make the base change smoothly interpolate instead of snapping
But tbh the fact that there's a base system built into CMC and it's fairly configurable is already a pleasant surprise
just out of pure curiosity, how are you creating the prediction? i'd assume C++ but not sure if you had any other method or that in getting some sort of prediction
Yeah I'm planning on using OnRep_ replicated property processor
Or whatever those are called. And offset train position on rail by how much it would've approximately moved but didn't due to ping
Nice, yea i would love to have the ability to make simple prediction code for certain movement mechanics. I have GMC but the switch is too great for me atm
Found the code that is creating the throbber. It appears UWorld::BlockTillLevelStreamingCompleted() is called which then calls a delegate that pauses streaming. void FStreamingPauseRenderingModule::BeginStreamingPause( FViewport* GameViewport ) { // If a movie is already playing donβt bother starting one if(GetMoviePlayer()->IsInitialized...
anyone know how to fix this being a issue?
those are all components, just make a single ACTOR with all the environmental lighting COMPONENTS inside it
I found it and it work ! thank you a lot for the perfect answer. I just got some other problem but not with directionnal light xD
How do structs decide if they changed and thus should be replicated to client?
properties marked as replicated are checked each frame for any differences
with structs you can also specify properties to be non replicated
Are they checked using the == operator or there is a specific function used for that?
is there any tutorial or documentation of how to make a multiplayer widget for a "character selection fighting game (like tekken)" all the tutorials that i find are like fornite character selection
is it really that different?
i mean the main difference is that you can see both selections of the players and fornite its more like individual
help! i am trying to set the time left in a round to a replicated variable but it keeps setting itself to 0 every tick on client side, what am i doing wrong?
The concepts are the same. Player 1 sends to the server the character they are currently hovering/selected. That then replicates down to Player 2 and it just shows who Player 1 has hovered/selected.
Timer handles are not replicated. I mean you can replicate them, but the client doesn't have that same timer so the timer handle key is useless.
What you should be doing is setting a float/double to the game time that the round will be over. You can get the current server time with offset from GameState, GetServerTimeSeconds or something I think? You can then do EndTime-CurrentTime and that is how long in seconds until the game is over. From there it's just some math to set up minutes and others.
Further to Authaer's advice, Event Tick typically runs on both the server and the client, so even though you may have a valid timer on the server and are trying to replicate the text down, the clients would likely also be running the same tick logic and setting that text variable themselves, which ends up with 0 being displayed more frequently than any replicated value being sent to them.
gate that by Has Authority
only let the machine with authority set that var
@kindred widget @sinful tree @dark edge boom. all i needed was Has Authority, works perfectly now.
Thx for help!
Does it tho? You're replicating effectively at least a 24 byte Text property (it might be more), every single frame... At 60FPS that's 1440 bytes/s, or roughly 28% of the 5KB/s budget that unreal wants to do per connection.... Just for a timer.
just replicate the initial timer information
yeah idk why you wouldn't just replicated a float or wahtever
you already have a "synced" network clock so I'd just replicate the end time of whatever phase
Is it good practice to respawn a player from the game mode class?
Probably where it should be done, yes.
Are you trying to access the game mode on a remote client?
whenever a player is sent to the first person map level (the one with this gamemode) it should spawn them in and assign them to a team
And the answer to the question is...?
i do not believe i am accessing the gamemode on a remote client
the gamemode is ran on the server
Do you have no spawn points with the right tag?
idk how to set a tag on a spawn point
So why does your code check for it?
because i forgot to add the tag to the spawn point lol
anyways i fixed that what would cause this
Accessed None errors indicate you're trying to access a reference that doesn't have a value set. In this case, it's within your BP_FirstPersonCharacter and you're calling a GetPawn node but it's returning an empty reference and you're still trying to access it.
this is my only get pawn call
Since this is in the pawn itself, you shouldn't need to get the pawn of the player controller. You just need to check if self is locally controlled
this is only causing an issue now though ,ive had it in there prior to the custom gamemode, game state, and playerstate
is there a way i can see where a node is being called in multiple blueprints classes
like a ctrl shift f on any IDE
but in ue5
There's a lot of reasons why it may be breaking now, but by just checking if the current pawn is locally controlled after casting to player controller should fix it for most of those reasons.
At the very least, it'll prevent that specific error from popping up, though you may still not get the expected results depending on what the actual issue may be.
how can i possibly find out whats going on?
my event begin play in my character class isn't even being called nor is my gamemode
You mentioned you created a custom game mode and game state.... When you create these, you need to make sure that if you used "GameModeBase" you need to use "GameStateBase". If you mix them then wierd behavior starts happening.
ah yeah i did have been not intertwined
which one is better for multiplayer base or no base i forget
It's not really about which is better for multiplayer... The non-base versions are somewhat set up for first person shooter type matches. If you're not sure, then just use the Base versions.
whats the differences?
Effectively, GameModeBase/GameStateBase are the base classes and GameState and GameMode are actually child classes of them with additional funcitonality. You can look into the API and the engine code if you want to see how it functions differently, but again, it's set up with a bunch of stuff mainly for FPS style matches.
well my game is an fps
but i remember hearing something in a video saying one is better for multiplayer and one isnt
which do you recommend i use>
multiplayer fps
Look into what is available. See if it matches what you need. If not, or you don't want to, use the base versions. (Just be aware, you may be reinventing the wheel by not seeing what Epic has made for matches in GameState and GameMode)
yep that fixed my issue
the incompatable stuff
ok, i am very new to this so what should i do instead?
and please tell or show me how, this sounds promising.
if i wanted a ui where players would select a team by clicking a button, then the host presses start, would i do this logic in the gamemode? or should i have the teams made prior to starting the gamemode
current logic (not sure where to continue)
my widget ^
You have several options for doing this differently.... You could replicate the float instead and then have the clients format it as they need it to text - this would reduce it down to 4 to 8 bytes (depends on if the engine is smart enough to use float instead of double), so at least a 3x savings of bandiwdth usage just from that alone.
Next, it appears you only really care about minute/seconds being replicated, this means you could probably get away with a timer setting the value every second rather than 60 times a second. That's a huge savings of only doing it once per second rather than 60x a second.
Finally, as others have already recommended, you could just use something like βGet Server World Time Secondsβ + the offset for the duration of when you want the round to end, and you'd only need to replicate this one time and clients can then calculate on their end using the replicated variable minus the Get Server World Time Seconds to give you the remaining time of the match, you just need to locally continually calculate what the value is (using a tick or a timer or a widget function binding)
So all the way from 1440 bytes / second for each client to only ~8 bytes sent once to each client.
Game Mode only exists on the server and is not owned by clients so you cannot RPC from clients to it.
If you want to allow clients to tell the server what team they are on you need to RPC through the PlayerController, PlayerState, their controlled Pawn, or any replicated components that are added to these actors.
PlayerState is probably the better place to handle a team assignment for a particular player rather than using a map on the game mode as well. If you want to check the list of players, there is already an array that contains all the PlayerStates in the GameState called the PlayerArray.
so in playerstate assign them to a team ? still with the hash method?
You wouldn't need a map in the playerstate since each playerstate would have their own team variable assigning that particular player to that team.
so on the button click set the team directly through the player state
this is my widget
how do i tell the gamemode to wait until the start butotn was clicked?
and spawn all the active people?
Btw, a cleaner way to do this is to call GetOwningPlayer and from that the PlayerState.
okay still, im setting the team on the widget, now how do i tell the gamemode to wait until the start button is created?
also dont i need to store all the player controllers in an array anyways?
like this
i would loop through my playhers to spawn and then spawn them in i just dont know how to set that up
even with this logic it doesn't wait for the UI it just spawns them in
is there a way to tell the gamemode to not spawn players in on default
and wait till i tell it to?
No. The PlayerState has a reference to the Player Controller associated to it, so you can use the GameState PlayerArray and loop through them and if you need their controllers, you can do a GetController from them.
As far as telling the GameMode, you'd make it so only your host sees that "Start" button and then you'd call a function, possibly in your game mode, to then start spawning the players.
As for preventing pawns spawning at the start, you can set the default pawn to none, otherwise, you have to override SpawnDefaultPawnFor in the gamemode and then customize when you want pawns to be able to spawn, or make your own functions that you call to handle the spawning, but then you also need to ensure that players joining after the round started are handled correctly too.
A better way is to delay the match start
To prevent spawning
I guess that would be the case if they were using GameMode instead of GameModeBase.
Iβm not using base
Iβm using gamemode
Hi, whatβs the approach for handling player death, precisely keeping bodies persistent within the level, so other players can loot it?
Well, lets walk through this logically - knowing what we know about how the framework works.
We know that the player controller is only on the owing client and the server. So we can't have inventory on that
Well, you could I guess - but it wouldn't be specific to the pawn
Because once you unpossess the pawn, due to death, there wouldn't be a way to loot
So, that leaves it to the player state or the pawn.
The playerstate could be used as well - but it has the same kind of problem. In that it may not have the correct pawn reference.
isnt Restart supposed to be called on the local player pawn for the client too? Seems like my VR pawn is not doing that, quite weird since im sure it normally works this way
So it would still not really be lootable. Plus it has the problem of respawning would bring the inventory with the player.
So that means the inventory would need to be on the pawn.
Then when you respawn, you just spawn a new pawn and have the player controller possess that new pawn. So the player will resume as normal but its old pawn will still exist in the world. Ready to be looted.
@meager aurora
Thank you for you answer, very insightful. I missed the ability that the pawn can be unpossesed, and left on the level after player disconnects.
Some curious roadmap notes for Iris in 5.6
hopefully epic expands on this on unreal fest next month
entity replication if it's mass will be big
What even is multi server setup?
im sure they dont mean server-meshing right, that would come out of nowhere too fast
maybe replicating different data to different servers?
I suppose we'll find out anyway in 3 weeks on unreal fest
I am making a game like Rust but I have an issue with my building actors (there all invidual actor pieces for ex. wall, foundation, floor, window etc. How can I optimize it? When there is very large bases it takes forever for the building objects to load in etc.
multi server is close to server meshing for me
if your static meshes are reused they should be instanced and not use that much compute?
Yeah Ive heard that is good to use I just have no clue where to start with instanced static meshes
you could probably directly swap to using them?
InstancedStaticMeshComponent
This is what I am using https://www.fab.com/listings/b2c5a428-e9af-4c6a-9daf-d10b8b04bddf
What is Easy Building System? Trailer v10Easy Building System is a project for Unreal Engine, which is based on a modular building system. In addition it includes several subsystems, such as a system for interacting with objects, a system for upgrading and repairing, a system for destroying buildings, save and load data of buildings, claim of te...
Each actor is BP_BaseBuilding Object the actor can be upgraded, etc. How easy would it be to swap it to using InstancedStaticMesh while keeping all of it's actor functionality?
does each BP_BaseBuilding bp already come with a static mesh on it?
it also seems like they have a discord
not trivial for others to give input on the inner workings of plugins, but im sure someone there or a dev has input
yes it does
Yeah I've been asking but not many people are familiar with it
I dont use this, i have my own building system.
But I break the world up into grids, and those grids instance the build part meshes based on ranges to each other.
The meshes on the build part class just disable rendering them in the main pass, etc on PostInitializeComponents() to maintain better occlusion, and keep the collisions on the server.
The grid managers are client side, so clients instance the bases themselves using HISMs
@mellow stag
In your system is each connected island of stuff a grid like Space Engineers?
or is the grid global
The grids are based on the size of the world. So multiple bases can be instanced inside a single grid, within ranges inside their grid
So bases 1000m apart aren't instanced together
I mean rotationally
When i snap stuff together into a straight line, is it a straight line globally or based on the first piece in that grid
This
or this
This is amazing, is your building system custom?
Mines all just indivdual actor pieces. so it's pretty demanding on server performance
Pretty sure thats exactly what it was.
I wouldnt be surprised if Fortnite morphs into an MMO
this might just refer to individual iris objects as entities., not sure
Iris internals do not care about uobjects
are there any known quirks/issues with using server travel in PIE? i'm trying to test map transitions in the editor running in dedicated client/server mode and when i call ServerTravel the server just disconnects the client and it never tries to reconnect
am I trying to use it wrong? for this i'd be happy with either non-seamless or seamless travel, haven't gotten either to work
Seamless Travel should be enabled by default.
You should not change this.
Unless you know why you wouldnt want it.
So make sure its enabled on all your GameModes.
all i can say
The plugin name is MultiServerReplication , the init code has been there for awhile.
i've tried enabling it every way i can find, I just can't get it to work (can't get non-seamless to work either). the server changes map, client gets dced (on seamless or non-seamless) and tries to reconnect but can't
not sure if its a PIE specific thing or not, all i see in the verbose logs is: LogNet: - HostClosedConnection LogNet: Verbose: Level client received: Failure LogNet: UNetConnection::SendCloseReason: LogNet: - Result=FailureReceived,
but that's after the server seems to successfully load the map with "Load map complete"
PIE doesn't support Seamless Travel by default. You can enable it but the flag is experimental and you might crash.
PIE always does a Hard Travel by default.
If you need to test Seamless Travel properly, you gotta run the game in Standalone or Packaged. Or bet on that experimental flag.
i'd be ok with hard travel for what i'm testing - should it work if i launch a client in PIE and have the option on for the dedicated server launched in a separate process? that's what i'm trying to do currently and still can't get it working
none-seamless ServerTravel should work fine.
Not sure about starting the Server as a second process in PIE. PIE is already so "special" in a lot of things it does.
would that work even if the server is in-process in PIE too? i feel like i've tried a lot of combinations and i'm not sure what i could be doing wrong to cause it to fail
I would just play under one process, set it to Play As Client and 1 player and that's it.
Yeah, ServerTravel should work just fine. It will disconnect the Client, that is expected, but it will auto-reconnect basically.
ok, yeah that's what i tried originally, if that's supported then it should be something i have misconfigured
You do have to keep in mind that the code-flow is different between Hard and Seamless Travel
There are a bunch of functions that won't run with Seamless Travel, as the Client is expected to stay connect and not join again.
If you init stuff on PostLogin it will call again for HardTravel but not for SeamlessTravel
So testing with HardTravel is potentially a shitty idea.
not currently calling anything on PostLogin so it should be ok - i'm just looking for a convenient local dev way to test map changes with a server running
i'm just calling ServerTravel from C++ on the server to initiate the process
still can't get ServerTravel working properly no matter what I do - when I try it as a listen server + client, the server properly travels, but the client gets DCed and cant reconnect (this is with both same-process in PIE - result is the same with dedicated server too)
**Current Output : 3 clients (A,B,C) -> A hosts a private session -> B tries to join -> B rejected because wrong password -> B goes back to default map (pop up notification does not show up, i suspect its because after showing popup engine calls client travel). -> C gets notification popup
Expected Output : 3 clients (A,B,C) -> A hosts a private session -> B tries to join -> B rejected because wrong password -> B goes back to default map -> popup appear informing the player**
I have a function bounded to OnNetworkFailure Event of Gengine class in my playercontroller , Basically what i'm trying to do is validate password server side, so checking password In Gamemode on PreLogin , at this time playercontroller doesnt exist so i assign message to ErrorMessage outparameter.
Here's the code
GameMode CPP
void ALobbyGameode::PreLogin(const FString &Options, const FString &Address, const FUniqueNetIdRepl &UniqueId, FString &ErrorMessage)
{
Super::PreLogin(Options, Address, UniqueId, ErrorMessage);
FString Password = UGameplayStatics::ParseOption(Options, TEXT("Password"));
if(!SessionPassword.IsEmpty() && SessionPassword != Password)
{
ErrorMessage = "Invalid password";
return;
}
}```
PlayerController CPP
```C++
void ABasePlayerController::BeginPlay()
{
Super::BeginPlay();
if (!GEngine) return;
GEngine->OnNetworkFailure().AddUObject(this, &ABasePlayerController::OnNetworkConnectionFailed);
}
void ABasePlayerController::OnNetworkConnectionFailed(UWorld *InWorld, UNetDriver *NetDriver, ENetworkFailure::Type FailureType, const FString &ErrorString)
{
UE_LOG(LogTemp, Warning, TEXT("NetWork connection failed called on playercontroller "));
if(!IsLocalPlayerController()) return;
PushNotification(ErrorString);
}```
Output:
LogTemp: Warning: NetWork connection failed called on playercontroller
LogTemp: Warning: NetWork connection failed called on playercontroller
LogTemp: Warning: NetWork connection failed called on playercontroller
LogTemp: Warning: NetWork connection failed called on playercontroller
As you can see its called multiple times , i dont know why.
and how do i know which client got Rejected? , because right now all clients are getting notification popup
do suggest if there is any better approach to this
ok for some reason, calling GEngine->Exec to run the console command for server travel works, even though World::ServerTravel did not. i have no idea why thats the case
Just make a couple scripts that launch the project as server or game.
It's super easy. It's the equivalent of right clicking the uproject file and selecting play game, with options.
Binding to GEngine is probably gonna cause it to show for everyone in PIE.
Also you'll most likely need to cache the Error and then have something in your MainMenu GameMode or similar that checks displays the messages.
I usually use the GameInstance to store an array of them and fill the array from the callback.
When the player has loaded the main menu again, I check the array and display the first message. When the dialog gets closed I check again until the array is empty
Chances are high that your PlayerController dies when the connection is refused. So that notification dies with it
And about it opening for everyone, you might want to check what the GameInstance is doing for its own events, cause I don't think that happens for it
If I use a Set Leader Pose Component, how do I use a Montage with it?
Aye! Thank you , It Worked
Can you explain what you are actually trying to ask here?
Cause both things on their own make sense, but combined the question seems lacking info.
Especially in a Multiplayer channel.
Is there a way for the AnimBP to know if its a proxy or not?
You mean SimProxy?
You usually have access to the Pawn/Character/Actor that the SkeletalMeshComponent is on. That you can ask for the local role
Hey guys,
I'm learning multiplayer in C++, and I'm stuck on a replication issue.
I have a system where the head rotates when looking up/down. It works fine for the owning client, but for others it's laggy/jittery.
I made headRotation a replicated variable, added it to GetLifetimeReplicatedProps, and call a server function if the client have not tje authority but it work with the lag.. (I don't even know how tf it can work)
Not sure what Iβm doing wrong. Any ideas?
it's probably only being replicated every so often due to its priority
best thing to do would probably be to interpolate its position on the client
that way you aren't using large amounts of net traffic replicating a turning head and it'll look smooth for everyone else
Hmm, okay, got it. Iβve experienced a similar issue with my sprinting, there was a bit of jittering. I managed to fix it by using some unusual replication methods xD
But if itβs just an interpolation issue, then is will be fine.
sprinting is probably you fighting the CMCs built in prediction
jittery character movement usually means a misprediction
aah make sense indeed alright I will try that thanks you
I have a head turning system. For the local client, its smooth and updates on tick but I want to update it only ever .5 seconds for the proxies if that makes sense?
I keep running into an issue where all the AnimBP's only use one system or the other.
Well I told you how.
Oh so I can just get the ENetRole use that?
I keep trying to use IsLocallyControlled which seems to always be false. Ill try that.
It doesnt. Ever. Its weird.
Anybody run into issues with binding a player into a networked Sequencer asset? Its something we were doing in 5.4, but in 5.5 when the sequence finishes my character no longer does attack animations at all.
Are you maybe calling this on an AI controlled character?
No, I got it working.
im trying to save data when player exits server, either by alt+f4 of the client or by just dsiconnecting, i thought to use event onlogout but it doesnt seem to fetch the playercharacter
is character destroyed so fast that i cant get ref to it?
Pawn gets destroyed when the PlayerController leaves somewhere in the PlayerController class. Could totally be that this calls before logout
You can override void APlayerController::PawnLeavingGame() to first retrieve the data you want from the pawn and then destroy it if you wish.
I wonder, should this object replicate properties, created in BP and makred as replicate?
- I have a
Component, that lives on thePlayerState. - That
Componenthas aFFastArraySerializer(which already works in replicating the objects).
The Object itself:
virtual bool IsSupportedForNetworking() const override { return true; }
virtual void RegisterReplicationFragments(UE::Net::FFragmentRegistrationContext& Context, UE::Net::EFragmentRegistrationFlags RegistrationFlags) override
{
using namespace UE::Net;
// Build descriptors and allocate PropertyReplicationFragments for this object
FReplicationFragmentUtil::CreateAndRegisterFragmentsForObject(this, Context, RegistrationFlags);
}
And on the component, I call AddReplicatedSubObject(Result); for the object.
Are the "objects" just UObjects?
A regular TArray would be fine for UObjects?
Not sure why you would need a FastArray if they are just regular UObjects?
I was just building it similar to another system (there i didn't teste the replicateion of properties)
But what I just now figured, there is some properties, that are on the base class in C++ with DOREPLIFETIME they are replicated for the object.
But for the class created in BP, where I set the variable to be replicated, RepNotify is never called on the client π¦
*RepNotify is called on the server but not the client
This also won't replicate
UFUNCTION(Reliable, Client)
void ClientProgressed();
while this does
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Status, SaveGame)
EStatus Status;
It's just so that changes to the array/list wont have to replicate the whole list.
is this true, that I won't be able to replicate blueprint variables on a Uobject?
Hello,
I dont know if its the good channel, but is world partition supported with listen server ?
Because i found a topic that said it wasnt supported but it was in 2022..
Specifically with ListenServer or multiplayer in general? I'm relatively sure it's working with Multiplayer, otherwise my current client(customer) would have a problem :D
@mortal blaze
I'm thinking the listen server would have to load every single cell players are in which might be a bit bit much in some situations
Where does it say it doesn't work at all on listen servers? Which part of it?
I mean, the world partition will work on the client the loading distance load only some mesh etc
but the server will always load all the map
You can try it out I suppose with a simple test map that has some cells
Your goal here is to not let the players in distant cells that the listen server is far from fall through the floor I assume
fairly certain abiotic factor does this with listen servers
It seems more like a typical sublevel workflow imo but I am not sure how to tell
Great game though
My goal is to get the server and all client with world partition, but i can't find a way to make the loading distance work on the server. All client did'nt load all mesh, but i have the impression that the server will always load all the level and do not take into account the loading distance.
Then i dont know if world partition will be the best solution.
That's why I was wondering if the worldpartition was suitable for the listen server or if it was just a limitation
Specifically with listen server, because i guess with dedicated server there would be no problem
I wouldn#t necessarily see a difference.
Server would need to of course load the different parts for clients too.
Yes, that's what I was thinking when I started my tests, but in the end I noticed that the server won't just load the location where it is + the locations of each client, but the entire level. And so I was wondering if I had missed an option that would help use the world partition on a game with the listen server
@thin stratus
Right, I sadly don't know, but maybe someone else will.
Thanks
Yes, that is the topic i found, but its in 2022 and i don't know if they made world partition supported with listen server on recent version
Hmm WP + Listen Server would be an odd choice generally speaking, not sure if there's anything specific that oesn't work in a listen server, but the performance would likely be worse for sure
Okay, thanks.
So, in a co-op game with a listen server, what's the best way to optimize? So as not to load the entire level for everyone?
Data Layers?
For everyone?
Yes, like client load only his part, and server load only the part where client are + his part of course.
yeah that's literally what jambax just linked
but it seems quite experimental
I would expect this to have confusing issues for things epic didn't use yet
Oh, ok ok, i see, ill try it later on my project thank you all
Hey hey everyone!
I've been reading through some of the opinions shared here on Mover/NPP.
I'm wondering though what the opinions are when thinking in the context of competitive games (server authoritative, snapshot interpolation, server rollback detections...).
Do you guys think it could be worth adopting all the current challenges of Mover to gain synced time and fixed tick, making snapshot interpolation and accurate rollback implementations easier?
Or has anyone maybe successfully pulled that off inside the CMC?
I myself am not aware of any CMC snapshot interpolation implementations. Although there does exists custom commercial stuff like SnapNet.
So please, Mover and CMC masters/masochists, share your opinions, it would be much appreciated!
pretty sure CMC already interpolates and does rollback
snapshotting would be on you
if you have really complex movement you will have to modify the cmc
otherwise it'll probably work out of the box
CMC isn't very modular, it isn't very fast, and it's a little cursed code-wise, but it's very functional and feels good
What kind of game are we talking about? CMC should be fine for a lot of games.
The Mover and NPP challenges can easily add weeks and months of development time. And the FixedTick stuff wills till only work in NPP land, so everyting outside of it still breaks the simulation (so GAS + CMC isn't solved via Mover and NPP).
And it's also very likely that simulations within NPP can't talk to each other properly either, without causing OOB changes.
hmm, good to be aware of this point, thanks for that
talking here about, say for example, movement heavy competitive fps, think quake, titanfall, apex...
CMC
CMC is battle tested by Unreal Tournament and Fortnite by Epic, and by tons of other games out there.
It has a metric shit ton of features and fixes for difficult problems compared to Mover.
Mover will go the Chaos Simulation way and it will still be a while before it has feature parity with CMC, if ever.
that's what it's looking like, yeah
what I'm looking into with CMC right now is pretty much the issues described in this article: https://snapnet.dev/blog/performing-lag-compensation-in-unreal-engine-5/
issues around accurate hit detection with server rollback
Mover won't fix that. You'll implement it there from scratch the same way you will need to for the CMC, and on the way you'll miss all the stuff CMC offers.
namely, time sync, and the simulated proxy potentially being in a state where it never actually was on the server
yeah but again I think that's a general problem
I see, I haven't looked into the inner workings of Mover yet, so this is the info I really wanted, awesome
I was thinking that at elast the time sync issue was somewhat resolved
Step 4 in that guide is also kinda missing that the Server needs to interpolate between 2 snapshots
You can't just take the best matching one.
and that implementing snapshot interpolation would be easier with Mover
Server is most likely ticking way lower than the client, so there is no chance that will align
implementing snapshot interpolation without prediction is quite trivial btw
that's what I was hoping would be the case if I tried doing it in CMC, but was afraid Im underestimating things there
the problem I see is that you seem to be mixing different systems
The CMC has Timestamps you can use for this stuff fwiw
am I missunderstanding here how the CMC works? I thought it only quickly smoothes/interps from the current extrapolation to the new state update from the server, then extrapolates until we get the next state update again?
how so?
there are a few techniques to replicate movement across network and they have pros and cons, but some tricks in one won't apply to the other because they operate on completely different assumptions and models
can I bother you to elaborate on this a bit π
yes, for sure, for accurate rollback, we'd need to get the 2 states before and after the time of event, and interp by the difference to get the actual state at time of event.
or at least the most accurate aproximation
For example snapshot interpolation (without prediction) assumes that client is always behind, and just smoothly updates position based on the last server updates. It therefore has a big delay on clients depending on how fast the snapshots arrive and how many are you buffering.
CMC is predicted and while there are common concepts such as the existence of snapshots, the fundamental premise is different because client is always ahead.
First case client and server always match because client just "plays" back what server did.
Second case they can missmatch if server/client disagree, which now needs some technique to correct the deviation.
I am mostly talking here about simulated proxies though
where, moving from extrapolating from latest state, to proper snapshot interpolation would remove one of the potential missmatch sources, at the cost of some extra latency on the simulated proxy representation
Server and AutoProxy usually communiate a synced Timestamp, so if you forward that to the Server when you fire the weapon, you'd have something on the Server to adjust all the timings with.
I think I remember seeing an approach that was doing this, where the conclusion was it still wasnt perfect
might be completely missremembering
"perfect" is also absolutely impossible.
would you say that's good enough for solving the timing part of event estimations most of the time?
You are dealing with 3 parties here.
AutoProxy -> Lives in the Future (Timestamp X)
SimProxy -> Lives in the Past
Server -> Lives in the Present
The Server can't just take the Timestamp X and recreate the situation that the AutoProxy saw perfectly.
The Timestamp only tells the Server when exactly the shot happened, so the Server can ensure that the AutoProxy is in the right location.
The SimProxy that the AutoProxy saw is however far in the past.
Simply going backwards in time to where the SimProxy was on the Server at Timestamp X doesn't work, because the AutoProxy saw something that replicated down to them, so you also need to move another RTT/2 backwards, and that is not something stable.
aah of course, thanks for clarifying that for me
It helps picturing where everyone is at a given point in time on the two/three instances.
could another way of determining what state we need to rollback to be to keep track of what state # the simulated proxy was at on the client at time of event, and forwarding that to the server as part of the event request?
roughly speaking
You could potentially replicate the Timestamp that the SimProxy data belongs to. The number won't mean much to the AutoProxy, but you could send it back to the Server so they know what you looked at.
Replicating floats can be a lot of bits though if you have lots of players.
yeah, this is something a fixed tick would help with
but even via timestamps, for low player counts, should still be fine I'd guess
I'll be looking more into this stuff then anyway, I'm for sure gonna be going with the CMC then moving forward
would you happen to know of any repos or such dealing with this kinda stuff I could look at?
(snapshot interpolation, rollback, hit detection, replay...)
and also, anywhere I can buy you a virtual beer Cedric? π
Your info and resources have been so valuable for me!
:P all good, don't worry about it.
Hm, no, not sure. That's usually technical enough to sit behing closed doors.
Maybe you can get @grand kestrel to update his repo with something.
so it would seem, although it's really surprising to me that a netcode approach widely in use since the early 2000s doesn't really have any openly available Unreal implementation
not that I can find at least π
Man, people like you, vaei, jambax, kaos... You've all done so much to make getting into this kinda stuff easier!
Poor poor WizardCell and Datura
of course, there's many more I could name or just haven't come across yet, warm regards to everyone and anyone freely giving deep knowledge to the community!
I feel like Epic's Unreal Tournament was such a good opportunity to do something like this, too bad it didn't really hit the mark on some stuff.
Wanna summarize for me lol
Hit Detection (shooter) with Client Prediction and snapshot-based rollback/interpolation on the Server to confirm the shot, using the CMC
It has been almost a decade since I wrote anything like that
Its not something I would spend time making unless I needed it myself π
Fair enough.
Many games don't actually use rollback for shooting anymore, because of how CPU intensive it is, if you were making Valorant then yes, but anything with high player counts nope
most of guides are written by the author for the author then shared because why not
There are a lot more simple checks/trust the client that happens than people realize.
Yep
Is there a way to replicate properties of a uobjekt implemented in blueprints?
Im able to replicate properties in a c++ class that are markef as doreplicate and when the uobjekt is added with addreplicatesubobject.
But when i inherit the Objekt as a BP and make bp properties as replicate they are not replicated π
you have to add it as subobject some how
I don't recall there being any way to add replicated properties in bp though
Yea that's done with the afdreplicatesubobject.
So it is just not possible to add replicated variables in bp then? π¦
I don't think so
i remember having the same issue with uobjects in the past and was really confused
this is specific to uobjects btw
it's really bugging me π
@glossy wigeon You can make a static blueprint function library that exposes this to BP pretty easily. Here is how i did it:
Header:
/**
*
*/
UCLASS()
class UBlueprintReplicationUtils : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
// Adds an object to the actor's SubObjectList so it can be replicated.
// The actor must be somewhere up the objects outer chain, and have ReplicateUsingRegisteredSubObjectList enabled
UFUNCTION(BlueprintCallable, Category = "Faerie|Utils", meta = (DefaultToSelf = Actor))
static bool AddReplicatedSubObject(AActor* Actor, UObject* Object);
UFUNCTION(BlueprintCallable, Category = "Faerie|Utils", meta = (DefaultToSelf = Actor))
static bool RemoveReplicatedSubObject(AActor* Actor, UObject* Object);
};
and Cpp file:
bool UBlueprintReplicationUtils::AddReplicatedSubObject(AActor* Actor, UObject* Object)
{
if (Object && Actor)
{
if (Object->GetTypedOuter<AActor>() != Actor)
{
UE_LOG(LogTemp, Warning,
TEXT("AddReplicatedSubObject: Should not register Object to Actor that does not own it."
" GivenActor: '%s', Object: '%s' DirectOuter: '%s', FirstActorOuter: '%s'"),
*Actor->GetName(), *Object->GetName(), IsValid(Object->GetOuter()) ? *Object->GetOuter()->GetName() : TEXT("none"),
IsValid(Object->GetTypedOuter<AActor>()) ? *Object->GetTypedOuter<AActor>()->GetName() : TEXT("none"))
return false;
}
Actor->AddReplicatedSubObject(Object);
return Actor->IsReplicatedSubObjectRegistered(Object);
}
return false;
}
bool UBlueprintReplicationUtils::RemoveReplicatedSubObject(AActor* Actor, UObject* Object)
{
if (Object && Actor)
{
if (Object->GetTypedOuter<AActor>() != Actor)
{
UE_LOG(LogTemp, Warning,
TEXT("RemoveReplicatedSubObject: Should not remove Object from Actor that does not own it."
" GivenActor: '%s', Object: '%s' DirectOuter: '%s', FirstActorOuter: '%s'"),
*Actor->GetName(), *Object->GetName(), IsValid(Object->GetOuter()) ? *Object->GetOuter()->GetName() : TEXT("none"),
IsValid(Object->GetTypedOuter<AActor>()) ? *Object->GetTypedOuter<AActor>()->GetName() : TEXT("none"))
return false;
}
Actor->RemoveReplicatedSubObject(Object);
return true;
}
return false;
}
but this wont solve the issue, that properties marked as replicate in blueprint won't be replicated right?
as long as:
- The base UObject class overrides IsSupportedForNetworking to true,
- The base UObject class overrides GetLifetimeReplicatedProps to fetch BP properties
- The properties are marked for replication
- The object is replicated by a replicating actor
then yes, they should
you may be missing step 2
looks like this for me
I do have to cast it to the bp class and then call getlifetimeblueprintreplicationlist as well?
or can i do it without the casting to specific class?
well you are just casting to the generic GeneratedClass. it will always be that class for BP classes unless you have a specific custom GeneratedClass, which is pretty rare
ohh but maybe this is the thing I'm missing
@glossy wigeon ooh, almost forgot, if your C++ base class does not have any replicated properties then unreal shits itself, and wont replicate the object correctly so add this macro to the header underneath the GENERATED_BODY
UHT is supposed to add that macro by itself, but it wont if the number of c++ replicated properties is 0. βΉοΈ
I even have one replicated property on the class
I think it already is added
at least looking at the generated c++ file
great
Now it is working!
I really think it's just this part, that was missing!
if (const UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(GetClass()))
{
BPClass->GetLifetimeBlueprintReplicationList(OutLifetimeProps);
}
Thank you so much! π
next step is to make it work using Iris
I already have this part in, since I'm builind on top of a lyra thing, but I read that there might be issues when switching to IRIS, so I'm a bit scared ^^
#if UE_WITH_IRIS
void UQuestInstance::RegisterReplicationFragments(UE::Net::FFragmentRegistrationContext& Context,
UE::Net::EFragmentRegistrationFlags RegistrationFlags)
{
using namespace UE::Net;
// Build descriptors and allocate PropertyReplicationFragments for this object
FReplicationFragmentUtil::CreateAndRegisterFragmentsForObject(this, Context, RegistrationFlags);
}
#endif // UE_WITH_IRIS
yeah, thats all you should need to do!
Also I know even less how IRIS works then the normal replication system ^^
and that would automatically replicate it, the same way as the normal replication system?
should be?
i've found that Iris is much for finicky with nested subobjects
so if your replicated object has a bunch of replicated child objects, every one needs to have AddReplicatedSubObject called on it as well. which makes tracking dynamic children a pain
I thought about trying it, but also I've soo many other things that I need to do, and then breaking stuff that already works because of IRIS, that was scares me a bit.
I see that sound a bit painful
my Inventory system is a bunch of repl' objects bundled together, and yes, its a chore
why would I even use IRIS is is just less network traffic?
its faster? Β―_(γ)_/Β―
^^
its multithreaded i guess
nice
might be the first step, towards what tim sweeney mentioned about ue6, where they want be able to really support millions of people in one world.
well sure, but more concretely, its part of the move away from "everything Actors, all the time"
how do you mean that?
epic wants to push "Scene Graph" and their new ESC tools, and stop using actors for everything
UE6 might not even have actors
ohh wow ok
the old replication system was tied directly to actors, so they needed Iris to decouple replication from the actor framework
i see so you have just a uobject and the things like replication and so on are modules you can add instead of the actor owning it?
i dunno, i havent seen how scene graph works Β―_(γ)_/Β―
they mentioned it alot at the last unrealfest, but i didnt get many details
we might get more at this next unrealfest
ohh wow I maybe have to look into that as well sounds interesting
that sounds nice but they'll have to replace half of the engine and I don't see that happening anytime soon - everything new in UE5 is significantly slower than their UE4 counterparts
Currently default stuff in UE doesn't scale even to a few hundreds
yea thats true
I was taking a look at the replication pipeline to see where rep conditions would be taken into account (for example at what point in the code it is decided what should be sent to everyone and what to owner only).
I thought the server would keep a change-list for each connection, excluding directly from the list properties that are not relevant to that connection, but seems that only one change list is made for all (?).
So does anybody know where rep conditions are evaluated?
What do you generally mean is slower in UE5?
TSR is like 10x slower than TAA, some stuff in Chaos was 2x slower, Lumen is also very expensive, etc.
I don't wanna bash it, it's new tech that needs work and also is not necessarly built with performance as first priority, but sometimes when I compare the marketing with the actual engine, there's a big gap hehe
Can anyone help me figure out why my Server travel disconnects my clients?
which replication system are you using?
In iris it's done in one simple bitmask function but I'm not sure about actor channels
I'm a having a hard time setting the net mode in my project (5.4)
Where do you typically set GameNetDriver?
The default one
inside Config/DefaultEngine.ini
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
I can't say much about the physics part, except that I know Chaos is also insanely more realistic and less buggy already than Physx. Likely why it costs so much. Physx is way too crazy about putting things to sleep too fast and it causes weirdness in the sims. There's a few side by side demos floating around that showcase it.
For the rendering side, that is a huge "It depends". The idea that Nanite/Lumen/TSR is slower, is not really true across the board. It is true in the sense that if you take a lot of older projects and straight up port them with their super optimizations for the old ways, you'll probably lose some performance. The new systems have a higher entry cost for sure. Even sitting in a blank map costs a lot more. But take a huge complex scene an you'll quickly start to see the new systems pull ahead. And just like the old systems, they have their own tech art quirks that you need to handle. You have to check your shadowmap invalidations, you have to optimize the lumen buffer, etc etc. And if you do things correctly, you'll start to see high frames in detailed scenes. This gets even better with the way rendering changed with passes. If you have 50 static meshes with the same material like say some sandrock. And you use these in a scene. In the old system you had one pass per mesh, unless you use ISMs which then it was still one pass per mesh type. With the new you have one pass for everything using that material. As you can imagine that is a few less drawcalls.
And they recently did some work on that whole indirect binding stuff
Also the multithreaded rendering stuff they did that I'm pretty sure is independent of the new systems.
If you can find some of those comparison videos - I'd appreciate it! (More out of curiosity)
This one always comes to mind and is easy to find.
https://packaged-media.redd.it/k9blsq3f9f4b1/pb/m2-res_480p.mp4?m=DASHPlaylist.mpd&v=1&e=1747393200&s=868972280c16e1387e73e7dc1171179801fb4a92
the finals exist so imo you can do it 
Chaos has gotten slightly better but yeah it's a shame
you can just use another physics engine if you hate yourself enough to integrate it 
Havoc
excuse you, you mean Havok π€
I just read a post about how lumen and nanite is daunting and how this person spent months optimizing materials and meshes and such for this. Then later went on to point out that they are running on DX11 because they noticed it runs better than 12.
Bro I don't know how to tell you this, but... all of your nanite and lumen optimizations.. kind of aren't... doing.. anything.
Physx5 gets used in industrial simulations... I would not accuse modern physx of being innacurate
The breaking difference will probably be no support for doubles unless I am missing something
Jolt for example can compile to use doubles but it runs about ~10% slower and converts math to be in local space with floats whenever possible
Is there an engine using "Modern" physx at the moment?
good question
Brickadia does https://brickadia.com/blog/devlog-1/
The sad part is that it compiles faster too, woof
Chaos templates are too much I guess
can you describe then problem more detailed? What happens excatly? Clients by default are not disconnecting while server travel (if it is seamless)
Truee, as I am continually made painfully aware of by the rampant cheating in many such games π
I'd love to read up more on non rollback approaches here, as I'm sure a lot can be done beyond the simple heuristics I could think of. Know any good resources maybe?
And thank you for the replicated movement repo! It's been so helpful for me as I was learning the CMC. π
I wonder how fortnite is doing it, it never felt like there's been a huge cheating problem, but they for sure are not doing rollback on that scale.
Yes, but documenting it, making it accessible, then potentially even responding to the people trying to learn from it, it's a huge time commitment. Respect for anyone who takes that on.
yeah im just saying this because ik zomg and I do this way 
making something 100% for others is a big time commitment, ive done it a few times and i spent multiple weeks working on it, so less time for actual game dev
can I implement a custom net serialize for a fast array item struct? or does fast array voodoo prevent me from doing that
Thanks for the insightful response, much appreciated 
I was mostly under the impression that it was slower due to my own testing and experience, also based on some comments around here. Will be interesting to deep dive then into how some of this stuff works
I was under the impression that the more regular folk understood that the new rendering stuff have a higher base cost, but scale much better. So - your little gamejam game, they're worse. A game like say, Split Fiction, they're better (in theory)
Of course you have to build for it to realize it (also, Split Fiction was just an example of size, not that it in particular would've benefitted)
Funny that it's basically the same as with TMap vs TArray.
The Hashing might be nice, but one only really benefits from it at scale.
i want to allow mini games to be started by players with their own custom rules for each one inside of an open world, there's a lot more to think about but im thinking of creating a component that handles all of the logic for each mini game and putting it on either the game mode or the game state, and clients would ultiatmely request to start one of them and the component would handle all of the checks / requirements etc and then (if player passes requirement checks) to start it and end it for those players that requested to play whatever mini game based on the rules for the mini game
does this seem like a good approach to handling something like that?
Hi guys, i'm having a real trouble, my character client side has jittery movement on platform that are moving
I'm using timelines or set actor, set scene world location, relative location, whatever, with replicated check, replicated movement checked or not, whatever i do i can't have a fluid movement client side as you can see in the video.
I'm using camera lag so it's way smoother to play with the character, i can't disable it or movement feels horribly stiff, but if i disable it i don't have any problem on the platform, some say it's my platform who is not well replicated, can someone help ?
Here is my code and a video, THANKS MUCH !!
This is an example. Note that we have very little support for non nanite/lumen at the moment. All we've done is LODs from an editor utility. I'd also note we have done nearly nothing to optimize for newer systems so far due to early dev.
Left is in game zoomed way out to show the whole map
Center is zoomed in very close
Right is in our main menu that is a blank world with widgets.
The top three are from Lumen and Nanite disabled with AA being set to TAA.
The bottom three are Lumen and Nanite enabled with AA set to TSR.
Kind of showcases that there's a much higher base cost. I get up to 320-360 fps without the new stuff enabled. And I get max 270 with them on in a blank map. But get into a real map with a lot going on, and you don't see much change from small cost scenes like the zoom in to the full zoom out, like where old systems just die trying to render it zoomed out.
I don't think there are any good resources
Have built it in the past, it is a lot of work, and CPU intensive
Ultimately you are just caching each hitbox with a timestamp, and looking for overlaps based on the timestamp, rather than where they are presently
afaik, FastArray's voodoo magic lies mostly in MarkArrayDirty and MarkItemDirty. I'm fairly certain NetSerialize isn't too closely coupled with those.
Getting this crash
#if WITH_EDITOR
const UPackage* ObjectPackage = Object->GetPackage();
if (ObjectPackage->HasAnyPackageFlags(PKG_PlayInEditor))
{
const int32 DriverPIEInstanceID = Driver->GetWorld() ? Driver->GetWorld()->GetPackage()->GetPIEInstanceID() : INDEX_NONE;
const int32 ObjectPIEInstanceID = ObjectPackage->GetPIEInstanceID();
if (!ensureAlwaysMsgf(DriverPIEInstanceID == ObjectPIEInstanceID, TEXT("FNetGUIDCache::SupportsObject: Object %s is not supported since its PIE InstanceID: %d differs from the one of the NetDriver's world PIE InstanceID: %d, it will replicate as an invalid reference."), *GetPathNameSafe(Object), ObjectPIEInstanceID, DriverPIEInstanceID))
{
// Don't replicate references to objects owned by other PIE instances.
return false;
}
}
#endif
callstack
Questions
- assumption : unreal multiplayer servers can be hooked up to existing python / c# backend systems which manage lobbies, player information database, iap transactions with crossplatform providers etc etc. True or False, Commonplace or Tricky?
Basically anything is possible with programming.
its pretty trivial to make http requests in UE.. so if the backend can accept http requests its pretty easy
Sure, the leading question is what sort of solutions are people using.
That sounds a bit slow though? But yes, it could be http, certainly. I haven't done this sort of thing much, and interested in investigating stuff - looking for alternatives like ZeroMQ etc. Optimally people who have done this sort of thing fairly recently to give some clues : )
On another page:
I'm a bit jealous reading about how Marvel Snap was made with c# on both client and server, so they could run the same authoritative server code on both client ( for standalone solo development during early production ) and server ( for the final product )
That's because they used Unity.
yes indeed, not going there though
You could use C++ for your server if you wanted
perhaps unlikely, seems like python is the current foundation...
Building all the existing infrastructure again is not an attractive proposition
Well, http is in any case the baseline so far. Will have to ponder things with the fellows
Hello,
I have this blueprint that allows me to check one array against another and empty it as the values ββin it are used. It works as I want; as soon as the main array is emptied, it no longer returns anything.
But I run into a problem as soon as I start using clients. I'd like these arrays to be the same for the server and each client. That is, if a client "uses" a value from the main array, it will remove it from that array, but it will only do so for its own array, so the others will be able to use that value.
I can't find a way to make these arrays somehow shared between each client and the server. I've used repnotify, but without much conclusive results. Unfortunately, I haven't found much help beyond that on forum topics, etc.
I'm new to variable replication, so I may have misunderstood certain concepts.
When I say I tried with repnotify, it means I tried to put certain pieces of bp in the repnotify functions of the variables used. But I removed everything as it did not work as desired.
so you're trying to have different versions of the same array on multiple clients? i think not possible or infinitely difficult
changing a replicated property should only occur on the server. so server rpc and change it
you're probably better off making a component or something that takes ownership of whatever is in the array and keep the "main array" the same for all
Since these arrays are present on BP_ThirdPersonCharacter, each spawned BP_ThirdPersonCharacter has its own copy of the arrays.
If you want a shared array between all of them, then you'd need to store and access the array from some other singular source, such as the GameState.
Can I call a play montage in a repnotify?
You can do w/e you want - it is just a function that gets called when some variable changes.
I'm trying to call the play montage in repnotify function, but the animation only works in the server side
This is actually EXACTLY how GAS montage task replication works
They even include the rate to play at and a section name
What is actually being received on the client?
Hey, I have a helicopter character class. When I jump out of the helicopter, I switch to falling mode. Visually, the helicopter falls down after I unpossess it, but when I possess it again, it continues from the position where I jumped out, not from where it actually fell. if I switch falling mode without unpossessing (meaning I fall together with the helicopter), and then get out and back in, I donβt have this problem.
So I think the issue is happening after I jump out specifically, after unpossessing. Any solution for this?
I assume this is client's perspective, it would also suggest that your helicopter is just falling on client while maintaining position on server in just jump out it situation. CMC doesn't really bother replicating the MovementMode
ZLO!!!
Actually it's the opposite on the server it's staying in falling mode but on the client it switches to custom mode when the character is unpossessed
the only ways server wouldn't be correcting client position is either its no longer replicating or the position on server is stationary, so it sees no reason to send updates. Possessing the helo again forces an update which brings you back to where you started.
but that discrepancy between MovementModes is likely whats causing the issue for you
yeah i'm working on a custom movement mode, probably missing something. thanks for taking the time
isfront is constantly changing when closing and opening the door. i want the door to open opposite to whichever side i am on. apart from this problem i don't understand how to do replication. normal door was working properly
my guess is its the overlap events fighting each other or something
maybe you could use position or something instead of overlaps? like transform the actor opening the door's world position into a relative position from the door and use that to see what side its on?
i tried that first but there was an error and i chose to try a simpler method. the collisions are on the front and back side of the door so i don't think there is a conflict but maybe the trace i created triggers the other collision. i need to take a look
Movement is, by default, not processed if there is no valid Controller.
You need to enable it to "Run Physics With No Controller" or something like that. Should be a checkbox on the CMC I assume.
oh this is working tysm
Don't worry. Even Valorant had that issue :D
still learning how to make custom movement components so i thought there was a bug in my code and wasted a lot of time
In C++, RepNotify functions are only "automatically called" for pure clients. If you're utilizing a ListenServer, you need to manually call the RepNotify function for the ListenServer after the code where you're changing the replicated variable's value.
In case of optimizations which network event is more recomendedOnRep or NetMulticast ?
iirc, OnRep is used in games which has some kind of open matches, player can join at any time existing matches
so they can see what was going on
and a multicast is straight forward and not taking into account to re replicated things to new players
so onrep is using a tick event somewhere running holding the old state and if new player joins, replicated that old state to them
does anyone have tips for replicating a state tree?
I don't think you should be worried about optimizing for performance of these things. You use the appropriate tool for the job. Stateful things - use an OnRep. If it's fire and forget and only matters for those that may have the actor relevant, multicast. If you are starting to have problems because of the sheer number of properties that you may have marked for replication and your CPU time is suffering, then you probably want to look into push model, not just using a multicast.
If you're talking about the AI state tree that is. Typically - AI logic only runs on the server. If you need to replicate anything, you'd replicate it via the pawn that gets passed in to the state tree schema.
gotcha
In our RTS we derive AI states almost entirely from player orders which are replicated, so that can be a way as well depending on the system
What class , if any , would be the default owner of an already-placed-in-the-world actor?
Pretty sure its the level itself.
Hmm ok is it possible to make the game state the owner on begin play or something? Maybe could spawn those specific actors from the game state in begin play or on begin play of the actor make the game state the owner
If thatβs even possible
Yeah. On begin play, check for authority - then if so, set the owner to the game state.
Is there a particular reason you need to have the ownership set like this?
Nice, good to know that I can @quasi tide
And yea good Q. Iβm honestly still thinking through a concept of having clients trigger mini game modes in the world, so Iβm thinking of how to properly control these actors.
But if Iβm honest Iβm still not clear on what the best method of approach for this is
Just have the client do a server RPC and have the server trigger it for the client.
Yea thatβs the simple way I originally thought about it. But because I was thinking of how to keep track of progress / status of these actors I wanted to have that data in the game state but again I was kinda looming for a reason to use the game state for this as it just seemed like the right idea. But yea still working through the idea
I can't think of a way that having the GameState being the owner of actors in the level would help you achieve your goal.
These actors themselves can be the things that manage the mini-games' state. if need be, you can have a component on the GameState that these minigame objects can report in to on their begin play or something in case you want some easy way of accessing them.
As far as triggering goes, if you're hoping for client input to trigger them, then an RPC through a client owned actor/component is the only way.
Yea I agree , I appreciate the thoughts. Def overthinking it a bit but this helps me feel reassured sad itβs a more comfortable approach
This is probably why I avoided it in the beginning now but yea typically would just do it from the character but was trying to a new approach lol
Will try to update with what Iβve tried in a few hours
Hi what is the "turn based" section?
Im making a super wierd version of poker and Im wondering if it might offer a way to handle the turn order in a way thats less likely to break
I have a question, how can I allow Unreal Engine players to download the host's mod when joining the room like KillingFloor2, KillingFloor1
how to scan the mod pak downloaded from the host to obtain the host's mod gameplay when joining the Session
i havent done anything mod related, but there is some support for mods from what i know, have you taken a look at this?
https://www.unrealengine.com/en-US/blog/new-example-project-and-plugin-for-mod-support-released
What you posted has nothing to do with what I asked.
Are you using Curseforge or something else?
Hi,
I have a problem with replicated UObjects not functioning with RPCs. Is this normal / can I do anything to fix it? This is more or less the setup:
UObjects are created inside a UActorComponent owned by GameState.
UObjects are replicated with the "new" and "IMPROVED" replication system which uses AddReplicatedSubObject() and bReplicateUsingRegisteredSubObjectList = true;.
Replicated variables work fine for these UObjects, but I just noted that RPCs don't actually do anything - they just result in a local function call!
Can this be remedied somehow? Otherwise I will have to set up everything I have already written quite differently...
π π π’
Which RPC?
this was a server RPC marked as UFUNCTION(Server, Reliable) - I can see in my log that it's executed on the calling client. So I suspect it's all RPCs that don't work, which would explain other issues I've had but couldn't understand
You can't make a ServerRPC on something owned by the GameState. Not even a component.
but netmulticast and client RPCs are okay?
And in that case - how do I then make the call get to the server? Do I need to explicitly place the server rpc ON the GameState? Or do I need to spawn an actor just for handling rpc?
Not client either. Multicasts should work. It's a simple ownership issue. A client cannot own the GameState who is the actor responsible for it's component and it's component's subobject's RPCs. So a client cannot receive ClientRPCs or send ServerRPCs, same as they cannot do through the GameState itself.
Thank you for that clarification!
So I REALLY do need to be able to send server RPCs from within these UObjects - would the normal solution be to just route it through the PlayerController? That would not, from an architecture standpoint, be what I want to at all - but I could accept if that's the only solution.
What exactly are these objects for? What is their context for needing a server rpc from a player?
It's a replication system of managers and submanagers for handling game flow, such as objectives, player deaths, enemy spawning, and much more. And some of them must be replicated to clients, so I cannot place them on the GameMode.
In this particular case, a client is using PCG to create the seeded level locally, and then inform the server when it has finished creating it.
I just need a way to send an RPC to the server.
Then yeah. Likely an RPC somewhere more generic that the player owns. Depending on how much this intends to scale with more functionality you could even drop this into some component on their Controller or PlayerState
I will think about it. Thank you so much for the help, highly appreciated! π
That's what we're here for. π
It's not, and as others already said you shouldn't choose one over the other for performance. If you do that you are doing it wrong.
I also don't get why you even still come up with such ideas.
OnRep is also not only for open matches. If you are thinking about optimization then you should be reducing the Relevancy Range of Actors. And if someone comes back into that range, the OnRep will still fire. OnRep is NOT only for newly connecting players.
Quick question, is there a way to store variables on the server that the client can then copy and discard without any saving it locally? I'd use default replication but my understand is it leaves a copy of the variable on the client, which is unecessary in this case as it's only used once.
What are you actually trying to do?
Who discards this data, the server or client?
The client
You probably just want an RPC
What exactly are you trying to do here?
What game mechanic
I have an actor that stores a bunch of walls, many of these walls are destroyed to form paths, so I've made it so that clients are given an array of integers (IDs) that tell them which walls to destroy. This data is meaningless once they're destroyed though, so I'm trying to make sure unhelpful data isn't being kept on the client.
What if a client joins after a wall has been destroyed?
But sure, just send a reliable multicast RPC with the wall ID
how many walls total?
Currently, the way it works is that the client asks for the array upon spawning, and the server provides it, so the server has to keep a hold of the array, at least for a while while clients are spawning in. Each client has a copy of the actor with walls, so each client is responsible for destroying walls themselves, therefore any other client destroying a wall doesn't affect the others. Also the number varies but it's about 1000 walls (so 1000 integers)
Keeping stale data is fine
You need to do that for join in progress bugs almost every time
Just be careful when you use it
Also this sounds like a good case to quantify the data a bit
1000 int32s will probably take a few separate packets to fully arrive
But if they only destroy a subset that's small enough
If they destroy an entire area maybe send the id that represents a group of walls as a whole
The problem with this is that the walls in question are part of a randomized maze. I would make the clients just use the same seed the server uses and generate the maze themselves, but I'm trying to keep it open to potential host modding (meaning the host can use some kind of generation mod while the clients can remain vanilla). Perhaps it's best to just have the clients generate the maze themselves, but I figured a quick 4kb transfer wouldn't be too bad, especially since it's only done once at the beginning of the game.
@lean oakYou could pack all of this into 1000 bits too btw if it got that extreme
It's really not that much data to replicate, and repnotify is the perfect usage for this
But arrays are a great idea here
if optimization is the concern, use push model π
multicasts are just never the right move
Iris still checks the whole actor when you mark a single property dirty 
working through this still, have the communication working properly now, basically
- go from character server rpc to actor
- client gets back current available data about actor via widget
- client then can click button(s), only have a few rn, but first one i did was "host"
- this then requests in a character server rpc a request to start / host a game but i actually just forward this to the gamestate where i do the actual logic, as this is where the interactable actor info is also stored from doing so on begin play (w/switch auth) sending it 'self' to the game state, and game state stores each game interactable actor in a single world game refs array. i'll probably change storing each game actor in the game state, but exactly sure if i did this for a reason, there would only be 7 max at any time, but that might not be ideal regardless.
- once game state confirms you can in fact start a game based on some basic checks rn, then (it should start a joinable "lobby")
- then, i do now have the client receiving confirmation or failure of the creation, and it adjusts the variables which will then change the clinets widget to show they can see their entry and it's joinable
what would be the best thing to store from players that join? (keep in mind, this is all not a real lobby / session, let us assume they are in a persistent world, where they are already all connected properly)
their net/epic id?
their player controller?
their player state?
something else?
i haven't done it yet, but i will probably want to create something in which i can store the created game's data all in one, and it would need to be client adjustable at runtime, and then validated on the server, but i am using data assets for the original game data/rules but im not sure how i'd use a data asset to do this as i feel if i make a "game 1 settings" data asset, then all the game 1 settings instances would be also changed so there would only be able to be 1 game 1 asset being changed , if i understand these correclty, that's my question after the rant on where im at, but i said i'd give an update , so wanted to share a bit and maybe get some ideas
also, i actually love using structs and data tables, and even using a struct in a data asset would be fine, but structs hae given me issues in bps and i would like to avoid issues, or smoene give me the haps on this structure cretaion in cpp method, i need the tutorial, on youtube. indies to a trillion
what would be the best thing to store from players that join?
In theory, always their NetId if you have an active OnlineSubsystem. Cause that can uniquely identify them across multiple session, when they reconnect, etc.
also, i actually love using structs and data tables, and even using a struct in a data asset would be fine, but structs hae given me issues in bps and i would like to avoid issues, or smoene give me the haps on this structure cretaion in cpp method, i need the tutorial, on youtube. indies to a trillion
You want a YouTube tutorial on how to create a C++ Struct?
that would be so omega , i certainly would be very appreciative of such
nice, yea im using EOS, so in theory should always have epic id and this is what i was using so i'll stick to that
Is there a reason it needs to be a YouTube tutorial over a write up?
lmao, oh not at all, i just personally love an actually good youtube tutorial, they help a lot
Does your project already have C++?
it does, very minimal movement is cpp but tbh, it's kinda broken too lol
it's source build too
Source Build is not relevant, as that's just the Engine Part of it.
ok cool but yea it is a cpp project, just very minimal used
i think the cpp indimidation factor is simply the starting point, and ironically, i don't want to break anything lol
So you have a basic idea of how to build your project with Visual Studio?
Yeah that's fine. It's free by now for personal use I guess. Before I would have questioned why someone would pay for it if not actually doing things in C++ :P
oh, i paid for it before it was free lmao , i had no interest of using xcode beyond what i had to do, but yea i was just a little afraid at the time so needed something to help visualize what what happening
Well, there isn't really much to creating Structs in C++, so it would probably be easier to know what part of it you are struggling with.
and rider did help, turns out i was just super noob*
literally just never tried
i've never made anything custom in cpp
so i wouldn't know how/where to start even
lol
type letters in and press f5
but by making a struct i think alot would be learned by default
your custom struct will need to use your module API macro if its used in other modules but besides that they are pretty simple
Right. Well, if you know how to open your project in your Rider, and how to compile Development Editor for it after changes, then there isn't too much about it.
Depending on your projects Source folder layout, you'd create a .h file and then you can add your structs and enums (+-).
also ustructs can't have ufunctions or the like, they are data only for blueprints in effect
but their properties are similar to uclass properties
you can of course make C++ functions like usual but not ufunctions
I wouldn't even worry about that stuff yet.
If the idea is to have Structs in C++ instead of BPs, then all of that doesn't matter much.
All of the types you can create in Blueprints will expose from C++ to BPs just fine. And BP structs can't have functions either, so there is no need to worry about that. That's only relevant if you actively need that.
And then you'd probably just throw them into a BlueprintFunctionLibrary. But again, not really important. Just leads to too much info at once.
I have a server RPC placed on my PlayerController, like this:
class AMyPlayerController {
// ...
UFUNCTION(Server, Reliable)
void Server_FuckingTest(AMyPlayerController* PC);
};
When I call this function on a client it gets executed on the same client - how is that even possible?
(pardon my language, I got a little frustrated)
Please show all the code involved.
prove you call it from the client
way too many people assume things with stuff like this
add {,,UnrealEditor-Engine.dll}::GPlayInEditorContextString to the watch window as well
void UDS_GameManager::HandleLevelCreatedLocally()
{
DS::LogInfo(this, "");
bool LateJoininingClient = !GetIsServer() && GetIsMissionStarted();
for (TPlayerControllerIterator<AMyPlayerController>::LocalOnly It(GetWorld()); It; ++It)
{
It->UpdateGameReadyData(EDS_GameReadyDataUpdate::LevelGenerated);
// If client is late-joining, GameMode will have disabled its movement due to falling through
// level geometry not yet generated on client. Now we tell the server that we are ready to move!
if (LateJoininingClient)
{
DS::LogInfo(this, "Calling Server RPC for late-joining client '{}'", *It);
//It->GetMissionManagerContext()->Server_EnableLateJoiningPlayerMovement(*It);
//It->Server_FuckingTest(*It);
It->WrappedFuckingTest(*It);
}
}
}
GameManager is owned by GameState.
what net mode is this
I'm 100% sure that it's called on the client - verified by my logs.
- What is
UDS_GameManager? - Where is
HandleLevelCreatedLocallycalled from? - Why are you iterating over all PlayerControllers, do you have more than one locally?
- What is
GetIsMissionStarted()? - What is
GetIsServer()?
ok nice, yea i wasn't sure what mega meant by the functions thing but that does sound nice lol but yea ok cool makes. essentially want to ensure that my structs can be safely created and adjusted without ever breaking the way the bp ones do sometimes, which has / can casue serious issues depending on which could break.
but yea i like the idea of putting all of those custom structs / enums into a bp function library isn't a bad call tho, i think i saw a tutorial by someone i like on that, so i could combine that with just starting by making a simple struct
I don't see your logs man
Remember: re are trying to see what happens here
The Structs and Enums don't go into the Function Library. Only the functions to modify the (or rather just the ones for the Structs).
ahh, ok well one step at a time then lol
The main reason is that, unlike Objects, Components and Actors, Structs can't expose functiosn to Blueprints.
a few semi related Qs
when making / adjusting anything in cpp, is there a way to safely do this while the editor is opened? does it matter?
for exmaple, i have editor opened, i want a custom strcut. would i need to close the editor before making a new struct?
i guess folder / where i'd make these as well would be something that would be good to know as well
GameManager is a UObject (replicated SubObject) created and owned by an ActorComponent owned by GameState.
HandleLevelCreateLocally is broadcasted locally by the client on the client from an event system (regular MulticastDelegate)
I'm iterating over PlayerControllers because we are going to look at local co-op later, so I'm trying to prepare for that.
GetMissionStarted() just returns true becuase the Match is already started, so I know the client is late joining.
GetIsServer() returns false, as it returns a non-replicated boolean which defaults to false and is only set to true on server.
- yes, if you ONLY change code in the cpp and not the "shape" of it in the header. Complex question that is explained in cpp pins
- new struct = restart every time
what is WrappedFuckingTest
you have Server_FuckingTest and this
This log is generated on the client (it's running in its own window with its own log, so I know it's all client-side):
[2025.05.18-11.10.37:849][296] Display: Client: [UDS_GameManager::HandleLevelCreatedLocally]
[2025.05.18-11.10.37:850][296] Display: Client: [UDS_GameManager::HandleLevelCreatedLocally] Calling Server RPC for late-joining client 'DS_BP_PlayerController_C_0'
[2025.05.18-11.10.37:850][296] Display: Client: [UDS_MissionManagerContext::Server_EnableLateJoiningPlayerMovement_Implementation] Broadcasting to enable input for late-joining client 'DS_BP_PlayerController_C_0'
breakpoint Server_EnableLateJoiningPlayerMovement_Implementation and show the watch I posted earlier
Just a desperate attempt because directly calling the server RPC didn't work:
void AMyPlayerController::WrappedFuckingTest(ADS_GenesisPlayerController* PC)
{
Server_FuckingTest(PC);
}
void AMyPlayerController::Server_FuckingTest_Implementation(ADS_GenesisPlayerController* PC)
{
MissionManagerContext->Server_EnableLateJoiningPlayerMovement(PC);
}
Neither of them execute on server
is this very early in the connection flow
C++ Structs/Enums
shouldn't be.. World is loaded, plenty of rep-notifies have already taken place, and it's a good while after client PostLogin
I have to go to bed but this seems like it should just work... I would see if other server rpcs work in the same context
The only thing I can think of is that there's something wrong with netmode on the calling site, i.e. inside the GameManager - because it's owned by GameState that makes server RPCs impossible. This is why I tried to move the RPC to PlayerController, thinking that would fix it
thank you for trying nonetheless!
the call place should not matter unless it is in like another thread
when making / adjusting anything in cpp, is there a way to safely do this while the editor is opened? does it matter?
Honestly, just don't bother with it. Close the Editor, do you change, build the project, start the Editor.
i guess folder / where i'd make these as well would be something that would be good to know as well
Depends on your Source folder. I can't answer that without seeing the existing stuff.
In theory you'd have:
- Source
- Public
- Systems
- SomeSpecificSystem
- SomeSpecificSystemTypes.h
- Private
GetIsServer() returns false, as it returns a non-replicated boolean which defaults to false and is only set to true on server.
That's redundant. Use the NetRoles for stuff like this.
there's some very good advice pinned inside the #cpp channel. In short:
- disable reinstancing from Editor Preferences
- close editor when writing code in header files OR in the constructor inside the cpp
- simply adding stuff inside functions in the cpp file should be safe to do with editor opened - just use Live Coding to compile
^ True, but as a beginner, just close the Editor. You will never be able to safely spot if Live Coding fucked something up.
You would need to do what Megafunk asked for, which is to use the watch they posted and to breakpoint the ServerRPC.
And then to share what the watch is showing.
very solid advice and makes perfect sense. keep if safe, and anything i'd do would be very off beat for me so i'd know to just close and attempt whatever
Is that really necessary? I'm running 2 processes with a batch script like this:
@echo off
"C:\Program Files\Epic Games\UE_5.5\Engine\Binaries\Win64\UnrealEditor.exe" "%cd%\MyGame.uproject" -game -ResX=960 -ResY=540 -log -WINDOWED
So client has its own viewport AND its own console window, as does the server.
I don't know that the suggested thing to add to watch window.. but I don't assume - I'm really quite sure it's running on the client, because the logs that I shared earlier only appear in the client's console window..
I could try to debug and check for some netmode settings or something - problem is I don't really know what I should look for π
But I really appreciate you guys trying to help me!
@keen slate A ServerRPC only runs on the Client in very specific scenarios.
It will only ever make it to the Server on a replicated, Client-owned Actor. Any other case will see it dropped.
so then the problem is I'm creating the server RPC function on an ActorComponent attached to the PlayerController, or rather - default subobject'ed ?
You are posting examples and test-cases where you are executing it on the PlayerController, or not?
ahh yeah, I guess I was.. then that's not the issue. First I ran a server RPC on a component owned by PlayerController - but that didn't work so I moved the RPC to the PlayerController instead
In theory there are only two scenario in which a ServerRPC called on the PlayerController would lead to it still executing on the local PlayerController.
- The game is not actually a connected Client, but just a Standalone game.
- The PlayerController is a locally spawned dummy.
And yet, neither is true.. this is very weird. I will keep trying things, and post the solution here if I find it.
Hello ! I'm working on a grab system in UE5 using C++. It works in multiplayer where the server sees the grabbed object moving smoothly, but on the client it's jittery.
I do the line trace on the client (it's a P2P game so it's okay), then call the server to grab the object with a physics handle and update its location and rotation on the server too.
I think I also need to update it on the client, but I'm not sure how. If anyone knows something that would be great !
thats so weird.. i can't find a single reference in UE source code that uses "WithNetSharedSerialization".. only code that sets it to true
Check for HasNetSharedSerialization
As well as ERepLayoutCmdFlags::IsSharedSerialization
ohhhh yea, i see it now
the FCapabilities struct is created with the { } and HasNetSharedSerialization is set through there which is why i couldnt find it being explicity set
@thin stratus if you are still here, and interested, I just did a little of testing on the server RPC issues... this is the testing code:
class MyPlayerController {
void MyPlayerController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (DoCallForNextFrame)
{
DS::LogInfo(this, "Calling this frame!");
Server_MyTestRPC(this);
DoCallForNextFrame = false;
}
}
void MyPlayerController::CallForNextFrame()
{
DoCallForNextFrame = true;
}
UFUNCTION(Server, Reliable)
Server_MyTestRPC();
private:
bool DoCallForNextFrame = false;
};
And instead of directly calling the server RPC I call CallForNextFrame() on the PlayerController. And now, the RPC actually runs on the server!
So I really think there's a problem inside the engine with the calling site overruling how the RPC works.
The calling site is a UObject which is owned and created by GameState, and replicated with AddReplicatedSubObject(GameManager);.
So it seems, that calling any RPCs inside any class member function of an object like this follows the net roles of this object, which is whatever GameState allows it to have, which as far as I understand is nothing.
If the call is inside the PlayerController it shouldn't matter what calls that
The next frame stuff feels more like it's generally calling too early
Also there is a timer manager function for next frame
I know the client has a local dummy for the PlayerController when freshly connecting
If you manage to call the RPC on that you'd get your current problem
The frame delay feels pretty much like the PC not being "swapped out" yet
It seems you are right. When I delay the server RPC with 1 second it does run on the server.. now I feel kinda stupid. At least it works! You guys rock, thank you for all the help!
If it's a "good while" after Client Post Login, then that wouldn't make sense though.
Exactly does this call in the flow?
Is this triggered from an OnRep when the player connects?
Cause they can call really freaking early.
it's triggered by an on-rep yes. But that on-rep runs a quite heavy PCG graph. But maybe engine doesn't Tick() while that PCG graph is generating, so a Tick() or a few is needed for the PC to be "swapped out" as you say. In real-world time I see the client PostLogin on the GameMode only a little earlier (maybe 100-200ms idk). But I have tried so many different things now, so I probably remember it wrong. I think it's more likely that not enough time has passed between PostLogin and serverRPC
PostLogin is server-side anyway, so whatever time passes there isn't even relevant.
You can generally expect OnReps to call very early, often even before BeginPlay.
yes I have noted they happen very early! Almost too early
#if WITH_SERVER_CODE
this is pointless for listen server multiplayer right?
That is UE_SERVER.
Yes it'll be useless for listenservers. WITH_SERVER_CODE is true unless you are specifically cooked for a Client only build. It's used to strip out and server specific code. Since Listenserver runs under the normal Game cook, it'll be true as well there since listenservers need server code.
UE_SERVER will be true only in Server builds. It'll be false under Game builds as well as Client.
whats the difference in this case?
There are three main builds. Game(all code), Server(dedicated servers), and Client(No Server code, cannot host stuff, etc).
UE_SERVER is true only when built as Server.
WITH_SERVER_CODE is true when build as Game or Server.
makes sense, thanks!
Hey Quick Question!
I'm currently working with replication in Unreal Engine and am wondering whether I'm using RPC Functions too much.
For example, I was setting the character's collision to overlap a channel instead of block based on if they were in a Hiding Spot or not, but it wasn't being called on the listen server, rather only on the client. And whenever the client would try to collide with the actor, the client would try to walk straight through, but since the collision change didn't get called on the server it kept flicking the client back. Once I set the function to Multicast, it completely fixed this problem. I do this for most of my functions either call them on the server or multicast.
Should i start using replicated variables more often? I'm not using RPC functions on everything, I know when something is too ridiculous to use an RPC on. It's mostly just little things like changing collision, or setting the position of something.
Hi there! I leave this question here in case someone has the answer!
I have 2 weeks reviewing and learning again multiplayer in Unreal 5, making prototypes. I'm using the Advanced Sessions plugin and today I decided to test a build with another PC to see how everything was working fine.
Well, in the build counted by ip, the server sees the client lag moves but as if it saw it at 5 FPS... The client sees the server perfectly! I have played everything about replication, read documentation and also debugged placing a player prefab of Unreal 5 (which also sees lag) and I have not been able to get why this happens. If anyone has knowledge on multiplayer in U5 it would be a great help!
That's great, and I come up with this idea because we have specifiers NetMulticast and a Client which is enough for a multiplayer game if later joins are not allowed, i only see the reason to use OnRep if the late joins are allowed to replicated the old state to them automatically.
but at the same time we can catch the old state manually and track if a new player joins just apply the cached game state to their current state without using the onrep
Does anyone know if the CMC or Mover component tries to keep clients relatively in sync time wise and performs any type of time/clock syncing? Otherwise you end up with larger corrections of one client is running far ahead if another.
From what I investigated on Mover, it doesn't seem to be the case.
in which scenario? clients as sim proxies or clients sending moves?
afaik they are independant in the cmcs case
it's not as much as one ahead of the other as the overall server time
each server + playing client has a shared timestamp they pass back and forth you can follow in the saved move flow
Executing the moves at the same real world time. Any differences in when things are executed will cause increased side effects of latency which is very bad for higher paced games.
Mover allows for a fixed tick rate and in principle could support syncing up the simulation tick
yeah, the regular old cmc doesn't have a shared frame for rollback purposes
afaik
they are independantly moved
as for mover I'm not sure if it throttles clients to be ahead or behind
it should not be too hard to make a custom delta time provider to throttle it manually but i'm not sure what values or math I would use
and even if it would need to be a delta time provider as much as inside of the fixed update
I would investigate where fixed ticks are triggered and why it decides to trigger them to see if you can force them to hold back a bit or catch up to the shared time
Yeah I was thinking that it would be something I'd have to add support for. I was just curious if I was missing where it was handled but this confirms what I was thinking..thanks!
Can anyone tell me why Onclick event for a static mesh doesn't work in my multiplayer session? Stand alone works fine, loading the level directly with client server works fine. but if i have both player's on stand alone and they connect to a shared session, click events no longer work. does that make sense?
jesus what do I have to do to get click events in multiplayer?
Maybe there's a widget in the way that is being clicked on that is consuming the input?
Can anybody point me into the right direction of replicating data assets? For example, how would you replicate the choice for your character in a fighting game lobby? To be clear, I have my characters data stored into PrimaryDataAssets. What should I send to the server in order for it to translate into a character data? The PrimaryAssetId? Can I get that if the Data asset is not loaded?
But that's wrong. OnRep is needed even if you don't have late joiners. You have the concept of relevancy for already connected players.
Yes the Id, and yes, that's the main thing you work for without loading it
The whole thing is constructed out of a Type and a unique Id within the type. E.g. "Weapon:GreatSword".
Either you send the whole thing or just the thing in front if you know it's a Weapon you are sending.
Most peeps use a GameplayTag for the Id part.
you should be able to just send the pointer over the network to serialize as an asset reference?
unreal does this for you... there is no need to try to get complicated here unless you are trying to avoid loading it directly
but your data assets should not be referencing 10gb of art directly anyways
Ok so rather than keeping the data asset unloaded, just keep the things within unloaded, and then just send the pointer over the network
exactly
Nice, so I can just register the type in the asset manager and then just send the Id over the network and it should just work
Yeah cause the asset exists on both sides anyway
There is also no need to load the asset to send the pointer and cause a sync load on the client/server. Just sending the id and then async loading it should be smoother
That makes sense, thank you!
It's weird that you have to type out the data type name in the asset registry, but otherwise seems straightforward enough
Thanks for sharing the knowledge )
sending the primary asset id?
although there is a cvar that allows you to asynchronously load any asset hard refs
during network reading I think yes
I'm honestly not sure if it's really going to help much to async load during network read
I was under the assumption io activity is not happening there generally
net.AllowAsyncLoading=1 is the one
yeah, I'm not sure how it works exactly in terms of when it applies the result
if its something not needed immediately it's probably fine it it adds an extra frame to resolve the path
net.DelayUnmappedRPCs=1 will the delay the calling of RPCs until dependencies are loaded
Hey, couldnβt find much about how to ban players using advanced steam sessions.Thereβs a ban player function but it looks like I need to use it with an array and probably save it somewhere not totally sure though. Do you know how itβs usually done?
thank you
question for the people doing projectile prediction with limb specific damage: when verifying a client hit, do you roll back animation as well as location of the person who got hit?
Hi all, I got a strange issue about replication.
I spawned an actor and attach it to the character, in spawned actor Ticks() I controlled the character's movement component, it works well on server, but on client the camera will be jitter, the character and spawned actor will move then be drag back (moved forward a little more than expected and be drag back to correct location).
I'm sure it's not because authority, in Ticks() method I have check if spawned actor has authority, so it runs on server.
The spawned actor is some kind of transformation, when activate ability, character will turn to another pattern.
Any idea?
the client runs it's own movement simulation locally.. if the server is moving the character and the client doesn't know about it, the client wont move until a desync is detected and it does corrections, which would be that jitter
Do you know how to fix it?
so its some sort of ability that moves the character in some way? i'd look into using the "Gameplay Ability System" i'm pretty that can handle prediction and works with the CMC
When I package the game, the create advanced session gives the output "On Success" and opens the lobby level. When my friend searches for the game, the find session also gives the output "On Success", but the result length is 0 and it does not see the server. Steam overlay is activated.
I believe most games that do this nowadays do roll back everything on server yeah
In the past it was more lenient with more primitive validations (client said it hit something, server does approximate check) but now I think games like CSGO literally roll back and redo the shot at that timestamp taking into account latency and what that client actually saw at that time
yeah i guess you kinda have too.. especially if you have crouching and stuff.. i wonder if i can get away with just keeping a history of transforms for player mesh's collision bodies and not have to mess with animation
IMO for most cases just verifying the clients hit with a bounding box is sufficient
prevents blatant abuse while being simple
maybe i am overthinking it lol
are you making a highly competitive 5v5 shooter where any cheating at all completely invalidates your game?
or is relying on client for where they shoot fine and just validate that the shot is feasible?
there's also other concerns like synchronizing RNG on client and server without it being exploitable (difficult afaik)
not overly competetive.. my prediction system i have now works with a capsule but i was trying to get it to verify specific limbs.. but now that i think about it theres no need. imo if someone was gonna cheat they'd just use auto aim and theres not a whole lot that can be done about that outside the usual
uncounterable outside of anticheat basicslly
Just means people can aimbot freely and hit all headshots without any way of the server knowing if that actually happened since the bounding box will likely be lenient enough to allow it
no matter what you do people can aimbot freely
you can waste your time getting into the countering cheater arms race but they're always going to be ahead
just don't make your game blatantly exploitable and it'll fix 99.9% of cases
the only reason to do rollback is to verify that well meaning players that are lagging don't accidentally hit a shot that's WAY off of what the server has
it does nothing against aimbot over other methods
yeah with my system the worst someone could exploit it (outside of aimbot) is make legit non headshots shots be headshots which isnt TOO bad since you have to land the shot legit still
I though the point of rollback was so that the server simulates the game as fairly as possible and trusts the client as little as possible? As in client just says "I fired" and server works out what happened at that time on their screen
To be honest fighting cheaters is very hard, it just takes one exploit to ruin the game and trust of players
even big games like call of duty are now rampant with cheaters
yes, to aid in stopping blatant cheating and compensate for lag perfectly
it doesn't stop aimbot any more than a bounding box does
Fair enough yeah maybe should have phrased it differently like sending false packets saying you hit headshots and such
yeah