#multiplayer
1 messages ยท Page 24 of 1
Well with the new changes, cheaters can end the games a lot faster hehe
Of all games, DBD is one game where it should be quite easy to not have so much client auth stuff.
They had a lot of changes in the past years. The game was Listen Server driven oriignally iirc
And is only recently a DediServer game
Yeah, it was. Dedicated Server only came before I started playing though. So pre-2020-ish at least.
Killers are still in favor for most of the game I think
High Ping Killers are a pita
Cause they hit you when you are long through the window
The hitboxes...omg the hitboxes.
It's so bad that higher skilled players actually purposely check if the killer has a high ping xD
Cause it changes the whole play style
I'm still baffled at how seemingly, the end game collapse isn't tied to the GameMode directly. Like, how else can the clients prevent it from happening
What is the end game collapse?
How on earth should a client ever be allowed to change that.
I think the issue is that cheaters managed to just call the event for it directly
Skipping the timer
But how that exactly works, no idea
People can do quite a lot in DbD. Heal themselves. Take themselves off of Hooks. Stand up. Teleport, etc.
Rip.
With so many people you would expect them to be able to afford it to fix stuff like this. At least things like teleporting, healing etc.
But then again, who am I to say that lol.
Money does not buy good programming. Money just buys more people to stare at the problem scratching their head.
I feel the same dude. I'm all about co-op games over pvp games.
pvp is fine, competitive is not
Money should absolutely be able to effort a programmer who can fix stuff like healing, teleporting hacks though. I get not everything is an easy fix but that just sounds really terrible.
Basically if I can fight with some friends against each other, all is fine. If it's against randoms for some made up currency and rank, then it's not
Don't forget the time when they could also use more than 4 perks ๐คฃ
idk if that hack is still a thing though
I remember the time where I had to change my location to Turkey to even find games
If this is the case in how it works, this would mean they do no server-side checks to see the actual state of the game before processing the request ๐คฃ
Honestly managing / checking state on all calls from a client is not a good time.
There are probably a million combinations in most games of when things are allowed and not ๐
In DBD's case, it'd be quite simple for this case. Literally just check if the number of gens completed == 5 ๐คฃ
Sure. But just in general it's not a fun time ๐
What I always wonder is how that even reaches the Server
But that might be me thinking the RPCs are the only way
Is it an Unreal game?
If you don't want to manage whether a client can do something then suck it up and eat the lag of not allowing client prediction and only ever send basic requests to the server.
Maybe some replicated timer for the UI
And that's about it
So I do wonder how a Client can even get the Server to execute an Event that theoretically doesn't exist on the Client, and even if it does it wouldn't affect the server state
It must literally run on the Server
Maybe something that interacts with the timer on the server can be triggered from the client? Never played the game so idk.
It's an incredibly simple game, gameplay loop wise.
Max of 5 people in a match. So it's not like they're hurtin' for performance.
No real AI in the game either (other than one killer's zombies, which gets like 2 of 'em)
The only client-auth thing I can think of, that would make sense imo, is the QTE's in the game. And that's just for simplicity sake. @thin stratus
Probably a PITA to make that server-auth
I have two actors in the same area that are not relevant to each other using rep graph but they can still collide, certainly this should not be the case right?
I mean, relevancy should not stop the actor from existing on the server
Which is the one that handles the collision
ah yea that makes sense
Relevancy is more about clients and servers, not the authoritative server itself.
hi there,
I am doing RepNotify, but it giving the error.
I am attaching the picture of code that causing error and also the error.
thanks in advance.
- Close the errors list and use the output log.
- Don't screenshot errors, copy + paste.
- That's a missing function you need to provide an implementation of in your class. SEe that link ^
thanks for the information this helps me a lot to resolve the issue.
does post login work for dedicated servers? My code isnt working on my dedicated server for my post login
How to properly setup a timer in Multiplayer game? I want to show the remaning timer as widget for the clients.
Alright I successfully made it and can say that it does sends you an invite directly to Steam hence you don't need to handle it ingame.
Yes
The remaining timer is not syncing with the clients when I'm trying to use it in the widgets. I know the ticks in seconds different for each client but how should i sync them?
I checked AGameStateBase::GetServerWorldTimeSeconds function in the game state class but i don't know how to integrate it with using TimerHandlers.
For anyone having trouble with building the Gamelift server SDK using VS22:
- use GrepWin to replace
vc141withvc143and2017with2022in all the files; - if it complains about a missing OpenSSL header, manually copy the
opensslfolder over from your UE5'sThirdParty\OpenSSL\1.1.1k\include\Win64\VS2015\folder; - if it complains about the SIO Client include dir and library file not being set, put the paths in the CMakeLists.txt directly (taking care to replace
\with/).
Hi All, I am wondering if it is possible to write a UE5 multiplayer server using Golang to serve levels and chunks to the players? If so, does anyone know of any examples that might be available some were. Thanks in advance.
I assume you can do whatever you want, but I doubt there is an example on this.
Most users who would share this info are using UE servers
@thin stratus Yea, you are probably right and I am investigating the UE servers as well. Just wanted to see what might be out there and available. Thanks
I'm not sure on the specific downsides aside from increasing the amount of data the server/listen-server will need to consume.
I also just posted a fix for RootMotion on the reddit post if that's relevant for your game
thank you! I appreciate that.
vori got your back: https://vorixo.github.io/devtricks/non-destructive-synced-net-clock/
From this channel pins
Hello, I have a another question, I have varaible inside my pawn and I want it to change when I press a button and that the server and all the clients know about the change , as I understand I can not change the variable from the client, what is the best way to do it then? .
I am spawning project title
It's only working on cliet or server.
Not working for both at same time.
On button press you call a server RPC that then changes the replicated variable
What is RPC ?
Remote Procedure Call
Ahh do you know anything about my problem?.
A function that can be executed in a remote callspace
Not that you provided any sufficient info or that I can understand you
There is a tool (a button really) called print screen
You have a client RPC that calls a server RPC. That smells bad
If you're already on server then do your thing
Project title is spawning but only on server or client at once
Yeah and i made 2 custom events. Run on owing client and server
Yeah I can already see that and it hurts me
Is it bad ?
Yeah I already said so
Spawn it server-side and make sure it's replicated
That's pretty much the workflow of replicating dynamic actors at a very basic level
I've seen somewhere that if you put them in struct and replicate the struct then they do
Yeah pretty sure they don't
GAS doc says they do which made me lose my mind a while ago lol
How do I know i am using tmap ?
Yeah literally nothing related if that's what's worrying you
๐
Because rpc to server is not working
Have you read the networking compendium?
Yeah that's why i am asking here
I test only client or server works at a time
Both are not working together. I don't understand this.
At this point what I intuited is that he wants to spawn this projectile to all connections, i.e. replicate it
But there seems to be a language barrier here
I did
do you say it should happen by default or do I have to do an rpc?
is this not correct ?
In both client
Replicated actor
I want all clients to see this projectile
You have to do an RPC, a server one
Look at the guy beneath you. Like that.
Server RPC that changes the replicated property in question
Then on SVR_spawn call the SpawnActor function
No need for the client RPC at all
And this ^
While the server owner gets on the vehicle, the customer cannot get on the vehicle. How can I solve it?
Yes because u are using GetPlayerController(0)
That's totally not correct for multipalyer
Input is local only. input won't happen serverside for your pawn
You'll want to do
Input -> Run on Server Event -> Do the Thing
In your case
Input -> ServerPossessCar -> Server handles the possession call
thank you
Self if this is in the PlayerController, Self.Controller if it's in a pawn
I'm pretty sure I have at least two times told you to read Cedric's compendium and I'm fairly sure you haven't looked at it
Found in this channel pins
is using a switch has autortiry node in the game mode blue print bad practice
I am having an issue where things spawn correct if I host a game but not if its a dedicated server
Right because it's always authority
Of course we can't guess your issue
Show the code
gamemode always has authority so that switch is doing nothing
I made a video

