#multiplayer
1 messages · Page 275 of 1
at this rate why not make the doors replicated components with a simple open/close bool
it should iirc
they're also replicated anyway afaik
I think their issue remains that the state is entirely handled with a single actor. It probably wouldn't hurt to split the doors into their own actors but then peeps might touch the damn child actor component to assemble the house.
and yeah I agree that this is a lot of work for 1 actor in the general sense
idk what the usecase is
CACs would not be too scary here unless serialized
in my mind CAC stuff only starts to explode when saved in a level
at least in my experience
why would they?
kinda thought they did
remember: replication is not about sending everything
yeah i know
it's about reproducing the state on both sides
just like, felt like something that'd make sense, or maybe I don't remember having to replicate model changes myself for a player
it's 1:30am heh
the actual information you care about is the offset of the mesh from the root which is handled locally entirely by transform replication callbacks in the character (besides the animation which ofc is already derived from OTHER state as well)
If handled in the house, a simple array with door state data that can be replicated and a TMap, locally that maps between MeshComp and Array index would probably resolve a lot of required looping
Initial bunch of that house with 50 doors would be a bit overkill though
nah just thought that the current skeletal mesh replicated so you could change it on the server, dunno why though
also you could send the set of open doors and closed doors separately and assume doors are closed
right it's the static mesh component that replicates, oops
so new joiners only see the subset of open doors
now you have even less information to send and iteration is strictly new information
ofc now you have to send an offset into the set of doors
but there are like 20 doors... you can send them as bytes each
That person is never gonna read all of this haha
yeah lol I feel like we are getting too into the weeds of fancy stuff
i feel like this is getting overkill just for doors heh
I was losing my mind trying to make a new floating compression algo that derives the mantissa bits from a grid set
(not to say I am making something novel, just something I can't find the engine that I don't know the name of lol)
one of the studios I worked for just had a bitfield held by each building
each bit was true/false for a component. components included light switches, broken windows, doors and probs more
basically why send the entire float if you know it's in area X where the mantissa for an actor transform will be identical every time
worked fine until you messed up and the bit mapping on server/client desync'd
you'd flip a light switch and hear a window break
with that stuff you need to have a n ack step imo to not go nuts
what I do for something similar is have an early step where clients and server share what they think each thing is offset to
I don't remember what the issue is but for something like this, deterministic cooking probably solves it anyway
have it map reliably while cooking and you don't have to worry about it
"deterministic" and "probably" do not work well together lol
but yeah in a perfect world we could gaurantee the order like that
I have a very similar issue right now I think with actors in levels where I think I might need to bake a set order
on the topic of late joiners, some people defends using RPC to change variables because "I won't have late joiners",
They should re-phase it as "No reconnection allowed"
late joins aren't the only issue
relevancy's another, as well as RPCs being more expensive in general
right
atp why not just use a replicated property
I did in fact just read through all of that lmao
Nice discussion, and good points and questions.
The building / house actor is a BP, but tbh it’s probably not a big deal to make the doors into their own actors. I just didn’t see the benefit other than the control of it being a sole actor, was trying to avoid that from a performance pov.
Could also just have no doors in interiors but for some I feel it’s necessary, but yea just for organizing having it all in one actor is easy. And these buildings/houses are made from HISM components
that doesn't give any context for the scale of in numerical terms or the rate of change
when we are talking about this kind of thing the decision in my mind about how crazy to go are largely driven by the actual amount of things happening over time
not as much "I do this"
how much??
which TBH I personally would not be able to guess at for my own projects
The doors would not be frequently opening and closing is that’s what you mean
even if you had like a rough idea for the general amount the information changes it would be something I guess
that helps because now we know that it's not like door #23 is constantly flipping in and out every frame
Yea no this would be honestly quite minimal , because of this, you could have a player on the other side of the map, and this is what I’m trying to figure out for
Basically late joiner / player losing relevancy to the actor / doors in question
from a performance pov in blueprints your only goals here are to reduce node eval in the frame and reduce total polling objects... profile it I guess
I was thinking more bandwidth than raw frame perf but yeah less objects will help I guess
less objects is less stuff for replication to juggle
In the case of them just being doors how would I limit the amount of objects? This sounds like using an HISM component would be best as it’s only 1 object?
basically the idea would be to reduce the number of unique network objects that need to be polled
idk if you can use full pushmodel in blueprints in a way that precludes polling though
this is kind of difficult for me to think about as I tend to do mp stuff from C++ only
where we have much more control
honestly I would say just... make it and if you find your servers or clients are being hit with a perf bottleneck
it would be easier to reason about what to change
What would be considered a unique network object? An actor? Just a component?
basically those, yeah lol
each REPLICATED object is given a unique handle
it kinda depends but generally speaking more replicating things = more stuff to bonk for changed properties
there are a number of ways to make this suck less but it's a long story
for example replication graph which is now kinda deprecated... etc
the big advantage of an object though is it is an atomic "thing"
it's way easier to make an actor cull based on distance than making a property inside 1 actor cull based on distance
so generally speaking if you have something that can be represented in space in a way where you could say "make this not relevenat 200 meters away" you would want an actor almost every time
or even an actor in a given area representing a the rough area etc
which is kinda how Mass replication (old way) worked which was like a sort of "door manager" in certain areas of which there can be more than one
where the internal data was sent in a fast array
I’m following you, I’m still not sure what I’ll decide but it does seem like it would be simple to make the doors actors but the buildings are already replicated actors and if I was to cull the doors relevancy id probably be culling the whole building in most cases so I feel it would still make sense to keep it in the actor.
Either way still leaves me to figure out how manage many doors at once which is only seemingly solved by making them their own actors
This also leads me to question my house/building setup in general. They are all replicated actors made up of HISMs and you can interact with more than just doors (although doors are the only things that have states)
The only relevant info that would need replicated would be the doors states tho now that I think of it. And it makes me think maybe I could just have the actors not replicate and only have the doors replicate as separate actors
But then instead of having 1 replicated actor, it’s having 2-15 replicated actors for the interactive things which i assume it would be worse but I could be wrong
Can you guys take look at this. My multiplayer Mission design.
I'm confused at certain points
-
Interaction between Objects and Mission as well as Trigger volume and Mission
-
Is player state good for storing or specific inventory system is good based?
-
Is the replication methods and planned design is good? Also, how to manage content between start & end of Objective.
Example, you have a generator and objective of the mission (Mission per level/gamemode) is to fix the generator, for that require 6 fuses. If player 1 gathered 2 and player 2 collected 4 that info would be stored inside playerstate as collection system isn't required in all missions. Once they put it inside the generator, the AGenerator would call an interface function on gamestate that'd send a RPC to Server for updating the objective.
Objective is data assets contains bool and few FString and FName for the name and description....more on such as cutscenes (for cutscenes, I actually thinking of trigger volume we I mentioned in the design)
I also have another approach. Making AItem with a function that itself is a server RPC and called whenever an event is completed such as all fuses collected.
I wouldn't recommend using RPC for updating objectives. It's easy to replicate the relevant state instead
I would probably use replicated properties for that
if you use fast array replication you can get a callback on clients when you add something to it. then just add a struct or something with completed mission details on the server
unrelated
anyone have guidance on changing the owner of multiple replicated subobjects? I currently have to loop through every subobject, get their subobjects, and then one by one add/remove them from the list for the root component
it's for an inventory system using UObject for Inventory and Item, where Items can potentially own an Inventory
Not sure if it's relevant to your use case, but UObject has a "Rename" which allows you to change the Outer
It's relevant and I have to use it on an Item when changing what inventory it's contained within
but that doesn't do anything for subobject replication sadly
maybe related? does renaming a replicated UObject cause it to destroy and get constructed again on clients? or does renaming occur gracefully?
I believe it's non-destructive, I have a plugin that makes use of it and seems to preserve the data
hmm. maybe I just use a single actor that replicates all these UObjects and then toy with the relevancy?
Not sure without a thorough understanding of the systems in general, but it sounds like you're on the right track
So I was doing more thinking about a replicated inventory system that is more “automatic” (FA, replicated u-object, etc)
And I saw u-object replication has a “net group system”
So I thought in using that a bit.
But, now that leads me into a new thought.
Is there a way to keep the like IDK what it’s called “replication ID” the same?
(As in destroy original ref, re-create an exact copy so that the original is marked for garbage, but then also not have to re-replicate a brand new exact copy to the client?)
Or is valid/ marked as garbage the same as whatever this “replication id” is?
There are a ton of ways to do things like replicated inventory, but it all depends on your implementation details. In a setup where objects are simple and cannot be modified (e.g. don't have durability, can't be enchanted, etc...), it's usually done via the server/client having a registry of inventory items where each item has a GUID. In that case you need only replicate the GUIDs for clients/server to agree on things.
If your items can be modified or are otherwise unique, it gets more complicated and you need to use different strategies
Even in a case with something like durability you'd still probably replicate a lightweight struct that references the item GUID, mutable state (e.g. durability), and then some additional GUID that represents this particular instance of an item.
I have a current working strategy (granted, not exactly tested in a complex scenario, but I can get 3 people to see 1 inventory and all things line up on a dedicated server)
But, I know my way is a bit cursed, and "out of the norm"
So, I keep seeing people talk about FA's, and replicated uobject.
and, it logically seems like those would make my overall code, less scuffed.
But, attempting to support said systems has proven to be harder then first anticipated.
(with planning to use full uobjects, with a decent but of vars for basic stuff, let alone if I go farther with it)
What's "FA"?
net group system?
pff, this might be exactly what i'm looking for
FA = Fast Array
Yeah, its perfect, for the objects.
Make me wonder if I even need an FA.
But, I also don't know how sub-objects are replicated?
Are they 1 by 1, like individual actors.
Or, send with the entire initial actor there linked with?
Cuz, I feel like I still run into issues.
Sure, now I don't know about the 15,000 items or something psycho.
But, when I open a box, I instantly learn of the 100, or 300 in it.
my understanding is that they behave unusually
lol
Where's the documention for net group system?
IDK about any docs.
But, the replication condition has a pretty direct comment about it.
I define a net group tag, and in the PC, I define what net groups I should know about
Then, I just give the sub-objects said net group tag
Would be dope if it worked for variables.
But, I think this might be good enough.
Sounds like I need to do some testing, in regards to this "behave unusually"
It still seems like replicating entire UObjects is a really expensive way to do inventory
Wouldn't it be the same as any other method?
It would still be 10 integers worth of data.
Or, do uobjects add a ton of base data for some odd reason?
entirely depends on needs
if you have a simple system structs are probably fine
but IMO, UObject for instances of items makes sense because a UObject is a unique thing in memory
has a lifetime, callbacks, and supports replication
I can see that, I'm just unsure of the cost of replicating a UObject vs. a USTRUCT (though I'm googling it now cause it seems useful to know)
well a ustruct is basically just a property
the initial setup of a uobject has infinitely more overhead than a struct
but otherwise shouldnt be all that different
I suppose as long as your UObject is more of a wrapper or reference to the actual inventory item. If it's the actual item that's going to get really expensive really fast if you're replicating otherwise immutable properties (e.g. FText Description, FText Name)
those wouldnt be replicated anyway
I'd hope not, but I've seen sillier things done
Yeah, I ain't that psycho/ stupid. 😛
tangentially related; unless they've fixed it GAS replicates FGameplayTags as fully serialized strings by default. It's expensive
Guess they haven't changed the default
I always found that one weird.
Why would client and server have different GameplayTags?
Seems like an odd scenario that a game would run into?
Like, nothings gonna happen if the client knows of only ever used by server GameplayTag. 😛
Creating tags on the fly would do it (not good practice, but since when has that stopped anyone)
Same deal though?
Just make both ends create the tag?
Seems most logical I guess. 😛
That breaks as soon as you have join in progress
Or your client recieves the RPCs that create tags out of order
(e.g. if they're not marked Reliable)
I guess valid.
Still seems a bit nieche, and like you said, not a good practice. 😛
ugh, theres no easy way to have a uobject use an actors relevancy afaik
?
I thought thats the entire idea of a replicated sub object?
Its replicates with the actor, thus follows its relevancy?
it uses the relevancy of whatever actor its assigned to, yeah
but im trying to have it be a subobject of a different actor
otherwise every time i move an inventory i have to loop through every single item and change what actor its a subobject of
Oh, I see.
Good thing i'm not moving inventories. 😛
i really hate how uobject/actor/component are different things in unreal
Hey, I want to make a cannon mechanic where you can enter and fire yourself, but not anything physics-based. Basically, like a shortcut on the map, you always land in the same place. I’m wondering how you’d approach taking control over the character from the server. Should I attach it to some component on the sequencer? I’m not even sure what to search for, what’s the optimal way to handle this kind of behavior?
you could disable input for the player and then launch them
theres a launch function for character iirc
calculating the velocity at which to launch someone should be pretty simple given a start, end, and launch angle
Interesting, I’ll check it, thanks. I thought there might be some “sequencer” approach, cuz I also have a “slide” where you can press the button, enter and just slide to the bottom, and the input is disabled while sliding.
with some animation of sliding during this
you definitely can use a sequencer but then you have to setup a path for a player to follow every time you make a shortcut
its part of the enivroment so its alwasy the same, setup during level design
Hello, shouldn't COND_InitialOnly only replicate whatever the server knows when the actor becomes relevant to a player? I've got this setup firing the OnRep quite frequently
AMESS_DayNightManager::AMESS_DayNightManager(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bReplicates = true;
NetDormancy = DORM_Initial;
}
void AMESS_DayNightManager::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION(ThisClass, DayTime, COND_InitialOnly)
}
UPROPERTY(ReplicatedUsing="OnRep_DayTime")
float DayTime = 0.f;
I change the DayTime locally on tick, so to have it smooth I only replicate the day time on join, and when the time is manually changed by an admin.
For testing purposes, I tried to change the client time, but it snapped back to server after a second. I tried to add the OnRep_DayTime to see whether it's being called more than once, and it is. It calls it once every second, which doesn't make sense.
To test things out even more, I tried to remove dormancy, and it made it replicate only once, which is the expected behavior... I don't even flush the dormancy for it to replicate the DayTime. I only flush it a few times when the game starts because I reset some of other replicated variables, but after that I don't flush it up until the next match.
I tried both DORM_Initial and DORM_DormantAll (even though the actor is pre-placed in the level), but both of them result into the same behavior.
Does anyone know why it might be happening?
Does it make sense for DayTime to be some function of game time?
Like, do you have anything fancy going on or do you just have a day/night cycle that is some multiple and offset from real game time?
There's already a synced network game time clock. All you need to cook up the same day/night time locally on all machines is the multiplier and offset.
Game time and real time aren't correlated. The game time is sometimes slightly sped up or slowed down depending on circumstances
Are you referring to GS ServerTime?
Can anyone explain to me how the loadout system will work in multiplayer ListenServer?
Single loadout, not 10 loadout like COD. There you can select your primary, secondary weapon/grenade and configure your weapon attachment.
Then spawn that loadout on the character at beginplay of the gameplay level
Ik it'll be struct passing to the loadout component.
But from a menu perspective, the widget stuff is kinda confusing me
not sure what you struggle with. With the widget??
Maybe try to pass a custom msg of each player and bring that to the game they joined.
If you can do that, then you can do the same with your load out.
this question is very hard to understand
the widget is the UI
the server doesn't care about a widget, but which thing you wanted
the server only needs to know about what the user said they wanted and that can just be some simple rpc
so for example maybe each time you change a weapon you send that they wanted X item in Y slot
doesn't really matter how they are represented
I'll take an example of COD.
You are on the menu level and selected the loadout widget.
Now you can modify your weapon and select the grenades / equipments (amount of ammo/magazine and grenades are prefixed)
When player joins/host the game, and travel to the gameplay level. All the players should spawn with their respective loadout
No
Player chose their load out, have it stored in GI or w/e.
Player join a game.
Player tell server their loadout.
Server receive the load out data then replicate it to all client.
That was the question, storage
Sorry couldn't explain it better
I was thinking of PC
I think this is a decent place for a playerstate component that has what their loadout is
anywhere that can be accessed from the client.
?
Player Controller (PC)
When they join a new map the PC from the main menu is destroyed.
you need to keep it somewhere pressistent.
I guess yeah this might need to be a combination of local storage in a savegame etc but this might start being more backend server stuff if you need like player progression from a shared server
Each level has its own player state since some may pickup the system inside the level like you need to collect fuses while the other level may not require that system.
this will be difficult to mix and match if they are all distinct children of playerstate
make them components or just have them all on the palyerstate but inactive unless you will never change this
I know, but I don't like it various reasons
Okay, so it'd be like
ULoadoutComponent that will hold everything including the current loadout and if any pick-up happens
This is my current planned structure for mission along with pickup like when you pick and give fuses to the actor
I don't know what any of this actually represents and most of it is hard to read
I think I can kinda see it if I try
what does this one say?
ouch
My bad handwriting though
my handwriting sucks way worse than this, I can't judge lol
you have data that needs to be stored somewhere and replicated
you have ui that is client only that is shown in menu
you have gameplay actors or components that will be created based on data
this is actually pretty nice compared to mine
eh, really? just write not italic but semi printed letters
my teachers would need me to read parts of my assignments to them... I was awful
What's the ultimate issue that you are having with?
You don't know how to pass the load out data to the game you joined, or is it something else?
I feel like they want some rough idea of how to architect this and what part the UI should talk to
i think he simply can't understand the basic concept how to add data for something that is show in ui, replicated and usable in game
Never mind, I think I made it too confusing.
I guess my hot take here is that the gamemode is something I tend to just deal with and generally 90% of the game code talks to gamestate or playerstate stuff
yeah
the gamemode kinda just defines how restarting players works and choosing default classes
as PS can be migrated after moving between lobby/game levels it is best option imo
all PS accessible from gamestate
Here's the question I've copied from my reddit post on unrealegine5
How can I have a custom weapon attachment inside the loadout system and send it over the network for a multiplayer game. Working - You opened the game, in your menu you setup your loadout (the game has single loadout only) and when you host/join, the loadout is set as your character's loadout on gameplay map like player 1 has M4 and 1911 pistol while the player 2 has Scar-H and Glock. This is the loadout but I want Weapon Attachment init as well, like M4 has acog and grip while Scar-H has only muzzle which affects the stats.
There is no multiple scope, but the scope aim is more like material zoom and not the camera fov.
Also, if I've an enemy how can make them have weapon and random attachments on it.
I know C++ so I've already setup
Soldier character Combat Component (handles Combat, and equipped Weapon and equipping of weapons that is dropped) Weapon (AActor)
X_X
this is just an inventory
also what does "I've already setup" actually mean... I don't know what you have setup or what is missing at all here
so I guess the question is you want to send arbitrary weapon loadout data over the network
it sounds like each item can have multiple child items inside of it (for example weapon has X scope)
How can I have a custom weapon attachment inside the loadout system and send it over the network for a multiplayer game
How much of Replication do you know? If not much then just read the pinned material and stay away from your system until you get the basic down (Try to sync a door or material).
if you can just make a struct that lists out slot + selected item for each item it's done
you can represent each slot however you want
they can be names, tags, integers, whatever
yea, if your items are DA - just pointers to DA then build gameplay elements (actors/components) from it
UItemAsset* Weapon;
UItemAsset* WeaponScopeOption;
UItemAsset* WeaponStockOption;
UItemAsset* WeaponMuzzleOption;
}```
this way it can be saved too I guess
UE5 – Movement replication issue:
Hey everyone,
Server never corrects client movement in my project.
Client moves with WASD and updates on server, but never gets corrected (only after jumping).
Even the default FPS template character has the same issue after migrating into my project.
Works fine in a clean FPS template.
Any idea what could break server-side movement correction?
I am really struggling with this one as it seems to happen on every project I have 😮
what does every project you have change?
do you modify the engine ini to turn off client corrections? (game network settings etc)
I don't I'd say but I will have a look into it thanks
you say "every project I have" without including what is unique about those from a starter project
surely they have some shared plugin/ini something you like to use to not repeat work
Good to know but I have not made any relevant changes to it
If I don't find the solution I will probably just migrate the whole project into a Default FPS Template 😮
is server accept client authoratative position on? Is ignore client movement error checks and correction on?
there are a numbe of cvars and per-instance settings that affect if a correction happens etc
you can look at any unreal bp class and see what differs from the default
with the filter button in the top of the details panel
default being parent type here I guess
server accept client authoratative position is turned off and ignore client movement error checks and correction is off
I have basically imported the Default FPS Character into my project to see if it works. And it does not, so it has to do something with the Project itself, The map, the gamemode etc. Really weird 😮 I am trying to see if migrating my project into the Default Template work
did you temper with the ini file?
maybe check for settings like tolerance for the correction
Normally no
also how would you simulate the correction?
are you saying the players are too far off from each other?
Thing is, i have no migrated the project into the default template, and it still does not work on my map. Maybe it then has to do with the Map ???
well we don't know what doesn't work. Maybe try taking a video.
looking for GameNetworkManager related things in your ini would be prudent
ClientAuthorativePosition etc
Server correction working on FirstPersonMap
Emulation is set to 'Bad'
Server correction NOT WORKING on my Development Map
This is all in the same project using the same gamemode. Just another map
Weird right?
@slow sierra is that level using manually placed floors or are you runtime spawning them?
What you describe sounds like based movement
Runtime.. 😮
Yeah your floor is the problem then
Server and client communicate based movement via a relative offset to the floor you are standing on
As long as that relative offset is the same it won't correct
Jumping will remove the floor and they will get back to world location comparison
At which point you get the correction
I imported the level content into the default map and in the red area the correction does not work but in the green one 😮
Thank you for that explanation
So I basically have to setup the level without the BP_DemoRoom from the Content Examples which generates it inside construction script?
If you take such a floor and rotate it only on e.g. the server by 90 degree. You will see the client and server walk in different directions but when that relative location is transformed to world via the floor's transform they will equal again, so you get no corrections
In theory runtime is fine but the transforms of the floors have to match
Something is causing them to be different. Or server and client fail to communicate the floor in general which should be indicated by lots of warnings in the log while walking over said floor
Yeah, i just checked there are a lot of warnings haha
output log should never be closed (at least check it every once in a while I guess)
Yeah the floor mesh components are probably not stably named or so.
LogNetPackageMap: Warning: FNetGUIDCache::SupportsObject: InstancedStaticMeshComponent /Game/FirstPerson/Maps/UEDPIE_1_FirstPersonMap_2.FirstPersonMap_2:PersistentLevel.BP_DemoRoom_C_UAID_0250F21C0400BC9702_1641946050.NODE_AddInstancedStaticMeshComponent-25 NOT Supported.
LogNetPlayerMovement: Warning: ClientAdjustPosition_Implementation could not resolve the new relative movement base actor, ignoring server correction! Client currently at world location X=3540.000 Y=-197.800 Z=98.200 on base NODE_AddInstancedStaticMeshComponent-25
I think I will just just try to recreate the level not using the blueprint that genereates the actors
Idk if spawning runtime mesh components in blueprints can even be linked up properly
I will do from now on thank you
Yeah so you are getting corrections but the client can't resolve them so it keeps the old value
can you convince it that it's a static base I wonder?
I don't remember
I would have to look
I have an idea, maybe just adding a fake floor will do the trick
Based movement is usually for moving stuff
if it truly is identical in shape on both sides I personally don't see the issue in terms of if it is possible
based movement is short for when you have a movement base (ike a moving platform) if that helps
What confuses me is that the components aren't being stably named even though they are probably spawned and attached
But I guess they generate a random name or so
so instead of sending the entire position you only need to know where you are relative to the object (for example, you only need to know where the platform is if the player doesn't move on the platform they are standing on)
spawned and attached when though
stable named is for when the same data exists on both sides from either reflection data or saved assets afaik
You are actually sending more info with based movement. The idea is that the moving base doesn't need to be 100% in sync
ofc you can declare random stuff stable named with 1 override too I guess
does it still send both? I forget
I think you are right... the idea is more for smoothing I assume
The vector is just relative but it sends the movement base and bone name in addition
it does make more sense as a smoothness thing more so than just quantization
but those ids will be pretty small compared to a full sized position
once exported/mapped etc
If you can design your demo room pre-runtime and get rid of the runtime spawned part it should also work
Just for you guys to know, I just place a fake floor and set it to hidden in game and it works 🙂
if it works it works
Yeah has to be above the other floor though or the other one has to have collision disabled
Might as well use a box collision though
It still sends a full sized vector
oh lol, I guess I assumed it was more quantized...
Na based movement is really not about saving bits
It does that anyway though or
it depends on the character quantization sending that or not, I forget
What I meant is that it doesn't send less while based
This was bugging me for months across all my projects (Doing Demo Maps for FAB content). And I always thought WTH am I doing wrong as CMC is basically replicating out of the box. Now I know it has to do something with procedural generated maps/Floors.
For me this case is closed but seems to be an interesting topic 😄
Thank you all for helping me finding the solution!!! Very appreciated!
Maybe it does by now. Been ages that I looked at it
and also a full sized non-quantized FRotator when relative rotation is sent but iirc those are sent as shorts anyways by default
This Project is in 5.0 btw
this code in the CMC is probably old enough to drive in most countries I would imagine
this is not new stuff
assuming the cmc stuff predates ue4 by a bit
otherwise it's a decade old... I don't know when based movement became a thing exactly though
not without fairly big changes here and there like adding an up vector etc
(not to say this is something easy to figure out... the cmc is complicated lol)
Pointers to objects sent across the net are converted to IDs and back. Replicated Actors, Actors placed into the scene pre-runtime and their default components are "stably named", aka they can be found via a path.
Runtime spawned components can also do this but one has to make sure they have a unique name within their Actor. The BP nodes to spawn instanced static mesh components probably produce some random names or so (or are somewhere marked as generally not stably named) and will not resolve. So the client has no clue what the server is standing on and can't do the relative to world math.
assets and the like are stable named as well
so sending a data asset etc or a specific bp class
Ya, they all count as default objects I think
In terms of being stably named that is. It can find them by their asset path
The most important take away is that you successfully ignored a spammed log for months
sending the path seems crazy bandwidth wise but in reality they can negotiate a shared smaller id
How does one achieve stable names? If I lets say spawn a weapon from the server, does it automatically when replicating that object create stable names?
You can see this whole stably named stuff a bit like finding a file on your PC in some folder. If two PCs have the same folder hierarchy and file name, they can talk/reference the same file. Aka I can tell you where your Programs folder on your C drive is
you don't need a stable name to send a replicated object or target it with an rpc or serialize the pointer
this is just how you send something like a UDataAsset* which isn't replicated and it shows up on the other side as the asset ptr
this is like a local mapping of the "files" that can turn into serialized network info as exi said
A spawned actor is going to initially replicate with its full path to the class object iirc. That's an asset more or less. The server tells the client the net id for that new actor instance that is based on that class and the client will spawn an instance and note it down as being that net id. Something like that
the server and client both know about the asset of the bp here
but the runtime created instance of the bp class is a regular old replicated object with a network id etc
After that the server will only use the net id to address the actor.
For the components both would know the "path" of the component relative to the actor class. That combined with the net id for a specific instance of an actor class gives you the specific component instance. But that only works if the component can be mapped like that. Which the one you had there couldn't
To touch a bit more, Unreal loads Objects from something called a UPackage, it contains 2 primary tables, one as an import table (which is objects this package references), and the other is an export table (objects that are saved within this package).
Objects are saved as a virtual path that gets mounted, followed by a "." deliminator to separate package name from object name, and then a ":" deliminator to separate sub-objects.
Because worlds are packages on both client and server, and can mostly be assumed to be located at the same relative virtual path on both machines, the objects can we loaded using the exact same flow on both client and server. That's what "stably named" essentially means, the UPackage and the referenced object inside that package exist at the exact same path.
Idk how one can get a runtime spawn component stable named in Blueprints
In c++ it's relatively easy. Give it a fixed unique name (within the actor) and mark it as stably named.
yeah stable named stuff = not your problem with bp only multiplayer I think
the only time I need to modify what is stable named is when doing crazy reflection scripting stuff with angelscript lol
at least so far
I’m curious on this first part if you don’t mind.
What defines this ID for replication?
I’m planning to do some stuff, that people might consider “cursed”
I wanna be able to re-create an exact copy of an object.
So that the original server side ref is invalid.
But, also not have to re-replicate an entire object each time I do this.
Does any one have a preferred way or somewhere I could look up for updating the local HUD of a referenced player controller on an actor spawned and owned by the server?
I believe I have the server spawning a character with a valid reference. (Image 1)
Then after the spawned character has received the possessed event I am updating the player controller with a reference to the unit (Image 2)
I am then using the player controller to hopefully update that players HUD (So far unsuccessfully) via the player controller. (Image 3)
My issue is that the HUD is only updating on the server visible on the listen server window...
I am basically just trying to show/hide a widget for each individual player based on if they have a valid reference or not within an AICharacter (Hide on invalid show on valid). Potentially from what i have found out so far the reference might be better in the player state and a rep notify?
That's way too many ServerRPCs in that Pawn. OnPossessed only runs on the Server to begin with. They can all be normal events.
Does the ClientRPC actually reach the Client?
It should as far as I can tell, but you won't be guarnateed to have a valid Pawn locally at that point. Instead of sending an RPC you probably want to have a RepNotify property on the PlayerController and just set that. In the OnRep you can then check if that RepNotify property is valid and if so initialize the HUD.
LocalPlayer?
dont know why people over complicate this stuff with loadouts, etc
LocalPlayer is the player, it persists the entire time
LocalPlayerSubsystem can hold the selected loadout, etc
it gets linked to there player controller, client simply tells server, hey this is my selected loadout
server verifies, and grants them the loadout
we kinda used a combination of localplayersubsystem and playerstate component to handle the loadout for a player, all orchestrated through a playercontroller component.
for a game where you have no online backend ofc.
how can the server verifies if there's no online backend to check for ground truth? Or it just look at the loadout and check if it isn't too unrealistic (like having 9999 bullets)?
you don't let the player decide how much ammo they have
have the player tell the server what weapons they want
server then validates it's a good loadout
server then sets that loadout and everyone can now see it
nvm I see kaos typed the exact same thing lol
I mean it just an example, not specifically ammo, I could be selected a god tier loadout instead.
the server has to confirm the client can use it
if unlocks are stored in the client then there's nothing the server could ever do to verify it apart from it being valid
how can you confirm if there's no online backend?
are your unlocks stored in the client and work on every server that someone would host? or saved on the server?
no backend meaning that it's stored in the client. The server just have the information that the client provides.
then under no circumstance could you verify the player truly unlocked those items
you can verify the loadout is valid though (which you should be doing)
you're trusting the client on what items they have unlocked. anything you trust the client on they can change if they want to cheat
my advice? don't worry about it lol
I know, that's why I asked since Kaos said that "server verifies" and "have no online backend"
him saying "server verifies" is that the loadout makes sense by the rules of the game, like I didn't equip 900 grenades or something
that the server can validate
Hi all!
I would appreciate any help in issue resolving that I can't resolve on my own.
So if there is someone skilled enough in dealing with multiplayer or replication I will be very grateful for trying to solve that.
TL;DR
In PIE play as client and in real online session clients either can't see other clients steering wheel rotation or can't see rotation for itself.
Details!
In my GameMode I'm spawning a pawn of class AWheeledVehiclePawn.
Pawn itself, mesh and vehicle movement components are set to be replicated, by default empty AI controller is set to control the pawn.
I'm not possessing car pawn to control it (possessed chaos vehicle don't want to move at all, but that's another topic), instead from player controller I use server RPC to set values like "vehicle movement->SetSteeringInput()".
In car BP threre is only a RInterpTo for smooth wheel rotation in tick.
So that all works completely fine for PIE standalone and play as listen server - everyone sees everyone rotating steering wheel.
BUT when PIE play as client or in real online session - clients either can't see their steering wheel rotation or can't see other clients steering wheel rotation.
It definitely something with replication but I cant figure what exactly.
if your game is PvP and players can unlock gear that's objectively better than other gear, it's going to be frustrating ngl
if you design your game where loadouts are just different and not objectively better, cheating on unlocks doesn't matter
if it's coop no one cares about cheating
I updated to not have the rpc event for on register unit in the AI character and to have the unit rep notify within the pc and just straight cast to the hud from there and this works. Thank you
show how the steering wheel rotation is done
entire path from input to wheel rotation being set
Let's try...
In controller for the left/right input I'm calling that:
{
CarMovement->SetSteeringInput(InValue);
ControlledChar->GetCar()->UpdateSteeringRotation(InValue);
}```
UpdateSteeringRotation() in Car.cpp:
```void ADHCarBase::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ADHCarBase, SteeringRotatorCPP);
}
void ADHCarBase::UpdateSteeringRotation(float SteeringInput)
{
if (FMath::Abs(SteeringInput - LastSentSteering) > 0.01f)
{
SteeringRotatorCPP = FRotator(SteeringInput * RotationAngle, 0.f, 0.f);
LastSentSteering = SteeringInput;
}
}```
Then on blueprint side - see pics
For blocks of code use:
```cpp
Your
Code
Here
```
start by printing SteeringRotatorCPP on tick and making sure everyone agrees
or put a draw debug text above the car so it's easier to see which car has which rotator, it shouldn't be a rotator tho, steering is pretty much 1 axis so you can just send to server and replicate a float
I did that and it shows same stuff on all screens - changing value of SteeringRotatorCPP
then keep debugging until you can 100% confirm that the last steering value is synchronized, that'd be the last one in the event graph of the anim bp
if it gets out of sync after that I'd guess it's animation shenanigans, I'd look at the Tick Pose and Refresh Bones setting on the skelmesh
Print out
I'll try to do that again.
But tell me one thing - why the hell it now works correctly for PIE client + client without changing any settings? The only thing that I did is dropped binaries/intermediate/save and regenerated project...
Anyway, thanks for the observer magic! 👍
Need to test now in online session if that fixed itself somehow.
bumping this, sorry
Thanks again! It's literally start working normally with current setup after project rebuild (drop binaries, intermediate, etc.) and creating new game package.
It's literally start working normally with current setup after project rebuild (drop binaries, intermediate, etc.) and creating new game package.
So, just rebuild your projects from time to time 🙃
Is there a way to wait until all players have connected after server travel to then do something?
For this check you need to know expected number of players and just check if everyone connected via Num(GameState->PlayerArray) or just counter after PostLogin() in GameMode
btw there's a function in match based game mode called ReadyToStartMatch() that is good place for this check if you are using AGameMode instead of AGameModeBase
I'll investigate this
Oh yeah thats easy
Was just wondering if there was a preexisting way to do it
404 on the first few functions I was clicking
you mean me? I don't think I said anything that precludes it being on the local player etc
I wonder if we actually need a #blueprint-multiplayer and a #cpp-multiplayer channel. 🤔 (no we don't).
5.6 version of the page seems broken. Check the 5.5 one via the drop down on the left.
I did, same results
Btw has anyone used this, lobbies interface for creating lobbies such as friends party and joining/hosting a server (public/private)
Shouldn't be. I can see the links just fine on the 5.5 version.
My bad then, it was 5.4
When clicking CreateLobby I get sent here: https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Plugins/OnlineServicesInterface/Online/ILobbies/CreateLobby?application_version=5.5
Hosting/Joining Servers is a different thing than Friend Parties.
Also since this is an Interface, it requires the underlying system to actually utilize it.
Like 2 friends together wanna host a public session to fill up the other 2 player seats. The lobby leader would host/join the session
Like EOS?
Yeah, but those are two different "system" so to speak.
While they probably use a similar underlying system of the OSS, they are still handled differently. Especially between the different OSS.
An example: Steam doesn't allow you to be part of more than one Session, even if it's a Party vs a Game Session.
So you have to handle this properly.
The second you join a Game Session, your Party Session will die.
Once you leave the Game Session you have to recreate the Party Session.
Ig that's why this lobbies interface is made for?
Like to utilize it for this work
The ILobbies interface seems to be specifically made for EOS.
There are no implementations of this interface outside of that. Steam doesn't use it.
This one right?
Yeah, ILobbies is used within IOnlineServices.
And IOnlineServices is currently only used for EOS as far as I can tell.
There is a "Common" implementation of it, but I assume that's the new "NULL" one.
Possibly, yes. I would refer to the EOS documentation for that tbh.
So I'm not sure if this is even possible? But here is the idea what I want to do! I want the plugin to be reusable in different project with that specific movement component feature. That's why separated it from project. And project has all multiplayer movement setup.
P.S: It may be sounded stupid but I have this itch in the brain to sync two different BP_character in one BP with all functionalities.
Nope
Only one base c++ or one base BP
So cpp plugin char -> project cpp char -> BP project char
Or
Cpp plugin char -> BP plugin char -> BP project char
have GameCharacter use AProjectCharacter stuff but with its cmc being APluginCMC
or have AProjectCharacter be a subclass of APluginCharacter
Hey, I'm making footsteps depending on surface type. The setup is simple: one line trace down on an anim notify and a switch on an enum based on the physics material. However, I'm wondering what the best solution is when it comes to communication.
When using anim notifies, it fires on all instances of the character, so by default this event makes footsteps audible to everyone. But that doesn't seem like a good solution, because the line trace is running on every player instance on every client. Still, I wouldn't be surprised if it's cheaper than doing an extra RPC to handle the logic on the locally controlled pawn and then multicast it.
If someone steps on a rustly leaf in the woods, and nobody is around to hear it, does it make a sound?
I'd keep that energy
in some way detect if you should be doing cosmetics or not, probably by distance from local player's viewpoint
if you have relevency already then don't worry about it, can't make sound if you don't exist
what calls CopyProperties?
Show the flow from whatever triggers this whole chain
its a default function that fires in the player state on the server if seamless travel is enabled. i do nothing to call it the enginge is suppose to which i confirmed is working
I just used a notify on the animation to trace and it synchs fine
probably a race condition
wait what do you mean it fires on the server, then why does it need to call a run on server event?
show the entire chain from whatever kicks this off, probably BeginPlay I'd guess
yeah its probably redudant but i didnt trust chat gpt that it was fired from the server
at first
First thing to do is to confirm that its firing and which machines it fires on, is CopyProperties an event you made or one provided by PlayerState?
provided by default in the engine.
copy properties is a built in function of the engine that fires during seamless travel
try just this
assuming it runs on server and it has the old serverside version of the thing that should just work
client does no work here, just server does
ohhhh
i see your proble
you're saying inventory = new inventory
not inventory = old inventory
yeah that part i get, the documentation arounnd it is poor which is why i did that
because i wasnt sure who was firing it server or host. im certain the host does
that doesn't matter here, your copy is going the wrong way
you're reading from new and writing to old
which obviously isn't useful
how often am I supposed to package the server when I run a dedicated server?
I had some issues in my game for the longest time, but after packaging the server (again) and running that, the issues were gone
how would i be i didnt create the new player state input
yeah same thing only the host loads their data.
im thinking race condition ill just throw some delay nodes
and see what happens
host loading the data should be fine
host loads data which is replicated so it'll make it to clients
what's the problem?
by host i mean the version of a clients playerstate that lives on the hosts's computer
yeah but it the outliner under client world im not seeing the data
confirm that execution makes it to the end of the chain
print Sanity on tick or something
My map is very small, max 8 players. You’re never more than two rooms away from the rest of the player. I didn’t decrease relevancy at all, so everyone will be in range. I’m using a listen server though.
Let’s say everyone is relevant, still wondering, would it be better to line trace after checking if it’s locally controlled and then multicast, or just leave it like that and trace on everyone without the extra multicast?
I'd trace locally
it's a total nothingburger
thats like waht, an average of 0.5 traces per frame?
You can run thousands
although you can probably not have to trace
you can just do a notify and if your character has its based component you can pull the mat from there
instead of "play sound based on what the trace hit" it'd be "play sound based on what the character is walking on"
idk if discord puts that in an undertsbale order
my inventory exists inside the player (I know i should have built it inside of the playerstate) so the the server has to roc the client to fetch the data
Inventory can still exist on pawn but be server authoritative
by player i mean pawn
it shouldn't be "hey guys we're changing maps, please tell me what stuff you have"
it should be "Hey guys we're changing maps, you're gonna have whatever I think you have when we get there"
use replicated variables
why is BTC wallet not replicated lol
thats what im doing inside the player stae. the variables are replicated
so yeah what your saying is what im trying to do. I have to fetch the inventory off the clients so the server can update all the playerstate and trasfer the data during travel
this one is ran on the gamemode
the loop calling the roc
They should be replicated during gameplay
There shouldn't be anything to sync right before a transition
The server should already have all the state you care about.
Right im aware nothing i did was inline with best practice
i figured it in any matter
the issue is indeed a race condition
I don't quiet understand that approach though. Why even RPC the data?
The player state in the host machine should be the one with authorative data.
why care what the client says about their current hp? The current hp in the server should be the truth.
Hello
I am new to multiplayer and i have a very weird issue.
In my player controller i am creating a UMG widget in begin play for local controllers.
This works in the starter map but when i seamless travel to another map the UI is not added to the clients. only the host has the UI still visible.
i am using 5.5 if it matters
Seamless Travel + PC BeginPlay
I led that horse to water but he just wouldn't drink it
Hey, I have a few questions about multiplayer:
1: Do components have their net IDs? My replicated actors have a replicated component (Mass agent component), however the component's state is always WaitingForNetID on clients.
2: Do replicated actors load the network during their lifetime (they don't have a net owner), if they dont have any replicated properties? I have 2K actors so it matters
- Network probably not if nothing that replicates changes. But they most likely make you bleed CPU performance on the Server for being polled for replication. PushBased helps with that, but I'm unsure if Epic probably utilizes that everywhere.
If they don't have replicated proeprties, you might want to think about having a replicated manager that spawns those Actors manually locally.
In my one multiplayer project, when a host leaves. Everyone just travel back to Main Menu.
How can I send a widget message to everyone that Host Left the game?
Or disconnect everyone before the host leaves the game
Like looping through the array of connected client and disconnecting them
Asynchronously and once the host leaves, then it can leave the session?
Hello, i m having an issue with lights, i m having a light that changes inensity based on distance, i obviously want it to be different for each player, i m making sure that the event is being executed on owning client only when changing the intensity of the light, but for some reason it gets replicated and the other client is also affecting it aswell for everyone
If the host leaves through "normal" means, as in they press a button in your UI, you can simply loop over the array of PlayerControllers and send an RPC if you want. By default, if the host leaves, the game will disconnect the clients and there will be a callback coming in (default bound in the GameInstance iirc) that notifies you of the cause. The same exists for failing to travel (join) to a server. If the host leaves due to other reasons (ALT+F4, crash, no internet), there is little you can do. Clients will simply time out. The callback will still come in though.
I think those events are only directly exposed to Blueprints (irony..).
/** Opportunity for blueprints to handle network errors. */
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "NetworkError"))
ENGINE_API void HandleNetworkError(ENetworkFailure::Type FailureType, bool bIsServer);
/** Opportunity for blueprints to handle travel errors. */
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "TravelError"))
ENGINE_API void HandleTravelError(ETravelFailure::Type FailureType);
You'd usually cache those and show them once the client returned to the main menu by using, e.g., the PlayerController of your main menu to ask the GameInstance for any pending messages (your own cached array).
The events are quite tightly connected to UEngine, but that one is just binding to them, so you can listen to this elsewhere too:
OnTravelFailure().AddUObject(this, &UEngine::HandleTravelFailure);
OnNetworkFailure().AddUObject(this, &UEngine::HandleNetworkFailure);
If you really want to stop the automatic traveling from happening, you might have to dig a bit deeper into engine code. By default, this whole stuff will end up inside CallHandleDisconnectForFailure, which calls UOnlineSession::HandleDisconnect, which ultimately calls UEngine::HandleDisconnect. This is what will cause the Client to travel back. UOnlineSession::HandleDisconnect is virtual, so it can be overridden within your own UOnlineSession child class. That child class can be set by overriding UGameInstance::GetOnlineSessionClass and returning your own class within your own UGameInstance child class.
You could then choose to simply not call UEngine::HandleDisconnect and to instead call it later through some button press on a UI element. Adding that UI element could potentially be done through that same function, since it gives access to the World.
No clue if that just works though, never done that.
You'd need to share your code. If you want a single light actor to change intensity based on the local player, then you usually don't need any RPCs or replication.
Thank you, I understood now
I tried that aswell first but it still did not work, this is an example of how it looks
You gotta share your code.
and the function GetLightIntensity()
UFUNCTION(BlueprintCallable)
float GetLightIntensity(float distance, float minDistance, float maxDistance, float minIntensity, float maxIntensity)
{
if (maxDistance <= minDistance)
{
return (distance <= minDistance) ? minIntensity : maxIntensity;
}
float T = (distance - minDistance) / (maxDistance - minDistance);
T = FMath::Clamp(T, 0.0f, 1.0f);
T = FMath::Square(T);
return FMath::Lerp(minIntensity, maxIntensity, T);
}
if (maxDistance <= minDistance)
{
return (distance <= minDistance) ? minIntensity : maxIntensity;
}
That is confusing. You should not even handle such a state. Max < Min should be an invalid usage of that function tbh.
Despite that, this part looks fine.
What calls ChangeLightIntensity?
Its in begin play
Your problem will be that this BP code runs on every character for everyone.
So if you have two players, it runs twice on each player, where each of the characters (local/autoproxy and simproxy) will try to force their distance upon the equation.
Are you playing with a ListenServer or a DedicatedServer?
right now testing on client and listen server
no, it should only be for owning client
Then move the call of ChangeLightIntensity from BeginPlay to ReceiveControllerChanged and check that the NewControlleris valid, as well as that the Pawn/Character is LocallyControlled.
That will ensure the whole timer stuff doesn't run more than once per client and only on their own local pawn.
+- listen server.
tha worked, but i m still a bit confused why it didnt work in beign play?
BeginPlay calls on every instance of the Actor that exist in the given game.
ListenServer: Character_A
Client: Character_B
So each of them have:
ListenServer: CharacterA_AutoProxy (their own), CharacterB_Authority
Client: CharacterA_SimProxy, CharacterB_AutoProxy (their own)
Aka both will have 2 BeginPlay calls. That means your timer will start twice on each player in this scenario. Once inside the local Character and once inside the Character of the other player. And both of those will try to update the light intensity, which means if, e.g., the ListenServer walks closer to the light, it will also try to update that on the Client, as the ListenServer's Character will also walk closer there.
With the change you now did you ensured that the timer only starts on the local (AutoProxy) version of the Character, so always only once per player.
With 3 players you'd have 3 Characters per game, so 3 BeginPlay calls, etc.
If i would do a locally controlled check in begin play would it still start the timer twice?
SessionSettings.Set(SEARCH_KEYWORDS, "Test Lobby", EOnlineDataAdvertisementType::ViaOnlineService);
is SEARCH_KEYWORDS being deprecated? i am getting error on it and also IDE can't find it
UE5.5
no, it will start only on the server
I have a case where I must replicate over a thousand entities constantly. I'm currently using a fast array and only replicate the components that had changed (location separately, rotation separately, etc)
What I'm doing on clients is I just interoolate to that location from the current one (VInterpTo)
It works flawlessly with around 100 entities, but when I have more than that it starts to get worse, and when I reach one thousand it has a horrible look, it looks like instead of updating every 0.25s it updates once per 1.5s.
Any recommendations? What should I do? And how do I increase the bandwidth?
The net load isn't that high, I get around 20k bytes per second with 1k entities
you can set them to not Replicate everytime instead, use dormancy and only update at certain point u want. but if u want to the replicate each entity. I'd say make a pool of them or use Mass framework
I'm using mass entity yeah, and I don't replicate the properties of the actors themselves, I utilize a FastArraySerializer, which is a single property withing my ReplicationManager.
And mass entity's native replication kinda uses fast array serializers too, so I just wrote my own one since it's much easier to use
When you say entities, do you truly mean an ECS entity?
Ahh
What?
How's checking if an object is locally controlled means it will only run on server.
You could limit what entities are sent to the client using a pseudo relevancy system
Also what do you mean by the components that change?
prev loc = 0
new loc = 1
prev rot = 0
new rot = 0
location is gonna be sent, rotation isn't.
sorry i misunderstand it has "HasAuthority"
When are you doing the interpolation on the client?
the thing is, 1K entities is the absolute minimum I wanna achieve, since the other entities will be further and I can decrease the update frequency for them
uh don't quite get what do you mean, I store the current ServwrLoc and interpilate to it every tick
This could also be net priority being too low
So it's not being done in parallel?
it is, I'm using a mass processor for that
with ParallelForEachEntityChunk
Assuming you gave this a look?
https://blog.ignaciodelavega.com/Unreal-Engine/Unreal-Engine-Mass-Smooth-Movement
havent really seen this one, ill check it out, but i followed the replication guide from this blog, and it didnt work the way i wanted. Ill actually recheck this plugin, since maybe it actually does support 1k+ entities
Hey, is it possible to have a component only on the client? The problem is that I’m using a listen server, so using a switch on authority and destroying on authority will remove it on the client who’s also the server. In a character, I’d use “is locally controlled,” but my question is about a custom actor blueprint. I want to create an overlap component, but it doesn’t need to be on the server. (except client who is listen server, then it is on server but is not replicated)
That would be a coinflip situation.
Cause BeginPlay is too early to know if a Pawn is possessed.
It might work on the Clients due to replication coming in with the Controller already set, and fail on the Server cause BeginPlay will call instantly after SpawnActor and before Possess is called. That's why you should use the Controller callback.
So you support both DedicatedServer and ListenServer?
You can just check specifically for IsDedicatedServer fwiw.
For now only lsiten server
ListenServer has no split concept of Server and Client for the hosting player.
So for ListenServer you'd never remove it on the Server anyway.
Yeah, but I don’t need the server to check if this overlaps with all clients. For the rest of the clients, I just want to run some logic locally on begin overlap, but it doesn’t have to be on the server. So I’d need the same kind of condition as “is locally controlled,” but for this specific blueprint actor.
Isn't it the Character that overlaps with that Blueprint?
I see, thank you!
Yes, it is, but the overlap component is on the blueprint actor. I just wanted to optimize it a bit and check if the pawn is inside locally, since it's only for cosmetics when it's inside the component.
Then just check if the overlap actor, the pawn, is locally controlled.
ok, when I turn off context sensitive, I can check it, but I'm wondering, since there's this conversion and it's replicated, doesn't that kinda defeat the point of this check?
I can cast to a pawn too, and I'm using the collision preset to overlap with pawns only, so that might be the solution?
Yeah this requires a cast.
Which only makes sense if you really only want to deal with Pawns.
Just have an idea but it's kinda very new maybe. If any of you can get a better understanding of how it can be done, then please explain. How can we add radio chatter like military noise effect yk that radios have but during voice chat like player 1 "zombies are coming" should have some noise and static in it to other player
Just do it
That's not too insane to do, can be done with convolution and noise
Assuming you are able to fiddle with the voice chat audio in some way, you can use convolution to make it sound like shitty radio, and just add a bit of noise before the convolution and it'll sound pretty good.
Do it in your DAW first
Actually I've never worked with voice chat so after looking at some video, ue does give us 2 options, attenuation and effect. So the effect one will be used imo
DAW means?
digital audio workstation, something like Reaper or Pro TOols or FL Studio etc
I found a video that achieved the similar way of military static but it uses morphvox or something like that
you can get most of the way to a radio effect by adding a high pass and low pass filter to the audio, and mixing it with some static audio
Let me know what you think in the comments below. Screenshots of settings, mic clicks, and diffstatic.wav file download here: https://www.mediafire.com/?csb2ae52rv50b37
For mic clicks: Just right click on your TS3 icon, go to Open Folder Location, look for 'Sound' folder and default; copy and paste included files over existing. Turn on mic click...
Beginner friendly software? Never worked much with audio system like that except da Vinci for some video editing and voice overs
For client, player state is called before the HUD.
For server, the Hud is called before player state.
🤔 trying to think how I can initialize a component in my player state which pushes a widget to the hud.
Why the more entities i have the less frequently my replication happens? With 100 entities they work really smooth, with 3K entities they only update once every 2 seconds.
I replicate them via a fast array serializer (basically just an array that only replicates the changed entities, for now it only replicates a single FVector_NetQuanitize per entity.
How can i fix this? I assume it may be because of bandwidth, but how do i increase it? I tried this, it doesnt seem to do anything at all
Yes, you can add a Source Effect Chain to apply voice effects (bitcrusher, high/low pass etc).
I did it a few years back with Vivox but it was a custom solution.
I believe if you are using built in Unreal voip then you can apply an effect chain when you create the VOIPTalker as part of setting up proximity voice chat.
void UMultiplayerSessionSubsytem::CreateSession(int32 NumPublicConnection, FString MatchType)
{
if (!SessionInterface.IsValid()) return;
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
TSharedPtr<const FUniqueNetId> UserId = LocalPlayer->GetPreferredUniqueNetId();
if (!UserId.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("CreateSession failed: LocalPlayer has no valid UniqueNetId (user not logged in yet)"));
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("❌ Can't create session: not logged in!"));
MultiplayerOnCreateSessionComplete.Broadcast(false);
return;
}
auto ExistingSession = SessionInterface->GetNamedSession(NAME_GameSession);
if (ExistingSession != nullptr)
{
bCreateSessionOnDestroy = true;
LastNumPublicConnections = NumPublicConnection;
LastMatchType = MatchType;
DestroySession();
}
// Store the delegate in FDelegateHandle so later can be removed from delegate list
CreateSessionsCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionsCompleteDelegate);
LastSessionSettings = MakeShareable(new FOnlineSessionSettings);
LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
LastSessionSettings->NumPublicConnections = NumPublicConnection;
LastSessionSettings->bAllowJoinInProgress = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowInvites = true;
LastSessionSettings->bShouldAdvertise = true;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bUseLobbiesIfAvailable = true;
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
if (!SessionInterface->CreateSession(*UserId, NAME_GameSession, *LastSessionSettings))
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionsCompleteDelegateHandle);
// Broadcast our own custom delegate
MultiplayerOnCreateSessionComplete.Broadcast(false);
}
}
the game is crashing
ig because i've added autologin
void UMultiplayerSessionSubsytem::Login()
{
if (IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get())
{
UE_LOG(LogTemp, Warning, TEXT("Online Subsystem: %s"), *Subsystem->GetSubsystemName().ToString());
if (IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface())
{
if (Identity->GetLoginStatus(0) == ELoginStatus::LoggedIn)
{
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Player already logged in"));
OnLoginComplete(0, true, *Identity->GetUniquePlayerId(0), TEXT(""));
return;
}
LoginHandle = Identity->AddOnLoginCompleteDelegate_Handle(0, FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::OnLoginComplete));
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Proceeding Autologin"));
if (Identity->AutoLogin(0))
{
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Auto logged in success"));
}
else
{
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Auto logged in failed, manual logging in"));
FOnlineAccountCredentials Credentials;
//Credentials.Id = FString("127.0.0.1:8081");
//Credentials.Token = FString("Prabhdeep");
//Credentials.Type = FString("developer");
Credentials.Id = FString();
Credentials.Token = FString();
Credentials.Type = FString("accountportal");
UE_LOG(LogTemp, Warning, TEXT("Loggin"));
Identity->Login(0, Credentials);
}
}
}
}
my login code
have you tried using an unreliable multicast RPC instead of a fast array? replicated properties are always reliable and movement updates dont need to be reliable so i dunno if fast array is best for this kinda thing
Do you mean passing the movement data as a parameter into a multicast function?
would that even work? i mean i havent considered doing that, i have around 3k entities in that stress test, in the actual game im planning to have around 1K
it should.. and also i wouldnt send the positions every frame, but at a certain rate and have clients lerp between the movement updates locally
Can anyone help?
"the game is crashing" yeah but where?
At create session
I was thinking you could point to a line in the code since the callstack will usually tell you
log lines starting with an emoji usually indicate gen AI code as well
Doing a quick search of Lyra on github, it seems they only have like 1 multicast RPC in the whole codebase. How are they replicating non stateful FX to other players when they trigger? I assume it's still fine to use unreliable Multicast RPCs over OnRep variables in cases where you have a non-stateful event happen like a player blocks a damage event 3 times in a second or whatever so you want an individual VFX pulse each time (shown to all players, not just the blocking player)
I haven't toyed that much with Lyra, but I would imagine a lot of them are likely going through GAS?
Yeah probably any cosmetic action is using GAS indeed, thanks!
Handles both the gameplay and cosmetic stuff without messing around with RPCs I imagine
Hey folks, in DataChannel.cpp line 5042/5043 it states this: // When replicating subobjects, the engine will by default replicate lower subobjects before their outers, using the owning actor as the outer on the client. // To have a chain of subobjects maintain their correct outers on the client, the subobjects should be replicated top-down, so the outers are received before any subobjects they own.
Anybody know where this could be reversed as mentioned? Also, why would this not be the default?
can anyone please help? i don't understand the exact reason behind crash and the crash report is also too big
void UMultiplayerSessionSubsytem::Login()
{
if (IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get())
{
UE_LOG(LogTemp, Warning, TEXT("Online Subsystem: %s"), *Subsystem->GetSubsystemName().ToString());
if (IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface())
{
FOnlineAccountCredentials Credentials;
//Credentials.Id = FString("127.0.0.1:8081");
//Credentials.Token = FString("Prabhdeep");
//Credentials.Type = FString("developer");
Credentials.Id = FString();
Credentials.Token = FString();
Credentials.Type = FString("presistentauth");
UE_LOG(LogTemp, Warning, TEXT("Loggin"));
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Persistent Auth"));
LoginHandle = Identity->AddOnLoginCompleteDelegate_Handle(0, FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::OnLoginComplete));
Identity->Login(0, Credentials);
}
}
}
void UMultiplayerSessionSubsytem::OnLoginComplete(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
UE_LOG(LogTemp, Warning, TEXT("Logged In: %d"), bWasSuccessful);
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
if(bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Login Success"));
if (Subsystem && Identity.IsValid())
{
Identity->ClearOnLoginCompleteDelegate_Handle(0, LoginHandle);
}
}
else
{
if (Subsystem)
{
FOnlineAccountCredentials Credentials;
Credentials.Id = FString();
Credentials.Token = FString();
Credentials.Type = FString("accountportal");
UE_LOG(LogTemp, Warning, TEXT("Loggin"));
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Account Portal"));
LoginHandle = Identity->AddOnLoginCompleteDelegate_Handle(0, FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::OnLoginComplete));
Identity->Login(0, Credentials);
}
}
}
this is my code
crash only happens when i click on Host button
you should really be using a debugger, since this should be printing to the output
and it will be clear as day what is going on
it is failing in a loop
breapoint?
void UMultiplayerSessionSubsytem::CreateSession(int32 NumPublicConnection, FString MatchType)
{
if (!SessionInterface.IsValid()) return;
auto ExistingSession = SessionInterface->GetNamedSession(SEARCH_KEYWORDS);
if (ExistingSession != nullptr)
{
bCreateSessionOnDestroy = true;
LastNumPublicConnections = NumPublicConnection;
LastMatchType = MatchType;
DestroySession();
}
// Store the delegate in FDelegateHandle so later can be removed from delegate list
CreateSessionsCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionsCompleteDelegate);
LastSessionSettings = MakeShareable(new FOnlineSessionSettings);
LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
LastSessionSettings->NumPublicConnections = NumPublicConnection;
LastSessionSettings->bAllowJoinInProgress = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowInvites = true;
LastSessionSettings->bShouldAdvertise = true;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bUseLobbiesIfAvailable = true;
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), SEARCH_KEYWORDS, *LastSessionSettings))
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionsCompleteDelegateHandle);
// Broadcast our own custom delegate
MultiplayerOnCreateSessionComplete.Broadcast(false);
}
}
well here the stack overflows because OnLoginComplete calls OnLoginComplete forever
this is Host button function
i do get logged in perfectly
and no issue
the issue starts when i click on Host button
yeah, and? I'm telling you the facts
i was trying to add Autologin for EOS so after logging once, u don't login next time
and since you aren't using the debugger it's hard to know why the recursion occurs other than it's an instant failure all the way down
it instantly fails if the player is already logged in
i do have debugger
use it?
just don't know how to use that advance debugging symbols
you already have them since you have a readable callstack
then? u mean breakpoint?
debugger doesn't work with outside of PIE?
if you're using standalone, then manually attach to the process or use ezargs to add -game and launch standalone directly from Rider
i am on visual studio
unrealvs can be used for that
what? i don't understand what unrealvs is?
Engine/Extras/UnrealVS/VS2022/UnrealVS.vsix
you install it
it's a VS extension
it adds a textbox to the VS toolbar where you can launch with additional args
like -game
done, but this blank screen comes
done
Unrealvs extension added
i can see the arg
void UMultiplayerSessionSubsytem::OnLoginComplete(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
UE_LOG(LogTemp, Warning, TEXT("Logged In: %d"), bWasSuccessful);
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
if(bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Login Success"));
if (Subsystem && Identity.IsValid())
{
Identity->ClearOnLoginCompleteDelegate_Handle(0, LoginHandle);
}
}
else
{
if (Subsystem)
{
FOnlineAccountCredentials Credentials;
Credentials.Id = FString();
Credentials.Token = FString();
Credentials.Type = FString("accountportal");
UE_LOG(LogTemp, Warning, TEXT("Loggin"));
GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Blue, TEXT("Account Portal"));
LoginHandle = Identity->AddOnLoginCompleteDelegate_Handle(0, FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::OnLoginComplete));
Identity->Login(0, Credentials);
}
}
}
found it
the issue is
Subsystem is getting null
due to which it retriggers the OnLogin
but on second, it let it continue even though the subsystem is null
due to which
when i click host the engine crash
Anyone have a fix for steam dedicated server in ue5.6.1 mine now just fails
Warning: STEAM: Unexpected GSPolicyResponse callback
[2025.10.13-07.15.01:788][ 25]LogOnline: Warning: OSS: Async task 'FOnlineAsyncTaskSteamCreateServer bWasSuccessful: 0' failed in 15.018529 seconds
[2025.10.13-07.15.01:789][ 25]LogOnline: VeryVerbose: OSS: FOnlineAsyncTaskManager::AddToOutQueue [FOnlineAsyncTaskSteamCreateServer bWasSuccessful: 0]
[2025.10.13-07.15.01:789][ 25]LogBlueprintUserMessages: [BP_GameInstance_C_2147482576] Server Has failed to create
just started using state trees and i have a simple move to task where im moving an actors location, and it seems to be firing separetly for each client instead of having the server just control it. i might be missing something simple but just trying to find the way to have the location be set by the server, which, it still might be but just seems like it doing it separately on each client as the actor moves at different times on each client. i do have a delay task as well, but i figured this wouldnt change anything as the 3 second delay should be the same if the logic was only firing on the server
maybe i fixed it last night, casue it seems to be working now, but i dont know if i just got lucky and the AI state tree started at the same time ? the locations are now corrrect for sure, i printed that to check, but the thing i was noticing was that the movement was happening as slightly different times which would not be ideal, but i suppose if the locations are the same it's ok , but i wouldn't understand why it would ever happen differently on separetly clients unless the server is starting the tasks at differetn times for each client, and thus the movement event is being fired slightly at diffetnt times
so to summarize the above, i have simple state tree, server does in fact set the location correctly but it appears the delay task is doing something weird where it's firing at different times on each client which results in the actor being at different locations on each client for a short period of time
not sure how i'd accomodate that unless i just made a custom event for the server to fire instead of the delay task node, which i'd assume is just firing locally
i assume it's all firing locally which is fine for the most part but the delay task node is not very consistnet, so yea not sure if the issue makes sense enough to help with, but really just trying to find a workaround for the clients getting the move event at slightly different times seemingly due to the delay task node in the state tree
Could some one let me know if I am looking in the right place or direction for updating the visibility of a static mesh within an actor for the local player only, ideally based on a variable one for bIsDead and another for the event on the server changing the phase?
Im hoping to have an actor/mesh in multiplayer only visible when a player is 'dead' think when you see the angel above graveyards in WOW. Technically the actor is always there just only visible based on the variable for the local player.
I dont believe I can go the actor no see route as the actor would technically be owned by the server and not an individual player. I think I would have to have an on owning client RPC in the player controller that can access the actor on the server via the game state and update SetVisibility on that mesh for that player only? Just everything I have so far doesnt work and just wondering if I am even going in the right direction
lots of approaches, but you could have a bIsDead variable for the player set to repnotify, and you could have an is locally controlled check inside that function and do the setting / unsetting of that visibility via that function (when not dead, set it to not visible etc)
prob better to not even do a repnotify for that particular one, but you could. or just do an owning client event when the server confirms the player died
So, I have never used State Tree, but my simple setup just has an enemy pawn with an AI Controller class configured. The AI pawn itself has Replicate Movement enabled, which is how clients see it moving.
The AI Controller is what runs the Behaviour Tree, and the Controller only exists on server by design, so the clients are not disagreeing about what the AI is doing as it is being decided on the server and simply the effect (moving) is replicated to clients.
Is there some way to replicate a pointer without a uproperty()? without suffering with NetIDs.
what does net serialize for a uobject ptr do?
nullifies my pointer on clients
I think the name resolution is part of deserialization
pointer to a replicated object right?
yuh, to an actor, it gets created and stands there
only need actor pointer as an identifier in my data array
anything persistent will do actually, im already fine with using a net GUID, but i cant seem to find any info on that
netguids work for objects that have already been established on server and client, then they resolve out to a path
for initial replication the objects path gets sent iirc
i just need to get it somehow, i tried NetDriver()->GetID something something for actor and it always returns some invalid ID
the actors ARE replicated
there might be a function in package map
whats a package map?
I believe it's just a map that translates object names to guids
i mean, how do i get it?
might be able to get it from netdriver?
thanks man, it finally works now
i honestly thought that net serialize on a ptr to a replicated object should do this for you
Hi, what's an efficient way to network a top-down character so that it rotates to face the mouse cursor? I was thinking about doing the calculations client-side and sending it to the server, but idk if that is optimal or if there is a way to minimize RPCs while keeping it fairly accurate and "safe". Is there a better approach?
If you're always going to allow turning (like a twin stick shooter), I would definitely do it client-side to keep it responsive.
Okay, yeah it is going to have twin-stick controls. Ty, so like
Client-Side calculation -> Server -> Other players
Yes, exactly!
Perfect, ty. Just making sure before I go too far into the project.
weird, im creating a session using the Steam Advanced Sessions plugin, then when it succeeds i server travel to my ingame map
and when users joins, the url they get is UEngine::Browse Started Browse: "steam.XXXXXXXXXX/Game/ImproGame/Levels/L_MainMenu"
im wondering why they get the old level and not the current server map
can doing an absoulate travel to the InGame map break the "tracking" ? edit: testing without absolute and have the same stuff running
well, before creating the session i am opening the InGame level
received URL from clients wanting to join the session still get the main menu URL
logs starting right before the friend invite join
for me the Your connection to the host has been lost error is because the client tried to travel to the incrroect level
Following on from my earlier question, is there a better way than in this image to update multiple actor on the server for the local player?
e.g. should i just be getting the array of tile actors from the game state or something?
as it stands this runs on an owning client event every time the turn reaches this phase
- In BP_Actor_Tile: Add a function called "UpdateTileVisibility()", inside of it, check your GameState phase, your local player "bIsDead".
The idea here is that your tile actor is responsible for its visibility state. What you're doing above is bad because it unnecessarily exposes implementation details about your tile to an outside class. If you decide there are actually 5 different things that happen when you "hide" the tile (e.g. hide the mesh, play this niagara system, change this bool, etc...) it makes no sense for an arbitrary outside system to manipulate that internal state. - In the BP above, call "UpdateTileVisibility()" instead of directly calling "SetVisibility()"... OR...
- In BP_Actor_Tile: Hook into an event dispatcher on your GameState (or which ever place your "phase" is stored) that is triggered each time the phase changes. Call your "UpdateTileVisibility()" function when that event fires
For "bIsDead" you can do something similar; In BP_Actor_Tile hook into an event that triggers when bIsDead changes and call your UpdateTileVisibility() function
How do I use dedicated servers? How can I test with dedicated servers in the editor?
I need urgent help. I really don’t understand this
Is someone here to help??? It’s important
@toxic cobalt
Yea I got it but my system of interaction us broken
The main thing to be aware of: the GameMode doesn't exist on the clients. Only your local PlayerController exists on each client. No client can access another clients PlayerController
Relevant checks you can use in BP for determing client vs. server are "HasAuthority()", "GetLocalRole()", "GetRemoteRole()", and "IsServer()"
My system is between clients. There is an intermediate blueprint. When 1 interacts with 2, via the actor blueprint placed inside the character actor, the blueprint should send a signal to character 2 for something to happen. But for some reason, this doesn’t work. Sometimes when player 1 tries to interact with 2, it may affect players 1, 2 or 3. I can’t find a pattern on which one is moved or why yet
Sounds like both are trying to use run on server events.
(only 1 person can, the owner/ usually whoever spawned it)
You'll probably need to look at the events you've created for those interactions. They can be "Run on Server", "Multicast", etc... you'll need to make sure they're setup correctly
If the "intermediate blueprint" is on "2", in the example above, "1" won't be able to do any networking since, as joehelp mentioned, only the owner can do that
Even in a dedicated servers?
Especially in a dedicated server
What you can do is, on your PlayerController class you "Run on Server" with an event/function that specifies the other actor that you're trying to interact with
Any networking type has this
Then for the server logic you can dispatch the signal as appropriate
No, because it seems to work in some instances. How it works is
1 has a trace: trace detects blueprint actor, we’ll call it E.
When 1 pressed left click, it triggers an event for E INSIDE of the actor that 1 is focusing on in the trace.
E will then use the fact that an interaction happened, and cast to its own character. In this case, 2.
Inside 2’s code, something should happen but sometimes it happens in 1s code, or 3s code
"INSIDE of the actor that 1 is focusing on"; 1 doesn't own that actor, and can't dispatch events for it
It does in some instances though
If you're using a dedicated server you need to pass the message through the server. You can't directly message between clients
With static objects with the same “E” blueprint, it works like a charm. Issues arise when a player is interacting with the “E” of another player
But a player can Interac with the E of a static actor or any object whatever
That typically happens when you're playing as a "Listen Server"
Because one player is technically both the client AND the server
What happens?
The players getting mixed up?
One player can do something while the other player can't
It’s not that. 1, 2, and 3 can all interact with the E blueprint actor associated with, for example, the elevator. The issue arises when 1 tries to punch 2
What happens when 1 tries to punch 2? Keep in mind that with a dedicated server 1 cannot directly damage 2, or visa-versa. Only the server can decide damage.
1 presses left mouse button, and then interacts with the E blueprint inside 2. 2 will then respond. But sometimes 3 does. Or 1 itself will punch itself
Or 1 itself will punch itself
Heh.
Here wait, I’ll send some screenshots of the code. There’s also an actor component involved
Yes. The movement associated with the interact supposed to be occurring on 2 happens to 1
Can somebody explain the lobby system? I'm able to create sessions, find and join.
But I wanna implement a lobby system like at first, you host and lobby is created then it's on the host with configuration such as number of players and in the lobby he wants to start the session, change map, or wait for players to join or invite the friends, private/public lobby. When the start session is clicked, the gameplay map should be open.
OSS used: EOS
hi, i'm trying to make a mod that works server-side only and replicates some actors that i delete so it applies to the client. the actor gets deleted on my side, but the problem is when the player moves away from it, it reappears again. how can i disable this feature using nodes?
https://medal.tv/ar/games/mordhau/clips/ljmJ3qB6QzdVB7Uic?invite=cr-MSxLM3YsNDQzNDYwOTEw&v=12
شاهد Desktop 2025.10.16 - 07.35.17.01.mp4 من TypicalJosh وملايين المقاطع الأخرى للعبة Mordhau على Medal. الوسوم: #mordhau
void UMultiplayerSessionSubsytem::CreateSession(int32 NumPublicConnection, FString MatchType)
{
if (!SessionInterface.IsValid()) return;
auto ExistingSession = SessionInterface->GetNamedSession(SEARCH_KEYWORDS);
if (ExistingSession != nullptr)
{
bCreateSessionOnDestroy = true;
LastNumPublicConnections = NumPublicConnection;
LastMatchType = MatchType;
DestroySession();
}
// Store the delegate in FDelegateHandle so later can be removed from delegate list
CreateSessionsCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionsCompleteDelegate);
LastSessionSettings = MakeShareable(new FOnlineSessionSettings);
LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
LastSessionSettings->NumPublicConnections = NumPublicConnection;
LastSessionSettings->bAllowJoinInProgress = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowInvites = true;
LastSessionSettings->bShouldAdvertise = true;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bUseLobbiesIfAvailable = true;
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineService);
const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), SEARCH_KEYWORDS, *LastSessionSettings))
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionsCompleteDelegateHandle);
// Broadcast our own custom delegate
MultiplayerOnCreateSessionComplete.Broadcast(false);
}
}
i am not able to find the session with
SEARCH_KEYWORDS
Any ideas why a joining steam player gets an incorrect map in the connection string ?
Hello, why does calling Wait Gameplay Tag Add to Actor in UMG only work on the Listen Server but not on the Client?
Getting any errors in your log from these nodes?
Looks good, no errors!
You're certain these nodes are executing on the client's side? Like nothing that would stop them from executing?
Lemme guess.
- This is called in EventConstruct
- The Widget is created in PlayerController or Pawn BeginPlay.
Probably Pawn.
In other words, I assume the Pawn is simply invalid at that point in time on the Client.
The string in the red box is being printed correctly on the client side.
that's not what you should check
Check if the controlled pawn is valid
nothing stop from the client from doing the print string, but as mentioned, it is possible that the controller has no controlled pawn yet in the client.
@thin stratus @dark parcel @sinful tree
Thank you very much, it’s working now. And is this best practice, or is there a better way?
Does it work for client? I Thought on possesed only run on server
never seen on possesed pawn changed though.
It's certainly one of the better solutions, but you'd want to ensure that "NewClient" is actually valid :P
And if it's not, then you might want to nuke these AsyncActions.
Each of those Wait nodes should have an AsyncAction return param that you can set. If the possess call comes back with an invalid NewPawn, then you unpossessed the pawn.
it’s working on client
And yes, that specific callback there works on Server and Client.
👍
The only thing that is to mention is that, if you already only spawn that Widget if the Pawn is valid, then this is, in theory, not needed, and you just need to change where/when in the Pawn you create the Widget.
This would only be needed if you create the Widget in the PlayerController.
any help please ?
That isn't typical behavior for replicated Actors. This looks like it's a different Actor alltogether. Might be some lodding system of the game you are modding. Might want to ask in the modding server of that game.
i thought it was from the mesh or something like that, and i searched about the issue online and saw some people saying it's because of netcull, but in the game's sdk i couldn't find a clear node to modify
No one here would know tbh. If you are modding a game, then it should have official modding support so you should be able to ask the devs or at least some community server.
Cedric, do you know how the connection string is made ine the OSSs?
For what I saw on EOS and Steam it can be prefixed in different manners, but at some point in the string there will be a map, and right now im wondering how the map is set. Is it by server when the session is made ?
Relatively sure things like EOS and Steam don't even care about the map when connecting. The map gets told to the player if they survived PreLogin.
Check UWorld::WelcomePlayer
Thanks, will do
Because right now my client joins friend from steam and the connection string has the MainMenu map, and not the InGame one (where the hosting player created the session)
Cropped logs
The FURL that gets constructed from a JoinSession call will have the old URL.
Since it was a hard travel, wont it have the InGame map
I don't think that matters. The initial ClientTravel URL comes from IOnlineSession::GetResolvedConnectString and depends on the individual OOS implementation.
JoinSession will usually call APlayerController::ClientTravel (unless you are doing something else). That leads to UEngine::SetClientTravel.
Which simply sets Context.TravelURL
That is then processed next frame via UEngine::TickWorldTravel.
Specifically with this line: if (Browse( Context, FURL(&Context.LastURL,*TravelURLCopy,(ETravelType)Context.TravelType), Error ) == EBrowseReturnVal::Failure)
Where the important part is this: FURL(&Context.LastURL, *TravelURLCopy, (ETravelType)Context.TravelType)
If you open the FURL constructor, you can see how it determines the whole string, including the map.
The default thing it will do is use UGameMapsSettings::GetGameDefaultMap() for the Map part of the string.
So how does it magically knows the correct map (usually) ?
The Server tells the Client the Map after PreLogin succeeded.
When i played with EOS last year i had the correct map in the URL
Okay ill do more debugging
It doesn't magically know the map. If the Map is part of the initial connection string, then it's part of the session info and EOS provides it that way. But that's not required, it's optional.
So on join i could manually client travel to InGame map and i should work if i joined ?
If your Server is on InGame map, then the Client will ultimately travel to that too.
Well rn nope
That's how it is though :D
I know you arent lying xD
void UWorld::WelcomePlayer(UNetConnection* Connection)
{
#if !WITH_EDITORONLY_DATA
ULevel* CurrentLevel = PersistentLevel;
#endif
check(CurrentLevel);
FString LevelName;
const FSeamlessTravelHandler& SeamlessTravelHandler = GEngine->SeamlessTravelHandlerForWorld(this);
if (SeamlessTravelHandler.IsInTransition())
{
// Tell the client to go to the destination map
LevelName = SeamlessTravelHandler.GetDestinationMapName();
Connection->SetClientWorldPackageName(NAME_None);
}
else
{
LevelName = CurrentLevel->GetOutermost()->GetName();
Connection->SetClientWorldPackageName(CurrentLevel->GetOutermost()->GetFName());
}
Funnily enough, the SeamlessTravelHandler part doesn't use the LevelName
No, it just also handles it.
The else handles the current map.
Ah, that's only setting the WorldPackageName.
It sends it a bit below that part with FNetControlMessage<NMT_Welcome>::Send(Connection, LevelName, GameName, RedirectURL);
LogNet: UNetConnection::Close: [UNetConnection] RemoteAddr: 76561198843334831:7777, Name: SteamSocketsNetConnection_2147482386, Driver: Name:PendingNetDriver Def:GameNetDriver SteamSocketsNetDriver_2147482449, IsServer: NO, PC: NULL, Owner: NULL, UniqueId: INVALID, Channels: 3, Time: 2025.10.15-21.15.33
im wondering why everything is NULL and invalid here
Server probably nuked your PlayerController.
before closing connection ?
I mean, you are on the Client here.
oh wait
i copied some BP graphs to quickly test friend invites with advanced sessions plugin
its joining the session use a PC get by "Get Player Controler (0)"
in the game instance
i bet it can give incorrect PC
I don't think that matters. If you are being disconnected from the server you should check as to why.
the invite has the controller index but idk to what its matching, i also have the net id but idk how to get a PC from it in BP
relevant warning and errors
[2025.10.15-21.15.33:335][100]LogSteamSocketsAPI: Warning: SteamSockets API: Warning [#3638775724 P2P steamid:76561198843334831 vport 7777] Relay candidates enabled by P2P_Transport_ICE_Enable, but P2P_TURN_ServerList is empty
[2025.10.15-21.15.33:336][100]LogSockets: SteamSockets: Now tracking socket 3638775724 for addr 76561198843334831:7777, has parent? 0
[2025.10.15-21.15.33:336][100]LogNet: Game client on port 7777, rate 100000
[2025.10.15-21.15.33:336][100]LogSteamSocketsAPI: Verbose: SteamSockets API: Log [#2375463113 P2P steamid:76561198843334831 vport 7777] closed by app before we got connected (1000) Connection Ended.
[2025.10.15-21.15.43:332][426]LogSteamSocketsAPI: Verbose: SteamSockets API: Log [#3638775724 P2P steamid:76561198843334831 vport 7777] problem detected locally (5003): Timed out attempting to connect
[2025.10.15-21.15.43:350][430]LogNet: Error: UEngine::BroadcastNetworkFailure: FailureType = PendingConnectionFailure, ErrorString = Your connection to the host has been lost., Driver = Name:PendingNetDriver Def:GameNetDriver SteamSocketsNetDriver_2147482379
[2025.10.15-21.15.43:351][430]LogNet: Warning: Network Failure: PendingNetDriver[PendingConnectionFailure]: Your connection to the host has been lost.
[2025.10.15-21.15.43:351][430]LogNet: NetworkFailure: PendingConnectionFailure, Error: 'Your connection to the host has been lost.'
[2025.10.15-21.15.43:351][430]LogNet: DestroyNamedNetDriver: Name:PendingNetDriver Def:GameNetDriver SteamSocketsNetDriver_2147482379
[2025.10.15-21.15.43:355][431]LogGlobalStatus: UEngine::Browse Started Browse: "/Game/ImproGame/Levels/L_MainMenu?closed"
from my understanding, Your connection to the host has been lost is triggered after 1-3s after the join because it doesnt find any server hosted on MainMenu
since server is hosting in InGame map
That's not how that works.
MainMenu isn't relevant to this.
The last line in your log is just the Client traveling back to MainMenu cause they lost connection.
You need to check the Server logs to understand why it doesn't connect.
LogSteamSocketsAPI: Verbose: SteamSockets API: Log [#2375463113 P2P steamid:76561198843334831 vport 7777] closed by app before we got connected (1000) Connection Ended.
That's also a bit sus.
i assume bInitServerOnClient in config isnt needed in my case ?
okay, the only log i get on server when i try to join (and fail) is LogSteamSocketsAPI: Warning: SteamSockets API: Warning Ignoring P2P signal from 'steamid:XXXXXX', unknown remote connection #YYYYY
i dont get any more logs with VeryVerbose
Does anyone know about this issue?
Try the net logs and whatever else shows up related to net travel and sessions
Is this a listen or dedi server?
listen server
btw thats what i got in my Ini
[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/SteamSockets.SteamSocketsNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[Core.Log]
LogSteamSocketsAPI=VeryVerbose
LogOnlineSession=VeryVerbose
LogSockets=VeryVerbose
LogOnline=VeryVerbose
LogNet=VeryVerbose
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
steam id ending with 82 is the listen server
and ending with 09 is the client
Are you using Advanced Sessions plugin?
yes
Not sure then atm. Might want to check where that print comes from that denies the client and see what actually determines that.
Currently not at my desk, so can't check.
not from engine code
from steam
-lognetapi - Logs all P2P networking info to log/netapi_log.txt.
I wonder if that works with ue
https://partner.steamgames.com/doc/api/ISteamNetworkingSockets
This is pretty low-level compared to UE, but UE must be doing the stuff under Accept Connection somewhere. Which means UE should be the one that denies this connection. I can also not find a warning message in the steamworks docs that matches. You sure it's not a UE warning?
all i know is that i cant find any code that writes this
and that all logs coming as LogSteamSocketsAPI: Warning: SteamSockets API: comes from steam
see SetDebugOutputFunction in ISteamNetworkingUtils
where did you find that ?
found it, i got the console showing in steam app
when i run my game i got a few lines like "overlay was activated for this app"
but nothing shows when i create a session, or when the player 2 tries to join
Are you on 5.6? @lament flax
All I can find is one other thread where people report the same on 5.6
ye
Do you only have that issue when doing invites or just joining through the normal FindSessions -> JoinSession flow is also f'd?
Please make sure that your SteamSockets plugin is enabled, as far as I can tell.
Solutions on the net are bit strange. They show stuff about OSS Steam being renamed, which should cause no problem though. And then they show a netDriverDefinition that sets the SteamNetSocketsDriver as fallback, which makes no sense given that's not how a fallback works.
But they do state that you'd need to enable the SteamSockets plugin.
i have it enabled
and used in the ini
so searching for lobbies has some "result" but they all seem invalid since at the end of the filter i get O and warnings
from what i gathered this can happen since multiple versions if the app 480 exists
Hey guys, what the hell is this number? Is that a common bug, or an actual issue? im profiling my network since my OnRep even sometimes takes 0.5s+ to be called (normally its supposed to be 0.0x), and finding this weird looking number
Hey, i am making a simple nameplate feature where we just have the name of our allies above their heads. So in the player state i have two parts, first i bind to the OnPawnSet and then i try to check for the team and show the nameplate if we are on the same team. The second part is a repnotify variable that contains the team of the player, and i do the same check as the onpawnset when the repnotify is triggered. This way it handles most of the cases were some characters are spawned before beiing replicated etc. My problem is that in a real case scenario with some lag (i tried with emulation lag set to bad), on the client side, the nameplate doesn't appear anywhere. I think i am overcomplicating things but i don't know what i could do to have a better version
If you have any advice on this kind of stuff with replication race issues i would be really glad to hear them
What would be a good approach to have a climbable ladder, that is replicated properly and to keep the animations in place?
That question is really vast
Yea I was initially thinking of having the climbing driven by root motion, but maybe I can have a custom Movement Mode, that then just drives the movement, but I wonder if I can sync the animation with it.
As long as the data used for the animations are replicated there shouldn't be any problem to sync the animation
You mean to driver it with root motion?
There are tutorials for climbing a wall, it wouldn't be any different than climbing ladder except the movement is restricted to one axis when it comes to climbing a ladder.
iirc, it just make the player go to Custom Movement mode or flying mode.
then from there it's just AddMovementInput
I mean I would create a Custom Movement Mode.
But the thing is how to sync up the animation with the movement.
Thinking about it, I t might has to be Root motion driven, since the animations might not have constant movement.
The question is how to sync them up, also with the waiting animations and so on, but the movement mode might has to be an interval movement mode.
I don't see it any different than walking
would probably use blend space
and just drive it based on velocity
The difference is, that the animation needs to be in sync with the position.
So that the hands and feet are synced up with the ladder rung.
bool FNetGUIDCache::IsDynamicObject( const UObject* Object )
{
check( Object != NULL );
check( Object->IsSupportedForNetworking() );
// Any non net addressable object is dynamic
return !Object->IsFullNameStableForNetworking();
}
What sort of exception am I looking at here? Clearly the object isn't null 0o. Is the object not supported for networking somehow?
I see, will dig deeper
easy way to tell is inspecting the value of it in debugger, if it's a load of garbage, that's probably the issue
usual candidate is a raw uobject pointer somewhere
or using them off-game thread
The exception only happened on client, 🤔 maybe the object got destroyed somehow when it reach the client?
new errors unlocked
somehow my standalone/packaged game fails to init steam ?
[2025.10.16-14.25.50:028][ 0]LogOnline: Verbose: STEAM: Steam: Starting SteamWorks. Client [1] Server [0]
[2025.10.16-14.25.50:052][ 0]LogSteamShared: Warning: SteamAPI failed to initialize, conditions not met.
[2025.10.16-14.25.50:053][ 0]LogOnline: Warning: STEAM: Steamworks: SteamUtils() failed!
[2025.10.16-14.25.50:054][ 0]LogOnline: Warning: STEAM: Steamworks: SteamUser() failed!
[2025.10.16-14.25.50:056][ 0]LogOnline: Warning: STEAM: Steamworks: SteamFriends() failed!
[2025.10.16-14.25.50:056][ 0]LogOnline: Warning: STEAM: Steamworks: SteamRemoteStorage() failed!
[2025.10.16-14.25.50:056][ 0]LogOnline: Warning: STEAM: Steamworks: SteamUserStats() failed!
[2025.10.16-14.25.50:057][ 0]LogOnline: Warning: STEAM: Steamworks: SteamMatchmakingServers() failed!
[2025.10.16-14.25.50:057][ 0]LogOnline: Warning: STEAM: Steamworks: SteamApps() failed!
[2025.10.16-14.25.50:057][ 0]LogOnline: Warning: STEAM: Steamworks: SteamNetworking() failed!
[2025.10.16-14.25.50:058][ 0]LogOnline: Warning: STEAM: Steamworks: SteamMatchmaking() failed!
[2025.10.16-14.25.50:058][ 0]LogOnline: STEAM: [AppId: 0] Client API initialized 0
[2025.10.16-14.25.50:058][ 0]LogOnline: Display: STEAM: OnlineSubsystemSteam::Shutdown()
[2025.10.16-14.25.50:059][ 0]LogOnline: Warning: STEAM: Steam API failed to initialize!
[2025.10.16-14.25.50:059][ 0]LogOnline: Display: STEAM: OnlineSubsystemSteam::Shutdown()
[2025.10.16-14.25.50:059][ 0]LogSockets: SteamSockets: Disabled due to no Steam OSS running.
did the steam overlay pops up when you run the packaged game?
oh wait, let me try packaged game
im iterating on some connection issues for so long i started to get lazy and only start standalone instances from editor
and if you look at the code of what prints that log message, it links to https://partner.steamgames.com/doc/sdk/api#initialization_and_shutdown btw
afaik steam won't work in editor, standalone or not.
i forgot to restart Steam on pc restart
if you are packaging on shipping you gotta write the devappid too.
overlay is working and warnings arent showing anymore, that was a dumb missing part from my end
im still stuck on that tho
also finding 0 sessions on app 480
Steam does work in standalone, just not the editor proper
so on server when my friends tries to join i just get a LogSteamSocketsAPI: Warning: SteamSockets API: Warning Ignoring P2P signal from 'steamid:XXXXX', unknown remote connection #YYYYYY
in friend logs i have LogSteamSocketsAPI: Warning: SteamSockets API: Warning [#470173019 P2P steamid:76561198274443582 vport 7777] Relay candidates enabled by P2P_Transport_ICE_Enable, but P2P_TURN_ServerList is empty
i really dont understand how it goes from "join succeeded" to "driver shutting down"
engine.ini
[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/SteamSockets.SteamSocketsNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
bInitServerOnClient=true
[Core.Log]
LogSteamSocketsAPI=VeryVerbose
LogOnlineSession=VeryVerbose
LogSockets=VeryVerbose
LogOnline=VeryVerbose
LogNet=VeryVerbose
LogSteamShared=VeryVerbose
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="/Script/SteamSockets.SteamSocketsNetConnection"
hey guys, I can currently connect through Steam invites, and most features are working fine.
However, I'm having an issue when a client leaves the session — no matter how the client disconnects, the server always crashes.
Here are the log files and Blueprints. Could anyone please tell me the correct way to handle client disconnection to avoid this crash?
Oh, the log file is quite large — should I only upload the part where the crash happens?
yeah
first off i would recommend not using the prue cast nodes to be 100% sur its no null
here is.
what version are you using ?
and in your case did you check what path (is server true or false) is run ?
i assume that you got player 2 (client) leaving, and player 1 (listen server) is crashing ?
or is this a dedicated server approach
UE5.6
listen server crash
why do you have 2 path here ?
if i remember correctly, a connected client just needs to run Destroy session, and for the host you need to call DestroySession for each client THEN destroy session for yourself
to test, first try to simply destroy session for your client, but this should be already what you are doing
only client do that?
yes
i cant help you more than "testing" stuff out because i didnt managed to get joining session work in 5.6 with steam
only with EOS in 5.4
whats your config DefaultEngine.ini values for the networking stuff ?
Oh, originally I couldn’t connect either until I followed this video to fix it.
- Enable OnlineSubsystemSteam AND SteamSockets
- Replace the NetDriver definitions in your DefaultEngine.ini file with the one below!
UPDATED - 7/16/2025
[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefi...
sorry is this
ill watch them even tho im pretty sure i already got the same setup
yeah its just the netdriver change to the socket one
ive got that already
does iris make a distinction between actors and objects?
a lot of the guides mention actors but it seems like a lot of the current source is object based?
like are subobjects even a thing anymore?
I can only join the server through Steam invites.
this is failing for me
oh
[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/SteamSockets.SteamSocketsNetDriver",DriverClassNameFallback="/Script/SteamSockets.SteamNetSocketsNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
yes
What does TearOff() actually do? I called TearOff() on the server to stop replication, and it's still replicating variables to the clients. (Repost because wrong attached image)
are you sure that's happening on the client and not the server?
bp onrep happens even on servers
Yes, I even confirmed if we have auth or not
if you just want to stop replication, probably better to just disable replication at runtime
iirc tearoff will keep the actor on the client
stops replication
hmm, is begin play getting called again after tear off on the client?
nope
That said, what I'm actually trying to do is for the server to send a last state to the client before calling TearOff(). So I'm testing if I can trust that the client receives that last state. But now I'm confused because TearOff() does not actually stops variable replication.
And if I do
// server
foo = true;
SetReplicates(false);
foo never make it to the client :(
