#multiplayer
1 messages Β· Page 127 of 1
If the camera is the child of the actor it will get rotated too
You might be talking about something different
U r probably thingking of control rotation
What do you mean?
Spawn pawn, set rotation, get z rotation and apply it on the client z.control rotstion
U can look it up
Or better yet, try to change your character control rotation and see if thsts what you mean by "camera staying in place"
Oh no it's not that.
I've already gone down that road
If you actually rotate the actor there isnt anything i can think of that make the camera stay in its place if its the child of the rotated actor
Same which is why I'm here lol
I've been stuck on this prioritizing other things because of it for like a week now
I still think you are thingking of the control rotation, not soo much that the camera world transform stay unchanged
One more question, this one is not related to the asset, but as someone who knows replication well, can you provide some guidance? I started the game on two clients. The first client starts moving, and the second one follows, but the second one collides with the first as if it's a ghost. It feels like the server understands that the cars aren't moving, but the clients don't. Meanwhile, the HUD displays that it's a sports car. Question: How to replicate cars? Is there a guide or specific settings to enable for this?
My guess is that you might be using physics which is moving the mesh, but not the actor itself which also has its own collision.
So i was looking at a project from a studio. Most of their server events are set to reliable. Is this good practice?
You set things to reliable that you need to happen for gameplay purposes.
Shooting a gun? That should be reliable.
Requesting to move an item in an inventory? Reliable.
thanks i'll check it out
hmm okay
Wanting to allow a client to tell the server where to move an actor on tick? Probably shouldn't be reliable on account that you're sending updates every frame anyway.
My print strings always show client 0 only for some reason
How would I go about showing the view of one client within another client (including some HUD elements)? Can I access HUDs / Cameras of other online-clients locally?
Since what I'm trying to do is turn based, I'd like to show the view from the momentary player to everyone
You cannot.
You would have to share enough data about the players to simulate the other player's huds.
You can do this, generally, by separating out the "player" from the "hud" and using the huds as a viewer for a given player, not for the local player.
If you have logic or data stored in the huds, you're doing it wrong.
Ok thx. The data is within the PlayerState/GameState, so that should work. The cameras are accessible tho?
Define what you mean by access, I feel like you get wrong idea of multiplayer
Every machine run their own instance
And each machine have their version of the actor/ camera
I'd like to show to the local player, the camera that is connected to a remotely connected client.
You would need to send camera data to the server from the client to update its current position.
And what's the idea of "accessing the camera"? Like a screen grab? The camera is just a comp with setting and transform. The rendering is done by the renderer
Then replicate that data to the clients.
Yeah I guess what I'm trying to do is not possible that easily. I do local turnbased multiplayer ATM and I have a PlayerController and Pawn with camera for each locally connected player. When turns are over I render the corresponding view of that players camera with a CustomViewportClient class that shows that camera fullscreen.
I think I have to create some kind of Spectator Player and simulate camera movement and HUD and then show that players view on clients
Most you can do is replicate the camera transform like suggested by daekesh. That will simulate what other client sees
Yeah thx for the help
Can the players move their own cameras?
yeah
So when a player ends their turn, it shows their viewpoint fullscreen to every other player?
That sounds weird.
Yeah, but Im doing this for local multiplayer atm. So each player gets to see their cameras view fullscreen and gets the right InputMapping added when it's their turn. What I want to do in the end is mixed local/online multiplayer. So when the momentary player is not present locally, I'd like to show the view from the player that is playing on another machine.
I can send a screen recording, might be easier to understand
So here I'm adding 3 local players and then "ending their turns" which shows the view for the next player
You made is sound like online multiplayer
Local multiplayer can be viewed as single player and they run using the same instance
Yeah the thing is i want it do be mixed online/local
So when the turn is happening on a remote machine, I want to show the remotely connected players view for every machine that is present
Have u got split screen working?
yeah
here it's splitscreen but goes to shared shared screen once the match starts
thats what the custom ViewportClient does (shared screen stuff)
Most u can do is replicate the transform of the camera imo
Sending image data is not even supported by default, if your idea is to stream what you see to other clients
Ok cool, I think thats what I'm going to do. I'll add a locally connected "spectator" player that will simulate camera and have a HUD and show it in the right moments
U can only simulate it , yeah
As for the HUD, u will have to recreate it and sync with w.e the other client do
Yeah. Might be nice, since I'm thinking about doing 4v4 and then I'll be able to customize what's shown from the remotly connected players.
Thx a lot for the inputs, this helpted a lot! π
I wonder how kill replay cams or play of the game replays works in online shooters, don't they have to access remote players cams?
Not at all
Pretty sure they just rewind back time
And use previous camera transform
As for live spectator mode, that's just a matter of replicating the camera transform
I have this code. As far as I know, server does not execute rep notify and need to be called explicitly. But where should I call this rep notify? Everytime I update the value on server?
{
OnPlayerScoreUpdated.Broadcast(PlayerScore);
}
Like this?
{
PlayerScore += Value;
OnPlayerScoreUpdated.Broadcast(PlayerScore);
}```
Or should I call
{
PlayerScore += Value;
OnRep_PlayerScoreUpdated(PlayerScore);
}```
either
Yep. If you want something to happen when the value changes on the server, you'd have to call it.
Ok, thanks β€οΈ
whether you call the OnRep directly or not is really just up to you
I've only worked with replication in BP only and there the RepNotify is called automatically after the value changes, that's not the case in c++?
if you're doing more than a simple broadcast in it then calling it directly might be better so you don't have to repeat the logic. But for this? Really doesn't matter.
RepNotify is only called on clients.
Yep, that's right
It's called on listen server as well in BP
Yes, that's a BP-only thing.
in a dedicated server setup when I run a Print String on a keyboard event, regardless of which client I use to press the input event, the Print String always says "Client 0". Is this because it's executing on the client and the client, having no awareness of the server on this input event, thinks it's Client 0?
Are you testing this in the Editor?
Yeah
In theory it should print Client X with X being the Client Number in the Editor
yeah it's worrying me
I want to see a Client 0 and a Client 1 but they both think they're Client 0
I'm running 2 clients in a Play in Editor new window
I get the reference to self then print the display name here, and you see the display names are different instances of the character blueprint but the print string says Client 0 for both
BP0 and BP_C_0 are the display names... which is interesting
got 6 instances going, as expected
okay yeah it's what I thought. Each client in this setup thinks it's client 0
Anyone have any good papers/blogs/resources talking about projectile prediction & hit detection.
I've read plenty for hit-scan and while some of them gloss over projectiles, few go into good detail.
Doing a lot of work with trying to get it to feel good for proxy clients, particularly the ones who might be getting visually hit.
How would you tackle the problem of random? π€
I don't need an already made implementation, but some logic thinking π€π€
To put it somewhat simple, what if I want my character to have a critical hit chance. The random and critical hit are authoritative, but is there a way to "predict" the random crit? π€
With seeds
A seed at the beginning of the universe and hope to keep it in sync? If you desync the server sends you the seed and how many numbers were generated so far?
π€
Just something deterministic
You mean that in server Auth you don't even try to predict the crit?
Believe it or not, that's enough justification for me π
I will do my thing with the fstreamrandom thingy and if one day I need a better random I'll get some cpp implementation and cry about it
It will.be great π
I'd hate seeing a predictive crit be wrong tho
Should I grab a cpp generator to begin with? π
On tf2 happens all the time π
Seems i dodged another bullet then π