I will make sure to like and subscribe
Pretty sure all playercontrollers are already in an array automagically for you
for some reason its not spawning it on the platform
on a dedicated server
what would cause it?
๐ 
thats what everyone says to me...
If you don't know, all the function paramters exist as variables in scope
you can just use get FUNCTIONPARAMTER and it's a little variable node
no need to spaghet all over
I wouldn't know how to fix it if it was my code
So 100% not if it was somebody else's
Your first assignment is to refactor that function to have zero pins connected to the input node
use the parameter variables and make it nice and neat
but what could cause it to not work on the dedicated server?
We can't tell wtf is going on, maybe you'll find a pin you didnt connect when you clean this up
Pretty sure there's that node
Make it look nice and clean like this
Adriel I'm giving you a ๐ช
Also IDK if you're aware or not but there's functions in GameMode you can override like ChoosePawnClass and ChooseStartLocation etc
idk if i got the names right but there's a bunch
you're basically recreating them
It's working now. But Static mesh is not showing
Adriel going off is the highlight of my day so far
Hi, what would be the proper approach for sending player inputs to the server? For example, when the player presses a button, the shoot function gets called. In the shoot function, it checks if theres any actor in the way, and if there is, damage is done to that actor. What do I need to add to the shoot function so the actual shoot logic runs server side and the results get sent back to the player?
- RPC to server (server RPC) - That's pretty much the only way to pass data from client to server
- Now from server to client you have either:
a) client RPC
b) property replication
To know which to use read this:
From this channel pins which I highly suggest
ok thank you, I'll check it out
If I simulate Ping in the Editor, with Outgoing MinMax = 5000 (totally overdoing it on purpose), my Net Clock shows a RTT of roughly 5000ms and a Latency of 2500ms.
That's fair. Now if I send an RPC to the Server to Start a Cooldown, and I also start the Cooldown locally at the same time, when the Cooldown of the Server comes to the Client (let's assume I replicate it somehow), shouldn't it be RTT off?
So if I reduce the Cooldown on the Server by RTT, shouldn't it, when replicating to the Client, match the Client's predicted cooldown more or less exactly? (Given the Ping is totally fixed and not going higher or lower)
How can i detect in an OnRep if the replication comes from the actor being relevant/created (for late joiner) ? I actually want to handle my onrep logic only in those case
I'm thinking about "COND_InitialOnly" but i don't know if the late joiner gets the initial bunch when creating the actor instance on their own
yeah i tried that a few hours ago but it does not seems to work ๐
Oh i know why lol
That doesn't look like an initial only property?
forgot to mark the property dirty
I only want this to be replicated to simulated
Properties should always be flagged as dirty on their first channel open
mmh
also for this
do you know if late joiner simulated proxies gets the initial bunch ?
even if the owner has the actor created since a few mins ?
that's what i want anyway but only for simulated
so COND_InitialOnly and checking if OwnerRole is simulated in OnRep ?
Could do but that has to assume that OwnerRole has been applied by the time that OnRep is called, which hopefully it would be
i'm also calling OnRep_IsEquipped in OnRep_Owner
cause i have some race condition where owner has not yet replicated and bIsEquipped has
yeah figures
do you know any way to disable the RepGraph ?
Does commenting this line do it ?
Alright got the confirmation that Repgraph is breaking my weapons ๐
Hm, when calculating RTT via ServerRPC -> ClientRPC, does it make sense to send the latest RTT with the ServerRPC to also have the number on the Server?
Cause I can't really get the number, or does UE have the RTT or RTT/2 somewhere accessible for me?
RTT?
Round Trip Time
And you need the RTT for a connected client, on the server?
I'm having this weird Issue. When jumping the camera seems to sort of snap to the jump location. It works fine however inside the editor and when running the build locally. When I add it to a dedicated server however I get this issue. Presumably because of ping. But other items such as eating are played without delay.
Points to note: Standard unreal jumping mechanic and animation
Replicate movement is turned on.
If anyone can point me in the right direction it would be really helpful.
If you have a straightforward back and forth over the server I'd just calculate the difference in world/instance time on the server
I would imagine you might be able to find the client's ping somewhere if that's of any use
Does this happen in Standalone/Listen-Server?
No when played standalone its perfectly fine as well.
Show your code for calling jump?
Let me know if you need more details or a larger resolution image
Nah that's good. Can you try removing the external functionality and just connect the Input Action to Character::Jump
yea can try. Will need to re-build to replicate the issue however.
Re-build?
The issue doesn't show up inside the editor. Only when packaged and deployed on a remote server.
When deployed locally the issue is non existent either.
Which leads me to believe that the issue is latency related. But everything else works quite fine.
Now that is odd
What is moving around like in the deployed client?
Perfectly smooth.
Jumping seems to be the only thing affected.
my jumping I mean camera movement
because, while looking at the person jumping through another character, the jumping seemed perfectly fine.
Since jumping is the only action which causes a jerk reaction my assumption was the sudden movement causes the camera to lag behind and snap into place when it catches up.
however I have no idea on how to test this theory or how to fix it.
I am currently trying your suggestion though. it's building as we speak.
Hi everyone
Iโm having problems with migrating a large level map with many items into my current Lyra project.
What do you think is the best solution?
Or is there any better ways?
Iโm a little bit of a beginner with stuff so any help or advice would go a long way ๐
This has nothing to do with multiplayer. You might want to check #ue5-general
And you already seem to have asked there at the same time so this cross-posting. You might want to keep yourself busy with #rules till you get an answer there
It is something to do with multiplayer because im asking about Lyra sample
Lyra is fully multiplayer compatible lol. You can even setup your own EOS integration if you want.
https://docs.unrealengine.com/5.0/en-US/lyra-sample-game-in-unreal-engine/
Online Multiplayer and cross-play support for Epic Online Services and Console Online Subsystems.
I know that ofc. But their question has nothing to do with multiplayer
And they insist that it does because it has the word Lyra in it
Ah alright.
Vori's net clock doesn't work in standalone mode I just realised. The betrayal D:
Oh wait nevermind it does.
But I wanted him to appear before court ๐
Lol.
Wtf? A SetTimer method doesn't have to be a UFUNCTION?
My life is a lie.
I was looking at his clock and was like "Why is the request internal not a UFUNCTION?" ๐
Things only have to be ufunctions when exposing to bp or using with dynamic delegates.
Yeah it doesn't ๐
Or other random UPROPERTY stuff like the hide condition stuff
I'll be busy removing UFUNCTIONS the next days ๐คฃ
IIRC also the input binding functions don't have to be either, but I could be wrong
Disprove me
That's effort.
I really hate this scenario, I have a timestamp for a countdown. But I don't want to put it in a RPC because people need to get that variable if they decide to join mid way through. But it's so ugly to put it in a DOREPLIFETIME :/
Better be ugly than it breaking 
Still it won't be synced that easy if it was replicated right? It has been ages since I read that vori post
Hm?
What won't be synced?
I'm saying if you go the for the built-in network clock and just depend on a replicated timestamp you won't get accurate results on different clients
Even in editor I couldn't get them to be accurate
Oh no, I'm using Vori's clock and a timestamp that then adjusts based on that.
Ah ok lol
But you don't need your timestamp to be replicated, right?
I mean it's updated by a client RPC
At least that's how I see it
I'm wondering though does he fire RPCs on intervals? Because then that doesn't make sense to me
Yeah he does so every second
Vori's clock fires RPC every so often to get a dynamic average, my timestamp is replicated so that if you join midway through it's still there.
I mean seems like an expensive task ehh
A RPC every 1-5 seconds or whatever really is nothing though.
And for the benefit of not having a dumb network clock totally worth the small amount of bandwidth imo.
Fair enough
I'm aware. But it's the best I can do.
Waiting for Unreal to replicate it's weird timestamp is just as bad lol.
And in the end it's the server that calls possess on the pawn, so eh.. Whatever ๐
There was a PR, but you know how it ended
I'm making a scoreboard and need it to regenerate it when a player joins or leaves but I'm struggling where exactly I should call a delegate to trigger that. At first I had placed it in AddPlayerState of the GS, but it would be called before the player states were replicated to all the clients. Just wondering where I should call that delegate from.
There's an event that happens when a player joins/leaves. Seems like a good candidate
Inside the GameMode
There is OnPostLogin but that shares the same issue with the player states not being replicated yet
AddPlayerState and RemovePlayerState is where I do it from
AddPlayerState and RemovePlayerState are called client-side from the newly replicated (or destroyed) PS actor, so it has to be there.
Okay, I'll have to look into it a bit more, good to know that I was at least on the right track.
{
Super::AddPlayerState(PlayerState);
if (UHT_WorldEventManager* WEM = UHT_WorldEventManager::Get(this))
{
WEM->NotifyPlayerArrayUpdated(this);
}
}
void AHT_GameState::RemovePlayerState(APlayerState* PlayerState)
{
Super::RemovePlayerState(PlayerState);
if (UHT_WorldEventManager* WEM = UHT_WorldEventManager::Get(this))
{
WEM->NotifyPlayerArrayUpdated(this);
}
}
void UHT_WorldEventManager::NotifyPlayerArrayUpdated(AGameStateBase* InGS)
{
check(IsValid(InGS));
checkSlow(InGS->GetWorld() == GetWorld());
ConditionalBroadcastNetworkReady();
OnPlayerArrayUpdate.Broadcast(InGS, InGS->PlayerArray);
}```
That's my code for it anyway.
u don't need to replicate anything
late joiners will sync their clock in postnetinit @twilit radish
their value will become more accurate over-time
๐
Is Playfab of microsoft same as AWS?
No, they are different companies and don't offer the exact same functionality or pricing.
I was referring to the start of my countdown, I do need to replicate that ๐
can someone help me on the following issue? iยดm replicating my avatars on my project on the pawn begin play, using two custom events one for the server (run on server /reliable) and another for the clients (multicast). But when a player joins late, it doesnยดt see the correct avatar from the rest of the players. The rest of the players see the correct avatar on the incoming player
Check the first one: #multiplayer message
Also check this channel pins for other cool stuff
will do! thanks!
Hi! Am I able to become a listen server at any point or only when I'm opening a level (with ?Listen argument)?
dude, this was exctlay what i needed! https://vorixo.github.io/devtricks/stateful-events-multiplayer/ thanks a ton for poiniting me out!
Normally when opening
Just start as listen server
does a switch has autority node inside of a rep notify varible make any sense, is it ok to do this or does the rep notify take care of all that
That doesn't seem to make sense to me. What are you trying to do?
wait
you might still need the switch for your mechanic. Repnotify fires EVERYWHERE (in bp), when the variable updates
if you wanna know if you're on server or not you'll want the switch
It isn't fired, by default, in c++.
So if you're not calling it manually on the server in c++, it makes no sense to use it.
If you're using BP, ignore my words.
They really should have made that consistent, it's the biggest bugbear for c++/BP networking
So If I want to Let people join only at some point(not from the start), I open a level as a listen server and when I want others to join I create a session or what?
If the listen server is running, people can join whenever. Whether it's discoverable is another question.
That's what we do
Game is a listen server on startup
how can I make a chaos vehicle client authoritative? is there any setting similar to CMC's "bServerAcceptClientAuthoritativePosition" ?
I've got a server RPC set up for whenever the player presses the enter key. The issue is when I go to do a line trace to check for an object, the camera's up/down rotation is not checked on server side. How would I replicate this?
this is the line trace from the server's point of view. On client side, it was looking up and down
Setting the camera component to replicate doesn't seem to do anything
And the UsePawnControlRotation option is ticked on the camera
I had an issue before with camera rotation and replication with my aim offsets. Not sure how you're handling the line traces, but you could calculate the camera rotation locally and send that information to a server rpc and set a variable on the server. Don't set the variable as replicated. If you're adding controller yaw and pitch locally for your camera, the server won't know that. But you can use the get control rotation to get camera rotation. That replicates only client to server if I remember
Control rotation won't replicate client to client however so if you need that you'll need to set a variable locally -> server rpc -> multicast -> set variable for clients.
Thank you, using get control rotation worked. But for future reference, by setting a variable on the server, do you just mean passing in a variable in the RPC function like this? UFUNCTION(Server, Reliable, WithValidation) void Variable(int VariableSentToServer);
Or do you mean store the variable on the server somehow? I'm still learning networking so sorry if this question is bad
Hmmm I havent spent time with c++ so I can't honestly say from looking at it. At least with blueprints I mean passing variable to server rpc -> set variable on server rpc. The reason I said don't set to replicate for the variable is because i believe that's more expensive. But I honestly don't know for sure. I'm also starting out with it.
thanks
if a client joins a dedicated server is it locally controlled?
What?
who, the client? yes
The server still, generally, has authority over it, but the client will control its own input.
Hey I tried making a multiplayer game about 1 year ago, and streamed 50 hours, I thought about putting a guide together, has there been any new development in multiplayer (i haven't touched ue5)
i went along the steam network approach
Correct me if can do better with widget creation for all players in multiplayer game:
First that I use GameState has array of Player States which we have a reference for each player in the world. So I take a reference via player state object and from the player controller. And thus creating the widget from the RPC which is "Runs only client(Client Only)" to reflect it is own HUD(which is locally controlled) from player state
Yes that's a good approach.
Nothing in particular. Maybe this new upcoming replication system called Iris has something though
did ue5 change much for mutliplayer, i see the docs have been totally updated
they still look very unintuitive however ~
actually i'm getting ptsd reading the official docs
If you mean the multiplayer related ones then I might be dreaming
Going to ask someone to pinch me, brb
Banter aside, they didn't even update their docs. They even have a popup warning that says that at the footer of the page.
Unless you are talking about EOS stuff then that's something totally different. And they are two channels next
When the server possesses an actor, the actor's movement gets replicated normally for all clients. But when a client possesses the same actor, it doesn't get replicated to other clients or the server. I'm running the possession on a server RPC. GetController()->Possess(Actor); What could I do to get the actor to replicate to everyone. The actor already has replication and replicate movement enabled
maybe you're right, I don't recognize much of it, but my anxiety remembers
does "net load on client" not load the actor for late joining clients?
has anyone here built an activation queue for multiplayer abilities/cooldowns?
Do rep notifies run on the server in BP?
yes
thank you
how do I prevent some actors, placed in editor and visible in world outliner, from spawning on clients? to be specific I'm talking about ARecastNavMesh. AFAIK there's this bNetLoadOnClient property on AActor, but this one is inaccessible on ARecastNavMesh in editor for some reason ๐ค
inb4 recast navmeshes are autodestroyed on clients anyway - yeah I'm aware of that, but we have a strange bug where sometimes recast actor's NavRenderingComponent holds a reference to the world in its Outer property and doesn't let the GC to finalize something which causes client crashes
The netloadonclient thing would probably only work if the actor is replicated or?
And the only thing it prevents is that it doesn't load from disc. It would then be replicated down with the newest info
Not sure if the boolean has an affect without replication
in regards to this.. just spitballing some ideas.. maybe i can have a timer both on the server and client for a cooldown and if the cooldown ends on the server before the client then it can wait until the client cooldown is over to fire?
would the timer ever end on the server before the client though?
Hi, any ideas why the beacons are not working in the editor ?
CreateNamedNetDriver failed to create driver from definition BeaconNetDriver
It's working in standalone
No idea but FWIW, most session related stuff does not work in editor
Mhh it's weird, the game net driver is working, will keep searching
Would anyone know any causes of clients disconnecting while using any RPC's?
This only happens in standalone (not in the editor). I've tested this in steam advanced sessions, both online and steam LAN, as well as local LAN without steam. All tests have the same result
Basically, I've noticed that when the client sprints, crouches, or interacts with anything using an RPC, they disconnect and rejoin the default map.
I'm using blueprints and I've looked around quite a bit without much success as to what can cause my specific issue.
-I'm also interested in any debugging strategies i can use that can help. Also, I find it very tedious to wait for someone to help me test multiplayer with steam. I feel like i could be using a virtual machine to do this, however, my CPU doesn't support this fully, so it'd have to be a remote vm.
First port of call would be to look at the logs and see why they're being disconnected. Sounds like the Server is kicking them to me
Would you know of any better way to test multiplayer without using 2 pcs?
Check you aren't overflowing the reliable RPC buffer somehow
There is no other way if you're using Steam
A VM
Would this still work with steam?
Yep
Virtual box?
The beacon driver def is just not here, but i don't know why
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
I added this in DefaultEngine.ini, but it seems to be ignored
Ok i found
Hello. I'm trying to replicate a massive amount of instances (static meshes) over the network. Now I can't really let the server do all the spawning / instance creating. I also really can't replicate the transforms because there are just too many. I've tried with only 3000 and already it takes ages for the client to get that data. So sending the actual data is not an option for my usecase sadly. So I'm trying to find a way to use random seeds. The thing is I don't need the instances to be replicated. I just need them to appear on the same location on all clients, that's it. So a random seed would seem perfect for this. Problem is, I can't get it to work. The seed produces always the same result on the server. But on the client it's always different. How can I get the same results on the client as on the server?
Send the seed generated on the server to the client in an rpc
Well currently I'm just using seed 0
on both client and server, but that doesn't work
shouldn't that work?
What function do you put the seed into, it should produce the same results on both independently
The seed is fed into a function which does a huge loop to generate transforms
The function fires on client and server
And when you say it's always different on the client, is it always the same different result on the client for the same seed or it's always a different result?
Lemme double check that
Results on the client seem to be always different
while results on server are always the same
Well that's what you should be exploring first, I can't tell without seeing your code but you want to get it to be deterministic.
does a bool array set to repnotify replicate if a boolstate inside of his array changes?
I wonder, does load priority of things influence the results of randomisation with seeds? Like could it be that because of replication not being always in a similar order be the problem?
Check this out. Network managers might help you https://vorixo.github.io/devtricks/network-managers/
Are you using SRand?
During testing, does it matter what GameLift region you upload your builds to? My default region is eu-west-3 but aws gamelift upload-build aborts with
Could not connect to the endpoint URL: "https://gamelift.eu-west-3.amazonaws.com/"
and I'm wondering if it's okay to try to upload it to another region.
I kinda don't atm. It's just a hardcoded number for now. Is that an issue?
It was set to 0, changed it to 100, but still the same issue
I mean it shouldn't be, it just sounds like the seed is random on the client for some reason
Hmm I never set or change the stream. It's always just a hardcoded number. o_O
Can you show where you set this?
I don't have much to go on ๐
This is the function that generates the transforms and in goes the stream
which is just a public variable with a default value set to 100
You might be calling the frotator/float from stream function more times on the client or something, everytime you calls those it mutates the seed
you'll only get the same results if you call it the same number of times
when you init the seed you get the same sequence of values everytime
but if you called it more times on the client it will get out of sync
There are multiple planets that all call this function. Could that be the cause? Like that on client it's never the same planet replication sequence or something?
Could be, like I said it's hard to tell when I only get a tiny window into your code
But that's something you could check
ill try removing all other planets and see if it works with just one
Make sure the stream isn't being replicated too, that would cause the issues you described
Yup, that was it. it's fixed now
Ok so yeah it's most likely the planet replication order
Ah good ๐
Thanks for thinking along ๐
np glad you fixed it
Would setting a custom seed for each planet solve this issue you think?
Because I wonder, does the seed mutate only when the initial value is the same? Or does it also mutate when other seeds are used?
I could centralize this code in a singular actor though and just wait for all planets to load on the client and then fire the instance generation code once
Yeah I'll do that
Yeah try it
The seed mutates every time you're calling those functions to generate floats/rotators, this is the cpp code and what's actually going on
Ah yeah makes sense, so basically each time the seed is used it mutates
yeah basically
Centralizing it will then be the best way to solve this I think as I can than guarantee that the seeds are only used once in a very particularly defined order
That means it's important to call the frotators/floats in the same order too, since the frotator function will mutated the seed 3 times as opposed to the float doing it once
If you're running the same code it shouldn't be an issue though
Actually maybe it doesn't matter xD
You found the problem anyway
Yeah, problem is though that there isn't really a way to define the order in which planets are replicated from the server to the client. And because each planet does it's own generation (each calls this function internally) I therefor have no control over which planet calls the function first and in what order they are called from the other planets.
Unless there is, but I'm not aware of xD
Ah I see, that makes a lot of sense now. Yeah having each planet actor self contained with their own stream (even with the same starting seed) as long as it's a new stream object each time
You need to eliminate the replication order issue
Actually you want a different seed I imagine
Yup, I'll just make a planet object spawner that waits clientside and server side until all planets are loaded to then spawn all objects in one go on all planets
otherwise they'll all spawn in the same spot
Np! gl
Right but Replication category is hidden for this one and prolly reason being is Epic doesn't want you to shoot yourself in the foot. And for your other issue, force garbage collection?
No it does load for late joiners
I have a float Points on server and I want to replicate it to client as if it was int32, meaning if the value changes from 0.1 to 0.8, it would still remain floored to 0. But if it changes from 0.8 to 1.1, it should replicate 1.1f to client.
I know it's a bit weird, but the value will be changing a lot by small increments, and those are not necessary to replicate.
:')
There's a net quantize version for vectors but I don't think there is for floats
You will have to make your own pretty sure
But it's pretty much to copy what they do for FVectors as they are basically 3 floats
anyone knows anything about this? ^
just wondering if there's already some setting I'm missing or if its something that has to be custom made
Thanks, will look into the Net quantized vectors
Never used chaos vehicles, only thing I know of with normal physics simulations is the bReplicatePhysicsToAutonomousProxy field which determins whether a physics simulation is server/client authoritative for primitive components.
When he dies he has to switch to the other player but stays on his own camera.
thanks, Im going to look into that
Hello guys hope someone can help me with this, it seems so simple yet i cant figure out why this does not work. This is on my gamemode bp and i call it from a widget and it does not work for the client. Im sure im missing something, i have tried replicating the event on server but still not working (maybe because i need to compile?)
does not pass to the other player when it dies
Right because widgets are local only, i.e. client-only for clients. GameMade in return is server-only, so there is no way to communicate
At this point your mission is to find the networking compendium in this channel pins and read it a few times
hey guys, quick question
im trynna make is like a 1v1 2d game, i want the player to face the cursor, i was able to do this by getting cursor position using controller and finding the look at rotation for it and setting players z as the result z, although i am unable to replicate it t the clients, and when a client joins it doesnt really follow the cursor as it should?
any idea why this is happening? or how i should make it work
Why do delegate declarations still giving me unknown specifier error even tho I included "Interfaces/OnlineSessionInterface.h"?
Copy+paste code and exacty errors.
error C3646: 'FOnReadFriendsListCompleteDelegate': unknown override specifier
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
FOnReadFriendsListComplete FOnReadFriendsListCompleteDelegate;
Hopefully that is enlightening!
Yes it's a type that is already included in #include "Interfaces/OnlineFriendsInterface.h"
oh shit
I do have #include "Interfaces/OnlineSessionInterface.h" only
thank you xd
Np
Is it possible to use create session and find session in PIE with the null subsystem ?
so not entirely a multiplayer question but kindof a multiplayer question but is there a way to load into a level with a different gamemode than what is assigned in the world settings?
Yes
nvm i think i have found it by googling some more
Anything special to do ? I'm launching 2 clients as standalone from the PIE, i create a session, the the 2nd client can't find it
It needs to be lan
SessionSettings.bIsLANMatch = true;
I'm in LAN aswell
Same things for finding
SessionSearch->bIsLanQuery = true;
Yep, got the same
DefaultPlatformService=NULL```
It's working only if i start the session from a standalone game (not in PIE)
I have steam, but it fallback to the null subsystem
Oh PIE doesn't technically work, since the other instances automatically travel with the host by default
So I was wrong about that
Ok so i have to start a session from a standalone game ?
Yeah
Ok thanks !
You can make it easy with a .bat file "Path_to_epicgames\Epic Games\UE_5.0\Engine\Binaries\Win64\UnrealEditor.exe" "path_to_.uproject" -game -ResX=800 -ResY=800 -log
When BeginPlay is fired, all replicated properties are sure to be replicated at this time ?
This should usually be the case, yes.
even on simulated proxies ?
As far as I've seen, yes.
bIsEquipped should be on true for simulated at this time
Mh i have a beacon server and client in PIE, i got no errors but the OnConnected is not called on the client, any ideas ?
I don't know anything about how Lyra is setup
Don't take attention at the Lyra name it's not anything from Lyra ๐
Ok i don't know anything about that code you sent ๐
so basically, i'm replicating this bIsEquipped only to simulated, i'm setting it to true when weapon is equipped, it's used to prevent late joiner that can't see other player's weapon equipped
I tried a few things since, using an OnRep_IsEquipped, but in some case owner has not yet replicated so i can't attach the weapon to the owner
Also tried OnRep_Owner BUT in some case bIsEquipped has not yet replicated and i can't check that the weapon is currently equipped
So i need a place where everything is replicated, BeginPlay should do it
Oh I see well in this case you probably need to try the setup in OnRep for Equipped and Owner
Nah it's not fixing anything as i said above
there is still a few cases where one of both has replicated in the "wrong" order
You can put them in a struct then, the structure will be replicated as a whole
My BeginPlay is only called one time, when weapon is added to inventory (when removed from inventory it spawns an APickup, so a different actor)
It will not fix anything tho
I can't put the Owner pointer in a struct it's literally smth build in the engine
Oh wait you also need the owner actor to be replicated. This kind of dependency is hard to handle.
Well if you want to attach your weapon you generally need the owner yeah ๐คทโโ๏ธ
that was kind of obvious tbh ๐
Trying to remember how I setup our weapons...
I've been struggling with weapons race replication for over a year now
i'm just so tired of that ๐ซ
Ideally the simulated proxy should not need to access the owner
Then again how you want them to attach the weapon to the owner ?
I'm sure there's a place where everything has replicated so i can't play with all these things without issues.
I don't think you can ever guarantee that, due to relevancy etc either actor may disappear at any point
Hey guys, over the last few days I've been trying to get a strong understanding of multiplayer. Would I be correct with the following procedure for handling a client shooting a weapon? In the parentheses, I've included stuff I'm not sure about.
- Shoot key is pressed
- Using a server RPC, the server does a line trace to check for other players
- If there is a player in the line trace, you call a take damage function on that player. (The take damage function does not need to be an rpc)
- The take damage function gets called on the hit actor. This function will just decrease the health variable (What is the difference between setting the health variable to replicated vs RepNotify)
- In the original server RPC, after calling the damage function, the ammo count variable is decreased. The variable is set to replicated so the client version knows how much ammo it has
- The result is the client only tells the server it pressed the shoot key. The server handles all the shooting logic and updates the replicated variables to the clients. This way, it is not possible to cheat
Seems about right. You could add checks before "shooting" to make sure there is ammo in the first place. The difference between replicated and repnotify is that repnotify is actually "replicated with notification" meaning that the client will have a function called every time that variable is replicated. For ammo and health you would use this to update the hud
As for cheating, it wouldnt go so far to say it's not possible. It's pretty much always possible but you are removing the authority from the player to tell the server "trust me bro, I can do damage to this actor"
Ok thank you!
Im doing unreal's multiplayer quick start tutorial (https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/Networking/QuickStart/), and when I play using two players, I see the damage logs on both?
My health update function, copied from the tutorial, looks like the attached code. Any ideas why the log is showing up for both players?
same thing happens if If I play with a server and 1 client
I see the logs on both screens
My guess is this happens because I'm testing all this locally on one PC? So all the clients are sharing the same Unreal engine instance, and so they all see the logs?
In the options there a checkbox for doing all multiplayer clients under 1 process.
Turn it off.
thank you that fixed it! I actually did try toggling that on previously, but was super confused when the Unreal engine loading screen showed up loll and just closed the whole thing
I'm new to multiplayer; would you recommend leaving this off most of the time?
I would recommend never running under a single process because it isn't a good simulation of a real client/server environment.
I imagine it's slower and uses more resources, though.
Definitely, but I'd rather make sure the client-server interactions are working
Indeed!
My general logic might be flawed. Here's my problem:
I'm working with PlayerController::GetInputKeyTimeDown() to check how long a button has been held down by a player. This works fine on the server, but since the player controller doesn't exist on clients, the call fails there.
Is there another way to keep track of how long a button has been held down on a client via e.g., the PlayerState?
I've gotten around this issue like so:
but it really smells I think hah...
NVM! got it all working now, although I had to do this...
Your logic shouldn't be working in such a way that clients would need to know about the input of another player. The client performing this action would need to RPC to server and then the server replicates what happens to the clients.
"Get Input Key Time Down" is likely only client-side too, so it wouldn't be something that the server itself would know about for each client.
The solution to this would be to have a server RPC triggered when the desired input key is pressed and save the time on the server, and when they key is released you send another RPC and calculate on the server based on the saved time how long the input was held.
Also, it's really bad to check those options in the CMC - they effectively allow your client to tell the server where they are located - in other words, those with know-how will be able to teleport anywhere in the game.
They're good for short bursts of movement where you may want to avoid the server correcting, but shouldn't ever be just left on.
Hi ! I have made a little level to test my cat character, and I made the mistake to put a "simple" ball replicated to player with it, with physic simulation... Now I'm at 4 hours of conferences and "hey I did it, but I won't show you how" videos about client prediction... What I did...
Anyway... Even in editor, without any lag, the ball is shaking a little, in particular when the client push the ball in continue. Someone have an idea about way it looks so awful ? I disabled physics sim on client, removed gravity, disabled all collisions... So I don't really understand what could cause this thing. At least a confirmation that this is due to client updates from the server and not a wrong setting on the client ?
I feel like I'm either encountering something "normal" that never occurred to me or a bug:
I have a Replicated Array of <FSomeStruct>. That Struct has 2 Properties that are actively marked as NotReplicated.
The Local Client can add to the Array (and in specific cases also remove from the Array), but the Server is the one (usually) to remove from the Array.
That has to do with predicting something locally and that works fine.
The problem comes up when the Server removes an Entry from the Array. In the OnRep it seems like the properties are sort of mixing up.
If I have an entry with 50 for one of the NotReplicated properties and another with 60, and the one with 50 is removed, then the OnRep suddenly has the replicated properties of the 60 entry (correctly) mixed with the NotReplicated ones from the 50 entry.
Or in other words, the 60 becomes a 50 for no reason.
[0] Some.Replicated.Tag.A | 50
[1] Some.Replicated.Tag.B | 60
When [0] is removed, the Server has:
[0] Some.Replicated.Tag.B | 60
as expected, but the Client has:
[0] Some.Replicated.Tag.B | 50
Like how does that mix up? Is it because the Array, when receiving the updates and running NetSerialize, only overrides the properties of Index [0] that are replicated and the NotReplicated ones are just kept?
I mean, that would make sense, but also really annoying :D
Yes, I think that is the case. do you use fast array or just array replication? As I think if you use just array replication it will basically copy the whole array to the client and I think it assumes the client is not changing it?
(In general, if you have an array replicated, that can be modified by the client, I'd write a simple custom replication for it, then you can properly merge that)
as the default replication doesn't know you removed / moved an element, and thus it will just replace the data from the server at Index N with the replicated values, but won't move anything (pure assumption, but it would make sens)
I use normal array replication because the array is small enough to not need fast array stuff
Then I think this will not take care of steps like remove/insert/move. it will just replicate 1:1
Yeah, minus the NotReplicated ones
Which is the issue I guess
But I can't mark the replicated cause the Data is different (on purpose)
eh no
it doesn't do move operations, so the values are likely to just be overwritten with the new data, and only the replicated data I think
UPROPERTY(Transient, BlueprintReadOnly, ReplicatedUsing="OnRep_AbilityCooldowns")
TArray<FAbilityCooldown> AbilityCooldowns;
USTRUCT(BlueprintType)
struct FAbilityCooldown
{
GENERATED_BODY()
virtual bool operator==(const FAbilityCooldown& Other) const
{
return this->CooldownTag == Other.CooldownTag;
}
friend uint32 GetTypeHash(const FAbilityCooldown& In)
{
return GetTypeHash(In.CooldownTag);
}
float GetTimeRemaining(float CurrentTime) const
{
return FMath::Max(Timestamp + Duration - CurrentTime, 0.f);
}
UPROPERTY(BlueprintReadOnly, Transient)
FGameplayTag CooldownTag;
UPROPERTY(BlueprintReadOnly, Transient)
bool bServerApproved;
UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
float Timestamp;
UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
float Duration;
};
Timestamp and Duration are the issue
yeah, I got that.
As said, I think the issue is, that the array replication das 1:1 "copies" of the replicated data, but doesn't clean already allocated entries
I can fix this in the OnRep I guess, because I have the old state
Yeah
It basically inserts part of the struct
well it copies what get's replicated and ignores the rest, as it doesn't have any data
It removes the [1]for the Client and inserts the changed data into [0], minus the 2 nonreplicated ones
Hmm if it's not replicated, client shouldn't be touching those values when it receives from server, very odd.
"NotReplicated" should effectively be invisible to net stuff
I can see it being a problem if you defined a NetSerialize tho
I did not
Is the issue actually caused by reordering elements on the client?
Yeah that sounds right then - it doesn't strictly care about element order, it just says "this is the data for element 2"
whatever is there will get that info
fast array addresses elements via a fixed ID so it's sort of impervious to that
[0] Cooldown.Ability.A | Timestamp: 500 | Duration: 3
[1] Cooldown.Ability.B | Timestamp: 700 | Duration: 8
Becomes
[0] Cooldown.Ability.B | Timestamp: 500 | Duration: 3
in the client when the Server removes Entry [0]
yeah, that makes sense to me
yep. as we described
Yeah it does to me too, but I need that to not happen haha
client resizes the array, then dumps data into element 0
Preferably without having to split this into more than one array
I have the old array in the OnRep, I guess I can check the values for the remaining entry and override
I think fast array would fix that, or write a simple custom replication, that replicates "remove element0" and not "copy into 0"
Not really nice though
yeah "fast" array would probably fix that, since elements are identified by ID instead
Is FastArrayReplication slower for small Arrays? (similar to TMap vs TArray)
If you guys were going to make an MMO type party system, (something like WoW where you can see your party members health bar and stamina next to your screen) where would you put the server sided logic?
Seems to depend, it has a constant overhead by writing the size,num deleted + num changed with every send
Plus the element ID itself is int32
on the server?
Playerstate, Gamestate, Or Controller? ๐ค
...
APartyState : AInfo
playerdata -> player state, game data -> gamestate, controller is only known to the owning player
In other words, I usually make new State actors for this
but each element in this case is going to have at least 1 index property (int32), two property headers (2x uint16) - so it might not be that measurable in practice
They can be listed in the GameState if you need it
And they have a list of Players via PlayerStates
And some additional data such as who is the leader etc.
I was thinking both yeah
You can override the IsNetRelevantFor to handle replicating it only to the Party Members too
you make an actor to keep track of the party?
Yop
maybe you could save some more by writing a netserialize, compressing the "duration" to a float 16 ๐
I do that usually for Teams
I'd start with FastArray and see if its a performance issue. if it is I'd write a custom replication that is suited for your exact needs
When you say Custom Replication, what does that even entail
Just NetSerialize stuff?
interesting, v interesting
yes, or delta. So write a wrapper struct to wrap the array and replication logic
yeah I'd go fast array, turn off the per-element delta serialize, and use NetSerialize and squeeze it down to a 32-bit float for timestamp and 16-bit float for duration. Each element is then 32 for ID, + 48 for data.
But I mean the Timestamp and Duration shouldn't replicate at all
Maybe Duration in the future I guess
But for now they are only meant to be part of the Struct for organization reasons
Oh it's a tag and cool - oh hell yeah, could make it utterly tiny then
tag index + a bit for bool
Yeah, right now I'm mostly wanting to fix the bug itself, before I optimize stuff
I will start with turning it into FastArray. Haven't done that yet, so yeaha for doing something new
yeah I think FA kills two birds with one stone. Problem is you have no way to identify the elements uniquely
Delta serialization on arrays... what would possibly go wrong ๐
I mean I do have the Previous Array in the OnRep
Which I can always check for the two values if needed
It's just not pretty
Also, would be interesting to see if this is impevious to packet loss and/or replication arriving out-of-order (which always happens for arrays)
you get a post replicate general callback and a per element one
yeah
you can just look at the source code, has a nice example for setting it up
There is at least one issue with the per-entry callbacks, in that they don't fire when UObject properties get mapped (but the array callback does). Not an issue in this case tho
Just a "fun" gotcha
Which messed with my inventory system for ages -.-
we had the same issue xD
Asking mainly due to currently having to figure out what the F actually changed so I don't notify everything about every entry every time
Cool
just be aware, that order on server and client can be different, if you change smth on the client. the elements will be mapped properly, but the order may be different
yeah that too
Doesn't seem like that would be a huge issue here?
Also you do have the timestamp already, could probably sort elements by timestamp maybe to keep order consistent?
Or even by element ID
I don't need sorting
The system is basically a partially predicted cooldown with server auth
Client can add to locally instantly put the Ability on cooldown for x seconds with timestamp y.
CooldownCondition on the client is "Is that Tag in the Cooldown Array?"
Server then later also applies the cooldown, which only replicates the Tag back, so nothing should change. (the boolean is a different story, but not so important here).
The Server then checks on tick if the CD (on its end) ran out and removes the element.
I do modify the actual CooldownDuration on the Server by RTT so it lines up with what the Client expects.
The bug with the data not being "kept", basically causes, visually, to have the remaining of the two cooldowns (if two are active) to just show "0.0", cause it takes over the Duration and Timestamp of the one that ran out
It doesn't affect gameplay, but shows the predicted time wrong, as the Tag gets "Mapped" to the wrong Duration adn Timestamp if the array shrinks
So no, I don't care about order at all
Most important is:
- The Tag is in the Array
- The Duration and Timestamp remaining untouched for the Client, as the Values differ for Server and Client
I will, in the future, change how Duration works, because we could have abilities that have their cooldown lowered, and not sure if that is always predictable.
And the Server has a different Duration value than the client so I have to split that in the future.
But one step after another
In a sense the fast array method of identifying items with a "key" is basically how GAS prediction works anyway
And is what allows clients to predictively do things and tell server "i did a thing", and get the result back
Yeah it sounds like a better approach
I didn't use it cause I thought it's the same logic as when to use Map vs Array
There will never be more than maybe 5 entries in that array
USTRUCT(BlueprintType)
struct FAbilityCooldownEntry : public FFastArraySerializerItem
{
GENERATED_BODY()
UPROPERTY(BlueprintReadOnly, Transient)
FGameplayTag CooldownTag;
UPROPERTY(BlueprintReadOnly, Transient)
bool bServerApproved;
UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
float Timestamp;
UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
float Duration;
};
USTRUCT()
struct FAbilityCooldownArray : public FFastArraySerializer
{
GENERATED_BODY()
UPROPERTY()
TArray<FAbilityCooldownEntry> Items;
bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParams)
{
return FastArrayDeltaSerialize<FAbilityCooldownEntry>(Items, DeltaParams, *this);
}
};
template<>
struct TStructOpsTypeTraits<FAbilityCooldownArray> : public TStructOpsTypeTraitsBase2<FAbilityCooldownArray>
{
enum
{
WithNetDeltaSerializer = true;
};
};
Does that look correct for the start?
Website tutorial I found seems to be a bit dated
yeah that's about the size of it ๐ - just a case of doing stuff like marking the FAbilityCooldownArray as dirty etc. when adding/removing elements
Yeah I read about it
I usually just have the array be private and add accessors to avoid forgetting about it
The callbacks are part of the Item, right?
you can do both
Surprisingly the fast array serializer header documents it pretty well
worth a look
Ah, I'm not used to documentation from epic
IKR ๐
are you in 5.0 or 4?
in 5.0 they moved it into it's own header I think, and also made some fixes
5
cool
4 is for noobs

