#multiplayer
1 messages · Page 273 of 1
yes, on Steam this will represent the 64-bit Steam ID
which is persistent
and on pretty much every other platform this will represent an immutable user ID of some kind
Thanks!
I like to call that "hitting the wall many times till you realize its a wall"
what is hour-glass wait ?
i could limit it to a certain amount of try to stop it from looping
but theoretically it should be at some point valid during load
Show what you're trying to actually show, but the answer is to use begin play and repnotify usually as the timing for when things are ready
Why do you have this? Player Name should just live in player state directly
it works pretty good right now
doesn't matter how the order of load
it always is correct
it does livin in player state
beginplay was unreliable for loaded stuff
i could probably put the same code in the beginplay though
Then what is this? Or do you mean "Try set player name on some widget"
where does the variable that is onrepping live?
yes on some widget
player state
Rename that function then, that function sounds like it's setting player name
which it's not doing, since it's triggered on the replication of player name lol
I think PlayerState defaults to a very low replication rate
and it shouldn't be telling UI anything, at most it should fire a dispatcher
i try to set the player name
which the UI can be bound to
Be very clear if you mean setting the name, or updating the UI
they are different things
makes sense
i'm just saying get the widget, set the text
widget should fetch the text on its initialization and also fetch it when the onrep fires through a dispatcher
widget cares about stuff, nothing cares about widget
oh right so set an event instead of just setting the text
whats the difference though ?
plenty. In general your game should work whether or not UI is around, and UI is a view/control layer that talks to the game
i mean i code the way i have learned
Now I don't know if PlayerState is guaranteed to be around when the widget wakes up, you need to check that. The hardest part would be handling the widget being alive, and not finding a playerstate to even bind its update event to.
i had problems with the state not loading
and also widget not being ready
so i just did this it works great
widget not being ready shouldn't matter, the only thing that should do anything about updating text is the widget. set it up like this:
Widget:
Initialize -> fetch playerstate you care about -> bind UpdateText to playerstates OnNameUpdated dispatcher -> call UpdateText
UpdateText -> fetch name, update the text
PlayerState:
OnRep_Name -> call OnNameUpdated dispatcher
nothing should be talking to the widget. Nothing needs to have a ref to it.
well i mean theres many ways to do a thing
this is just what i have learned so far, i will look into dispatchers though
for stuff like that i think the retry thing i'm doing works
basically what i have is wait untill the pawns ready, wait for the widget
then set the text
Sure retrying is fine. Retry from the widget
the playerstate doesn't give a shit about the widget
widget can retry getting the playerstate if it wants
i mean is it really that much different ? is this just because it's preferred ?
i don't see the big gain from doing it the way your saying
so with rep notify and the authority check
the client needs to be within a certain range of the server ?
i tried always relevant on the player and enemy still same thing
playerstate is always relevent
the widget comes with the pawn
if the pawn is there, the widget is there
Ok so the widgets work fine for the name Ata distance but my health isn't working
The hits and health are not working when I'm at a distance of server player
so far we've been talking about name, this is the first mention of health
Yes I fixed name it's np
This problem is my hits not working
It works fine within range of server
show the hit not working
i checked always relevant
i didn't up the net cull because from what i read always relevant is supposed to override that
you're gonna have to show the code path from the animation to health update
they are both just collision, has authority, change variable, on rep, change display
you can see it stops working for both
the player and enemy
you need to show the code path
the enemies are spawned on server and replicated right?
yes
yeah might be the server doesn't see the bones move
?
yup that's it 100%
if the server is what decides if it hits based on the server collision
on the server, the sword isn't being swung
then the server has to animate those characters even if they are not visible
mesh -> always tick pose
might need AlwaysTickPoseAndRefreshBones to move the actual kinematic bones? I forget
I'm not sure if refresh bones is needed for kinematic transforms
one good middle ground is OnlyTickMontagesAndRefreshBonesWhenPlayingMontages because it will only update when someone is playing a montage (I assume you have a montage for attacking)
but ofc if the other player has to be hit on their skeleton then it must update as well I guess
yes thats a good choice because the attacks are montages
yes that works
thanks again
keep in mind when it says tick montages that also applies to montage events and states
so if this stops ticking montages those just kind of stop
this is if you use one of the options that DOESNT tick montages
and switch back and forth
from being rendered or otherwise
Oh ok ya tick on montages seems logically correct consider everything is still replicated and then my onreps work still on montage
I'll try this out and see of any bugs
I'd like to yell my love for actor dormancy. I dived into it hoping to gain a few frames after some profiling, and it exceeded all my expectations.
Are you doing this with blueprints? I’ve found it doesn’t really work correctly in blueprints, for example if i have something set to dormant as default, it doesn’t seem to actually set it to dormant. Initial gives similar results, so I’ve actually never used it to potential because of this
Nah, in CPP. I'm already beyond the threshold where I need to really optimize stuff. On actors with non-frequent operations on replicated members, I set DormInitial in the constructor, then I call FlushNetDormancy before operations.
Because I have many, many actors like that (I have basically an infinite 3D maze, lots to replicate, but really not often), I really reduced my stuttering.
This is exactly what I’d like to do. But it literally just doesn’t work in blueprints lol. Essentially, you can’t set things to dormant as far as I’ve tried. But tbh I could have missed something to do. My big play was to set those actors update frequency to like 5
100 by default seems a bit insane anyway
Yeah, I guess it only makes sense for a Doom-like where everything moves all the time except the map itself.
I am working on a climbing mechanic via extending CMC. I followed a decent guide which worked for single player, now I am trying to get it working in multiplayer. I extended the SavedMove and the mode is switching correctly, the bit that is not working is when I change the capsule orientation to follow the normal of the mesh he's climbing on. The sever and client disagree and it is causing major orientation glitching.
I looked through the base UCharacterMovementComponent and it seems that they never change the orientation of the capsule away from vertical.
Is capsule rotation something I should just avoid for multiplayer?
character capsules do not sweep changing their orientation at all, it's very much something that is not mathed out much
you can change their up direction I guess
I don't know how you are changing the capsule orientation
if it works locally then in theory the server should be able to follow along most of it...
show debug for net corrections at the very least and try to compare the input and result on both sides
vlog would be useful here to track it over time (perhaps with the timestamp etc)
Just via the usual SafeMoveUpdatedComponent call. But there's some code that lerps from current orientation to surface normal, and I suspect that's where it's going wrong. That, and, if the position is different on server+client slightly then the surface normal may be quite different.
"code that lerps from current orientation to surface normal" in what step of the movement update?
and is "the posision" the final transform or a seconary variable you made?
PhysCustom is where the code runs.
Now I'm looking at it, I think the client and server are in agreement because there's no net corrections going on.
The problem is when one client is observing another, their orientation is flip flopping.
and yeah slightly differing positions could give big changes in results... I wonder if you could just smash the normal into the sent input
difficult to verify on the server but if this isn't a competitive game I doubt people will spoof it
the position of the normal hit on the rock in world space should be fairly consistent though unless the rock moves. even then it could be sent relative to it
if this was just simulated proxies I would definitely not say "The sever and client disagree" because to me that implies a server correction
for sim proxies this is way nicer beacuse all you have to do is interpolate the values correctly
yes I agree, I was wrong in my initial evaluation. definitely an issue just for sim proxies
which is easier said than done in some cases but you might want to see if you can bake your normals (well, not bake but just... use) into the smoothing steps of the cmc update
Does the sim proxy run a subset of the CMC code? Maybe it's not running the code to set the orientation?
or it's expecting the orientatio0n to be replicated but it's not
the cmc on sim proxies is very simple... it just gets an onrep and then moves in that way and then does some math to smooth the mesh offset from the capsule
because of this it's VERY important to see both the real capsule and the skeletal mesh at the same time to see what is actually happening with its true position which jitters a lot compared to the real mesh's final offset pos
is there some debug vis I can enable?
it might receive the transform of the actor in the onrep but idk how it would rotate and resolve in the same way without knowing about it
sort of, there's p.visualizemovement
honestly easier to just add some vlog shapes to the variuos steps
or use the actor rewind debugger (if it's okay with this situation)
visualizemovement does not show orientation, but I can see already that the position is glitching too.
I'll look into vlog, thanks.
or change the movement so it does not rely on changing the capsule orientation 🙂
are you quantizing the location heavily?
not intentionally.
capsule location is being moved via SafeMoveUpdatedComponent
ohhhh hang on, I'm also calling UpdatedComponent->MoveComponent after that to snap to the surface
I'll need to refactor that to go through SafeMoveUpdatedComponent
maybe
All variables in GameState are replicated by default? Or do I have to set them to?
Most, if not all, of them are afaik.
Common ones like PlayerArray etc are definitely.
You can check the individual vars in the source and see if they have the Replicated tag in their UPROPERTY.
Isn't PlayerArray actually not replicated, just kept in sync through some other mechanism?
yea, when a playerstate spawns, it registers itself to that array
so naturally when they replicate, they'll be added
I found the problem! the PhysClimbing function had a check for bCharacterWantsToClimb and if that was false it would switch to Falling mode.
On Simulated proxies this bool is always false, so it was constantly toggling in/out of climb mode.
I'm not quite sure why this is. On Autonomous proxy the bool is set by inputs and replicated to the server via saved move. But it seems like this saved move is not replicated/applied to simulated proxies?
For now I wrapped the switching to Falling mode in a if (CharacterOwner->GetLocalRole() > ROLE_SimulatedProxy) check, which seems to have fixed a bunch of issues.
sim proxies never see inputs from saved moves, only the result and how it affected their replicated variables/velocity/pos
Well, not "Replicated", but reconstructed on the client side, for that one. But the point is it's available on the client.
embrace the array
arrays wont work
i have a lot of maps but i use them to map various enums to structures or references
how large are these maps, as in total number of key value pairs?
It's probably literally faster to iterate and check (Array.Find) in the small case anyway
This is why you need to do multiplayer on day 1
yeah ive been doing mult but i added some new systems
its just breaking for multiplayer saving
i have a save game object with a lot of maps
the client needs to load its save
I think TMap has a function to crank out arrays of keys and values
i did see someone like wrap it for replication
converty to array -> rep -> convert to map
yeah that's what I'd do
or just have it be 2 arrays from the get-go, for small sizes it doesn't matter
one of them is a kill log
150 monster names to structs
oh its counts
that's still not that bad
you're not sending it every frame right, just at GimmeTheSave time?
no this is just for loading client saves
yeah I'd just make arrays work
i basically have made the maps just get updated in multicasts
thats a bummer
so you think like convert all the save data to arrays on saving and then on loading use arrays
I'd just have an array of monster,kill structs and call it a day
Okay but then its not indexable by the monster name enum
so just find it
and id have to use loops to add stuff
you can look at a lot of enums in the time it takes to hash something
pretty inefficient
probably more efficient for small arrays
also since monster name is an enum
just cast it to int
and thats its index
pretty hacky but its something ive thought of doing
You have an array of KillRecordStructs whos size is MonsterNameEnum.Size
although enums for stuff that's really gameplay data is a bit icky to me
should be a GameplayTag IMO
its there a better way to arrive at a dictionary type structure that will rep correctly ?
UEnum::GetIndexByValue
yeah ive done similar things for like selecting random enums
then you would just put them in the same order as the array
and get by index but select the enum, get index
getting by index i believe is still O(1)
yes
getting by index is literalyl the fastest way to do this
well id have to convert many maps to arrays but not an impossible task
btw friendship ended with TArray, now TSparseArray is my best friend
also friendship ended with TMap, TMultiMap is my other best friend
ya dun fukt up a-aron
makes no sense why you cant rep a map
I think at the core of it is the fact that even if you end up with the same logical data, the backign data of a map would look different based on how you got there
with the whole hashing and collision and buckets and all that jazz
all it needs to do is send the map structure and it will contain that
You and me could agree that the map looks like:
Tom, 34
But we might not agree on what bucket that data is in
yeah but that can easily be handled locally
idk, make the pull request and see if Epic bites
do you know where in array.h the replication is handled?
Given it's still not a thing 10 years later, you can trust the fact that it's not an easy thing, or even something one should try to do. Stick to Arrays if you need replication.
I'm sure writing your own netserialize would be fun and not painful at all
Gotta be an Iris one to ensure it also stays relevant.
im not someone who enjoys easy things more into the challenging
Aight, good luck!
On another note, I just noticed that the Iris serliazer (NetSerializer probably too) of FHitResult recalculates the Distance locally from the FVector_Quantized. Good thing I didn't quadruple check my code to find out why there is a difference between Server and Client when it was coming from the HitResult replication cutting away precision.
added to my todo list haha 😄
idk why TMap doesn't have replication because fast array serializer sends deltas as a map iirc
I can't think of a time where I've needed to replicate a map though
There is no way that happens
What are you talking about, it's obviously easy to replicate TMap and they just have been lazy about it for a decade.

Good point, it will definitely happen
Gotta say, if they replicated it, I would not want to use it
Better to make your own struct
Can't imagine the pointless overhead with replicated TMap for general use
It has been done before
but I can kinda see why they never bothered to implement this in an official capacity as its pretty simple to work around
also on smaller arrays just doing AddUnique and searching by iterating will sometimes be faster than a tmap anyways
albeit more annoying
Is there any solution to replicating maps? I tried using a struct but that variable then just refuses to replicate?
TMaps do not support replication.
Usually you will create an array of a struct that has a property that is the type value and then another property that can uniquely identify it.
hilariously the message literally above this is talking about map replication
it is possible if you completely make a custom serializer but... don't do that if you can avoid it
array setup is far more simple
Whoops, sorry, I should have scrolled up. Thanks for the responses.
Hii everyone, I'm trying to create something like a spectator feature, my client 1 is a character class and client 2 is a spectator pawn whose view target is initially set to a actor with a top down view during that time when the client 1 is moving in the view his movement is very smooth after that when the client 2 view target is changed from that top down view to the character there is suddenly a movement jitter visible in the character(client 1) can anyone explain why there is this jitter as character class comes by default with client side prediction so why when I set the view target to the client 1 it shows that jitter and how can I fix this ?
Is there any reason to not move CheckJumpInput inside PerformMovement?
I cannot see any reason against moving it there. But i might be missing something
I assume you are following the Capsule Transform and the MeshComponent Transform is interpolated/smoothed.
Doesn't the comment above it say why it's placed where it is now?
I'm setting the view target to special child actor which is attached to a spring arm with a small lag which is attached to character mesh
Hm, not sure then. It does look like the mesh is moving differently than the capsule.
hmm I just noticed that after this implementation, server is able to see what happen in the client side but what happen on server is not shown xD
In ForcePositionUpdate it says // TODO: this is basically copied from MoveAutonmous, should consolidate. Or consider moving CheckJumpInput inside PerformMovement().
While in ControlledCharacterMove it says // We need to check the jump state before adjusting input acceleration, to minimize latency // and to make sure acceleration respects our potentially new falling state.
But in all three functions where CheckJumpInput is called, the same operations on Acceleration are performed, and PerformMovement is called right after
You gotta apply the AnimLayer within an OnRep that specifies the currently equipped item.
Is there a reason you can't just leave it like this?
I want to override the jump logic if there is a wall in front of the character to implement a mantle mechanic, but if i set the movement mode to anything that is not walking or falling during the mantle, OnMovementModeChanged will reset the jump state including bPressedJump.
This is annoying because CheckJumpInput happens before bPressedJump is store in SavedMoves
The only reason against it that i can see would probably be that changing acceleration before ReplicateMoveToServer makes it so the move cannot combine, but i bPressedJump already blocks combine before the end of a move.
It just feels like it is wrong for it to not be there
UFUNCTION(Server, Reliable)
void Server_EquipmentLinkAnimLayer(USkeletalMeshComponent* AttachMesh, TSubclassOf<UAnimInstance> AnimationLayer);
UFUNCTION(NetMulticast, Reliable)
void Multicast_EquipmentLinkAnimLayer(USkeletalMeshComponent* AttachMesh, TSubclassOf<UAnimInstance> AnimationLayer);
void UEquipmentComponent::Server_EquipmentLinkAnimLayer_Implementation(USkeletalMeshComponent* AttachMesh,
TSubclassOf<UAnimInstance> AnimationLayer)
{
Multicast_EquipmentLinkAnimLayer(AttachMesh, AnimationLayer);
}
void UEquipmentComponent::Multicast_EquipmentLinkAnimLayer_Implementation(USkeletalMeshComponent* AttachMesh,
TSubclassOf<UAnimInstance> AnimationLayer)
{
if (UAnimInstance* AnimInstance = AttachMesh->GetAnimInstance())
{
AnimInstance->LinkAnimClassLayers(AnimationLayer);
}
}
On Item equip i called this (it is replicated as Item was spawn)
//Link animation layer if not nullptr.
if (IsValid(EquipmentFragment->GetEquipmentLayer()))
{
Server_EquipmentLinkAnimLayer(OwningSkeletalMesh.Get(),EquipmentFragment->GetEquipmentLayer());
}
I usually don't reuse the Jump flag for traversing stuff.
Anyone know an easy fix for spawning actors on the server, not replicating to clients
I'm expanding the cmc for general purposes, so i wanted to provide a hook to stop the jump mechanic under certain conditions, and execute other logic instead
"easy fix"? I mean, you either do it correctly or not :D
Is your actor marked as replicated? Are you sure you are spawning it on the Server? Do you maybe have a reliable RPC on tick somewhere or stuff like that?
If you don't see an issue then just try it.
That's a multicast. Shitty idea for something that has state.
how do i further improve it?
ah i see haha
Yes its replicated, spawning on server, i did also try using an RPC but its spawning duplicates, also tried rep notifies
what is a better way ? learn about OnRep?
Somewhere you are equipping your item. That is hopefully happening on the server already. That currently equipped item is probably replicate, or?
I mean, you should learn about that anyway. You barely use Multicasts usually, so if you never used that before then you potentially have a sh*t ton of wrongly coded multiplayer logic o.o
I asked mostly to understand if it was a bad idea to begin with. But if there is not any counter indication i will give it a try
equipping item and unequip it is working as it is able to spawn equipment to attach to player hand or removing it
You'd need to move it into ReplicateMoveToServer and PerformMovement I guess.
ReplicateMoveToServer calls PerformMovement already
Yeah, but too late.
It already needs the Acceleration earlier.
Yeah, then you should have an OnRep for the Equipped Item soemwhere already.
That should trigger the LinkLayer fwiw.
it was using server reliable and multicast xD
It seems like Acceleration in ReplicateMoveToServer is used only for SetMoveFor, why would it need to have a post jump Acceleration?
Well i'm stuck regardless cause not having a source build i need to copy paste the functions and i need some CVars that i cannot access
Could you DM me if your available so i can elaborate more? Thank you
Cause Jump puts it into falling which will clamp the Acceleration differently.
I tested it and if i move the logic to PerformMovement it works but applying root motion there causes corrections, if instead i move it to UpdateCharacterStateBeforeMovement it works fine under any aspect.
In both cases i get no correction for the default jump logic.
Yeah i get the need to clamp the acceleration if we jump before SetMoveFor, but i do not see the reason why the jump should happen before that
@thin stratus thanks! OnRep solve my issue ;D
How would you go about displaying health of all other players in your group ?
i did get it working, but i was wondering how would be good
i used onrep and some loops/checks
we need a sarcasm font
if you use a onrep you probably don't need to loop or check anything
well one thing i have to associate the widget with the user so i use a unique id
s i need to loop for that
but also i had to use a workaround
why do you need a loop?
just add a delegate to the onrep of whatever holds the player HP and have your UI bind to that delegate
no looping, no id needed
hmm
idk what your saying i think use an event ?
dispatcher
for me it's ok because i only have a couple players
I can't entirely remember what they're called in bp but I think that's it
UI should pretty much always communicate through delegates
Throwing this out there in hopes someone knows of a way. I need to run memreport -full on a headless server to find out why a crash is happening. The problem is the server doesn't have a built in console to run this from. I tried adding it through the command args in properties but that's just ignoring it or messing with the level being passed in. Any thoughts?
this isn't ideal for a large group
and also have another loop
i will try with event dispatcher
but i'm not sure how to go about this lol
Your game logic shouldnt change regardless of if your UI exists or not
A delegate is the best way to do that
i just want to avoid all the loops tbh
it works and is ok for a small game like i'm saying for my purpose it might work
In your onrep for HP, add an event dispatcher
Then your UI bind to the event dispatcher in beginplay or something
hmm ok
When the onrep gets called, the event dispatcher is broadcast and the UI then updates
hmm but i need to tell each on the correct player
so when it fires off i actually want the local stuff to change
the health is on the player
Actor?
yes
You might have issues with relevancy later, but you just need to get a list of teammates when your UI first initializes
That works
and it works and one logs out it fires off and everything works
it's just that for each player onrep i'm doing all this loop
So UI BeginPlay->loop through teammates and setup UI
Each player actor health has its own onrep
well i also need to setup when a player joins
because that would just say when you join and show the players, but when others join it wouldn't show up
so i set it up in the player controller
on acknowledge possession
with a few retry hacks
and on game mode, login/logout
i'm trying to think of how to fire off the proper event on whatever machine is running ?
i was going to use rpc, but i assumed onrep would be more performant
but i think with all these loops, perhaps an rpc would be better
RPC is probably more performant but you should never use them to change state on clients or to react to changes in state
OnRep is ideal
The client sets up the binding to delegates themselves
The OnRep will trigger on any client where the actor is relevant
hmm
The only way to control what machine "receives" the OnRep is by controlling relevancy
You probably don't want that here
Relevancy will actually probably cause issues if players are far apart because the actor will despawn on clients
ya i want them to be able to spread across the whole map
not a huge map, but still
i have the enemy and players, always relevant
You can also toggle "always relevant" which is probably fine
Yeah
Enemies maybe you don't want them always relevant
But for a small coop game teammates being always relevant is perfectly fine
well i want the players to be as far as part as the map allows
as far as if they want
They can always do that on the server just fine
It just keeps the actor loaded on every client at all times
So you will still get health updates and such
wdym always on the server ? if they go to far from server player the on reps don't go off ?
would i have to do something on the client side to display ?
and then let it sync later ?
When an actor becomes not relevant to a client, it is effectively destroyed on the client
When the actor becomes relevant again, it gets constructed again and goes through BeginPlay
Server always has everything loaded for itself because it's the server
If an actor is too far away and becomes not relevant, the client doesn't know it exists and will not get OnReps
So you either have to make the actor always relevant because that's where your health is stored, or relay the health through something that is always relevant to all like PlayerState
And tbh, probably makes more sense for clients to bind to a delegate on PlayerState. then in case the actor being possessed changes, the UI doesn't care because it just binds to the PlayerState
Sorry if that's a bit much
The pinned messages here have some good resources
@lament flax saves his notes online and has some decent replication sources
i can also put my loops in c++ might be just fine like that
atleast untill i can figure out what your saying, i think i get it the health shouldn't be on the player, it should be in player state
but i have no problem getting the health
or setting it normally
just getting every other players health and updating on my ui when other player changed
but events seem the best way to go, i'll look into it thanks
Performance isn't an issue here
Well, health can stay on the actor if you want. But changes to health on the server would get forwarded to the PlayerState which then replicates to every client
thats all i'm worried about lol
if the way i'm doing it doesn't cause a performance issue then i'm fine with it
for what i been trying to get working, a lot of the sync stuff is a pain
but now it doesn't matter how they log on, order, timing
everything syncs up
the real test will be with latency i guess over the actual web
I guess you were meant to put this one in #source-control ?
Oops, yeah
heyy, right now when I try to interact with an editable text box with a client doesn't let me interact but with the server yes. I think it could be maybe a focus issue or something but I'm not sure and I don't know how can I be able to interact in the client too. if anyone can help me pls
Does Unreal’s replication system provide a built-in way to check if an actor’s state has replicated on the client? Like some sort of counter or “change id” that increments each time replication happens, so you can confirm you’ve received the latest server state across actor channels?
Not that I know of for like per var sorta deal
(There is a function that gets called for the entire actor)
But, from what I heard.
Vars and stuff is repliable, so it should happen, as soon as possible.'
What are you intending to do?
Just knowing when client has a value change, but from the server? (since server needs to send the change)
PostNetReceive can probably be used for what want perhaps.
I have this inventory system...
// Ther user calls this function, which saves the OnResponse delegate along with a request guid.
UKhaosInventorySystemComponent::TryMoveItem(FKhaosInventoryRequest_MoveItem Request, FKhaosInventoryResponseDelegate_MoveItem OnResponse);
// Which calls
UKhaosInventorySystemComponent::Server_MoveItem(FKhaosInventoryRequest_MoveItem Request);
// Which calls, on success, it needs to call the OnResponse delegate.. However, only if the UKhaosInventorySystemGameState (which holds state) component has also replicated the change from the request.
UKhaosInventorySystemComponent::Client_MoveItem(FKhaosInventoryRequest_MoveItem Request);
So my solution is having something like this
// Where Revision is UKhaosInventorySystemGameState::Revision. This way I can call the Delegate if we are up to date, or wait till the UKhaosInventorySystemGameState::Revision >= Revision.
UKhaosInventorySystemComponent::Client_MoveItem(FKhaosInventoryResponse_MoveItem Request, uint32 Revision);
Hope that makes sense. Basically I am trying to ensure sync between actor channels.
I never got what that was for, it has no params? Is it just "anything updated"?
Not sure I follow the inventory system.
But, sounds like you would just want an on rep variable?
Yeah, I think so.
Or, are you trying to keep multiple moves in order?
So, if I move it from 0 -> 5, then someone else does 5 -> 3 You wanna have moved in the correct order, and such?
Cuz, that also sounds like what it is?
In which case, your over-complicating it.
It's just to make sure that when the calling client receives it's acknowledgement from the server (though Client_MoveItem). It does not call the OnResponse delegate assiated with the request before the game state is also up to date.
Otherwise there would be bugs where the client tries to do something with a newly created item in the OnResponse callback, and the action fails client side validation because the state is not synced.
I feel like now i'm more lost, or your describing it weird?
Client moves it, has a callback, but the callback fails, because the client didn't move the item it just moved?
In actor channel 1 (player controller): Client sends a request to move the item. Now the server updates inventory state and acks the requesting client.
In actor channel 2 (game state): Inventory state was just changed, and is being replicated.
The issue is that i cannot assume that actor channel 2 has replicated the state on the client when the client recives the Client_MoveItem RPC, and thus I need some sort of sync key to determine it. That key is passed with the ack to Client_MoveItem, can can be checked against UKhaosInventorySystemGameState::Revision.
if UKhaosInventorySystemGameState::Revision => Client_MoveItem's revision we know it's safe to call the OnResponse delegate, i.e. it's safe to trust what was sent in the response struct.
Oh, I see.
Its a miss-understanding of how I usually envision item replication.
Then, yeah.
An on rep would make the most sense here.
I replicate the items themselves, then just move them around with reliable RPC's.
Request Move
Server Move
Client Move
Since its reliable, it should keep everything in-sync.
So, when the client has its RPC move replicated, it moves the item, and done.
Should be all in-sync.
I see, I am not really able to do that here with FastArrays.
Ah, I see.
Yeah, I don't use any of that special stuff.
It makes the items that part of like unknown if sync'd but the item themselves matter far less, then client clicking on raw meat, but server thinks its a sword or something goofy.
Store health in the player state which is copied in the Gamestate and is replicated to all regardless of relevance.
Hello! Has anyone encountered compiling a dedicated server on Linux if the project includes Wwise? The client build is purely on Windows, the Wwise license is purely on Windows, and Wise is not required in the server build.
If everything is clear with sound calls, just wrap them in a macro and that's it. But what to do with Wwise volumes and portals on the map and in the BPs, i can't wrap them in a macro))
I understand that wrapper classes can be created, but they would be inconvenient to configure, as Wwise classes have many parameters, and transferring all of them to a wrapper class for each one seems like a hack.
But maybe there's a better solution?
The WWise licence will only cover their SDK code. It will not cover the plugin. So any plugin code, like Actors that wrap their SDK is perfectly acceptable to use as you will.
Therefore, all you need to do is to compile out any calls to their SDK.
A Blueprint callable function is not covered by their licence, the call to their SDK that the Blueprint callable function calls is what you want to remove.
So the Blueprint function becomes an empty stub basically.
Personaly i make the PC call a reliable RPC on server with slot info and the client will get the replicated state through OnRep
And next to the server rpc call in the widget i would also update the slots like the change already happened to have some fancy item prediction
Update the item like it already happened?
That seems wasteful?
2 reps to move an item?
Nvm
Brain fart. 😛
not 2 reps
1 local "update slot display" for local client prediction
the server will rep the state back anyways
When making an indie multiplayer game, is there a difference in frame performance (game heaviness) between Unity and Unreal Engine?
Please consider the game design as Lethal Company.
What exactly do you want to know? Most of this is up to the developer, not the Engine.
I see.
When I asked GPT, it said that Unreal Engine is photorealistic, and because of its high performance, it tends to be harder to optimize and generally heavier than Unity.
I’m glad to know that’s not really the case. Thank you.
Sorry for asking something so trivial.
Yeah, you can make all kinds of games with UE. And maybe UE is initially a bit overloaded, but especially for an Indie Multiplayer Game, UE offers a lot more stuff out of the box. I'm pretty sure you can make an equally unoptimized mess with Unity if you aren't making sure your code and assets are fine.
if (SoldierCharacter->IsLocallyControlled())
{
if (bWeaponEquipped && EquippedWeapon && EquippedWeapon->GetWeaponMesh() && SoldierCharacter->GetFPSMesh())
{
LeftHandTransform = EquippedWeapon->GetWeaponMesh()->GetSocketTransform(FName("FP_LeftHandSocket"), ERelativeTransformSpace::RTS_World);
FVector OutPosition;
FRotator OutRotation;
SoldierCharacter->GetFPSMesh()->TransformToBoneSpace(FName("hand_r"), LeftHandTransform.GetLocation(), FRotator::ZeroRotator, OutPosition, OutRotation);
LeftHandTransform.SetLocation(OutPosition);
LeftHandTransform.SetRotation(FQuat(OutRotation));
FTransform RightHandTransform = SoldierCharacter->GetFPSMesh()->GetSocketTransform(FName("hand_r"), ERelativeTransformSpace::RTS_World);
FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(RightHandTransform.GetLocation(), RightHandTransform.GetLocation() + (RightHandTransform.GetLocation() - SoldierCharacter->GetHitTarget()));
RightHandRotation = FMath::RInterpTo(RightHandRotation, LookAtRotation, DeltaTime, 30.f);
}
}
hand is rotating, but weapon rotation is getting wierd
Client RPCs?
It won't keep state synchronized if a player late joins or relevancy changes
Cant figure out why UKhaosInventorySystemComponent::OnRep_Backend (replicated subobject) is being called with nullptr on owning client. What am I missing?
// AMysticPlayerController
class AMysticPlayerController : public APlayerController
{
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inventory")
TObjectPtr<UKhaosInventorySystemComponent> InventorySystemComponent;
};
AMysticPlayerController::AMysticPlayerController()
{
bReplicates = true;
InventorySystemComponent = CreateDefaultSubobject<UKhaosInventorySystemComponent>(TEXT("InventorySystemComponent"));
}
// UKhaosInventorySystemComponent
class UKhaosInventorySystemComponent : public UActorComponent
{
virtual void BeginPlay() override;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UFUNCTION()
void OnRep_Backend();
UPROPERTY(ReplicatedUsing = OnRep_Backend)
TObjectPtr<UKhaosInventorySystemBackend_GameServer> Backend;
}
UKhaosInventorySystemComponent::UKhaosInventorySystemComponent()
{
PrimaryComponentTick.bCanEverTick = true;
bReplicateUsingRegisteredSubObjectList = true;
SetIsReplicatedByDefault(true);
}
void UKhaosInventorySystemComponent::BeginPlay()
{
if (ensure(GetOwner()) && GetOwner()->HasAuthority() && ensure(!Backend) && ensure(BackendClass))
{
Backend = NewObject<UKhaosInventorySystemBackend_GameServer>(this, TEXT("InventoryBackend"));
check(Backend->IsSupportedForNetworking() && Backend->IsNameStableForNetworking())
AddReplicatedSubObject(Backend);
}
}
// UKhaosInventorySystemBackend_GameServer
class UKhaosInventorySystemBackend_GameServer : public UKhaosInventorySystemBackend
{
UKhaosInventorySystemBackend_GameServer();
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
// Replication plumbing
virtual bool IsSupportedForNetworking() const override { return true; }
virtual bool IsNameStableForNetworking() const override { return true; }
virtual int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;
virtual bool CallRemoteFunction(UFunction* Function, void* Params, FOutParmRec* OutParms, FFrame* Stack) override;
}
I feel like I am doing everyting written in the docs.. https://dev.epicgames.com/documentation/en-us/unreal-engine/replicating-uobjects-in-unreal-engine
Use the replicated subobject list later in that resource
And is the actor you have this on replicated?
How do you mean?
Yes.
I set bReplicates=true and bReplicateUsingRegisteredSubObjectList = true in constructor.
I think you might also want to create the New object only on the server and have it replicate down
Also not sure the name is stable since you're using NewObject
Yeah, this is what i am doing here
void UKhaosInventorySystemComponent::BeginPlay()
{
if (ensure(GetOwner()) && GetOwner()->HasAuthority() && ensure(!Backend) && ensure(BackendClass))
{
Backend = NewObject<UKhaosInventorySystemBackend_GameServer>(this, TEXT("InventoryBackend"));
check(Backend->IsSupportedForNetworking() && Backend->IsNameStableForNetworking())
AddReplicatedSubObject(Backend);
}
}
Hmm, I will try to return false on that one.
Though I just needed to name them the same in NewObject.
Aha! That was the issue. Thank you very much :)
I think the networking system tries to look for a stable name first, then goes elsewhere
Stable name would be for something you can uniquely create on both client and server and have them match
Or assets
I see. That does make sense.
Hi all, looking for a bit of direction on this one. Just not sure how to plan it out. Basically I have server AIUnits that a player passes 'Actions/commands' to and the server executes this command at a certain point within the turn. However I want to start the game with players being able to choose a spawn tile. I got the logic for selecting the tile but I'm just mentally blocked on how how to show/hide the tiles dependant on if the server unit is alive or dead.... didnt see a game logic kind of channel so asking here as it is multiplayer
in my head im setting on the player controller if the unit is alive or dead and updating the hud and showing/hiding the tiles then but fdor some reason it just doesnt make sense and im after input on a direction to go if it doesnt
Im assuming on the destroy of the event i hide all spawn tiles and on event destroy i show show them and update the HUD at the same time? or should the unit begin and destroy events call the 'Command controller' attached to the unit and update from there
can anyone answer, im trying to make a system where when you transition levels in a session data like inventory and health travel. im aware the game instance is usually the go to but since the GI is persistent the whole engine runtime and i dont want the data in ouside the origin lobby is it a good idea to save it inside the playerstate?
(ugh just came to the revelation seamless travel doesnt work in editor)
Hey, I’ve got a progress bar for something like health. It doesn’t need to be updated every tick, only on certain events. The “health” variable is replicated on my health component, but when testing with lag, I noticed the widget bar that uses the replicated variable gets out of sync on client.
I made a workaround by creating the same variable on my character (not replicated) just to update the widget. The downside is I now have to update two variables: the one on the component and the local one.
Is this a good idea, or is there a better way to handle updating replicated variables on widgets?
its not really a big seal since an int or a float are using 4 bytes of memory as long as it fixes your issue
If I have a very large replicated struct array on GameState with maybe 10k-30k entries, is there any reliable way to know when that array has finished replicating for the first time on client login?
If I make it repnotify, when does the notify fire.... only once when it has completely finished replicating? Or does it replicate large data in stages and fire multiple times?
depending on how big the elements are you're going to run into issues
You might hit the size limit per bunch
i would make your own system to chunk it and reassemble it on the other side
which would solve your problem of knowing when it's fully ready on the client
may as well send size of the array
Hey, by default components exist on all instances of the character. Is it possible to make a character component only on the server? I want to create a detection radius for a certain character, but if it exists locally someone could just hack its radius, right? Also, there’s no need to create this on all clients since only the server will fire the overlap event. Should I just destroy it on locally controled characters? It seems to work fine
you could also add it dynamically only on the server but this should okay assuming the object can't do anything between spawning and ending play
In C++ you have more control over it. In blueprints you would need to remove it the way you currently do. You still pay the price for creating and destroying it but at least it won't be part of the updated component transforms.
In terms of cheating, there is nothing the client can do unless you allow them. If the component doesn't have an ServerRPC, or is altered by one from the outside, that modifies the radius on the server, then nothing can happen anyway
Is there a good way of doing per-connection filtering of fast array entries? I basically need a relevancy check per entry.
no
maybe if they point to a specific sub object, those can be filtered
Well shit.
the easy thing is to just make multiple fast arrays
Oh, how?
making replicated sub objects and filtering them with groups etc
iirc you should be able to just not replicate them to some clients but
I don't know what the data actually is
or why it filters per client
making a whole new object for replication is not free of course
Hmm. Okay. I am looking to add some sort of relevancy to items, such that they are replicated based on their proxy actors position, what inventory they are in etc. All items UObject subobjects of the game state. Not sure what the best pattern is here.
so why not just have it on the proxy actor? is this some kind of global list of them?
having a network manager is a great idea for some things but idk if this should be a global list of spatial things
Yeah, i have a InventoryStateComponent on the game state which holds a list of inventories and items. Just the data, then the proxy actor refers to it by handle. So the items, and their data in themselfs are not spacial. I have a lot of data on the items in a component like system, where each item trait has their own data. They are called item fragments. So I thought it made a lot of sense to keep a state component with that owns the data.
having fragments tends to be in a definition at least in Lyra
which is just a class path networking wise
I have two types of fragments. Static and instanced. Instanced fragments has per instance data, which is individually serialized to the database. Static fragments are just gotten from the item definition primary asset.
The spacial relevancy of the actor proxies is easy. But in the current implementation, the non-relevant item data is also replicated to all clients, which inefficient due to replicaing too much data and insecure since a client would be able to just read the memory and see what items are in the game.
That is really the part I am looking to change. How do I make relevancy per subobject, and how do I connection-specific view for lookup.
I still don't see any part of this that needs the global manager on the gamestate
How should it be then? Who owns the subobjects?
the actor instance that they represent, no?
And then change ownership when the item is picked up?
I guess idk why the handle here to the gamestate matters unless you want to have them sort of exist even when not nearby to serve as a global lookup
either that or just recreate the instance entirely
Hmm
Forgive me if I have been rattling off an iris-specific feature... I assumed groups were in the old netcode as well https://dev.epicgames.com/documentation/en-us/unreal-engine/iris-filtering-in-unreal-engine#group
No problem.
is there a notion of "teams" or alliances in this game? could there be a bucket per-team?
or are there more than a handful of potential sets of items you want to send
So, the inventory system is designed for a survival extraction shooter somewhat like Tarkov, or Dayz. We have ~1-2k items per map. I am still a little conflicted on the who owns the items question. I guess you could have a point that the actor/object representing them should also own them..
if the items are on the floor then they should just replicate by distance, no? I'm confused
you could probably do something fancy and pack them down into a network manager for each rough area or grid cell like Mass replication does (they have a manager actor for groups of entities called bubbles but idk exactly how they transition between them)
It just seems like a lot of sync barriers, and not sure what effect is has on rollback. The current implementation is highly transactional, so it's easy to have a list of "predicted transactions", there is also that the user API has an OnResponse delegate for each requested action. That means that the per-client system component needs to wait for all side-effects of the request to be fully replicated before sending a response, which is somewhat easy with a central manager- and likely also doable if the items are owned by actors. I guess that would just be OnRep if they are reconstructed
yeah the single holy list does help avoid dupes I assume
also
the idea of this transaction does not have to be replication, the replication could just be representing where the item is
the transaction could be a series of reliables
where other clients just see the results as the represented areas
the representations could just be a potential request into the global manager, but the representations are spatial etc
This kinda boils down to the philosophical question of is an item actor the item, or just an interface for item. The interface for an item model works very well for UI, because the UI is totally decoupled from the actual item, so server build can just disable the game feature providing inventory UI and work anyway. But for world actors it more nuanced.
which is kinda what you do now but what I mean is to not have the instance data in the global manager replicated, but maybe sent alongside the sort of spatial thing where they are results from the holy database
indices sent that you arne't close to or can't really own are ignored etc
Hmm. yeah.
No, it's needs to be per connection filtering.
so the holy gamestate list could serve as an authority only thing
where it is sort of the goalkeeper of the item and serves to represent the path it took to get to where it is
but the players see an actor with stuff on it etc
they don't need to know about the gamestate, they just need to see an item on the floor and press E on it
That might not be too bad
but I honestly have never had to make something like that from scratch so don't take my word for it, there might be some nice examples around of people making similar pvp/extraction etc survival games where item transactions are an issue
I am wondering what not having that list on the client would mean. The only think I can think of is prediction of actions, like showing green text if i can pick up the item based on some fragment condition, and red if not. If the client only knows the actor, that would have to be a server RPC to get that information. Also other types of "can I move an item here" checks, that are currently done based on the clients version of the "holy gamestate data".
It's a pretty smooth solution for solving the relevancy issue tho.
And likely the simplest and fastest as well. Due to replication graph / iris.
Hello everyone, currently bashing my head against the wall known as "Steam Advanced Sessions Setup" in UE 5.6. I've been through every tutorial and fix and just can't get it to work. I have what is nearly a default thirdpersongame going on but with a main menu screen to create/join sessions.
Every single time the Join Session node fails where it has the "failed to join session2" print string. I've got no idea what I'm doing wrong or what I could even troubleshoot at this point. Got some experience in single plalyer games, this stuff throws me for a loop. Would greatly greatly appreciate any help or insight getting this rudimentary multiplayer system working.
Also note this isnt a packaged project, all testing has been done in the editor with 2 windows for testing 2 players.
Thx for any info/assistance in advanced 🙂 👍
(there are many videos but this is the written guide I'm trying to follow: https://unreal-chronicle.hanayou.dev/docs/miscellaneous/advanced-sessions-setup
I'm stuck on Testing Multiplayuer in the Editor, since I can not get Join Session to work)
when you test, test on the listen server itself as a listen
to test the actual steam stuff you need to have two computers or two accounts running somehow
but if you package your game
when you run it
while steam is running
Hello, I have a fast serialized array with structs that contain object ptrs. Everything gets replicated as it should, but when I started testing it, client-side it seems to GC the uobject eventually. Server-side it's always valid, but client gets rid of it for some reason. The outer of the object is an actor component which the client has, I double checked and MyUObject->GetOuter() inside PostReplicatedChange() is correct... The server never GCs it unless it doesn't want to have the object anymore.
What could the reasons for it to be GC'd in case the outer is valid? Is there any way to hook to something that would tell me what object got GC'd?
nvm I was changing the outer server-side after AddReplicatedSubObject, so clients had it set to the old outer which got destroyed
you should be able to see your game name next to your name while your playing
so when you hit host does it travel to the listen map ?
hey all , I dont think this issue is unique to Steam networking but, with steam implemented in my racing game, im noticing I need Seamless travel enabled on all my gamemodes .
However , enabling this makes restarting the scene kind of impossible? as in the Restart Game Node, no longer works , im not sure if there is a work around, I use the restart game node mainly for restarting the races in all my various modes in my game, its pretty important.
but if anyone has any ideas id really appreciate any and all insight, thx
TLDR how do you handle restarting in seamless travel scenarios?
You should always be able to server travel to the same map again.
hey, I have a actor, inside, I use SetOwner(MyPawn) if the player interact with it. I override OnRep_Owner(), I added a log inside but this funtion seems not triggered, any idea?
oh wait..that..makes sense , iunno why i didnt think of that , thanks lmfao
It's not perfect in all cases. Try it. If it works it's a quick solution.
Do you have UFUNCTION on your override function?
That is
UFUNCTION()
virtual void OnRep_Owner() override;
compile error
Override of UFUNCTION 'OnRep_Owner' in parent 'AActor' cannot have a UFUNCTION() declaration above it; it will use the same parameters as the original declaration.
Ah, my bad. Though that was required.
Are you calling SetOwner from server?
bReplicates = true?
Is the actor relevant to the client?
I also assume you expect the OnRep to be called on the client, not on the server?
yes
and yes
Does the actor have a new owner before you set it? (HasNetOwner())
it's a actor, so null I guess
When in the object lifetime are you setting the owner?
fully closed editor and compiled?
are you positive your actor derives from your class with the override?
does anyone know why an animation would affect player position on server, but not when playing as client?
some setting within the player bp
it's going through an RPC and works with a different character, just cant seem to find why
Thanks for the reply! I have been testing with Play As Listen Server set for the Net Mode. Was just trying to test everything out in editor before properly connecting it to Steam to test the packaged product. Got plenty more game to build before packaging, just need to make sure players can interact in real time before I can develop much further.
When you hit host it doest travel to the listen map, even for both players without a problem! Only issue is no matter the order the Join Session button has never worked, and always returns the "Failed to join session2". So all I have right now is both players who are able to host their own games, both of which use the same listen map.
step one is to show code
Hello, does anyone deal with moving uobjects between different outers? I want to give a different outer for a replicated uobject, but it seems not to replicate that change. I had to change it client-side, as well as move the sub object from actor channel to the new outer for it not to be marked as garbage when the original outer gets destroyed. It seems to work, but the approach seems wrong, I feel like it can break easily. Did anyone else try to do something like this?
changing outer especially in a replicated context is very prone to issues like the ones you stated
what you're doing is pretty much what I've had to do as well so that sounds right
Make sure you remove the object from the previous outer's replication list, and add it to the new one
Yes, that's what I do, but I still have to manually unregister the sub object from actor channel client-side
Otherwise it gets marked as garbage when the old outer gets destroyed
yep
Did you have any other problem with that?
an interface that may help you is IActorSubobject_Interface
i think thats what it's called
I'll look into that once I'm at the computer
you can slap it on the UObject and it has functions the engine will call when it's created/destroyed from replication
but that's about it
keep in mind the object will be recreated on the client
i wouldn't attempt to move it there
you'll end up with dupes
or worse probably
So it'd be better to recreate it server-side, and don't change the outer altogether?
Are you sure though? The only reason I had to deal with it is that the object got GC'd. I move it from one fast serializer array to another, which reside in different actors, yet the object got GC'd as if it's the same one
I'm trying to access the HUD from the player controller, but it keeps failing ?
I'm looping through the player array
And using the controller of the current in the loop
To call an event in the hud
Hmm, I'm trying to update player cards when postlogin
I generate the cards on possession np, but when others join after I'm having an issue rebuilding the cards
Thanks! You're my savior) I just downloaded Linux files of plugin without license for Linux and all compiled. Thanks! 🔥
Show your code
HUD exists only locally on each client, no server instances
so i tried even calling the event elsewhere and it still not working
why looping through the player array and getting hud through controller is failing ?
Looping in server? The reason I wrote above
You need to create in player controller Run On Owning Client event and in it call event in hud
When you looping server controllers - call this event(Run On Owning client)
i have tried this
it doesn't work
maybe i was doing it wrong
in the controller i have an event
that sets runs an event on the hud
this works fine when ran from the controller
but when in game mode, on postlogin it's not working as expected
Show your code)
Reread my solution)
HUD dont't exist on server
You call Get HUD in server
You need put get HUD in controller event
so pass the player ?
not the hud
i'm not understanding lol
HUD is local to each player
listen server has one
clients have one each.
they are local, not networked nor reachable by other player other than the owner.
Maybe what you want to do is,
As server -> Tell every client to do X?
In that case,
As server -> Loop every controller -> Execute functions in that controller via client RPC.
RPC is for event based though, the cards should always be updated via OnRep imo.
Updating variables with RPC is recipe for disaster.
betteer solution to read documentation about networking, to unerstand how all it works. As said ColdSummer - if u fix that function and it will work - it's doesn't matter, because the current method for updating cards is incorrect in itself.
i'm updating widgets, and only on login/logout
z1kot shows how server can tell clients to run function.
But for what you want to do, you shouldn't even talk to anyone's HUD.
ya the docs
You don't want to update anyone's widget.
server don't even need to know anyone's widget or any player widget for that matter.
what you want the server to do is to propagate STATEs
So in this case, think of card as Inventory and items. They are normally represented as actor component.
Server -> Get Player -> Get CardComponent -> Set Card values or w/e.
the card can be a replicated variable. Clients will eventually get the server value on the next Net Update.
In which they client can do OnRep (Card)-> Broadcast.CardUpdated.
and here, the Widget listen to the broadcast
i'm creating them dynamically
so whenever the card is updated on client side, it updates the widget.
Yes, and the answer remain the same
Having server telling clients, hey update your widget
is noob mistake, sorry for the language.
just my honest opinion
and yeah im noob too
but I believed Im over that stage
yeah but once you understand replication it's actually the easy part.
i guess i can use onrep
it's best practices, not abuse)
idgaf about all that
i just want these damn cards to work lol
i been stressing for hours over this crap
give your self weeks
I dunnoe about others, but I went through countless errors.
until one day, it click.
try that didnt work
show code
@lyric heart Check again my message))))
wdym ? the get player controller not work ?
Multiplayer or singleplayer - it's doesn't matter. Widgets always just listening, also in singleplayer you must not call directly update widget)
But singleplayer forgives many problems and it works) But not in multiplayer)
Many youtube create dependency with the widget =(. They even do Hp subtraction there.
so when widget doesn't exist, game break.
He’s not casting a player state to a player controller…
Hahhaha))
fact
Yep, sorry, didn't see
and it's succeeding
@lyric heart
Show code X_X
yes i just tried this it didn't work
Second reason - client version of player controller didn't exist at that time when you calling event. And it will not replicate to client
PostLogin is generally too early to do anything with the player state IIRC.
Depending on if you’re doing seamless or not, HandleStartingNewPlayer is the function you would want IIRC.
RPCs are for event. so Like welcome message, or good bye message.
For your cards, just make your card a replicated variable.
what ever the server set the client will eventually update.
Wild suggestion: If one needs to react to a player joining locally and needs access to the PlayerState of said player, one could use the BeginPlay method of the PlayerState.
assuming an object is present in multiplayer that is a distinct property or object is always a bad idea
replication-wise at least
Iris seemingly makes this worse, as even the few order rules we had for RPCs and Properties went out of the window.
one simple thing is if you have 2 things that can show up at random times is to just have both do the same "are we both here yet?" call that can only trigger once and puts them into an initialized state and does the actualy "do stuff" code for whichever one is second
I love how whenever someone is asking for specific help on a topic they don’t understand, it devolves into everyone talking more in depth into something the person clearly doesn’t understand 
Iris internals are them literally bending over backwards to make it at least resemble the old order
relying on the old order was a bad idea in the first place imo but yeah there are some weird onrep orders sometimes
Glad we do something you love. Hope you enjoy the ride.
It's not solution - to ask a question and get fast answer. Because he don't understand multiplayer and just right answer fix his current problem, not future problems. But if he understands more - he can make less mistakes in future
Seems like the original issue was mainly accessing the HUD on the server and expecting it to be valid.
But yeah, I do see a lot of tutorials and such use PostLogin to notify players about a new player.
And that's not necessarily wrong, but if it requires certain other actors to exist locally, then it quickly breaks.
While fair and I support that thought, I'm pretty sure Elliot meant the Iris talk.
Or maybe my suggestion, but I can't say I posted that to actually answer the question of the poster.
No I just meant everything in general, it was a joke tho. Not to take literally
@lyric heart Fast solution for your problem.
But i recommend to read docs, there're many useful info and good examples
it's kinda difficult for us to follow along with what changed here without seeing what the code is and what the result pressing play is
@lyric heart repeat it and if it still don't work. Show your code TryTryAgain event in player controller
ya i'll have to fix it i broke the fkn thing
I mean, engage is here for like 2+ years or so. And I'm pretty sure they worked on multiplayer stuff before. Confuses me sometimes when I see peeps still struggle that hard and then also fail to actually post proper information instead of "now it's broken lol".
brb
no shame in multiplayer stuff being confusing I guess
Yeah I guess. Just somewhat expected some of the basics to be there by now.
this is my first time doing multiplayer
it's ok
I’ve seen that phenomena a lot and I just attribute it to wanting to make a game more than learn how to make a game and improve. (Not to say that’s exactly what’s happening in this situation, but in general).
That’s why it’s often more you’ll see people wanting to just have their code fixed instead of explained. (Again, not saying this scenario, Engage).
Guess I just remembered wrong. All good.
now all of a sudden the player isn't spawning ?
i have a backup but i'm hoping not to lose a days work lol
The ladder half though 
Blame Epic Games for exposing some functions as ImplementableEvents and some as NativeEvents.
HandleStartingNewPlayer is a native event.
You gotta call the Parent function, otherwise you are overriding the C++ code.
show your code, pls)
It's the lack of the Parent call in your simple setup you shared.
They made some changes to gameplay cues a while back (not sure if they reverted), that had the same “feature” and it drove me up the wall
It fully replaced this:
void AGameMode::HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer)
{
// If players should start as spectators, leave them in the spectator state
if (!bStartPlayersAsSpectators && !MustSpectate(NewPlayer))
{
// If match is in progress, start the player
if (IsMatchInProgress() && PlayerCanRestart(NewPlayer))
{
RestartPlayer(NewPlayer);
}
// Check to see if we should start right away, avoids a one frame lag in single player games
else if (GetMatchState() == MatchState::WaitingToStart)
{
// Check to see if we should start the match
if (ReadyToStartMatch())
{
StartMatch();
}
}
}
}
ok, yes that was the problem
thank you
What sometimes gets me is BeginPlay itself. It's not a Native one, so calling the Parent on it in the first Blueprint child class won't do anything.
But if you have a custom C++ parent class and you are doing something in BeginPlay, it usually calls AFTER the BP one due to that.
But why it's calling my event in player controller and debug print string return hud name?))
calling the parent is super unintuitive in bp in general for me and I wish it was kinda more clear "hey, there COULD be a parent here but there isn't" which of course is sometimes the point but should at least be clear
E.g.
void ASomeActor::BeginPlay()
{
// Doing something that is required inside a child BP's BeginPlay would work here, but now the Actor as a whole "hasn't begun play yet".
Super::BeginPlay(); // This sh*t is calling the child BP's BeginPlay.
// Doing something that is required inside a child BP's BeginPlay is too late here.
}
Inconsistencies make us stronger in unity 
Why wouldn't it?
I didn't see, he wrote player not spawned) Sorry
@lyric heart can you take a clear screenshot of the entire extent of everything you’ve connected to the HandleStartingNewPlayer event?
i'm not using that event, it fkd everything up
atleast i don't know how to use it
Do you know how to call a parent function in BP?
UE knows exactly what class, super class, event, etc. it is displaying with a node. They could easily add a button to Event and Function nodes that spawns the Parent call node whenever the Event is inherited and the Parent is another BP or when the Event is from a C++ class and a NativeEvent. Having us to remember and rightclick the node to spawn it is annoying, yeah.
@lyric heart Please start explaining what doesn't work. You will drive people away from helping you like this.
I understand it’s frustrating, but you need to put in effort as the person asking for help, to expect others to give their time
it's not updating the huds in each player
What does TryTryAgain do anyway?
you would assume it would try try again on each one ?
I think it’s a spin wait
it works, it creates the widgets
Can you post a screenshot of it, please?
The code in the image you shared can't be at fault. If you put a print string into TryTryAgain and it calls properly for each new player on all connected players and the new one, then it's not at fault.
Which means TryTryAgain or anything after that is at fault.
Ok let’s, start over
That's not enough info to help with. Which of these events are all calling and which aren't? You have a PrintString node there. Put more into it. Check if everything calls the way you want it.
Now I understand what you said about) I think only one must answer for asker. If not, it's unreadable list of messages, which more confusing asker)
wait no, that’s not what I meant
That only works if the person answering 100% knows their crap though.
ffs all i want is cards for the players lol
the try try again works for when possessed
it shows the ones that already logged in
i run it on acknowledge possession
All you want is to have everyone update their hud when a new player joins, right?
i want to remove all created cards, and create cards based on the player array
which trytryagain does
set all widgets is on the hud
That's easy. As server -> Get all player -> Get each card variable, set to null. Done
what ever you want to set the value, just do it in the server as replication goes from server to client.
@lyric heart The big thing here is that you have all the options to debug this instead of showing these images to us hoping we spot the issue.
You have Breakpoints and PrintStrings. If something somewhere doesn't work, then a PrintString and a Breakpoint would both indicate that.
You clearly don't know where and why it fails, so please do yourself the favor and figure that out first.
Put PrintStrings along the whole execution chain, from PostLogin or whatever you use up to where the Cards are created.
And print meaningful information with that, not just a random string. Print the Object DisplayNames, the PlayerNames, etc.
Once you have that it should show you where it stops working.
Because right now all you do is show us parts of your code, saying "code works" but "it's broken".
Who the hell should know how to fix that with that info?
My light doesn't go on. But the bulb works (haven't tested), the breaker is in (haven't checked) and the light button is functional (haven't pressed it).
Please tell me why the light doesn't work.
I'm gonna die in Hollow Knight a few times now. That'll be more enjoyable I guess.
i'm generating them on them each time
they are not created yet
hmm, ok
it's failing on the cast to hud
How can a person(which know 100%) help if everyone starts writing in parallel? engage don't understand what he do and solution is to help step by step with code screenshots or try tell basics. In this situation he need just solution step by step, but every saying smth and he gets even more confused.
Good, that's a first clue. Are you sure the HUD class is set to your BP_HUD Blueprint?
@lyric heart ^
-.-
If you are unsure, please print the DisplayName of the TargetHUD variable when the Cast fails.
It will either say the wrong name or none. None being invalid then.
its empty
he said about this
running as owning client fixes the cast fail
but for some reason it's still not working
Running what as onwing client?
More PrintStrings/Breakpoints.
if i knew the problem i'd solve it lol
i can't figure where its failing, it seems to run just fine
like it's not stopping
Do you think any of us know the problem in our code without debugging it?
you don't need all this checks. just
and just in hud get game state and make your logic
thanks but thats exactly what i've done and doesn't work
You are still at the stage of figuring out the problem.
it seems to run just fine
It certainly isn't, otherwise you'd see your expected result.
-.-
where is fail? in controller event or in hud event?
Cedric’s just angry because he’s on his 10th death in 5 minutes hollow knight 
i've tried so much stuff lol i'm really frustrated tbh
I'd like to help you, just answer my questions about fail
Take a break maybe. But you won't get around debugging the code and sharing the exact results with us.
We can't help without the info.
the try try works
the code i sent doesn't work
when i mean doesn't work
it just doesn't do what its supposed to do
if i knew why i wouldn't be here
i'd fix it myself
@lyric heart Sure, you still won't get around putting PrintStrings in and showing us the result of all of this.
"Doesn't work." "Doesn't do what it's supposed to do." is all not gonna help us helping you.
Cause, as you said, if it was working and doing what it's supposed to do, you wouldn't be here. (:
you never send the updated code though.
making it almost impossible to even know what's on your end.
This make no sense btw, why is the server passing a HUD?
Remember HUD are local to each client, server doesn't have the client's HUD, so I don't even know what you are passing there.
In any case TargetHUD will be null.
i'm wanting to update all huds when a user logs
when they come into the game, update all lists of widgets
for every player
i've tried several ways and it's not working
there is not a fixed amount widgets
i'm destroying and recreating based on player array
but it's not working
and yes i said (not working) becausei have no clue why
i have not tried onrep but i don't want this as a state i just want it to fire off when people join
and what would i even do ?
on rep what ?
Card is a state, stop trying to tell client to update via RPC.
Client update their own widget when their values are updated, simple as that.
Client widget will just listen to their OWN world state. It reflects values that they currently hold, regardless what it is.
Anything that needs to be sync = don't RPC it.
hmm
- Player enter the game -> HUD is created -> Hud gets the Card component -> Hud bind to all the delegates (e.g CardUpdated).
following soo far?
above is all local logic.
nothing networked.
you just have to make sure that the card component exist. If it live inside a player character then you need to ensure that the client already possess a character.
you are approaching the problem incorrectly
but when people login, i need it to update on all machines
the sooner you accept it the sooner you will be able to move on.
People update stateful things with RPC all the time
and say, look it work.
untill it doesn't.
i wonder it's the way i retry ?
so in a loop i do if fail, delay and retry
but the retry is inside the loop body
do you think this is fkd ?
i'm new to latency as well
something i never really had to deal with
not about latency but you are adding more complication.
Code can be clean with proper event triggered.
why this doesn't work is all i'm asking
and is this a failure ?
will it goto next loop value ?
OnNewPlayerJoin -> Tell the clients that a new player join.
Client receive the RPC -> It execute function to create a widget for that new player and reflect it's state.
Why tell client, destory and re-create everything.
even if it's wrong
What you want is just to push a new widget for every single player that join.
i just want to know why it's not working
I don't know what's not working.
but I can see you are doing it incorrectly.
Yeah but that's not even networking related
right but it's true right
it will pull the wrong value ?
if you delay and call an event inside the loop
i think i fkd that up
not sure what delay even do here.
Delay inside loop doesn't do anything afaik.
cuz the default bp macro loop runs in a single frame.
do you not understand what i'm saying ?
if i have a loop
and i have an event inside the loop
if i call the event inside the loop on a fail
to "retry"
on a fail?
of like a cast fail or something
a different path
and then i run the event again
to try again
I have no idea what you are saying
ok nvm
also delay does nothing here
i'm pretty sure i'm correct
no logic that you need requires delay whatsoever
New Player Join -> Tell clients, a new player has join, go push a widget to your HUD for this new player.
The new widget is but a view model that show the Cards of that player.
So that specific PlayerState-> Get the character of that player -> Get the card component -> Get the cards and display it.
Player Left the game -> Tell clients, hey that player have left the game, go destroy the widget that belong to that player.
ok i'll try this
could even possibly have the playerstate just do its thing on begin play and not deal with RPCs on player join/leave
my biggest issue is reorganizing the widgets
but i'm working on this approach to just add a widget when logged in
I can't create a widget in the controller ?
Only local player controllers can be assigned to widgets
1.) PlayerState BeginPlay
Hud Logic
and the widget
Card container is just a widget that has a horizontal box, where whenever a new player join, a new widget (player card) get pushed in.
@lyric heart
gonna sleep, gl.
i think i figured most of it out, if i'll look at what you posted if it's not working
i created the widget in the player state
and used a multicast
I just notice there's a bug on my end
client have some extra values but oh well, i can't look into it now.
Don't
but I can't stop you
if you insist
you are just shooting your own foot
once i learn the dispatcher method then i'll be better of
but it's not a bunch of players
it's just a few players
doesn't matter really, you are complicating it.
i'm not worried about complication, i'm worried about performance
You are still trying to let server telling clients what to do.
when it's client job to create it's own widget and view the state of it's world.
All server need to do is set the card values, no more no less.
Client can handle displaying it on their own end.
Nothing to do with performance btw.
I spot my mistake, I changed the values as client.
setting the card should only be a server action
why the ++ isn't working ?
if i set a random y i can see it fires off multiple times
and i can set the value initially as well
my guess would be it would have something to do with replication
i tried with + 1 it didn't work
It's quite unorthodox to change the value of a replicated variable from a net multicast...
Hey, I’m wondering what your recommendation is, since I don’t really have the experience to know what problems I’ll stumble upon later. I’ve got two different pawns for two different teams, where team members are selected at the beginning of the round. Those two characters have slightly different UI, but still share some stuff in common.
I’m in the early prototype phase, so the difference isn’t huge yet, but I’m wondering where I should create widgets in the long run. Right now I’m creating them on pawns, and I’ve got two different HUD widgets for each team member. At first I was creating them on Begin Play, but when testing with lag, clients didn’t get it without adding a delay node, and that felt kinda sketchy. So I moved it to On Possessed. Since you’re only possessed when the team is selected (not on level start or travel)
I was also thinking about creating them on the player controller, but then I’d need to switch every time based on a variable that defines what team member you are, and that feels like it could turn into spaghetti real quick.
Second idea is to create some widgets on the common parent that these team members are derived from, and only create unique widgets on the children. But then I couldn’t have one HUD widget where all the other widgets are, right? I would have to create individual widgets, or using widget switchers?
What’s your take on this when you’ve got two teams with different characters and different UI (but not completely different)?
I quickly changed this creation from screen above to a parent, (like in the second idea I described), and I feel like it might be the best option. The plan is to create HUD child widgets as generic as possible, then just tweak some variables on them, like the name in this screen above, for example. I won’t completely avoid using widget switchers, but for now this still seems like the easiest idea.
OnControllerChanged is where you would want to create it.
OnPossessed is server-only.
OnControllerChanged calls for both, so there you can filter for IsLocallyControlled.
Pawn-specific UI you can create in the Pawn. Game-specific UI in the GameState.
Team-specific UI in, for example, a custom TeamState.
It should be called ReceiveControllerChanged for pawns*
Yeah, can never remember the damn BP name
Yeah, I hate the inconsistency
I would have to create individual widgets, or using widget switchers?
Not sure about the switcher, but it's probably a good idea to have one core Widget that acts as a base layer manager and then add the different widgets runtime into predefined slots and what not.
Depends on your game what you need.
Okey, thanks. Is this a big differnece than calling on possesed from server and tnec custom event on owning client liek in my example, is this more performance friendly?
It's redundant would be one argument.
It's just more correct, there's no reason to fire an extra RPC for something you already have
I wouldn't do it like that.
Your UI should pull the data from the other objects.
You don't really want to set the name on the UI like that.
For your goal I would try to use UIExtension from Lyra. You can define extension points that can receive other widgets from anywhere in the code. It's a small encapsulated utility plugin to extend your UI in a modular way. You can pretty much copy it from sample project, and paste it directly in your game
O I'll look into that, thanks
Good to know, could you elaborate why?
I doubt that that progress bar will be anything but stamina. Why don't you write "Stamina" in the widget itself?
Cuz different team doesn’t have stamina but a stealth bar. I wanted to create it as generic custom progress bar in my HUD class with a canvas panel, and then just change the name for the eacch team
How do you update the progress bar though?
Im using set percent function Im calling fromm pawns where this widget is created. I made simmple function inside this widget. Screen on the left is from pawn, and on the right is function inside widget
You rarely want your gameplay code to deal with UI. The UI should be self-contained, and pull all the data from your character, components, controllers and whatnot.
So, you would have your progress bar reading the stamina or stealth value depending on what it is. Most likely that would be two separate progress bar widgets. They might share a parent for common stuff, but they would be two different blueprints for ease for extension. One would read stamina, the other stealth value. You eventually might also want to add different visual properties to them depending on what they are, and it'll be very easy to do since they'll be already separated.
In case of UI Extension plugin, you would define an extension point where the progress bar should be, and then add the one you need depending on the team
But what if it’s changed only on events? I don’t want to read this value every tick, only when needed. Then I should use an interface to trigger this event with some value as input? I don’t want to cast to my pawns on every widget to read its variable.
Reading that on tick would be considered bad practice. You usually shouldn't cast to your pawns to read the value, because these values shouldn't be on pawns directly. Usually people create separate components to handle things modularly, even if you use it only in that pawn, it still makes sense to isolate your stamina and stealth in components to make it easier on you. This way, you would need to GetComponentByClass out of GetOwningPlayerPawn instead, and then use event dispatchers to read the values when they are changes
Ok, thanks for tip, I'll try to do it. Im using components for stealth/stamina, but I didnt know about GetComponentByClass
That should be enough to make it encapsulated. However, note that this is #umg territory 😄
Yeah, that was unexpected turn xd
It just scales a ton better if your gameplay code doesn't need to necessarily care about the UI. It should only provide getters for data and delegates (event dispatchers) for important events.
Hey all, Im trying to figure out when the player controllers are reloaded in a server travel restart (as in server traveling to the level were already in to restart the scene)
If im understanding correctly, the player controllers are not unloaded in this scenario, but the Game Mode is. So if I check for all existing player controllers when the game mode loads back in after the restart, all of the playercontrollers should already be loaded by that point correct?
If I have an Actor on the Server and the actor has a static mesh. I can currently Hide/Show that mesh for all connected players, how would I go about showing/hiding for each player individually? e.g. looping through the connected players array and showing/hiding based on a var in the player state?
the server owns the tile so dont think owner no see workss even more so as any player could need to 'see' the tile if dead etc. Think this is the direction i need for it to work or even achieve what i want (its a spanw tile that you should only see if your dead/dont have a valid character)
I think that's typically done w/ either RPCs or and override of IsNetRelevantFor
But depending on your use case, you might just do it all on the client. If the client knows which conditions a tile should be visible/hidden, you could hook those events on the client (e.g. an event when they're dead, or don't have a valid pawn) and control visibility there.
i updated the function to a multicast but i dont think im in the right ball park currently (I also changed the valid get to is not valid) will look into IsNetRelevantFor
@coarse cave thank you, I think the later part works for me in this use case
as in the following works for each player individually so i should be able to use this
geez i figured it out mostly, just got a few more tests but i think i got it working, not the best approach but one that works.
It should be in HandleSeamlessTravelPlayer or something like that.
this is the closest thing that came up in the GameMode, I didnt find anything in the playercontroller
C++
Not sure this is exposed to Blueprints.
Multiplayer without C++ is wishful thinking.
You can use that method you posted but it will call for post login too
There should be one for seamless travel
But if it's not exposed then not sure.
C++ 😅
I mean its gotten me pretty far already but ahh, brutal. thanks for the insight tho , I appreciate it. ill experiment 
I know. But sooner or later you hit the wall.
I dont doubt it , ive already had to jump through alot of hoops i didnt expect and make work arounds for my racing game.
whats the best way to replicate a timer?
need the time remaing to be read by clients as well
replicate either the end time, or the start time, and know the length of time.
Like, if all matches last 60 minutes, you can replicate the start time.
Or, you can just replicate the end time.
Both have some end result.
I have a similar question about timers,
does anyone know if there's any method to create fps independent timers?
ive read alot of mixed information and settled on using really long Timeline nodes, but ive noticed that they are inaccurate if the framerate drops.
That's why you use a start time or an end time as suggested above. You'll only run into framerate related issues if you're trying to accumulate DeltaTime
Shouldn't timers???
Be independent?
Technically everything is "FPS dependent"
Something gotta handle the math for stuff, and if that math happens less, then it happens less.
But 1 second on 1 FPS, or 500 FPS should still be 1 second?
Same reason why a timeline still has issues.
Cuz, the same thing that drivers timers, drives timelines, and everything
Timers are already independent of frame rate?