I dislike dealing with multiplayer now
Did you set your tolerance value for hits? Or are you keeping the shooter game default of 200 meters?
π
Try local+online
With midjoins
Both local and online
im just trying to do lazy predicted timers
like, not even trying to actually predict anything
just starting local timers
but then my setup doesnt work when it's not dedicated server
ugh.
bad setup, i know i know
See, the secret to making multiplayer enjoyable, is to just do co-op games and don't care if people cheat
That's probably it
we had a grandiouse plan of unique id's and whatnot but wth
if ppl wanna cheat, we'll just let 'em
wont lose any sleep over it
That makes it waaaaay simpler
has any 1 touched iris? how drastic are the changes to code to make it work? does any 1 have any examples?
I believe Kaos* has posted some about it
...and it's troubles
#cpp message Around here there's some talk about it
just search for it in the logs
I wouldn't bother with Iris unless you're already pretty experienced. Wait until it's actually stable or at bare minimum, usable to the commoner.
Why do my print strings only show client 0?
Hi, i have a replicated actor with a beacon client actor as net owner, but my server rpc is not triggered, any idea what did i miss or how to debug this ? I don't have anything in the logs
Hey
In a replicated actor,
I set a Rep Notify on a struct TileUpdate and it is correctly updated on the client and on the server
However, my gridTiles array with Set array elem does not change the first value in my array on the client but only on the Server. Do you have any idea why?
Are you setting it on the server?
yeah
Tile Update is correctly updated on the client and the server
But it does not update the same way for grid tiles (only on server)
Who's setting (or adding) to "Grid Tiles"?
When actor is spawned, at begin play, it fills the GridTiles array
The spawn function is called from the GameState
Only server can replicate to clients, so can I assume this is server only code?
Yes, it is
depending on what GridTiles includes of variables , number of elements etc, it could take a while to replicate it
especially if it needs to resolve some hard refs along the way
My purpose is to change one value at specific index 
Ok, so, I cannot replicate an array? (with 250~ elem) then updating a value at specific
You can, it's just hard to say how long it would take
250 elements isnt a scary number, but it depends on what the struct contains aswell
how do you know it's not being replicated ?
I am verifying like this
Then I am checking the value on server and on client
I can see on server, the value changed but not on client
and this is what my struct contains:
The value that I need to update is the tile type (Enum)
Hi, I'm trying to use replication, but I'm having a build error that says it doesn't find the replication function
I have declared the variables and functions as per the first image.
The error is in the second image.
Any ideas what could be wrong?
I tried searching for something on google, but couldn't find something useful.
missing UFUNCTION specifier
Oh my god, thank you, you are right!
Really appreciated!
@hoary spear Thank you for your time, I added a delay just for testing purpose and now it is correctly replicated
I have to think about an another way to change/update my value and working with array
Does anyone know cuz i cant find out
i was just asking out of curiosity nothing more
I just replicate a boolean which starts the ragdoll stuff client side. That way I don't have to send over all the position data for the bones. Have you setup the physics asset for your skeletal mesh already?
After you set that up you can just replicate a boolean and have it call some event with repnotify like this.
There's no need to run anything on tick like how you've got it.
I'm using the third person template. In the character blueprint I can increment an integer variable and then print it as a string. The variable is set to replicate. If the server increments the integer, the client doesn't see the change. If I set it to RepNotify, the client still doesn't see it, but if I make an OnRep function it can print the integer. π€·ββοΈ
They're separate characters, so they shouldn't(?) share the same variable, but then I don't understand why the client is able to print the server's variable in an OnRep function.
The OnRep fires because the replicated value was received by the client.
You should be something printing like:
Client: <number>
Server: <number>
This indicates that the server's copy of the character's integer was set, the server prints the OnRep, and when the client receives the replicated variable it prints the value as well.
Hi, Can someone confirm that if i have a Client (AOnlineBeaconClient) and a Player actor with Player->SetOwner(Client); i should be able to use RPC from the Player class ?
Mhh seems i have 2 differents netconnection, i guess that's why it's not working
I'm not sure what multithreading has to do with network simulation.
I mean, sure?
Race conditions aren't specific to multithreading
You can have a race condition caused by networking, it's a very easy problem to run into. It just doesn't have anything to do with threading.
attempting to modify data in two separate operations that have the possibility of that same data being modified between them
My inventories are server authoritative to avoid that kinda situation
which is the bog standard cause of most race conditions
being server-authoritative doesn't avoid it
It's not gonna be mt, and if your server validates data (and rejects the bad second command) it'll work
That's still not a solution to race conditions.
Race conditions can be "valid" as far as the server is concerned but can result in incorrect behavior or unexpected results on clients.
I mean it kinda doesn't matter in most cases, like if a client clicks "too late" or whatever and it doesn't work, and updates shortly after it's fine
The most important thing to keep in mind is that you need to handle essentially any order of packets
Client asks to move item A from slot 1 to slot 2.
Server, at the same time, tries to swap item B from slot 3 to slot 1. Server executes before client.
Result is that item A is not in slot 2, it's in slot 3. And Item B is now in slot 2.
This is technically correct by the rules of the system. The programming error is referring to slots rather than items, but it is still not solved by being server authoritative.
The ideal result here is the client's move being rejected outright or item A moving to slot 2.
But not having the ideal result is still fully server-authoritative.
Yeah I think both are reasonable
But don't end up with deleted items on server
Which is the original probelm
Replace what I said with "delete item in slot 1" and you have the same issue
Like both those cases are fine results for bad network conditions/etc
My point is race conditions aren't solved by being server authoritative.
They're solved by protecting against race conditions.
He's talking about an item being permanently deleted from swaps, which won't happen if server validates
We have no clue how the inventory mentioned works.
Hahah
If only
again: "server validates" is not a solution. What does validate mean? What data is being validated? Does the client send enough data for the server to know that the operation its performing is the one the client requested?
I can say I've shipped more than one title, and I haven't had any deletion issues
Anyway, hard to help without more info about whatever this operation is
What data is being sent from client to server
What other operations could potentially happen at the same time
all stuff that needs to be thought through
If you are, like in my example, sending slot numbers rather than referring to specific instances of items then that'd be the first thing to fix - that's fraught with problems.
Here are some options:
Send slot indexes to swap. Server does it if it's valid, done and done. Sometimes clients will get unexpected results if other people are also messing with inventory, but you'll never have an item get overwritten or deleted.
Option 2: client sends slots + items, and if they don't match, it doesn't do the operation. It means sometimes things don't happen for the client, but again, no bad state on the server
Though I have no idea if you are.
Most important is that you don't dupe or delete items on server
Everything else is just client state that should be corrected shortly
Yeah I'm telling you I've shipped full ass multiplayer games lol
You don't need like mutexes and locks for an inventory
Or... don't send slot numbers as the target of an operation.
But this is the Internet and you can make your own mind up
The race condition that results from the server swapping items at the same time as a client is something that gets solved eventually by replication, but it's also a completely avoidable problem in the first place.
And without being any more complex.
Regardless, still not any new information to go on.
No, I don't know your situation.
You haven't given enough details on how your inventory works.
And even in this hypothetical "eventually" is within a second or so.
Yeah - it really does depend on how you're handling it
It doesn't just happen unfortunately
I usually use fast array rep, or in prototype cases just onrep some lightweight version of the data, so I'll get updates from the server when it changes
If you're relying on purely rpcs or something else it'll be much trickier
lol ok, night.
@cedric_exi
How accurate are the network emulation settings? I implemented a circular ping buffer and see anywhere from 20-30ms ping above what I would expect. Is that just induced added time of getting the network in/out of unreal on each end?
well actually it's interesting... only when the windows have focus is ping way up 
iirc, there is also frames counting into that :P
Yeah I can believe that, I guess it's on the game thread so it has to get down to that point, but the difference seems pretty high... now that I see the ping dropping to reasonably close levels when I don't have focus on the window, I'm suspicous
I think it's reasonably accurate
I implemented a more precise net clock for a MOBA last year and tested it for Cooldown stuff with NetEmulation Ping and it reported the same numbers.
Same numbers as in, setting the in/out time to 25 25 on each end you'd see 50ish on the ping?
Yeah, sort of. It's the time 2 RPCs take from Client to Server and back.
Yeah makes sense, just regular unreliable RCP, nothing fancy besides that?
Pretty sure they were reliable. We don't sync that every frame
fair
Right now I'm doing every 1 second and just waiting for the time to come back on the client but seeing weird things, gonna look into it more
ty
Honestly I'm going to chalk it up to the editor being weird when changing the emulation settings. I thought it might be that I was updating the control rotation (player looks towards the mouse) every frame, but I see expected numbers now that I rebooted the editor (within 10ms)
although now it's shooting back up again lol so who knows
Why does this return true on ai controlled pawns?
it says controlled by a HUMAN player. Since when is an AI a human player? xD
Nevermind! Was reading the wrong ref
Is it better to replicate chaos vehicle movement via transform or just replicate movement?
transform should be cheaper?
That's literally what replicate movement does
Then i don't understand why a studio replicated transform instead and has movement disabled
hey Question
if i wanna play a montage and on the notify begin
since i dont wanna RPC everything after how can i get a "Return" from the notify begin
this is the way im doing it now but there must be a better way ?
put the montage and sound in a repnotify, should work
I don't fully understand what's the problem with your current approach?
I would also like to know why my multicast is not working when set to reliable
You have only 1 event for the RPC. The "continue body slam" you could remove and put the logic in the same place as playing the sound. So you basically have only 1 event. How is that many unneccessary events?
If what you mean is that you only want to call "Continue Body Slam" while running on the server, you should just be able to use a Has Authority node and continue from the Authority path.
hmm thats acctualy a good point
Multicasting reliably is costly, and if you can avoid doing it, it's usually best if you can, so a couple potential reasons:
- Too much data attempting to be sent through the multicast.
- Attempting to send the multicast too frequently (ie. On Tick)
I think, like the only reliable multicasts I do are level events (like, ending the match) and game wide messages.
I believe something like ending the match needs to be run on the server through the game mode. It should automatically happen client side
I don't think you want to abruptly move your clients outside of the current map.
That'd be an awful experience
Idk why but I read that match as ending a round lol. I'm an idiot ignore me.
So all gameplay related server events should be reliable and most if not all multicasts unreliable?
It dependsβ’οΈ
Use reliable if it absolutely has to be received, unreliable if it doesn't matter.
What is required or not is game dependent
If i see actions happening on different clients like they are supposed to can i assume they are replicated properly? Idk if i'm using print strings properly
Yeah, as an example, if your game requires your player to say, hear a sound playing in order to know they can move and would die otherwise, you probably want to reliably multicast it. If it's just some background noise, it can still be a multicast but it doesn't need to be reliable.
"Replicated Properly" can't really be answered without context of what exactly it is you're replicating and for what purpose.
If you are sending a multicast and that multicast prints the "Hello" string, you should see something along the lines of:
Client 2: Hello
Client 1: Hello
Server: Hello
The print strings don't make sense at all. Playing on client 1 & 2 but it shows 0 on both screens
I see actions happening properly on both clients
I'm trying to figure out how to communicate between server and clients. I'd like to broadcast event's when certain things change on the server and have clients add functions to these events.
What I'm thinking about doing is declaing a multicast deleagte within GameState and broadcast that event from within GameMode. The clients then add functions to the delegate. Is this a good idea?
I'm not sure what you're trying to do.
If you're talking about the client broadcasting a delegate inside of an OnRep, that is fine.
Or if a mutlicast/client RPC just triggers a delegate broadcasting, that is fine as well.
GameMode only exists on the server though. So client's won't even have that.
I have GameMode triggering certain evetns. I'd like to react to those on clients that subscribe to these events. That's why my thought was to do this on GameState since its replicated on clients
They can't. They're entirely different computers. You have to use an RPC
On the receiving side of the RPC, you can trigger the delegate, sure.
But wouldn't GameState exist on the client machines too?
Yes.
But the way you're saying what you want to do is coming off as saying that you want the client to connect to a delegate on the server. Which just is not possible.
I'd like the clients to connect to a delegate on GameState, but the delegate.broadcast() would be done on GameMode
So use the GameState to RPC to the clients, then in that method, execute the delegate
I still lack mulitplayer knowledge π
Maybe I have to do one more round of research π
This won't work, unless the delegate.broadcast() also has the GameState fire off an RPC and then in the RPC method it broadcasts a delegate.
They are entirely different computers
Ok thx, yeah then I'll do some more reading first
Server: Broadcasts Delegate on GameMode
Clients: Cannot "Get" game mode to subscribe to the delegate being called.
Server: GameMode calls a Delegate on GameState
Clients: Receive nothing as they don't know that there was any broadcast as it wasn't communicated to them VIA RPC that it should happen.
Server: Calls a multicast RPC on the GameState
Clients: Receive the multicast RPC notification, they can react to that multicast call however you want. If they bound to a delegate on the gamestate the multicast could call it here for each client to then respond to.
Cool thx a lot. Then option 3 is what I want. I'll do some research π
Working through some basic multiplayer stuff to get a grasp on it. I made this simple blueprint.
I basically have a barrel that after 5 seconds will fire an impulse from a Radial Force Component, and I have a few boxes that react with physics that will be knocked away.
What's happening is everything seems to be replicating properly, except the boxes reacting on the client. Meaning the boxes get knocked away on the server but not the client.
What could I be missing?
(red is server executed, blue is client)
(When setting lifespan, you dont need to destroy )
Oh really? It'll just automatically destroy when the lifespan is up?
okay cool thanks for that, that's good to know
Woah that was actually the problem! I guess it was getting destroyed before the client had a chance to apply physics
I'd never imagine destroying the actor after an RPC was 'queued' would somehow stop it from executing
then again, i've never had that scenario (yet)
Hm.. yeah and actually now that I think about it, it wouldn't be a timing issue either because I was destroying after 2 seconds anyway. I wonder why calling destroy breaks it..
Ohh right right heh yeah of course
I'm just setting the lifespan
and then destroying
^^ exactly
I also think your "Explode" event could be directly replicated
and SetLifeSpan would just be set right after Set Timer by Event
Hmm how do you mean "directly replicated"? I guess my understanding was this is how you replicate events. You trigger them on the server and then multicast them to clients. What's the more direct way?
That is correct,you trigger them from the server,
and the server in this case is starting the timer
and is also firing the bound event (Explode)
thus, if Explode were set to multicast, it would just be the server calling a multicast
ohh I see, so there's some way to make an event itself multicast? When I select the event these are the only details I see:
I don't see any reason that wouldn't work. Does the radial force component exist clientside? Crank its numbers up
Also try just applying impulse to things directly, see what that does
you must disconnect the binding first
kinda feels like a bug to me π
weird.. why don't I see that? hmmm sec
disconnect the binding
the red wire
then re-select the node
ohhhh got it
ah neat! Is there performance benefits to that? Or just makes the blueprint easier to follow?
no performance gain to talk about
less nodes is less nodes π
so readability yeah
haha fair enough π
Okay so is this supposed to be correct?
looks about right to me atleast
well
except
Lifespan must be > Timer
so 2 is not enough π
5 is probably π
or 6
6 would be equal to what you had
that's what's confusing to me, because it looks functionally the same as the last one, but SetLifeSpan appears to be called "more immediately"
guess that's a drawback of doing it this way
ahh okay, so when is it called in the first one?
Yeah, because lifespan is set at the same time as the timer starts, instead of after the timer has executed it's delegate
After Timer has elapsed
ohhh got it got it, that makes sense
okay. Well I copy pasted to make my change anyway. this blueprint is supposed to be an example for me later so its good that I can demonstrate both ways of doing it. Thanks π
You should also take notes about how to do this statefully
Like for a door that opened
RPC's only fire on clients that are currently within relevancy range
so if someone was outside this range, and stepped inside, the door would not be in the actual state that it should be
Yeah, I have an example of that but its using C++ to replicate an bIsOpen property on a treasure chest I have, and then when it changes I fire an RPC to set the door hinge at the right place
is that kinda what you mean?
ah yeah you're right, I'm looking at my diff, my RPC was for an interaction component
perfecto
there's a diff in c++ and bp OnRep tho
apparently OnRep for bp's fire on server aswell π
which doesnt happen in c++
Heh yeah, found that out the hard way too :p
same .. annoying π
haha well cool, thanks for the help! I'm sure I'll have more questions but I think I'm good for now π
No worries, forge ahead!
Anyone happen to know why OnActorHit is called properly on the owning client and AutonomousProxy but not on any of the simulated proxies?
I would think a simulated proxy hits things and triggers as well. I'm trying to play a montage when the actor hits, and it works for everyone except the simulated proxy. Wondering why the simulated proxy isn't triggering that same event
This is happening from a Gameplay Ability as well
void UCombatComponent::EquipWeapon(AWeapon* WeaponToEquip)
{
if (Character == nullptr || WeaponToEquip == nullptr) return;
EquippedWeapon = WeaponToEquip;
EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped);
const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket"));
if (HandSocket)
{
HandSocket->AttachActor(EquippedWeapon, Character->GetMesh());
}
EquippedWeapon->SetOwner(Character);
Character->GetCharacterMovement()->bOrientRotationToMovement = false;
Character->bUseControllerRotationYaw = true;
}
void UCombatComponent::OnRep_EquippedWeapon()
{
if (EquippedWeapon && Character)
{
Character->GetCharacterMovement()->bOrientRotationToMovement = false;
Character->bUseControllerRotationYaw = true;
}
}```
Why are the two expressions in the OnRep function only executed on the player that has equipped the weapon. I thought that OnRep was executed on all clients, meaning if one player equips a weapon (the server for example), then the clients (who may not have eqipped a weapon) will also execute ```Character->GetCharacterMovement()->bOrientRotationToMovement = false;
Character->bUseControllerRotationYaw = true;```
OnRep is executed on all clients, but it's triggered on the single actor.
So you have:
Client1 in control of Character1
Client2 in control of Character2
If you call EquipWeapon on Character1, then the OnRep will be called on Character1 for both Client1 and Client2, so they both should see that value getting changed and will execute what is needed on Character1.
Ahh thankyou for you response @sinful tree! Can I ask why the code from the onRep function is repeated in equip weapon? If the character rotation method is set from the server, why do we also need to set it locally once equipped weapon has been replicated?
It's not necessarily a value that is replicated automatically.
ie. Doing it on the server, then doing it again on clients could be required in order to have the desired result.
It's a little bit extraneous as there's no failure condition, so once it's done once, it'll always be like that anyway, so it's a bit strange.
Hi
If this is working from a "Player" actor :
Cast<ANVBeacon>(GetOwner())->ServerRPC();
I should also be able to call RPC from this "Player" actor right ?
Not necessarily. If the player actor isn't replicated, then they wouldn't be able to RPC to the server. It can still have a valid owner which could be a replicated actor which is owned correctly to allow the RPC.
Otherwise, yes.
bReplicates = true;
bAlwaysRelevant = true;
NetDriverName = NAME_BeaconNetDriver;
So it should work with this
My server RPC (from the player actor) is not called but i can't find the problem then
Hi, I am trying to modify the first person template to basically have the gun pickup available to both players and then they can shoot each other with it this is working for server but not for client , the client seems to be teleported upon firing not sure why though please? π
Greetings guys!
I am encountering weird replication issues where my component wouldn't replicate a property for some reason. I am sure i just missed something obvious, but i honestly can't spot it after about an hour or so. Here is a code snippet of what I am doing:
.h
class UTestingReplication : public UActorComponent
{
GENERATED_BODY()
public:
UTestingReplication();
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
void BeginPlay() override;
private:
UPROPERTY(Replicated)
TObjectPtr<AActor> HelpMe = nullptr;
};
.cpp
UTestingReplication::UTestingReplication()
: Super()
{
PrimaryComponentTick.bCanEverTick = true;
SetIsReplicatedByDefault(true);
}
void UTestingReplication::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ThisClass, HelpMe);
}
void UTestingReplication::BeginPlay()
{
Super::BeginPlay();
if (GetOwner()->HasAuthority())
{
FActorSpawnParameters ActorSpawnParameters;
ActorSpawnParameters.Owner = GetOwner();
ActorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
const FTransform SpawnTransform = GetOwner()->GetActorTransform();
HelpMe = GetWorld()->SpawnActor(
AActor::StaticClass(),
&SpawnTransform,
HoverboardActorSpawnParameters);
}
}
Would anyoine be able to spot what i am missing?
Thanks
The Autonomous Proxy never receives the replicated value of the UPROPERTY
Well you are just spawning an empty AActor???
Thats not going to Replicate
Because Replication isnt enabled by defualt on AActor
Why are you spawning an empty AActor?
no i am not lol
You are
just stripped down
AActor::StaticClass(),
no what i am saying, this is not the actual code from the project
π€¦ββοΈ
anyway, you are right, i don't think i am setting the actor to replicate
When asking for help, always post the EXACT code...
nda bound
Then just redact it, dont put something in its place that would cause extra confusion
got there at the end, thanks!
is this a correct mental model of how the replay system works?
As in the replay system should simulate incoming RPCs?
I'd have thought the replay system would simulate regular replication, not rpcs.
Well that's alarming π
Replays do record multicast RPCs
You can override the replay (spectator?) player controller if you want to record RPCs sent to it into the demo. iirc ShooterGame did that
The replay system wouldn't send RPCs back to the server though @unkempt tiger
Ah. I thought he meant it would somehow work exclusively on rpcs.
Hi, I'm trying to use Lyra to make a multiplayer PvP game. Preferably build on top of it, edit the default blueprint to replace Lyra with own BP, change a few game modes etc.
Any suggestions/guidance on where to look and where to start?
You need some way to uniquely identify a specific item. In Lyra that'd be the item instance, in some other system it could be an id of some sort. The important thing is that the id is both unique (for the current inventory at least) and unchanging - that way when the client says "do X to Y" the server knows exactly what it is the client wants to do.
Right now you're open to a bunch of different race conditions because if a client says "move item in slot A to slot B" the item the client thinks its moving may already be elsewhere by the time the server gets the command, and the server won't know that the operation it is about to do is the wrong one.
A guid would certainly meet that criteria
so you could say "move <insert guid here> to slot A"
the guid uniquely identifies an item to move, and the slot uniquely identifies a destination. There's no chance of a race condition unless your behavior depends on slot A not having an item in it already.
The solution to which depends on what you want to happen - you could simply reject that action, you could swap the item slots, or something else.
Sure, but you still have a single slot that it "starts" in, yeah?
So there isn't really an issue with what i suggested then
Not really. You have some complications around making sure there's room for the item or w/e but you have that regardless.
You do have a choice of what to do when the server finds something in the way, though. You could reject the move, you could swap item positions (which could still result in rejecting it if the swap isn't possible), or whatever else.
Something you will need to deal with is re-marking the item as dirty even if the server rejected the move.
Assuming you've predicted the movement on the client I mean
If you don't predict anything then there isn't really a problem here. If you do then you need to mark things dirty even when the server hasn't done anything because the server needs to re-send the existing data to correct the client's prediction.
Let's say the client moves item A to slot 2 and the server rejects this.
The client now has item A in slot 2 because it mispredicted the movement. The server isn't going to correct this because as far as it's concerned nothing has changed.
Since you're using a fast array serializer the fix is easy - simply mark both slots as dirty even though nothing moved as it will have the server re-send those items.
correct
just something to keep in mind for the future
something else to keep in mind is that the order of fast array items isn't guaranteed across the network. If you need to maintain a consistent order then items need to store their own index into the inventory.
one of the guarantees fast array replication gives up is ordering unfortunately
If you have to change the index property on everything after you delete or change item orders, are you really saving anytihng with a fast array serializer?
Well, some of the time, I guess.
yes, because swapping two items only marks those two items dirty
you don't have to re-index everything
you also don't have to physically move the structs. You just set their new index values.
I'm saying if he wants to maintain an inventory order.
given that what was mentioned was an inventory that represents actual space, that's not an issue
i.e. you can have gaps in the indices
so inserting an item in between other items doesn't involve re-indexing everything
But he's also literally just complained about it not maintaining order π
probably because there were actual gaps in the array serializer
that sounds like whatever operation you're doing is just wrong then
though you'll still need to fix everything mentioned
Is UE's OnRep_ supposed to automatically handle not calling itself on the same client if the property value is still the same, to prevent the "double spawning" problem?
yes, that's why REPNOTIFY is a thing
hm. Okay.. mine's not doing that, and I'm getting double spawns on my client. sec lemme just verify that I'm not crazy
(sigh) nvm its not getting called. The double spawn is somewhere else
ctrl+shift+f "NULL object, place a breakpoint, see what's calling it
The double spawning only happens if I set bReplicates = true in my projectile base. What's a good way to figure out what's calling the constructor of my projectile twice on my client?
err, that sounds like you're spawning a replicated projectile on the server and separately spawning it on the client
well this is the code that spawns it. StartAction is 1:1 with that projectile spawning.
bool UARLActionComponent::StartActionByName(AActor* InstigatorActor, FName ActionName)
{
...
if (Action && IsValid(*Action) && (*Action)->CanStart(InstigatorActor))
{
if (!GetOwner()->HasAuthority())
{
ServerStartAction(InstigatorActor, ActionName);
}
(*Action)->StartAction(InstigatorActor);
return true;
}
}
So if I'm the client, then I just call ServerStartAction, and then I call StartAction locally immediately to spawn my projectile. Calling that sets bIsRunning = true; on the action, which is replicated.
void UARLAction::OnRep_IsRunning()
{
if (bIsRunning)
{
StartAction(nullptr);
}
else
{
StopAction(nullptr);
}
}
But OnRep shouldn't be called because bIsRunning should be true on the client already
err, no
you spawn the projectile on the client, sure. That projectile is not replicated because clients can't spawn replicated actors.
The server then runs ServerStartAction which I assume also ends up with a projectile spawning, but this one will actually get replicated
so now you have two projectiles, one spawned by the client and one spawned by the server. But the server's is replicated so the client sees both.
yeah the server one is just
void UARLActionComponent::ServerStartAction_Implementation(AActor* InstigatorActor, FName ActionName)
{
StartActionByName(InstigatorActor, ActionName);
}
in the end you're running the spawn code twice. Once on the server, once on the client.
The OnRep isn't running twice.
ohhh.. The server will call (*Action)->StartAction(InstigatorActor); which will spawn it for the server and also replicate it for the client
yes
okay.. yeah that's bad. What's best practice to handle that? I do need it to replicate because there could be multiple clients
but I need it not to replicate on the.. original client
instigating client?
you do though, because the server may correct the position
one solution to this is to have the client send an id it generates with the request to spawn a projectile. It stores the id on the locally predicted projectile, and the server uses the same id when spawning its own projectile
when the client receives the server's version of the projectile, it searches for its local version with the same id and deletes it, letting the server's projectile take over
to make things even more lag resistant you can have the client interpolate the server's projectile between the position the old predicted projectile is in to the server authoritative position over a short period. UProjectileMovementComponent does have some tools for doing this but there's little to no documentation on it.
to be clear, the projectile movement component has utilities for interpolation/smooth movement. It doesn't help with prediction ids - that's up to you.
okay, yeah conceptually that sounds reasonable. I'm gonna try and implement that first part and iterate on it with interpolation next. First I have a couple questions
"have the client send an id it generates with the request to spawn a projectile".
What would an implementation of this look like? (not looking for actual code just conceptually I'm a bit lost on the mechanics). For example, where would I store that ID? Would I need a list of "in-flight" projectiles? Currently I don't have any stateful objects that represent a "server" or "client", I'm just checking with HasAuthority, do I need to move away from that?
"when the client receives the server's version of the projectile"
What do I hook into to "receive the server's version of the projectile"? Is there some sort of replication overload I can use? Or I guess at what point can I do that check?
What would an implementation of this look like?
you could have a subsystem that stores the list of client-created projectiles and the ids. The id can be a simple number that increments every time a new predicted projectile spawns, it doesn't have to be unique across the whole game - only unique to that specific client.
What do I hook into to "receive the server's version of the projectile"?
BeginPlay of a projectile. If the owner of the projectile is the local client and you don't have authority then you check for a locally predicted version of the same projectile.
so... log them? Not sure what the question is there.
Ahhh okay, yeah BeginPlay makes sense, that's easy enough.
What do you mean by subsystem? Who should own it? Would it just be.. let's see there's exactly 1 GameState object that's replicated but then I'd have to be able to lookup assoicated clients... PlayerController is 1:1 with a client, would I put it there?
ohhh nice! awesome I'll check that out, thanks a lot!
It says its lifetime is tied to its parent, so if I want it to exist as long as the client exists, would it be LocalPlayer or GameInstance?
this would make sense as a world subsystem
projectiles aren't going to last past the lifetime of a world after all
Okay.. how many instances of the UWorld are there? Would there be one per client?
yes
hi
on aws gamelift how to set the session keep active for 20 minutes aftern then its terminted
any blueprint are there ?
// In ARLActionComponent
StartActionByName(Name)
static int64 Id = 0;
if not FindAction
return
if HasAuthority
ServerStartAction(..., Id++)
StartAction(..., Id)
// In class UARLAction_ProjectileAttack : UARLAction
StartAction_Implementation(..., Id)
WSS = SomewhereGlobal->GetWorldSubsystem()
Projectile = CreateProjectile(Id)
WSS->TrackProjectile(Id, Projectile)
// In AARLMagicProjectile
BeginPlay()
WSS = GetWorldSubSystem()
if (AARLMagicProjectile* Projectile = WSS->FindProjectileById(Id))
Projectile->Destroy()
Am I grasping the general idea?
yes but Id++ here is incorrect
you're passing an Id, then incrementing it. Which means the subsequent StartAction is using the next id.
Ah yeah you're right. I want to increment it with the conceptual "request". So the batch of client/server StartAction, I'll fix that.
BTW is PlayerState an okay place to own the world subsystem?
Ah okay. I think I don't know enough about subsystems. I love benui but his subsystem page is basically a dictionary definition haha. I'll find docs for it
I get the impression that you're asking for where to create the subsystem. The answer is you don't, subsystems are created automatically by the thing that owns it.
And the world owns world subsystems. They are created automatically and you don't do anything to manage them.
With the slight exception that you'll want to override the DoesSupportWorldType function on your subsystem so that it only gets created in PIE and Game worlds, for some asinine reason it defaults to also being created in editor viewports if you don't.
Okay so you create a subsystem class that inherits UWorldSubsystem and has the API for adding/removing, and the (I'm guesing TArray) container. How does your derived world subsystem get created though?
automatically
subsystems are created automatically by the thing that owns it.
you don't do anything
the thing that owns the subsystem automatically pulls the list of all subsystems of the type it cares about and creates instances of them
it just.. looks through my project for anything that derives from UWorldSubsystem?
wow. that's pretty neat! How granular do you typically make them? I'm guessing they're not too expensive. Would.. "ProjectileTrackerWorldSubsystem" be too granular? Or would you have a broader "state tracker world subsystem" or something
that's really up to you
okay, cool
Wait so if there is the subsystem class exist somewhere, it would be auto created without any link? That sound like magical stuff
and then I think last question i have is, how should I store the Projectile and ID pair? If this were std c++ I'd just store std::vector<std::pair<Projectile*, Id>>, but I'm wondering if that's safe with Unreal's objects. Like.. I guess can I store a AActor* that points to the Actor* that SpawnActorreturns? Or do I need to do something special
UPROPERTY(Transient)
TMap<int32, AMyProjectile*> IdToProjectileMap;
Okay. Yeah I thought about using map but.. it'll be such a small list vector is usually faster anyway. something something cache invalidation
wait what's that Transient flag?
just means that the property won't be saved into anything (like a blueprint or anything else using reflection to serialize data). It's not strictly necessary because nothing should be trying to serialize a subsystem, just a good habit to be in.
Got it, good to know. Thanks again!
btw, is this only a problem because this particular action spawns a game object that has replication? I'm thinking of instead of sending an ID into my StartActionByName, having my ActionBase class have a bRequiresPrediction property. Then if that's set, instead of calling StartAction(Instigator) it'll call StartActionPredictive(Instigator, ID). This way its more explicit as to who has to care about managing these IDs and stuff
Hi, is it possible to get the previous value after a repnotify call ?
In C++ you can, Blueprint you cant I dont believe.
How ? (i'm in c++)
Oh !
For example
Thanks ! π
Unreal auto fills the first param matching the var type thats replicated
I see, never saw that yet, very useful ! :p
Keep in mind, if you are calling the OnRep for the Server, you will have to then manually pass in the old value
Yep, thank you !
When considering RCP vs Prop Replication, is one typically faster to update than the other, assuming no packet loss / etc?
(Update on the receiving clients)
Depends
Mostly on the amount of data
But you should not be choosing one over the other based on some preconcieved notion of "speed".
Yeah I guess that makes sense
I'm struggling to predict projectiles and make them feel good for both clients so my brain is going in weird places π«
Generally the idea with predicting projectiles goes something like this.
Client spawns a "Fake" version locally, while sending a request to the Server that it needs to spawn a replicated version.
When the replicated version from the Server comes down.
It replaces the "fake" one on the Client.
This way the Client has immediate feedback (predicted projectile), while also allowing for maintaining Server authority (the replicated projectile)
So I had that working pretty well and turned that off for now, I guess my main problem is making it "feel" ok for the client potentially getting hit
What do you mean?
Sometimes the projectile visually doesn't hit me, so figuring out a system where I can fix/fake that
Actually, I have an image
You may need to advance the Servers projectile based on the ping of the Client that created it
hmm that's a good idea I haven't tried yet
I played around with advancing the projectile based on the local client difference
Its an old implementation, but the bones are there.
π
I'm new to unreal and was feeling fairly confident until I started working on predictive netcode
but it's fun to have actual hardish problems to solve
Are you new to game dev/multiplayer gameplay programming?
yeah
Generally the advice is to start on something simpler than something like predicted multiplayer projectiles
Yeah I can start to see why
Until you get grasp of most of the tools available to you
I read a bunch about common hit-scan implementations and it seems a lot more straightforward
Well yeah, hitscan simplifies a lot lol
I think the visual feedback of projectiles makes it difficult for me
I kinda had an idea to use predictive roll-back on the client to tell a "point of no return" where I have high confidence a projectile would hit me and there wasn't anything I can do about it, then I'd be able to fake it a little bit
so I mostly implemented that, but still it didn't line up as well as I would have hoped
Just make sure you arent trying to bite off more than you can chew at this early stage.
Yeah it's something to consider
I think I've learned a lot so far, might try to make a melee system which I think would be a lot easier
π
Hello,
Any suggestions on how to replicate an Instanced static mesh that'll contain a couple hundred trees?
Should I for example periodically update an array of Instances and their transforms which is set as RepNotify?
Probably because you are doing it too early
I would start with using a FastArraySerializer and that holding info about each instance
You can then alter the actual ISMC with the callbacks that this thing provides
I see, thanks Cedric π
I mean, possessed is server only
If you have a ListenServer, then that's fine
OnRep is theoretically also fine. Can you break point it to see if the PlayerState is actually valid?
Although
It would crash if not
i use listen server
Are you setting the Owning Player properly on the Wiget itself?
what do you mean by setting?
i just do this
in the character BP
And what calls that?
So I should use its callbacks and not a RepNotify?
My general suggestion for UI that relies on Pawn and PlayerState is:
- Create Delegates in your C++ PlayerController for when the Pawn and the PlayerState become valid/invalid
- Call those in Possessed and OnRep_Pawn/OnRep_PlayerState
- Create a C++ UUserWidget that acts as the base for widgets that rely on those two or any of the two
- Ensure you add those Widgets inside the PlayerController and set the "OwningPlayer" of the CreateWidget node to "this/self" and then bind in the C++ Parent to the Callbacks
- Expose some BPImplementableEvents for when Pawn and PlayerState changes so you can use them in your Widgets
That doesn't work, BeginPlay is too early
Your Client won't have the replicated PlayerState at that point if they just joined
You either have to do what I wrote above, or ensure you create the Widget when the Player has all required info
Also craeting it like this will create it once for every character on every player
So if that's an actual UI Widget, you will have that x times for x Characters, overlaying
You need to ensure you only add it for the local player
Which is again better done in the PlayerController
If you do the list I wrote, you can add the widget in the BeginPlay of the PlayerController, with an IsLocalPlayerController check in front
Okay, i got it, bind a delegate so it can wait till the right time
Yeah you want to additionally call the BPImplementableEvents once when binding
In case the values are already valid
void UPlayerWidget::NativeConstruct()
{
Super::NativeConstruct();
ASomePlayerController = Cast<ASomePlayerController>(GetOwningPlayer());
OnPawnChanged(ASomePlayerController->GetPawn());
OnPlayerStateChanged(ASomePlayerController->GetPlayerState());
ASomePlayerController->OnPawnChangedEvent.AddDynamic(this, &ThisClass::OnPawnChanged);
ASomePlayerController->OnPlayerStateChangedEvent.AddDynamic(this, &ThisClass::OnPlayerStateChanged);
}
With OnPawnChangedEvent being a multicast dynamic delegate with one param APawn*
And the PlayerState one similar
That code there is pseudo code that I wrote just here, no clue if that compiles
okay, thanks u cedric
Eh, the callbacks
But the file where that is delcared has a huge comment tutorial
So just read that
Alright ty
What`s the best way to make a synchronised timer that works with late joiner like a 30 second timer in a game lobby that start when at least 2 player are ready ?
Put timer on Server
Do something when Timer Ends, like blocking New Players to join and start the game ?
@somber ivy
You should make the timer parameter replicated only if you need to show it to clients, otherwise state should do the trick.
ok thx
I have a system that you make a pregame lobby then the host moves everyone into the game mode.
Once in the new game mode how do I ensure all players from the lobby are connected? Right now I have an incredibly janky and slow system that checks the logged in controllers and sees if it changes within x seconds if it doesn't it launches the game.
It takes like 30+ seconds or so for a match to start after the host logs in. I feel like for what I have, it's incredibly slow. I had to slow it down due to slower connections not connecting in time to receive the start command.
anyone have any insight or sources for learning?
I don't understand why this is happening - maybe I don't understand how CMC works for simulated proxies? In this watched variable the Client 0 and Server both get the vector value from Get Current Acceleration. The simulated proxy (Client 1's version of Client 0) gets no vector data from this at all.
Yet the simulated proxy of Client 0 is moving around on Client 1's screen.
This is running on Tick in the character bp and the execution is firing. It's just not pulling any value.
And it appears the simulated proxies don't use the full host of movement functions that run on the autonomous proxy and the server
And Get Current Acceleration appears to derive from inputs, which is maybe why a simulated proxy is getting nada.
By default, the acceleration is not needed to show simulated proxy movement (technically velocity isn't really needed either but can be useful for visual effects). If you do want the acceleration, take a look at the Lyra starter project, their CMC does the extra work of replicating an acceleration value to use for various animation cases (at least I think Lyra does this from my memory, I could be wrong about that)
Copy that, thank you
I spawned a large number of actors on the server, and i have their meshes max view distance very low and I can't see any of them, but my FPS is still hovering around 10-15 with them just being in the world. What's the proper way to handle this?
I attempted to remove always relevant (cant ever see them even close), and use net cull distance (no impact)
I'd take a look in the profiling channel, but generally you'll want to fire up Unreal Insights and do a profile trace to see whats taking up your frame time
I'm assuming it's just large 0(1) every tick on actors that client knows exists, even if mesh doesn't render
so i assumed or hoped it was a network issue of relevance
It's going to be hard to tell without knowing what your actors are doing on the client, it could be rendering, could be ticks, could be something else, the profile will help reveal that
can you point me in the direction of some reading on that?
or am i good with 'tutorial profile channel'
There's a discord channel for profiling in this server, I'd check what they have pinned there first, using Insights is generally straight forward but if you've never done profiling before, just googling some docs would be good as well
Hi I am trying to modify the FPS template for a simple 1 v 1 shooter, i have set it up so the server can "see" the hit traces and register the hits but the client cannot see the line traces at all ? is this because i have the line traces to only run on the server??
Sounds like a plausible reason
this is my current setup
I guess i need a ClientFire custom event and use a Authority on the Shoot input (just trying to make sense of how this MP stuff actually works) XD The server applies a decal on hit of something but the client can do the line trace as the server reports hits but does not place a decal for client hits.
but then i was thinking if i use a authority that means only the server will process fire and check if the player has ammo to fire and allow the firing if ammo is available and if i do a clientfire that will be letting the client check if they have ammo which could be exploited correct?
The spawning of the decal is only for the local machine which is denoted by that little display icon on the top right of the node. If you want the decal to only display for the owning client of this actor, then yea, you'd want to do a Run On Client RPC. If you want all clients to see the decal, you'd have to use a multicast.
I'd also recommend against having a run on server event calling another run on server event as theoretically that can allow a client to call the second one without the first being executed which you might not want.
ah ok thanks!
so if i wanted to use a multicast i would need to create a new custom event called "Spawn Decal " and then choose Multicast for it to appear on all clients?
In real prod code, how do people generally go about executing Server requests?
Do people just
if (!GetOwner()->HasAuthority())
{
ServerStartAction(InstigatorActor, ActionName);
}
Or is there usually some sort of wrapper that encapsulates the server call in a Request object that has at least an ID so it can be contextualized in client responses?
So if i change the ServerFire to Multicast does that mean that the server and clients should all be able to do line traces over the place and register hits?
No. Multicasts can only be called by the server. You could potentially change server hit to a multicast and then all clients should see the decal being spawned.
You also don't necessarily need clients registering the hits.
ahh ok so how would i do a server check if client has ammo before allowing fire? this is a bit confusing at first XD
You already have it.
oh ok
But then you're relying on the client to tell teh server how much ammo they have...
Have the server control the ammo variable and read from the server's copy of it.
In other words, don't pass the value through the RPC.
that makes sense, so i guess the only question left is how i do the line trace so all can see π
"Seeing" the line trace doesn't really matter as it is only a debug feature. On your multicast you would spawn some sort of particle effect or what have you so people can see the actual effect.
Does anyone know of a way to implement host migration in a multiplayer arcade style game? If the host leaves I don't want the game to end prematurely.
Use a dedicated server
Also just found this plugin but have no idea if it actually works or not https://www.unrealengine.com/marketplace/en-US/product/host-migration-plugin?sessionInvalidated=true
I saw that one. Doesn't work with UE5 IIRC
Trying to avoid dedicated servers.
Only because of price. It would be ideal if a game could just migrate to one of the clients but I'm not sure how realistic that is
Itβs a problem that makes a lot of sense. If the host is where all these important state variables are kept and the host suddenly leaves then all that data is lost.
Yeah I know. I'm thinking maybe something like shadow hosting on another client at the same time, but that, if possible, still could be an issue.
I have read some about EOS + sessions but as far as I understand (which isn't far right now) that still requires dedicated servers, right?
EOS is an #online-subsystems which comes with a bunch of free features but I donβt think host migration is one of them. You donβt need dedicated servers for EOS. Should also mention it has its own channel #epic-online-services
Well right, same as steam subsystem right? But for the purposes I want to use them they're no different than steam.
My purpose meaning migrating the host if the host leaves. I guess like a p2p setup?
I dunno I havenβt used it before might be better to ask in that channel.
Cool, thanks for the help
It's a 2 part problem.
- Make sure enough state is on the clients to be able to reconstruct the server's view of the game
- Make sure all the clients can somehow keep in touch after the server goes kaput.
Assuming you have some way to synchronize data so clients can find the new server in the case of a failure it probably isn't insanely hard.
From a high level I was planning a shadow copy of the server on another client. Not really sure what the implementation would look like or if it's even really possible.
I suppose I could have clients store stateful information of themselves and then pass that all back into a new server.
That or maybe each team knows their teams state at some interval
if you're worried about info leaking
It could be as simple as a savegame MyLastState
and a pre-set order for clients to fire up as server
Server shits the bed
Whatever the first client was fires one up
Everyone else finds it through some mechanism or key that was shared in 1st session
They log in
They send their state
???
profit
exact perfect state would be hard but the basics wouldn't be too bad
Yeah I see what you're saying. I'm not sure if it fits well with what I want to do though. You can imagine the game I'm building being something like fall guys.
fall guys with listen server will already be hard enough
Would have to be a seamless transition and I don't think this is that.
Yeah I'm thinking dedicated is really the only option.
Not worth the trouble for a small operation IMO, even the big guys can barely do it. Seamless that is
Yeah but in an arcade style game with anywhere from 10-20 players per lobby... Idk how else you'd do it really other than dedicated
PlayFab has a host migration setting, so maybe that
PlayFab seems like a decent option in general but then setting up their OSS just seems like a whole other monster. And dedicated is just so much $
Other option being transition to hosted lobbies instead of a MM system. Don't love that though
I mean if you're trying to make a matchmade game then you'll already need some servers so just do it
I'm going for the TF2 / GMod model where you can just listen host or host your own dedicated
My code is bad enough as it is, I don't want any of my code able to run up an AWS bill
Listen host is what I have currently
By MM I really mean just faking MM by using listen over steam
Click TDM and get sent to a lobby. The problem is if the host leaves, right? Then the lobby crashes for what- 19 other people?
I mean that's life
with 20 people you'll want dedicated
now whether you host or community hosts is up to you
I'm lucky that my project makes sense with an always-up server
a bit like garrysmod
while nobody "hangs out" in a COD server for example
Yeah. I'm thinking maybe moving off steam SS and into PlayFab. They offer automatic listen server migration if a server dcs. It's hard to tell what services you have to pay for though.
Do you use a hosted dedicated server site? I can't find one that's not crazy expensive.
I'm using pingperfect atm
Though I'm going for a community hosted
Nice, I'll check that out. I've looked at PlayFab, gamelift, and IBM but they all $$$
It's dedicated servers so idk if that's what you want
I'm not even sure tbh. Ideally a listen server with host migration capabilities but that's not baked into UE
So I'm thinking dedicated or playfab are my only options
@keen hound can you host dedicated servers of a new game on pingperfect? I just see current games
I just sent them a ticket
playfab does not solve this for you, they're only managing the "lobby" side of things (i.e. figuring out who is the new owner of the lobby). Playfab has nothing to do with unreal's networking layer and can't actually migrate the live game for you.
Tragic
Also you arent going to get a session management service for free...
Or without work.
You can utilize the EOS backend
But you need to provide the Servers
Dedicated or Listen
If you go Dedicated then you obviously need hardware to run them on
And a martialling system
Otherwise, pay the $$ for Gamelift/Playfab etc and have all of that solved for you.
Yep, looking into dedicated as it seems to be the only option! You guys have all been very helpful. I'll let ya know how it turns out
Does anyone know how much overhead component replication/RPC actually is?
I believe the overhead is enough such that the component can be identified.
Which is attached to every packet
You're mostly just paying for an extra header field to say which component it is. I wouldn't recommend worrying about it until you profile and see that it is actually a problem
I'm not worried about it, as an FYI. Just curious, that's all.
The CMC avoids it because its a critical pathway.
The CMC uses RPC proxies on the Character
So it can avoid the overhead
Since it sends lots of RPCs and its a critical feature, its worth the trouble.
Yeah. All this I understand. I was just more curious about any hard numbers and what not.
Hey there!
Has anyone used root motion animations extensively before in a networked environment?
I've been researching the topic for quite some time and figured that either I'm doing something completely wrong, or the engine just cannot handle these root motion animations deterministically to ensure that both client and server play the root motion the same way.
Let me give you a brief description of what I'm trying to do and what I've tried so far.
So basically, the concept is really simple. I have a character that uses Unreal's CMC (so moves with client-side prediction). The client controlled player has the ability to fire a "dive forward" ability/action predictively. When he does so, a simple forward dashing/diving animations plays out. No rotations, nothing, just simple forward movement. The server follows up when it gets the latest move/update from the client and executes the same ability/action to do the same and plays the exact same animation with exactly the same parameters.
The animation itself is wrapped in an animation montage, the sequence that plays in the montage has root motion enabled.
What puzzles me the most is that at the end of the animation (or sometimes midway through it), the client receives net corrections from the server and I can see a tiny snap on client-side.
I've tried:
- routing all this through the CMC's prediction framework with compressed flags triggering the animation montage
- encapsulating the dive action in a gameplay ability and ensuring that it plays on both client and server (ability was local predicted for client)
- firing the animation while being stationary so my initial position should not be the cause of net corrections that occur midway through or at the end of the animation (I even tried the dive AFTER I got a net correction so I made sure that I'm in a position that is 100% valid from the server's POV).
All this, makes me think that RM animations are just non-deterministic and they'll always differ.
Any clues?
Extra note: the character/anim bp is set up to play root motion from montages only (obviously).
hey giys
im seting a static mesh inside a function thats being called on the server
the print is print that it has a "new" mesh"
but its not updating on the target for some reson :/ ?
generally, you'd want to put that static mesh into an OnRep variable in the actor that owns the component, then set the mesh from OnRep itself
hmm
aye i think it could be related to this tho
this inside a Widget
how do i get the Owner of the widget something '
Hello,I have a Question.
We are currently developing a two-player shooter game, but the character animations are not synchronized.
It is working fine on the Client, but the server side behavior is not in sync with the client side.
Does anyone know of a solution to this problem?
@dull tulip seems like your variables are not set to replicate?
and I'm not sure with Multicast to update, I think you just need to replicate the variable and update the value on server
Hi, wonder if someone can explain me what would happen if you done this ?
@dark parcel
Thanks for the reply.
Replicating the variables did not change the result.
It should be facing the same direction as the camera it is facing, as shown in the image, but it is not working correctly on the Client side
@dull tulip I have little to no experience in multiplayer but I think you should not update with multicast. Doing so will update the value to all machine.
I am suprised if the animation not janky because as you move, the server will keep sending you the previous value you sent.
The problem should be more apparent if you emulate lag
Anything movement related imo, client set their values locally, then send an rpc to server. The server then replicate the data to other machine (other proxies) where they can interpolate to the value they received
Isn't that the same as executing an event with an owned Client?
You want to set the variable instantly on client, then you do Server RPC with the values. If the variable is set to replicate, the server will then replicate the data to Other machines
im trying to pass a Widget reff thru the server is that not possible :/ ? anyone know
Picture this, if you multi cast.
You move 10 Units , few ms later server receive your data, then it replicates to all client
Since it;s multicast, you get the values back again. At this point you might have move anotehr 5 units, but then you get the values back again so you get rubber banded back.
im trying to send a reff of this "Self" widget to the owning client so i can get variables from inside that widget thats all but thats not allowed ?
no
hmmmm
And it doesn't make any sense. Widgets only exist on the client machine
yeah
but i made it so when u
ill just show u 1 sec
my items i pick up from the ground gives the player a "Widget"
and when equipping that the widget got variable stats inside that needs to be sent to the server so it updates
but im getting access none from the widget
and i think its weird since the owning client owns the widget and got the varaibles, why would he be able to send information about that widget to the server :/
hmm when i said it i was acctualy able to solve it
The widget isn't replicated or created by the Server, it's created by the client, so it's impossible for the Server to know about it or do anything with it.
yeah so the problem was i tried to fetch the info from widget on the server side wich cleary dont owkr
yeah exactly
but if i get the info from the widget on the client first then send it to the server
thats what i did wronfg
Yeah that's what you need to do
yeah cool, however one small issue left
Does this mean that variables should be separated from server RPC events without replication?
No, you need to send Server Rpc to update the variable. it's the only way to communicate to server and server to other clients
im changin static mesh and i get prints from both target , new mesh
but nothing happening :/
tried server & Rpc even tho components are Replicated
@dull tulip I can recommend you a FPS tutorial that goes over setting up shooter game, but it's in cpp and cost some money
but the breakdown and the wisdom is worth it imo
Can I understand it even if I have barely touched cpp?
I don't think it would be easy to follow along. Also working with Unreal CPP kinda requires you to get a plugin (Rider, Resharper) and they cost 150 USD or something :S
forgot about that part
visual studio is free
notepad is free too
any fast action pace multiplayer game is hard. cpp kinda required for those.
There are some things that bp can't do for you
one example is the character movement component. Adding functionality like crouch or sprinting would probably require you to write some code
I guess that means multiplayer development is harder than it seems.
Is it likely that blueprints alone will not solve the problem you just mentioned?
@dull tulip depends on the scope of the game
if you can give up on the fancy movement
you can use the current Character Movement Component as is
multiplayer development is hard, replication is the easy part actually
you have to deal with client prediction, rewinding, Server auth, etc
and that's crucial in FPS game
but for something like turn based game or Card game, you can probably still make a playable game using bp alone
There is no fancy movement in what I want to implement, I just want to fix the direction the camera is facing forward and synchronize it with the server screen and Client screen.
Other than that, it's a simple game where if you get hit by a bullet, you blow up.
hey i need help, I was testing with net emulation to simulate high ping and no matter what the clients that are moving arent being smoothed on the server, So they are really choppy and teleporting to where the client is
ListenServer has no proper smoothing for Clients in that regard
Reason is that they are ticked via the ServerMove and not per Tick
Hey, what are the main components a programmer should learn to do in c++ regarding multiplayer ? Thankyou!
find network compendium link in pinned messages on this channel and read it @rocky knot
aah is there no work around?
This is the error im having btw, (Not concerned about the animation, Mainly concerned about how the character is choppy when viewed from the server or another client)
yea thats a bit too choppy imo
you dont happen to have your character movement component tick rate set manually to something do you
Anything I can do manually record an event or some kind of data during replay capture for better replay construction?
I have a custom method for maintaining a synchronized server time seconds clock on my player controller, but since it uses normal (non-multicast) RPCs, it's not being recorded by the replay system
C++ with some ugly overrides, but the code change since I originally did that so I can't really guide you on anything.
The gist of it is that the Character sets a boolean in the Poccess function iirc that disables the ticking of the mesh.
And in the CMC it then calls TickPose from the Move RPC
There are reasons for this, but I honestly never understood it
I'm getting a libcurl 65 error when sending a http POST from my server using unreal's HTTP module
LogHttp: Warning: 0x5bcc2f93200: request failed, libcurl error: 65 (Send failed since rewinding of the data stream failed)
from the libcurl message info cache, i can see the TLS handshake was completed. anyone know how to fix?
nvm figured it out
I want an object to vanish when a character is near it, only for that character. I've got an on begin overlap on the object (which has a ref to overlapping char). Do i need an RPC on the player/controller to handle SetVisOnActor and to call that from the obj?
with RunOnOwningClient
Less 'niche' question: is there some kind of 'replay time seconds' that can be obtained, that respects the original recording's world time seconds?
Is trying to get references directly from a widget blueprint impossible when it comes to replication? What's the general flow for populating data on the clients widgets? I'm assuming using replicated variables and manually populating widgets from their owning actors and not from the widgets themselves?
Widgets aren't replicated, so it's impossible to reference them across the network.
You'd need to replicate the data in a replicated actor and have some means of updating the widget when the new data arrives.
A good way of handling this is to have event dispatchers that your widgets can bind to and you call those event dispatchers in the OnRep functions of RepNotify variables passing along the new value into the dispatcher call.
For a quicker set up, you could just set up value bindings in the widget itself which attempts to retrieve the value on tick from the source, but this would still require those values to be replicated on a replicated actor.
This is quite curious, I would maybe have expected option 1. to work without corrections since it's the only flow that would be perfectly synced with movement. When you're testing this are you using any form of simulated latency change or packet loss? Unreals CMC doesn't handle these perfectly so that would definitely cause move corrections regardless of using root motion or not
I thought so :(... Thanks!
There needs to be a meme here for cruising through developing multiplayer games on ue then crashing into a wall labeled latency
Anyone have any learning resources regarding movement and latency for unreal
What aspect of it specifically, that's a deep rabbit hole
i'm a novice on the subject, but have u confirmed that the server is playing the root motion
Anything and everything I guess.
Specifically what started my leap into the hole
Test 1: everything is smoothish at 60-70ping from friend.
Test 2: game is unplayable because any client over 30 ping now teleports everywhere as well as (now fixed) but could flood inputs despite the checks i originally had to stack abilities before the server could tell them they were on cool down lol.
Went back after fixing the input flooding to Test with network emulation active, same thing client becomes unplayable for some reason.
Also to note
Playing the game on my 8 yr old half running laptop at 20 ping it works as it should
Are you using unreal's default CMC or have you customized it? Sounds like maybe you have if you're doing some custom networked input scheme
Default cmc.
There's no custom movement or anything.
Just move around flat on the ground, sprint, jump.
Wasn't doing anything custom with networking.
Was just adding lag for testing
The default CMC shouldn't be completely unplayable with a bit of jitter/packet loss. What are your test settings?
70 ping <1% loss
Playing on a packaged demo through steams public server
Do you run into the same issues if you play on a local server with the same simulated settings? Could be that the steam public server is adding additional jitter/packet loss
What is your forced move threshold time set to?
When running in the same server my half running laptop runs it smoothly
But it's also on the same wifi which also gives it like a 20 ping.
Not sure I know what you mean.
I'm still kind of new.
Try running it on your laptop and use the NetEmulation settings to add in some latency and see if the issue happens
sprinting without prediction is not playable
for CMC you want to work with FSavedMove
most tutorial you found in youtube covering "sprint" in multiplayer with bp is fake and doesn't work in the real world where lag, no matter how tiny exist
About the only tutorial I've seen online that covers it is on Reid's channel
https://www.youtube.com/watch?v=urkLwpnAjO0&list=PLXJlkahwiwPmeABEhjwIALvxRSZkzoQpk&ab_channel=delgoodie
Follow this one
https://discord.gg/uQjhcJSsRG
In this video I am introducing a series I will be making which explores the character movement component and how you can extend it in depth.
0:00 Intro
1:00 What is the CMC?
2:00 Do you need a custom CMC?
5:35 What does the CMC provide?
7:10 Outro
should be the most informative for CMC
^ If they're routing the sprint through the compressed flags it should be fine
yup, that's not bp territory
Thank you. I'll give that a watch in just a bit when I have a chance. I learned what you mentioned in your last comment the hard way last night.
Just really confused why things were smooth one day, then showed the true face last night. However, going forward I'm gonna do all network relevant testing with some form of emulation.
Hopefully this is just another hill to climb over and learn. Cause so far seems pretty daunting.
you should always emulate lag when developing multiplayer
the perfect world where network plays in 0 ms doesn't exist
even 5 ms, already make your movement jaggy if not done properly
Movement is one of the harder things to get correct in multiplayer scenarios because even minor disagreements can be brutal to player experience since the camera is often tied to character movement
the video I sent cover everything you need to know with cmc
When I finish my mechanic/feature - I always test in 0 latency to make sure things are designed/functional the way I wanted. Then just go to normal emulation settings and then go to the worst one.
I should keep that in mind
So - I do a lot of testing to address issues. Before I even package the project and test on a live network.
Because packaging and distributing and getting people together for testing is just a dang slog
Yup, take ages to test even with a laptop next to me
I'm learning all this the hard way I suppose. This is the first time I've tried to move something to be tested. I thought the network smoothing etc was more or less what the network prediction would do. As well as the proper way to test things etc. Also had a funny lesson on setting logic up for the client to run and server to correct yesterday lol.
Unfortunately to really understand things, the hard way is the way to go. You try something, it doesn't work, you do some research to find out why, then do it the right way and now know in the future what to look out for. Until you know what doesn't work (and why) you'll keep doing things the wrong way, but that's how learning multiplayer works
prediction and server rewind is something that you need to do your self
some part of CMC obviously already implement it
but anything else you do, eg Shooting bullet, reloading, damage, etc will require work from your end
Yeah I picked that up off a comment you sent someone having a similar issue earlier which is where I realized how deep of a hole i just found myself in lol.
well my brain not big enough for MP too
It's quite bottomless tobh
Summary of my whole journey into learning game development/programming so far lol. It's fun but rough sometimes
i'm about to start my self
I see you in here helping people frequently don't lie π you know some stuff.
Single player stuff
my Multiplayer project still stuck in character customisation and loading screen
about to finish so I have to deal with movement soon π±
What MP game are you making?
Well best of luck in your endeavors then. I'm pretty sure you will get it figured out quickly.
it's a simplistic small time moba.
Control elemental orbs, try to knock out the other team.
I'm learning GAS for my RPG game but I don't know how much I can do in MP
always open to revert back to SP
I think if my game didn't work out I can fallback to turn based
Depending on the game, it's not a bad option.
I think you will figure it out. Imo what I've learned so far on replication/multiplayer-networking, other than this movement stuff recently, isn't too bad once you get past the initial trial and error bumps.
i say the trial and error bumps because when you're making your stuff it's easy to get lost in what the tutorials are trying to impart on you sometimes.
Turn based games are so easy to network. I wish that was what I was working on.
Odd as it may seem, it happens with 0 net correction too. Can confirm that both sides are playing the anim with the same params (play rate, delta time, etc.).
Even delgoodie (guy with really good tutorials about the CMC) was puzzled as to why these corrections happen with something simple as a forward dash, and so on. I'm starting to think it might be related to floating point errors or something as logs seem to indicate that when client and server are playing the root motion montage, they're both progressing the animation at with the same delta time (I believe server uses client's delta time to progress the anim at the same rate/steps). Then when the delta translation is extracted, for that tiny part of the montage, it continues on next tick. So what I'm seeing after some time, is some divergence in RM extraction start and end positions but the error is sooo small (in the 0.0001 range), that it might be irrelevant, idk.
I've tested this in a clean project as well, the issue seems to happen there too.
So after some research I couldn't find how to properly get a correct 'ServerWorldTimeSeconds' during network demo playback, so I ended up having to modify engine code and put float GetDemoServerWorldSecondsAtStartOfRecording() const { return ReplayHelper.PlaybackDemoHeader.ServerWorldSecondsAtRecordingStart; } inside the DemoNetDriver (with the corresponding ServerWorldSecondsAtRecordingStart member inside the FNetworkDemoHeader struct, so that I can then add it to the final GetServerTimeSeconds getter...
Can anyone confirm that this is indeed necessary, and that indeed there is no better solution atm in the engine that I might have overlooked?
Hey I have a problem where Media texture won't play on different computer. I have a mechanic where you have security cameras and when you switch between them a sort of "tv static" video plays. I tried testing it with my firend, but when he tries it, the "tv static" just doesn't work, but for me it is working fine. No matter if I'm client or listen server. Also when I try testing in ue on client, this error keeps popping up. Accessed None trying to read property. Node: Add to Viewport. Because the static screen is a widget
If the position delta is that small, it wouldn't cause corrections. I would next see if you can break on what is causing a correction to be sent to narrow down what parameters of movement are getting out of sync
I'm trying to replicate a UObject within an actor component but I cannot get it to replicate properly
UCLASS(Blueprintable, BlueprintType, Abstract, meta = (DisplayName = "CustomObject"))
class CUSTOMSYSTEM_API UCustomObject: public UObject{
virtual bool IsSupportedForNetworking() const override { return true; }
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(Replicated, VisibleAnywhere, Category = "Custom")
TEnumAsByte<ECustomStatus> CustomState;
}
void UCustomObject::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
UObject::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UCustomObject, ECustomStatus);
}
How I am instancing the Objects:
UCustomObject* CustomObject = DuplicateObject<UCustomObject>(Base->GetCustomObject(), this);
if(!IsValid(CustomObject ))
{
UE_LOG(LogTemp, Error, TEXT("CustomObject is not valid"));
return;
}
InstancedObjects.Add(ProgressObject);
// AddReplicatedSubObject(ProgressObject);
OnRep_InstancedObjectsArray();
I'm authoring the objects in the editor and using them as a base for the duplicated objects
You must replicate it manually through owning actor channel (the objects' outer must also be set to the same actor)
In owning actor or component owned by the actor, you can replicate it in UObject::ReplicateSubobjects function by calling Channel->ReplicateSubobject(MyObject, *Bunch, *RepFlags);
You can check how GAS is replicating the attribute sets
UAbilitySystemComponent::ReplicateSubobjects
What is the generally idiomatic way to update connecting clients with stuff that's already set on the server? OnRep_Something doesn't trigger when the client connects because it already happened on the server before connection
Nvm I'm dumb, my actor's Replicates was false π₯±
Weirdest thing. In a listen server situation my host has just stopped executing 'on post login' for itself. It executes it when the client joins, but not when it starts the session in pie. This has been working flawlessly for a week, and all of a sudden it stopped working a few minutes ago
I hooked up a print to on post login and it only fires once for the client. I have video of this working only a couple days ago. What could possibly stop the hosts player controller from calling on post login?
if i start it as a listen server with 1 user, the server does run post login. server + client and the server doesn't run it for itself. this project is haunted.
The server doesn't log in to itself...
Post login is called when a player joins, for that player. Be it remote or local.
A dedi server has no player, so nothing is called for it.
It's not a dedicated server. It's a listen server. on post login has always been called after start as setup for both the host and client are called then, and it's been working for a week straight and just stopped working.
I'm talking about on post login on the game mode.
I do two things on post login, assign a player area and a colour. That's been working fine for host and client and has just suddenly stopped.
In this situation, it starts a 'server' and this prints once, for the server. If I change this this to two, it starts a server and a client and only prints once for the client. It wasn't doing that yesterday.
nope tick rate is default also sorry for late reply
Anyone used new online services from unreal which came with unreal engine 5.0? just curious I am still at EOS buy may change if there are any advantages
So after some experimenting, I have realised where my code is going wrong. The duplication of the object for some reason means that it won't replicate
// This works but the variables will not replicate yet
UObject* Object = NewObject<UObject>(GetOwner(), Objective->GetObject()->GetClass(), NAME_None, RF_NoFlags, Objective->GetProgressObject());
// This won't work
UObject* Object = DuplicateObject<UProgressObject>(Objective->GetObject(), GetOwner());
Should I expect PlayerState->ExactPing to read out ~140 on local players with this setup?
I think when I ran 60s across the board it said my client ping was like 180-240 lol
Ok cool so it's not just me
Dunno how this works exactly so idk if it was reading accurately or not
Maybe your numbers make sense if its set to both clients and server?
Only way I got under 100 ping was setting minimum to 0 and max to 1
60*4 would be like 240
Makes no sense to me. I gotta dig into the documentation or something about that feature tbh.
I don't think it adds all 4 values
At least to me logically I believe it's supposed to fluctuate between the min and max
And add together the out and in values of each occurrence for the actual ping
Well if the target was set to clients + server then I'd expect the delay to be applied on both
but in this case it's just set to client and im still getting 140 where I'd expect closer to 100
Yeah it's weird and it feels janky.
yeah for sure
But just play with it til you get it where you want
Try the 0/1 like I did see If you get the same results I did.
I'm guessing I can at least trust PlayerState->ExactPing on the client?
I think it put me at 80
I believe so
Now I'm even more confused on that thing lmao π
I saw UT uses it for prediction so I'm guessing 
I had my own ping that accumulated 10 seconds and dropped outliers but I was wigging out since it was still off
then this is also off, but even more off, probably because the averaging is different
but I guess yeah you have a good point, I'll just play with numbers until it reports what I want for the in-game ping...
Yeah, could be.
I know there are plenty of features in unreal that don't mesh together like they should be expected to.
There's also 3rd party programs that supposedly work much better and are easier to understand.
Saw a video on one earlier
Just throwing options
Yeah good idea to look into
ty
Setting 10-15 for min/max on in/out for both client and server gets me to 100ms so w.e.
Nice. Well hopefully it holds up the way you expect. Best of luck on your project π
Could use some advice: I'm trying to determine where to build my on-kill logic. Things like awarding player xp & calculating loot drop. Would that sit on the player pawn or the game state, does it matter?
Those are like very different things
Awarding XP and doing Loot Drops are totally different
We set up an custom "Awards" system which designers can create any type of award they like, which Players can attain for different things (like Kills, even deaths for particular reasons).
An Award can give the Player XP
It even handles doing UI stuff
And playing Sounds etc.
It sits on the PlayerState as a separate encapsulated component.
The Server issues Awards, they get replicated down (via just an incremented integer).
At the end of a match, all the Awards are "counted" and that becomes the final XP amount for that Player
They also get sent to the backend by the Server to calculate rewards and update player records etc.
Oh cool, that sounds pretty clean. Thank you!
@fossil spoke Taking it back to the projectile conversation from the other day, I read through the UT source code and got some good ideas on how they've decided to handle things, so thanks for that tip π
One thing I couldn't really understand is whether or not UT silently suffers from phantom hits, both on the shooting client and the client getting shot. Maybe it's just less obvious in an FPV but it didn't look like they were doing anything there - maybe their custom movement comp / prediction is just good enough to avoid that case a majority of times
I cant remember if UT does any sort of rollback
I saw they have rollback for hit-scan definitely but projectiles, I'm not too sure
yeah
I almost wonder if in a top-down game it's better to not predict since it's more obvious on having phantom hits, then maybe I can just make it server authoritative and make the hits "look" good when / if they happen
I guess if the projectiles are in the past a little bit I get more time to smudge it when the server decides there's a hit
There is really only so much you can do.
Are you expecting having players with high ping differences playing together a lot?
Seems like you would want to prefer them be closer
I was trying to target having like 100ms ping be playable
Which drastically reduces the need to solve that issue
This is a lot of the reason why Region locks exist
yeah true
You just simply cant get around the physics of the issue
yeah
Generally, you usually target the best play experience for the Player doing the actions
And then limit the ping differences
makes sense
Ever thought about things like adjusting the hitbox on the server based on movement?
Yeah that's where my brain stops, it sounded like a cool experiment but it's just a shittier roll back
Just buffer old positions
Rollback on the server and check against whatever it is that needs verifying
Yeah I have that in, just need to use the saved positions
Honestly, unless this is a fast paced competitive shooter, you wont need anything more complex than a simple rollback for hitscans