Na jokes aside, yeah found it
I assume the "Order of Lists not being identical" is just a matter of handling it via some order int fwiw
If I ever need that
Or some context driven order
Like timestamp as you said
yeah basically elements are identified by ID, it doesn't care about the order when replicating
Server + Clients maintain their own ID->Index map
Ah the website I found basically just had an outdated copy paste of the header comments
haha
:D:D
How to get clicks
/** Step 6 and beyond:
-Declare a UPROPERTY of your FExampleArray (step 2) type.-You MUST call MarkItemDirty on the FExampleArray when you change an item in the array. You pass in a reference to the item you dirtied.See FFastArraySerializer::MarkItemDirty.-You MUST call MarkArrayDirty on the FExampleArray if you remove something from the array.-In your classes GetLifetimeReplicatedProps, use DOREPLIFETIME(YourClass, YourArrayStructPropertyName);You can provide the following functions in your structure (step 1) to get notifies before add/deletes/removes:-void PreReplicatedRemove(const FFastArraySerializer& Serializer)-void PostReplicatedAdd(const FFastArraySerializer& Serializer)-void PostReplicatedChange(const FFastArraySerializer& Serializer)-void PostReplicatedReceive(const FFastArraySerializer::FPostReplicatedReceiveParameters& Parameters)Thats it!*/
So
-You MUST call MarkArrayDirty on the FExampleArray if you remove something from the array.
I assume I also have to pass in the removed entry into that?
negative - just remove it, then call MarkArrayDirty()
It goes through and rebuilds the ID->Element info and figures out what has been removed next time it replicates
You can provide the following functions in your structure (step 1) to get notifies before add/deletes/removes:
Only one of them has Pre in the name, yet the comment says "before add/deletes/removes"
(also remove and delete is the same or not hehe)
Ah no, you get "Pre" remove, and "Post" add/change
Right and the FFastArraySerializer has some sort of way to get a hold of the class instance that the struct lives in?
But it also fires when GUID's are mapped too, I think the params tell you whether it was a genuine "received from server" or just GUID's being mapped
So I can actually make use of the callbacks
It doesn't - but it can only be a member property (can't be embedded in other structs etc) - so it can be common to just store the owner inside
GAS does that a lot
So my item just needs the owner
Ah I see, it would have it if we use PUSH MODEL
FFastArraySerializer()
: IDCounter(0)
, ArrayReplicationKey(0)
#if WITH_PUSH_MODEL
, OwningObject(nullptr)
, RepIndex(INDEX_NONE)
#endif // WITH_PUSH_MODEL
, CachedNumItems(INDEX_NONE)
, CachedNumItemsToConsiderForWriting(INDEX_NONE)
, DeltaFlags(EFastArraySerializerDeltaFlags::None)
{
SetDeltaSerializationEnabled(true);
OwningObject hmmmm
Hah, interesting. Yeah I've never used that, I just make my own property
It's pretty cool tbh, gives a lot of control
Becomes one of those things you start using way too often ๐
Yeah I just always put it away under "Whenever I have to do an Inventory in Multipalyer."
Which I never got to
Clients always want funky movement features from me. Send help
boi do I have the plugin 4 u
Not that anyone will buy it when I launch it because inventory is one of the more fun parts of dev
Why is it, that the more hardcore Multiplayer programmers consider shit like this fun?
Like, why do we love touching Inventories and Movement
Can I just do whacky BP shit please, for gods sake. Whoever reads this: Never become good a Multiplayer and C++ and offer your skills to others. Run!
So you are making a plugin for Inventory stuff?
I always feel like the Marketplace would probably mostly provide โฌ$ for Editor shit
Based on the amount of Editor Mods I had to write for people
Yeah, it started out for the hover tank game then realised I could quite easily adapt it to handle a lot of different styles pretty efficiently. The actual inventory portion is ready, just I have to make some example projects now and I really cbaaaaa
I usually run into situations with stuff like this where it becomes increasingly difficult to allow users to just plug and play things if they could be reaaally different for every project
Yeah I 'm hoping I struck a good balance with this one
definitely never going to have the "be all and end all" system
I am working on a fpp multiplayer game.
I spawn weapons and attach them to fps arms. But it's visible
And i have to show weapons in third person
How do you manage equipping/attaching/weapon visibility on HLL ? for late joiners.
I have the same setup as ShooterGame for the weapons equip functions and attaching
Todd Howard Voice - It just worksTM
I tried like 10000 ways to avoid race replication issues for late joiners
but yeah i can't figure out how to do it properly
We're doing nothing different to what ShooterGame provides AFAIK
I don't remember if ShooterGame handles late joiners tho
It does
Isn't it enough to have a State in the Weapon that OnReps?
That's usually how I handle that
{
SetCurrentWeapon(CurrentWeapon, LastWeapon);
}
void AShooterCharacter::SetCurrentWeapon(AShooterWeapon* NewWeapon, AShooterWeapon* LastWeapon)
{
AShooterWeapon* LocalLastWeapon = nullptr;
if (LastWeapon != nullptr)
{
LocalLastWeapon = LastWeapon;
}
else if (NewWeapon != CurrentWeapon)
{
LocalLastWeapon = CurrentWeapon;
}
if (LocalLastWeapon)
{
LocalLastWeapon->OnUnEquip();
if( NewWeapon )
{
NewWeapon->SetOwningPawn(this);
NewWeapon->OnEquip(LastWeapon);
}
}```
i don't have states in my weapon
Then in the Character fwiw
at least not like ShooterGame
i have bIsEquipping, bIsEquipped, bIsReloading as states tho
but not like shooter game
I tried a few things since, using an OnRep_IsEquipped, but in some case owner has not yet replicated so i can't attach the weapon to the owner
Also tried OnRep_Owner BUT in some case bIsEquipped has not yet replicated and i can't check that the weapon is currently equipped
We don't predict weapon equips - because fuck that headache
The Owner is the thing you need to OnRep
i have the same code
either directly or via a Struct that has some more info
There's a key part here btw:
// Make sure weapon's MyPawn is pointing back to us. During replication, we can't guarantee APawn::CurrentWeapon will rep after AWeapon::MyPawn!
NewWeapon->SetOwningPawn(this);
RaceCondition between Properties -> STRUCT
Yeah that's not identical - see above
i can't put owner in a struct
Why not
i have something like that
GivenTo does the same
You're not doing it in the OnRep
You also have no garauntee what order properties vs RPC's will arrive in
here
struct FWeaponEquipState
{
APawn* OwningPawn;
bool bIsEquipped:
}
void AWeapon::OnRep_WeaponEquipState()
{
if (WeaponEquipState.bIsEquipped && IsValid(WeaponEquipState.OwningPawn))
{
// Attach
}
}
I need the two to be replicated when i do my stuff
+- USTRUCT/UPROPERTY etc.
We don't replicate the equipped state independently
The problem you have is two independant actors deciding whether something is or isn't equipped
mmh
You need to determine it from one actor/source only
Yeah, again I usually have an Struct with the required data in my Weapon
In our case the pawn is what decides - since only one weapon can be equipped at once and it avoids race issues between weapons
When I equip the Actor, I tell it who it is equipped to and that it is indeed equipped
If the Pawn doesn't exist yet but the boolean is true, you get a non resolvable netID the first time the OnRep calls
also
Once the Actor exists it will call the OnRep again usually
since CurrentWeapon does have an OnRep and then call Equip inside
If you look at ShootertGame btw - you'll notice "IsEquipped" is not replicated by the weapon
With the pointer being valid
late joiners should also have it
but Owner is also not yet replicated when they get that
That's why we call SetOwner() manually
I may need to convert my GivenTo to simulated proxies
actually i imported it from UT4 to avoid race replication but for owning client
i also searched to see how UT4 was avoiding race replication
So you've got UT4, Lyra and ShooterGame all mixed in :D?
and yeah it's kinda crap
That's a fresh sort of hell
Well at the start it was ShooterGame, then UT4 and recently Lyra
idk, this seems rather straight forward to solve if you simply handle the state yourself?
And even if you use two different OnReps, you can still call a TryEquip function
Which checks both values
You essentially have redundancy atm - too many properties being used to replicate the same state info.
yeah currentweapon and bIsEquipped
Weapon is replicating it's equipped state, clients are being told via RPC to "equip", and the pawn replicates it's current weapon too
i replicated bIsEquipped to see if it would fix the race replication with owner
That can all be boiled down to one prop which defines all state
but it's worse tbh
IMO - what is and isn't "equipped" is a pawn-level property, as in it determines what is/isn't equipped.
It also avoids weapons fighting with each other over whether they are/aren't equipped or not
Yeah if you can only have one at a time, then the Character makes more sense
Which would also make it even easier with a simple OnRep_Weapon
If you don't want to set the owner client-side the way we do, you can follow the same path Cedric said and call a "TryEquip" both when the owner is received, and when the currentweapon is received. Then you check both properties
yeah
that's what i already have
i just need to ditch bIsEquipped tbh
yeah, it shouldn't be replicated at least
The fewer points of contention you have between properties the better
i do anyway ๐
It's creating an extra race condition
ClientGivenTo set the owner on it's end
Yah but that's also not going to work
Hi!
You don't even need that RPC, the Owner is already a replicated property
And the RPC is also going to be fighting with the various states
Do you know if there is a simple of example of a local multiplayer game done with Unreal 5 and C++?
Thanks!
And if that RPC is changing persistent state, it's a bad RPC
i don't have any RPC for my weapon switch
ClientGivenTo is setting the owner - it's bad straight away
Owner is a replicated property, there's no need to RPC it
And the RPC will have it's own inherent race condition
ah you meant for GivenTo
ye - get rid of that
it fixed most of my issues ๐คทโโ๏ธ
Client can already figure out what it's been "given to" when it receives OnRep_Owner()
like when spawning and giving weapons
Any RPC that changes state = bad
Especially if that RPC is also changing an already replicated property
It's just another race condition waiting to happen 1/99 times
So i should just ditch GivenTo and use OnRep_Owner to make my given to logic ?
definitely
but it will just fuck all of my weapon logic ๐
This is also how shootergame handles it btw
{
if (MyPawn)
{
OnEnterInventory(MyPawn);
}
else
{
OnLeaveInventory();
}
}```
ClientGivenTo also handle the "if it's your first weapon tells the quickbar to active it and equip it"
If i do that in OnRep_Owner it will do that for everyyyyyyy clients, every weapons
You have another race condition right there btw
yeah but they have a separate Pawn property
"IsLocallyControlled"
not the owner itself
why ๐ค
No garauntee the pawn will be able to determine if it's locally controlled when it receives that RPC
What if pawn/controller relationship hasn't replicated yet?
Yeah true i might already have this issue ๐
basically, and i mean this nicely - this is all wrong ๐
it's a total nightmare ngl
You need 2 properties to do all of this - and one of them already exists (owner)
Also Lyra's inventory can suck a fart IMO
yeah i'll try the shooter game way then
i don't use lyra inventory
also not lyra quickbar ๐
This is all very confusing ๐
That's stuffs from my old project, i merged to lyra to benefits Experiences (gamemodes mainly that's the only thing i had not)
I know, every time i'm sharing my code people tell me "i'm sorry i don't know how Lyra works" but it's not Lyra code ๐ซ
But yeah it might be confusing, i might replace "Lyra" next time i share code to not confuse people
{
CheckEquip()
}
void Character::OnRep_CurrWeapon()
{
for (AllWeapons)
{
Weapon->CheckEquip();
}
}
void Weapon::CheckEquip()
{
bool bShouldEquip = GetOwner() && GetOwner()->Weapon == this;
if (bShouldEquip != bIsEquipped)
{
// Blah
}
}```
There's a simple psuedo-code setup
Using the simplest logic I can think of
yeah but Equip also needs to happen on Server
That's why the current way i do it (like shooter game) is good
It will - the server sets the CurrentWeapon property and thus calls the CheckEquip() also if required
UT4 has something like that
but with like 4-5 RPC ๐น
but i might try your way, it seems already more reliable than UT4
Probably because UT4 also does predicted weapon equipping which is a fresh hell in itself
HLL/ShooterGame etc. has latency when changing weapons - but I'd rather that tbh
What the actual f
yeah i also have some on high ping
but it's the cost
Fortnite also has latency for weapon switching on high ping
I'm 99.9% sure UT does what it does anyway - but UT does some mad stuff for that 120Hz..
Yeah honestly predicting weapon switch is utter chaos
Would rather suffer the lag and tell people to download more RAM
"Tech support hello, yes, did you try moving to a country with fiber"
Avoiding weapon race replication issues + predicting weapon switch is how to have a good nightmare in your code 
But UT4 is old af, i'm wondering how it would looks like in 2022.. with GAS ๐
Well UT4 is also unlike most other stuff Epic releases, in that's it's very tuned to make a specific game.
I mean even the bots aren't using any of the engines AI tooling really, it's all custom and likely copy-pasta from past UT games
Yeah but seeing the code they could simplified like 60% of the game with GAS ๐คทโโ๏ธ
Yeah GAS wasn't really around then though, or at least was very unproven
UT4 predates Paragon IIRC
Which is when GAS got it's first trial by fire
UT4 is very old stuff by now, yes
yup it was not a thing
Also, since it was the fourth game - they probably didn't need an ability system ๐ Safer to just copy-paste from the previous 3 games
and they switched over Fortnite later
I'd play UT with abilities tbh
that would be cool
Splitgate ?
Also obligatory "bring back paragon" TM
I would still not play Paragon though
Aww I liked it ๐
I don't even remember why the game failed
was it a mess with marketing ?
or with the game as a whole
No direction + fortnite raking in cash
Fortnite was not out at this time
Paragon wasn't that financially successful IIRC
- competing against mf DotA
or you mean development cost
Yeah and also competing with so many well-established games
Just never took-off the way Epic expected I think, and they kept changing really fundamental things that made it hard to keep up
Sort of lost focus towards the end
I think the formula simply wasn't attractive enough in the face of entrenched, well supported competitors that run on potatoes
The visuals were seriously dope, yeah
Was like the good old days of playing a new Gears game on X360
they did whaaaaat?
anway.. back to work ๐
@chrome bay Do local changes trigger the callbacks?
Or do I just call them locally by hand?
yah no callbacks for local change
so I tried digging into the cpp myself but couldn't figure it out with my limited knowledge. PlayerID is a replicated property that can be found in the playerstate.
It randomly assigns a value to players that is always unique. I'm wondering if anyone knows the limit to this PlayerID ? I would like party members in my game to know who's in their party based on an array of playerid's but I want that array to be a byte and not an int.

tbh, I would not use that ID
I would use the UniqueNetId
Which is provided by whatever Subsystem you use
Which should be truly unique per Player Account
this party won't be persisting, once you log dc you're out. And we will be using steams but I'm pretty sure it's like 20 chars long
my goal is to keep the replication cost as low as I can get it
Is there any gain to marking the array dirty locally or should I put that behind auth checks?
As far as I can tell from the code, PlayerId is limited to int32 - 256 as it only starts at 256 @short arrow
int32 AGameSession::GetNextPlayerID()
{
// Start at 256, because 255 is special (means all team for some UT Emote stuff)
static int32 NextPlayerID = 256;
return NextPlayerID++;
}
Lovely to have UT stuff in UE...
so I should be able to pass the value as a byte with no issues then?
right but I can convert it, int32 - 256 means 0 - 256?
oh
that's weird
my player ID's are usually between 100 - 200
oh wait a second
mayb not kek
that's super lame
thanks for confirming it for me!
No worries
How would one properly exit a server session as a client? According to this https://forums.unrealengine.com/t/networking-how-to-properly-leave-a-session-as-a-client/346022 , just opening a local map is not enough and Destroy Session needs to be called. But In Lyra, Epic just opens local level.
Admittedly, the post is quite old, but I wanted to confirm if Destroy Session is needed or not while leaving server?
I'm not the most knowledged about this so it would be better if someone else confirms. But as far as I know if you're just travelling to a server with URL without joining a session, then it shouldn't be necessary and loading a local map should be enough. But if you join the server by joining the session then you should destroy the session as well
Join Server and Joining Session are two different things
You can join either without joining the other
But usually, one joins the Session and then the Server
That does mean that one needs to leave the Server and leave the Session
So in fact, destroying the Session is somewhat needed. Now I don't know if Epic does this in Lyra somewhere outside the Leave Game Flow (e.g. in the MainMenu GameMode or so)
Now I think the Server registers players with the session
And also unregisters them