#multiplayer
1 messages · Page 285 of 1
That's one downside of those
You'll want your data to contain an index of sorts if you need order @pallid stone
yup no garauntee, if anything you should expect them to be in a different order
fast array is optimized towards the use of RemoveAtSwap so you don't have to constantly shuffle huge blocks of memory around
I definitely recommend reading the behemoth of a command at the top of the fast array serializer file, I’m pretty sure it mentions specifically that order is not guaranteed, as well as pretty much explaining replication in general
It does thank you. It seems using the tfastarray is not an option as I have a 400kb initialisation for it that is larger than the max 65kb you can send as a packet and needs a custom setup via chunking to send a byte array of the data. The order setup for the replication is just a black box I am struggling to understand so changes to all the stuff I've been trying after my custom intialisation don't match up :/
You probably want to post this to #1054845249945616404 instead, even though this hardly qualifies as a tutorial and is more or less an ad for your service.
You, as a user, are basically never interacting with this community. So a blog post that largely contains lists with info from official docs, links to those official docs (of which some aren't even pointing to relevant content), and otherwise just stuff specific to the service you offer, doesn't really seem all that genuine.
I don't mind companies creating blog posts in which they, additionally, point to their services. DigitalOcean, for example, has some really great tutorials. However, their posts are hands-on tutorials, with lots of steps, examples, or even full walkthrough.
The lists at the bottom of your post seem nice as a starting point, although I do have to wonder if some of these points wouldn't benefit from a more detailed explanation or even an example.
Might be worth considering replacing that blog post with a step by step guide on how to profile a Dedicated Server in general, without your service, with images showing actual problems and how to identify them, and only posting your service related info at the end, as a bonus. At that point I wouldn't even mind pinning the post.
Deleted. Thanks for the pointers. 😄
Hi guys I have a mode where defenders must protect an artifact from being picked up by the attackers, the defenders can move the artifact around the Site but once they try to go through doorways it shows a red box visual indicating they cant go through the doorway with the artifact as they would be leaving the Site. This message and visual only shows for the server though, not the clients, however the clients. can anyone help me make it so it only effects whoever has the artifact carried variable on the player rather than just effecting the server?
This is the code which is on the doorway/sitewall
So i want it to show for whoever has the artifact and is walking into the doorway not just the server
@quartz iris thats an obvious wrong case of using Multicast.
Tell me what Multicast RPC does.
Tells the other clients
Also never cross pins like that. (The blue pin goes to other node from other events)
By whom?
I tried the on owning client
server
nothing
It will just run the function for it self at best.
The only way for client to communicate with server is via server rpc
So if you need the client to tell server to run a function then use server rpc.
There's no instance where client speaks to other client directly.
Unreal uses server to client model.
I need to read again, what r u actually trying to do?
@quartz iris who do you want to send the msg to? Both side or just the defender or just the attacker?
First of all, if that's the case. Client doesnt even need to do a single thing.
No just the player that has the "Has artifact" as enabled
You can just show the msg locally. Without a single networking if the artefact is already possessed by the time the client hit the overlap.
This will eliminate the feeling of latency as well.
Optionally you can have the server tell the client that posses the artefact.
so when they hit the collision i just do the code i already did without any rpcs?
If you are going with server telling client to display a msg.
Then do this.
Component overlap-> has authority (true) -> get overlapped pawn -> if has artifact -> run client rpc -> display msg.
because I need the visuals/msg to ONLY show for the player who hit the wall
Only the player who hit the wall or only the one that has the artefact?
Only one player can pick up the artifact so the 1 defender who has picked up the artifact
So only display msg when hitting the wall only to the player that picked up the artefact?
Yes
Ok will do, thanks!
@quartz iris btw you will need the client rpc method inside your pawn.
Create a function、call it display msg that takes text.
You can then call that function as described above.
This way the function will only run on the owning client (owner of the pawn)
@quartz iris work?
this SoftPtr.LoadSynchronous() will work on dedicated server?
for me it gives an error target file not found
target file is the object passed using TSoftObjectPtr
loaded from hard coded FSoftObjectPath
tested with editdefaultsonly TSoftObjectPtr, giving the same error
can you please explain the context what are you trying to do?
loading object Synchronously when its needed from a hard coded FSoftObjectPath
Is the asset packaged on your server?
as far i know we do not package assets with server so that is the reason for the error it throws.
I am sure its not excluded in packaged, so it should get packaged?
If the file doesn't exist, it isn't packaged. Surely.
It's a dedicated server package? Or listen?
Dedicated linux server, and windows client
Package your server without pak files and see if it's there. Or use a pak explorer.
Yeah its not packaged
LogStreaming: Error: Couldn't find file for package /Game/Montages/StandUnEquipMontage requested by async loading code. NameToLoad: /Game/Montages/StandUnEquipMontage
LogStreaming: Error: Found 0 dependent packages...
adding that Montages folder to cooked directory list will solve the issue?
I think since the asset path is hard coded, the cooker ignores it cause its not referenced to any bp asset?
Could be. How are you referencing it?
In theory, you don't need to manually add it to the cook list if it's used
StandEquipMontage = FSoftObjectPath(TEXT("/Game/Montages/StandUnEquipMontage.StandUnEquipMontage"));
Yeah you should properly reference this in an Asset and not hardcode it
TSoftObjectPtr<UAnimMontage>& TargetMontage = StandUnEquipMontage;
GetMontageSafely(TargetMontage);
UAnimMontage* UWeaponManager::GetMontageSafely(TSoftObjectPtr<UAnimMontage>& SoftPtr) const
{
return SoftPtr.LoadSynchronous();
}
And is it a UPROPERTY?
Ok, still it is possible to add it to cook list and not refference in editor?
No
well there you go
TSoftObjectPtr<UAnimMontage> StandUnEquipMontage;
Avoiding reflection for hard coded path's
why? and why are you using hard coded paths?
If I want to make it UPROPERTY, i will just fill it in editor
the cooker won't be able to see the soft reference
Don't hardcode paths
bp's oftenly corrupts, just to not refill it, hard code save lots of time
Like, this is wrong. Do it correctly and the cooker will find it
It's wrong though.
very wrong
I am using lots of live coding
Don't care. It's wrong. Do it the right way. Reference it via an Asset.
Live coding is irrelevant for this.
Ok, and this next approach is also wrong?
UCLASS()
class ARMA_API UWeaponMontageData : public UDataAsset
{
GENERATED_BODY()
public:
UWeaponMontageData()
{
StandEquipMontagePrimary = FSoftObjectPath(TEXT("/Game/Montages/StandEquipMontagePrimary.StandEquipMontagePrimary"));
}
TSoftObjectPtr<UAnimMontage> StandEquipMontagePrimary;
};
AWeapon.h
UPROPERTY() UWeaponMontageData* WeaponMontageData;
AWeapon.cpp
AWeapon::BeginPlay()
{
if (UWeaponMontageData* NewMontageData = NewObject<UWeaponMontageData>())
{
WeaponMontageData = NewMontageData;
}
}
TSoftObjectPtr<UAnimMontage>& TargetMontage = WeaponMontageData->StandEquipMontagePrimary;
GetMontageSafely(TargetMontage);
UAnimMontage* AWeapon::GetMontageSafely(TSoftObjectPtr<UAnimMontage>& SoftPtr) const
{
return SoftPtr.LoadSynchronous();
}
lol what is going on here
since UWeaponMontageData is NewObjected, I think it should let the cooker know its an object and exists
Just expose the soft object pointer to the Blueprint and set the montage there.
Don't start making up a solution for a problem that doesn't exist.
and than just TSoftObjectPtr<UAnimMontage> TargetMontage = StandUnEquipMontage; by & would not be needed?
What you afterwards do with the exposed soft object ptr is up to you.
But referencing the asset should be done via that exposed property
You can then pass it around as soft object ptr, or load it and use it, or load it and store it in a transient variable, etc.
This is some serious questionable design decision
It’s obviously for their crazy super hackers and insane performance
Hey man sorry i'm not able to update you im away for 2 days. I will be back tho to lyk !
I added you as a friend on discord 😄
How does replication work inside a non replicated gameplay ability? I remember people saying that Epic doesn't recommend setting gameplay abilities as "replicated", if that's the case, how would you go about replicating a montage being played inside a gameplay ability so other players can see the animation being played?
I'm just running Net Exeuction Policy "Server Only" since it's for AI but I can't see the animation playing at all unless I replicate the ability
There is a play montage node specific to gameplay abilities that'll handle that for you.
I will still mark an ability as replicated just so I can do an RPC. Target data is dumb.
oh yea forgot about it lol
ty
why is targetdata bad?
Why am I having these issues? I couldn’t really understand much from the server logs either.
Aren’t ISMs replicated?
I said it is dumb. It is annoying to setup mainly. Passing the information around is w/e.
Because your BP_BlockManager_C_1.NODE_AddHierarchicalInstancedStaticMeshComponent-1_1 isn't stably named and thus can't be resolved across the net.
(Which usually starts throwing warnings when standing on them)
I use dinamic
No idea what you want to say with that.
Is that done during ConstructionScript?
I don't know if Blueprints can runtime spawn such Components outside of it, while having them properly named.
hm
and datatable eek but yeah this is problematic
I did this intentionally.
If I limit the blocks, players won’t be able to place new ones.
I set up the ISMs to be loaded from the database.
If I don’t use a database, I’ll need to define a new block inside the Actor for every new block.
Am I thinking about this wrong, or is this correct?
Having the blocks as (H)ISM is correct. Shouldn't be a new Actor for each.
It's just that I'm not sure if Blueprints can spawn stably named components runtime.
Might be a limitation and needs C++.
why does it need to be replicated for anyway?
couldnt the client just know what isms it needs to create
i make dediced server game
If I don’t initialize the world on the server when it opens, how will other players see it?
Or would it work if I initialize the ISM builder on the client instead?
Maybe it will help you understand.
0:15 You will be able to see and visit worlds created by other players.
Each world will have its own markets, and players will be able to farm.
For players to see each other, a new server is launched on a separate port for every opened world, and that world is run by the server.
However, because ISMs are not replicated, the blocks are not visible.
If there is no one in the world, the server shuts down within 15 seconds.
This reduces RAM usage and prevents unnecessary server load.
However, when someone enters the world (either the owner or a guest), the server is started again on its own port
You'd usually replicate the data that then is used to create the ISMs instead of replicating the Components.
If I have multiple pixel streaming components in a scene, does each make an individual connection to the signaling server or do they somehow share one?
I have a walljump system in my game. The way it works is every tick it does a sphere cast, and if it finds a wall it updates the wall variable which contains info about the wall. Then when you press jump, it checks if you’re currently on a valid wall, and if so do the walljump. I have it in tick instead of looking for a wall when you jump so that effects and stuff like that can constantly know whether you’re on a wall. The problem is the client and server disagree on if a walljump happened or not, and when the client mispredicts its pretty bad. What should i do?
Hi everyone
I am having an issue with UE5 Multiplayer. When a Client approaches a 'BP_Chair' and interacts with it, certain events should trigger—for example, the character should sit on the chair. My problem is that instead of the Client who performed the interaction, the Server's character is the one sitting down, even if the Server is far away or didn't interact at all. The logic is only affecting the Server. For the system to work correctly, it must affect only the specific player who triggered the interaction, regardless of whether they are the Server or the Client. Could you please help me resolve this?
Possible to start the game in late client mode?
can i have more details about how it works? is the chair calling the logic on the player or the other way around? if its the chair, how does it know which player to act on?
To do it the correct way you gotta get into CMC
i am into cmc
in C++
yep
is the wall check happening in the cmc tick or outside of it?
i overrided the jump function to have walljumps and im calculating the wall in the tick function of it
inside
is that bad
you are almost certainly accidentally using something that uses the local array of controllers/pawns etc like get player controller
https://wizardcell.com/unreal/multiplayer-tips-and-tricks/#2-beware-of-getplayerxxx0-static-functions
but I can't see what you are actually doing in the server rpc
Yeah, iirc theres a setting for late join
Haven't done one my self though
only in recent ue5 versions
@boreal flicker https://m.youtube.com/watch?v=F2IOnzzOCT0&list=PLXJlkahwiwPmeABEhjwIALvxRSZkzoQpk&index=10&pp=iAQB
Github: https://github.com/delgoodie/Zippy
Discord: https://discord.gg/uQjhcJSsRG
In this video I create the Wall Run and Wall Jump mechanic. The player will automatically enter a wall run while in the air and moving parallel with a wall.
Topics covered in this video:
- Custom Movement Mode
- Saved Move State
- Geometry Testing
- Mirrored Anim...
Is she still trying to get the game run on toaster?
nothing wrong with making a game for lower spec systems but we will always assume people are talking about a version we all actually use
I am on 5.4
well there is another way to achieve it, launch server from command line and join second client from command line lately
Much easier to "Enable late join" in editor preferences, then just start the game in PIE as normal, there's a new button next to the Play button to load a new client
just found Allow Late Join
now every client is a late joiner?
No... the number of clients in the drop down list for Listen Server or Client mode join at the start, not late joining.
hmm seems like not very usefull
🤦♂️
running server from editor using command line and joining it with command line early/late is more freedom
it is very useful if you want to test late joining in pie
you asked directly to be able to late join in client mode, that is an example of how to late join in client mode in play-in-editor
it is exactly as they say, it just makes the play button add a new pie client after the original number is created based on pie settings
Hi any one know is vehicle movement component with chaos wheeled supports replication
Hello, im currently troubling with steam multiplayer connection. I have enabled both steam oss and steam sockets plugins. Steam overlay works, i can create session, but when i try to join from another pc nothing happens. Im using ue5.7.1 and yes, i have implemented accept invintation events, i attach all neccessary files. Any help appreciated 🙏
P.s Create session function on screenshot is not vanilla but my own implementation, which i attached in SGCreateSessionProxy.cpp
DefaultEngine.ini
do you have a log for the server thats hosting?
also i've heard appid 480 can be buggy and not work if lots of peopple are using it
yes, gimme 5 minutes i will recreate it
i use listen server
it might be, but those features should be working as far as i know, and it worked before, back when project was on ue4.26, but then i used find session instead
Error Unable to communicate with ANY of 30 Steam Datagram routing cluster. Possible problem with local internet connection? it cant connect to any of the steam routers for some reason.. maybe a firewall thing?
if you type ping 8.8.8.8 in command prompt, do the pings go through successfully?
i also noticed this message and first thing i did i disabled firewall on both machines. 8.8.8.8 pings on both machines as well
Here is a repo of my project by the way, if that might help https://github.com/Kokapuk/shooter-game
you don't need the multicast since you already have onrep
https://github.com/Kokapuk/shooter-game/blob/main/Source/ShooterGame/SGCharacter.cpp#L219
Did you enable both steam sockets plugins?
You should consider using AdvancedSteamSessions plugin as it has a couple of workarounds for engine issues.
See this post where I got a minimal example working on 5.6 (I did this was just a few days before 5.7 came out).
#online-subsystems message
I also recommend enabling verbose logging on these categories, by adding this to DefaultEngine.ini
[Core.Log]
LogSteamShared=VeryVerbose
LogOnline=VeryVerbose
LogOnlineSession=VeryVerbose
i think i still need it, since i need to broadcast death with bIsHeadshot parameter to everyone
but maybe it would make more sense to disable OnRep then
never heard of need of the other plugin, ill try tinker around with it a bit more
you can broadcast it in onrep with an authority check, death should only be handled on server and simulate effects on all clients
still i need to pass bIsHeadshot somehow, which is not a case in OnRep
void ASGCharacter::AuthDie(APawn* Killer, const bool bIsHeadshot)
{
if (!HasAuthority()) return;
OnDie.Broadcast(Killer->GetPlayerState<ASGPlayerState>(), GetPlayerState<ASGPlayerState>(), bIsHeadshot); // on server only
bIsDead = true;
OnRep_IsDead(); // simulate death effects
GetMovementComponent()->Velocity = FVector::ZeroVector;
}
event should fire on clients aswell so im not really following
ok sure
@tidal saddle you can use struct to include your headshot data.
that sounds like an idea, thanks
@tidal saddle if you need more data such as vector (e.g to dictate force for ragdoll) on top of what you have right now.
Maybe just piggy back of HitResult instead creating new struct.
At the end of the day, does the same job imo.
instead of set the velocity manually I would call
GetMovementComponent->StopMovementImmediately();
totally agree
Question about RPCs: Is it possible for reliable multicast RPCs called before the client joins the game, to be received by the client once he joins minutes later? It seems to be the case in the editor, but not in packaged mode and I can't find documentation about it.
Simplification:
- Host is playing alone and calls a reliable multicast on Actor1
- Client joins the game 2 minutes later and automatically creates Actor1 locally, but isn't the authority.
- Client receives the reliable multicast.
afaik multicast are once time run and forget, for late clients use onrep
that was my understanding too, but they seem to be queued and resent later under certain conditions in the editor.
I could be reading the data wrong though, will continue looking.
If it's the case, that's a big problem.
show code
how did client make the actor but isn't the authority?
or rather, show the code that ends in calling the multicast
The actor is owned by the server and the server set it to replicate, so the client gets this actor when he joins the session
I'm taking care of the kids, will get back to this later.
No?
How are you simulating late joiners in editor?
Rpc is a one time event. Any player that is not in the game will miss it.
I set the editor to spawn 2 standalone games. Then I connect them together through a listen server.
One of the standalone is the listen server, the other connects to it later, minutes after the RPC was sent.
This isn't cut and pasted code, I edited it because it's pretty complex.
`UCLASS(config=Game)
class ASprite : public AActor
{
GENERATED_BODY()
...
void SetReplicates(bool bInReplicates);
UFUNCTION(NetMulticast, Reliable)
void ReplicatePostInitChanges(...);
}
`
`void ASprite::SetReplicates(bool bInReplicates)
{
AActor::SetReplicates(bInReplicates);
...
ReplicatePostInitChanges(...);
}
void ASprite::ReplicatePostInitChanges_Implementation(...)
{
...
}`
And I essentially call SetReplicates on my ASprite somewhere in the code.
I'm going to continue debugging my issue now, if the kids go to sleep.
not directly besides the velocity afaik
I see... thanks.
you can add replicated acceleration if that helps with a setting
you can also completely replace the onreps and replicated properties of aactor (acharacter etc) with enough cheesy macros and overrides
this is only really important if you need perfect atomicity though
for a slower paced game it won't matter though
Trying to tie this to CMC predictive movement.
well, the cmc for sim proxies is pretty much just using the actor replicated movement and a few more flags/bools in ACharacter::GetLifetimeReplicatedProps
ReplicatedMovementMode, bIsCrouched and not to forget ReplicatedBasedMovement
see PostNetReceiveLocationAndRotation and UCharacterMovementComponent::SimulatedTick
you can absolutely just add a cond_simulatedonly replicated property that has more context you need but be aware unless it is in the same struct (with iris) or manually serialized all at once it will be kinda arbitrary if it shows up exactly at the same time as the velocity + transform it was intended for
If I can get away with RPC, then I can just pass the direction there, but not sure if it will break predictive movement.
rpc here doens't make much sense unless it changes extremely often and also isn't very time sensitive
for example if it's kind of okay for it to be late or too early
and if it the things it changes are not very impactful
I tried to replicate via flag,
But not sure where my PlayMontage should be.
Tried to do it on BeforeMovement and AfterMovement, but it doesn't get played on other machines.
what does PlayMontage have to do with this? you said "movement direction"
is it a root motion montage?
Oh sorry, I'm trying to do 180 turn. But putting the multiplayer aside, I noticed that it doesn't turn the way I wanted due to TurnRate, so I figured I will need the direction input for the final look at rotation which in multiplayer context need to be passed.
I'm facing too many problem right now X_X.
yeah root motion montage, but I need to tackle the first problem.
Pretend that I haven't said anything above.
How would you handle characters playing a montage all while respecting CMC client prediction.
the regular replicated transform updates will completely get skipped during root motion
Yeah, I'm looking at this atm.
it depends on what "respecting" it means
it's literally just onrepping the transform + velocity and movement mode then simulating it locally, then smoothing the result to hide how much it jitters internally
UCharacterMovementComponent::SimulatedTick is where I would look first.. I am personally not really sure exactly how sim proxy root motion works in detail
during root motion that will kinda replace how everything else works
basically what I want to do =(. How would you tackle this?
should I still do it via compressed flag or not much sense to do it that way?
It depends... if it's just done locally via acceleration changing you could kinda just rely on that with some fuzziness I imagine
Making it a real "event" from the server will increase the chances it can miss
I tried checking speed change but other machines won't get updated fast enough resulting the condition get skipped all the time on other client.
TLDR it's been unfruitful to just apply the animation logic locally.
on simulated proxies you need to remember the mesh and actor location are entirely separate things
the true actor location is going to jitter
you can see how this actually looks if you turn on p.VisualizeMovement
the mesh location is smoothed and will interpolate based on a variety of settings
isn't that already handled for proxies
yes, but think about what that actually means
the motion you actually care about might be more the smoothed change in mesh position more so than than the raw velocity from the server
here is a cube on a sim proxy's mesh
this video looks choppy and that's not just because the recording sucks, the actual updates are very sparodic
I'm thinking I would personally try to consider the actual mesh to have its own velocity so to speak
of course you would need to consider and ignore really harsh corrections that skip smoothing it I suppose if those would cause false positives etc
honestly just trying replicated acceleration might be good enough though, I would suggest at least trying that first
the issues here imo is what do you do if it starts getting false positives that would never happen for the true local player
you could maybe have an idea of the true stage at which you did the "about-face" rotation and it was sent from the player itself from client->server as part of their saved moves somehow. You could make the sim proxies get an incrementing counter and/or a current "flip direction" as a byte or something if missing this is very bad
personally I would be okay with this kind of small animation flip being missed occasionally during extremely bad network situations... property replication is not a perfect series of events and probably should not be for sim proxies in most games unless the state is 100% required on all peers
Just remember that sim proxies do not care about saved moves, this is just a way to get that information to the server. getting that information to sim proxies has to be from something replicated on the character/a component/some rpc etc
which I think replicated acceleration will generally be pretty damn close to the intended movement direction while walking in most setups
FWIW I have not personally done that kind of turn-in-place from braking movement before so I'm sure someone else might have an evem more simple answer
All good, need all kinds of ideas atm.
show the line of YOUR CODE that it crashed on
UWeaponManager::OnRep_CachedEquippedSlot() Line 426 and the things before it
not accusing you of making a mistake here, just not possible to determine what is going on inside of a null pointer/garbage memory
also this time I am going to suggest sharing context
void UWeaponManager::OnRep_CachedEquippedSlot()
{
UE_LOG(LogTemp, Warning, TEXT("OnRep_CachedEquippedSlot 1"));
if (CachedEquippedSlot != 255)
{
UE_LOG(LogTemp, Warning, TEXT("OnRep_CachedEquippedSlot 2"));
if (UCharacterAnimInstanceBase* CharacterCurrentAnimInstance = Cast<UCharacterAnimInstanceBase>(OwningCharacter->GetMesh()->GetAnimInstance())) // Line 426
{
UE_LOG(LogTemp, Warning, TEXT("OnRep_CachedEquippedSlot 3"));
CharacterCurrentAnimInstance->SwitchToArmedState(GetEquippedWeapon());
}
}
}
this has 2 ways it can crash instantly
is OwningCharacter null? is OwningCharacter->GetMesh() null?
you need to read the current state of the memory around these lines
No, onrep is called after check ensure for owningcharacter and the mesh and animinstance on server
uh... this onrep is running from an actor channel receiving replication
why would it being valid on the server matter to the client?
owning character is a replicated variable
which I am mostly guessing because you did not include the context of which side this crashed on but I am pretty sure this onrep is called from a regular replication onrep
so? why does that matter?
it can still be null
server sets it
please show the state of the pointer at this line in the crash in the watch window
if you want help
I will crash it again in a moment
the server setting a replicated property does not gaurantee the client has it ever ESPECIALLY for a random unrelated property (CachedEquippedSlot)
they are two separate properties and there is NO gaurantee they will arrive in any particular order
Even if they do arrive at same time for this particular actor, that doesn't meaning OwningCharacter has arrived and is valid yet.
to fix this just don't dereference a null pointer in here and when OwningCharacter is set it also can just do the same thing as whatever OnRep_CachedEquippedSlot does to make sure the work is done when everything is there
this is a really common problem in unreal networking
you have two things that happen at random times and they need to both be there to do X, just do X in both places for whichever one happens when both are there
yeah owning character is null
Just Bret Hart doing some code review.
so yeah, maybe have an onrep for the character pointer and have it call
CharacterCurrentAnimInstance->SwitchToArmedState(GetEquippedWeapon());
so that it will apply the right setup when it comes in
or just poll for it in the pre anim tick (sometimes dumber is easier)
It's a good habit, networking or otherwise, to always nullcheck your pointers and gracefully handle their fail states. Nothing in gameplay code should be causing an app wide shut down.
this should not even be an error log, it can be assumed it WILL be null in some cases
replication does not care
ideally the stuff that expected it to be there can be done when it shows up
is there a way to debug project with rider but only for example client 1?
dunno if there's a specific way but if they are different processes you could attach your debugger to the one you want
I tried but it seems it is not working. Rider only recognize one process even tho two or more windows are opened
Where do you guys manage you ui from?
I might be super over complicating shit for myself, but basically I have a main menu, a lobby and a match level.
Both menu and lobby have access (through a ui button) to a firing range built in the level.
This means that i need to have basically the same game mode / player controller / pawn for all levels.
I guess i could put what widget to display on the HUD class and use a different one for each level. But this does not feel completely right either.
Also some ui depends on the game state, for example during the match there is a phase to select the weapons.
hey there, im trying to make a little lobby system where players from the main menu can invite each other / create a party, and then load into the game once everyone is ready. i was wondering, what is the most ideal way for the clients to see other players names etc on UI? I was replicating a players array but noticed some issues with that
Maybe try lobby data that's shared between all lobby players by using the session interface
Anyone know any plugins or articles for smoothing movement on autonomous proxies? Movement corrections being performed instantly makes it impossible to have smooth player-versus-player knockback, and I'm wondering if there's an existing solution for this.
CMC corrections are smoothed fwiw
Party Systems are usually done via Beacons.
Well, the ones where you party up in the MainMenu at least
if they are a listen server they may need to enable the cvar though
but they did say autonomous proxies ah. What I said there is for sim proxies (woops)
What are beacons? R they just another backend service from steam?
No. Beacons are lightweight connections that allow replication stuff like properties and RPCs but without actually opening the server's level.
They come with a subset of classes, like BeaconHostState and ClientState. That are very similar to GameState and PlayerState.
But minus all the game related code.
So you can use them to have a party lead and party members in the main menu and replicate minimal data like names or what character is selected via them
0o? How does the connection established when players are not connected?
It's how, at least originally (not sure if still) the invite lobby of Fortnite works
Epic service?
so you can poll for information like number of users, game mode etc?
interesting
Gears of War was one of the first majors to use it. I think one of them still does.
That's up to you. Beacon connections are just socket connections. It's the same as normal connections, just more lightweight
You can create a special session in your backend to handle them
Steam has the PartySession name for it as opposed to GameSession
EOS, no idea
So are most of the heavy lifting already done in the steam interface for Party Session?
It's the same concept in the end. The session backend just communicates the address to connect to
It's worth noting that you don't need to use the OSS specific stuff for them.
Don't know. I only ever used normal sessions but as PartySessions for them
They're just an actor basically that can send and receive RPCs from the server without going to the map. No replication.
Yeah OSS/Backend and Beacons are two concepts
Similar to how OSS/Backend and connecting to a server are two different things
In theory, yes, Unreal Tournament used them to reserve dedicated server slots
Don't need to connect and travel to then learn that someone else connected faster
I'm struggling to see how this work. So someone still have to be the server?
In theory, how does it start when a group of friends want to form a party and chat?
I think there is a pinned post in #online-subsystems about them
There are probably plugins but natively they are c++ only iirc
One of them is the "Server". AKA Party leader.
So essentialy, it's like hosting a map for people to join without hosting the map 🤔
Correct. The PartyLeader creates a BeaconHost, which is similar to a ListenServer. Aka it has an open socket connection and waits for connecting BeaconClients.
Similar. And no replication. All RPC based.
Replication should work. Unless I misremember
Been way too long
btw I got a question about Turn Stop movement.
Maybe. I could be going off of old info. I didn't test that, just the RPC bouncing.
So I finished a mechanic to turn 180 degree for the character, but I end up using RPC and montage as opposed to including the info in SavedMove.
is this not recommended? I always thought RPC for movement related is probably a bad idea. But I see ALS community version handle turning replication with RPC too.
trying to take a video atm.
No idea tbh. Never touched ALS or had to implement a 180 degree turn
I would probably just handle that in the CMC directly. Maybe by using ControlRotation or adding something similar.
Probably needs to be predicted. If it's driven by player input then it shouldn't be too difficult to just do it in the CMC
I tried to just locally check the deceleration but can't get it to work for Sims proxies because they don't update fast enough =(.
and my attempt on predicting it also failed.
My take earlier was to use replication acceleration or just add a new sim proxy only thing for it but an rpc might be more than good enough if it ends up timed okay
If the RPC is only for the SimProxy then that's probably ok
I don't know enough about 180 turns tbh
well it goes like this.
Autonomous do 180 turn -> Tell server to 180 Turn -> Multicast
kinda eww, but coudln't get it to work other way atm.
SimProxies are a problem in all those things. Flags that can be missed usually need to be a uint8 that gets increment instead
May I ask how it actually works math-wise when simmed locally? This is partially me wanting to try it myself more than just helping I guess
I always imagined it was some kind of like acceleration threshold that eventually locks you into a little turn-around move
Yeah. You have three values to work with I guess.
InputAcceleration, so input direction times acceleration.
in my case sim just not behaving the same. For example, I calculate speed locally to do a stop animation when sprinting.
But sim doesn't update the value fast enough that it skips the check.
Ideally, I just want to rely on acceleration / speed that I can calculate locally. That way I don't need to care about networking.
Acceleration itself (current one).
Velocity, also current one.
If I hold W along the X axis it would be some (X,0,0) input acceleration
And then some resulting current accel and vel
If I then hit S suddenly, it would still be the same velocity start of that frame
But input accel now points opposite
Which is a good point to notice the 180 turn I guess
Since CMC doesn't replicate shit to SimProxies, they only get the final velocity I guess.
I'm confused. Isn't this mostly just a root motion montage?
So gotta replicate some incremented uint8 flag in the character to indicate the turn
Eh, na, this is more TurnInPlace style stuff I would say
RootMotion takes too much control away and is too stiff
initially I don't want to use root motion because I want some slide effect like ice skate. So trying to rely on acceleration / deceleration for the effect.
but I end up with root motion anyway. Skill issue.
Players with gamepads could do 170° turns
You also lose a lot of control with the RM approach
Not saying it can't be done with RM
But then that also needs to be the exact result you want
Yeah I was just thinking the quick spin around effects some games have. Probably falls apart if you do it slower than a quarter second or so.
If you notice the turn you can just play a root motion montage, sure. And you can use some motion warping to fix the cases where players trigger it from gamepad and didn't do an exact 180 turn.
And the sliding kills that idea too.
MotionMatching is a perfect system for this if it wouldn't be so damn fucking expensive
Like you don't even need to use it for the whole animation locomotion
Can just feed it some reference point calculated from the input and use that grab the best montage with the best start time of that montage to get the perfect result
tried with 400 ms, doesn't seem breaking yet. But working outside the prediction system, I am not sure if I'm going to get issues in the future.
Mid 180 turn you do another 180 turn? MotionMatching can pick the best matching montage for that too. Sadly expensive and needs tons of animations
why is OnWeaponReplicatedNotify not always broadcasted for late clients?
void ACharacterBase::ServerPickupWeapon_Implementation(UWeaponItem* WeaponItem)
{
if (!WeaponItem || !WeaponItem->WeaponClass || !WeaponManager)
{
return;
}
FActorSpawnParameters SpawnParams;
SpawnParams.bNoFail = true;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
SpawnParams.Owner = this;
SpawnParams.bDeferConstruction = true;
FTransform Transform;
if (AWeapon* Weapon = GetWorld()->SpawnActor<AWeapon>(WeaponItem->WeaponClass, Transform, SpawnParams))
{
const FName EquippedSocket = "Equipped_Gun";
Weapon->FinishSpawning(Transform);
Weapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, EquippedSocket);
WeaponManager->SetWeapon(Weapon);
}
}
void UWeaponManager::SetWeapon(AWeapon* NewEquippedWeapon)
{
PrimaryWeapon = NewEquippedWeapon;
OnRep_PrimaryWeapon();
}
void UWeaponManager::OnRep_PrimaryWeapon()
{
OnWeaponReplicatedNotify.Broadcast(PrimaryWeapon);
}
void ACharacterBase::OnWeaponReplicatedNotify(AWeapon* Weapon)
{
UE_LOG(LogTemp, Warning, TEXT("OnWeaponReplicatedNotify broadcasted"));
}
ServerPickupWeapon_Implementation is reliable
and DOREPLIFETIME_CONDITION_NOTIFY(UWeaponManager, PrimaryWeapon, COND_None, REPNOTIFY_Always);
probably binding the delegate after onrep is called
onreps can get called before begin play
character binds it in beginplay
if (WeaponManager)
{
WeaponManager->OnWeaponReplicatedNotify.AddUObject(this, &ACharacterBase::OnWeaponReplicatedNotify);
}
tried calling onrep with 1sec delay, nothing changed
its like failing 1 out of 5
stick a debug log print in the onrep and right after the delegate is bound and see whats going on i guess
Print on tick to check if you actually get the right value? Its probably just race condition.
this seems to work fine, so yeah this shows that weapon onrep calls before the delegate actually binds successfully sometimes
if (ACharacterBase* owningcharacter = Cast<ACharacterBase>(GetOwner()))
{
owningcharacter->OnWeaponReplicated(PrimaryWeapon);
}
value of weapon?
in ctor?
nope (there are a few other things before beginplay and not in the ctor) https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-actor-lifecycle
as ultimately the onrep triggering is random... may as well just call the function you were binding for when you first bind to it if it has a meaningful value when you first see it
also as I mentioned earlier, if (WeaponManager) can silently fail if the weapon manager is null but if it's a default subobject it might never really matter
I dropped like 40 items in the map and the on Rep got called in batches
Ahhh this is what i saw online but wasn’t sure if this still accurate tbh
Roles question.
If LocalRole is SimualteProxy, then can we distinct if this Actor/Pawn is controlled BY server or* Other Client?
🤔
cause it looks like I have to check this other way
What do you mean by server of other client?
There is the server and there are client / clients.
Sim proxies are other pawn that you dont control.
Lets say 3 players, i am the listen server, john is 2nd player, mary is 3rd player. Each of us controll a character.
In my machine : my role is authority over all the player character.
Meanwhile in john computer : my character is simulated proxy, mary character is simulated proxy. His own character would be automous proxy because he controlled it.
In mary computer : john and my controlled character is simulated prozy. Her own character is autonomous.
Simulated proxies are smoothed, but autonomous proxies aren't—at least not with a default configuration. If you're a client and the server corrects your movement, you're instantly teleported to the server's location. Looking at the CMC's code, variables like Network Smoothing Mode, Network Max Smooth Update Distance, and Network Simulated Smooth Location Time are only used when correcting simulated proxies.
"or" , so I can see if its AI bot (server) or player :d
cause I guess ListenServer is Player
Do you know if Beacons work fine in 5.6 with Steam? I'm searching around in the Discord and it seems like people were having issues - also saw this forum post 🙁 https://forums.unrealengine.com/t/online-beacon-compatibility-with-steamsocket-plugin/2665805
Hi, I’m trying to use the Online Beacon plugin. In Lyra’s Steam\DefaultEngine.ini, I noticed a comment stating that SteamSocket doesn’t currently support beacon connections. Is that still the case? If not, I’m testing this in UE 5.6 with the SteamSocket plugin. I was able to establish a host connection, but I’m unable to get the cli...
you can maybe bind to it in ready for replication
I wouldn't be confident in it existing yet, though
You should probably just have a bind function that immediately broadcasts the initial value
Or something along those lines
will the CharacterMovementComponent automatically run PerformMovement() witht the same input vector for consecutive ticks if multiple ticks worth of time have passed on the client framerate?
Or am I supposed to implement my own tick cycle?
it works in a while loop and has settings for min/max ticks iirc
I am unsure how it handles extreme cases with keeping input or not (I would assume it keeps it)
Really? The Mesh is not smoothed on AutoProxy? Small corrections are usually pretty much invisible. It should only teleport the mesh too if the distance is too large. Maybe I misremember or it's really all just SimProxy, but I'm not convinced. Don't have access to any PC for a bit.
(not saying you are wrong, but wouldn't be the first time that someone states something that they were also not sure about in the end. Will probably check the code once more next week when I have my PC set up again)
No clue. Haven't used Beacons in a while.
Think that's only for sub stepping.
Aka to have a bit more precision for collision and such
Are we not supposed to change the parameters of the character movement component? I don’t see anything in the docs about the networking accounting for changes in configuration of the movement component across different ticks
Do you mean on the server?
yeah I guess it's still one tick
Changing default properties runtime is probably not really expected. Would need to be done through outside replication and potentially causes corrections.
E.g. the WalkSpeed variable is usually quite set in stone.
You can alter it via some OnRep property in the character, but that might lead to a few corrected frames
So what’s the intended flow for defining a bunch of custom moves that may be similar to walk or sprint or jump in nature but have slightly different mechanics?
Im not sure what the intended extension point of the system is
Inherit and extend where needed.
So we would inherit the component and add potentially more modes or parameters?
There are some basic examples pinned to this channel.
Yeah
Extending movement is usually a matter of inheriting and adding your own stuff in c++
Adding more parameters and modes doesn’t sound too bad because it should be mostly independent from the awesome framework unreal provides
I’ll be sure to take a look at the pinned examples. Thabks for the help!
This is still a bit of a vague question btw
Server doesn't tick client movement after all.
Client sends RPC with all input data and the delta time and server performs the move when receiving the RPC
Server frame rate doesn't really matter due to that
Doesn’t the client send on a fixed tick rate?
No
Oh really they send by frame? That’s odd to me
CMC uses an "independent" frame rate.
Each client uses their own frame rate.
Above 60 FPS it will try to combine moves.
That concept is also the reason that animations can look choppy on listen servers when it views other players.
Cause the pose of the skeleton is ticked via the same RPC on the Server to ensure animation and movement events are in sync.
Do you know how the independent frame rate is different from a fixed rate?
Question doesn't necessarily make too much sense
It's in the name what the difference is
the cmc kind of just has timestamps in each sent move
I am now calling a dedicated function directly from the owner instead of broadcasting it, it works fine but the only thing I don't like is casting to owner to access the function
other option I can just add this function to AActor and override it in the Character class
this will be the case if I really want to avoid the cast, but I will not since this is not a rapidly call operation
Rapid call or not probably wont make difference when it come to casting
I mean we don't want that cast on tick
Doesnt matter though?
What do you have to lose
for me this is a bad practice to cast in tick
cast exists to access a member once and save it cache it for later use
in my case I am not saving it since character can have many weapons and players can join/leave
so the old cache can be invalidated or crash if not refreshed
Btw for your on rep condition rat race, maybe you can just use a boolean as a state to see if the required component already initialized.
Use it to determine wether to call the onRep or not.
Kinda see this pattern in GAS when addressing race condition
that's a great idea, maybe will consider it if things gets complicated again in future
Hey Devs, I've a Pickable actor which I spawn on server and is replicated. It has Collision , Mesh and Audio Component, I wanted to play the sound when some player pawn touches it, So I used a client RPC to execute the call. The call is executed however the sound doesn't play.
However when I try to do it in single player it works fine .
Here is the .cpp
`void ABasePickable::ClientPlayPickupSound_Implementation(AActor* OwnerActor)
{
UE_LOG(LogGOG, Log, TEXT("Inside Client RPC call"));
// Only play if this client is the one who picked it up
APawn* LocalPawn = GetWorld()->GetFirstPlayerController()->GetPawn();
if (OwnerActor && LocalPawn && OwnerActor == LocalPawn)
{
// Play sound directly without spawning actors
if (PickUpAudioComponent && PickUpAudioComponent->Sound)
{
UGameplayStatics::PlaySound2D(this,PickUpAudioComponent->GetSound(),1,1,0,nullptr,nullptr,true);
//PlayLocalPickupSound();
UE_LOG(LogGOG, Log, TEXT("Playing Audio Cue"));
}
}
else
{
//UE_LOG(LogGOG, Log, TEXT("Owner Actor Not Same"));
}
}
void ABasePickable::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (CollisionActor == OtherActor )
return;
if(CurrentPowerUpActorState == EPowerUpActorState::PickedUp)
return;
if (OtherActor->GetClass()->ImplementsInterface(UPawnInterface::StaticClass()))
{
CollisionActor = OtherActor;
if (GetLocalRole() == ROLE_Authority)
{
FString compName;
OtherComp->GetName(compName);
FString enumName;
const UEnum* WeaponStateEnum = FindObject<UEnum>(this, TEXT("EPowerUpType"));
WeaponStateEnum->GetValueAsString(InventoryInfo.Item_WeaponType, enumName);
enumName = enumName.Mid(14);
//UE_LOG(LogTemp, Warning, TEXT("PickedPowerUp is %s"), *enumName);
// UE_LOG(LogTemp, Warning, TEXT("On Server, found %s"), *compName);
// UE_LOG(LogTemp, Warning, TEXT("Overlapping Pickable!"));
if (UVehicleBlueprintFunctionLibrary::GivePowerUpToThisPlayerController(CollisionActor->GetOwner(), InventoryInfo))
{
//UE_LOG(LogTemp, Warning, TEXT("%s Powerup To: %s collided with %s component"), *this->GetFName().ToString(),*CollisionActor->GetFName().ToString(),*OtherComp->GetFName().ToString());
APawn* PlayerPawn = Cast<APawn>(CollisionActor);
if (PlayerPawn)
{
AController* PlayerController = PlayerPawn->GetController();
if (PlayerController)
{
ClientPlayPickupSound(PlayerPawn);
UE_LOG(LogGOG, Log, TEXT("Calling Client RPC"));
}
}
`
here is the .h
`UPROPERTY(Category = Pickable, EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
class UAudioComponent* PickUpAudioComponent;
// Add RPC to play sound on specific client
UFUNCTION(Client, Reliable)
void ClientPlayPickupSound(AActor* OwnerActor);`
``Typically an Client RPC should be called on the client which is colliding, and then there I picked the objects audio component to play it.
Its not playing the sound, however the function executes, what is wrong I'm doing ?
@desert breach where do ClientPlayPickupSound lives?
Mind you client rpc only gets called if the actor is owned by that specific client.
So if the client rpc function lives inside the PickupActor then you are not doing it right as the server owns that replicated actor.
You can have the function in object the client own.
By defauly, its the player controller, character and player state.
I say controller make the most sense here. And if you dont want to bloat your controller, make an actor component, have the function inside the actor component then attach it to your player controller.
Heres what you can do.
Create a client rpc function in player controller.
Call it Client_PlaySound. Input is USound and just do PlaySound2D(InSound).
Now in your pick up actor.
1.On picked up / overlap.
2. If authority
3. Get overlapped / interacting character -> get controller -> cast to your controller and call client_playSound.
Done.
I think player controller already have these client rpcs to play sound etc
Cool, I never explore them 😆
Yeah, I just double checked, player controller have lots of client stuff
Nice but its unreliable rpc 👀
Guess not important enough if missed
Hi everyone, I'm running into a strange desync issue on Quest 3 (Client) vs Tablet (Server).
I am loading multiple small sub-levels using a ForEachLoop calling Load Stream Level (by Name).
To prevent freezing the HMD, I added a 0.1s Delay between each load (see screenshot).
On the Client, some Static Meshes inside these streamed levels appear displaced/offset.
- The Server sees them correctly.
- It is intermittent (happens randomly to different objects).
- Meshes are set to
Staticmobility.
I suspect the Delay + LoadStreamLevel is causing a Race Condition where the actor's transform replication arrives before the level is fully initialized on the Client.
Question:
Has anyone experienced this offset with streamed levels? Is FlushLevelStreaming the only way to fix this, or is there a better way to chain level streaming in Multiplayer without freezing the VR headset?
Thanks!
so there isnt any proper real time replciation on the world ?
the game state server delta is very rought, when emulating bad net conditions i can get 0.5s late time
it seems it doesnt try to simulated past time but only some smooth/sync when the var is replicated, i might have to do a custom solution
@lament flax simulate past time? R u trying to get the network clock or something?
i just want an elapsed server world time a minimum accurate on the clients
currently reading https://vorixo.github.io/devtricks/non-destructive-synced-net-clock/
as this probably outdated https://medium.com/@invicticide/accurately-syncing-unreals-network-clock-87a3f9262594
Yeah thats the article i would go for if you want to implement your own.
Was gonna link the firsf one.
I dont think it can get any better. It just send burst of rpc and calculate the average. You can modify the frequency of the rpc being send.
There was complain with player state server time due to player state having low net updats rate in the past but some people say it has since changed.
Ive already copy paste the code from the first articlr so i never use the one on player state.
i was using time to have server and each local client simulate passed time to basically move a platform
but since any ssolution requires RPCs anyways, i might just go for the classic transform replication for my platforms
Well if all the machine can agree on the same time then the platform can be simulated locally.
Provided that the platform always move in the determistic way.
yeah interaction sound is not important and should not be reliable I think
Interaction sound sounds like a local thing to me
I have it as client rpc atm as server is the auth for picking up item.
I can just force play the sound locally on interact but that will be premature if there is delay since server have to give the green light if the item is picked up or not.
The moment my interact data is removed from replication. The sound also plays.
You dont predict the pickup?
If there are a lot of platforms maybe its better to have the transform not replicated. If they are determistic all you need is for everyone agree on the time.
You can translate the platform based on the time.
You can always apply correction too since tou try to sync the time 24.7.
Better than syncing all platform. And as a bonus, the platform would be on the same position even other people have significant delay. Not sure how that will play out with cmc prediction movement though.
No, do you?
What if other people picked it up? Do we have to snatch it back from the player 🙁
Yuss!
Uno reverse
Buut i suppose you could wait. I do that too atm, but its instant anyways since i just test local atm
Was thinking of dealing with it later if it gets annoying
Hi, I'm having a rather difficult time trying to solve a crash issue after updating our project from 5.6 to 5.7.
For our game we use listen servers and SteamIP net driver (with the correct location of the net driver change in 5.6: +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/SocketSubsystemSteamIP.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver"))
After the update to 5.7 we could no longer play our game over the internet, LAN was fine.
I tested out SteamSockets net driver (+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/SteamSockets.SteamSocketsNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver"))
It crashed due to SteamSockets seemingly not supporting non-seamless ServerTravel (https://issues.unrealengine.com/issue/UE-239936)
So I enabled seamless travel for our Lobby and Game gamemodes and added a transition map. It works, we can now play our game over the internet.
However, if we want to restart the game map, all clients crash.
Call stacks seem to indicate that some Niagara hooks into Chaos are the cause, but what I can do about, I don't know.
We have tested this with an empty map to make sure our maps aren't doing anything weird.
We are restarting with the ServerTravel ?Restart option, same as the RestartGame AGameMode function does.
The host is launching the Lobby map with the ?Listen option.
All of the testing for this is done via a packaged development build on Steam using our Steam app ID.
In PIE this all works ok (using net.AllowPIESeamlessTravel 1 to enable seamless travel in PIE)
We are using the standard distributed Unreal Engine builds via the Epic Games Launcher.
The last thing from the client before crashing (crash seems to happen after the transition map and going back to the game map):
[2026.01.12-15.30.15:452][ 53]LogWorld: SeamlessTravel to: /Game/Maps/Map_EmptyPlane
[2026.01.12-15.30.15:467][ 55]LogWorld: BeginTearingDown for /Game/Maps/Map_EmptyPlane
[2026.01.12-15.30.15:472][ 55]LogWorld: UWorld::CleanupWorld for Map_EmptyPlane, bSessionEnded=false, bCleanupResources=true
[2026.01.12-15.30.15:473][ 55]LogSlate: InvalidateAllWidgets triggered. All widgets were invalidated
[2026.01.12-15.30.15:507][ 55]LogAudio: Display: Audio Device (ID: 1) registered with world 'Map_Transition'.
[2026.01.12-15.30.15:510][ 55]LogAudio: Display: Audio Device unregistered from world 'None'.
[2026.01.12-15.30.15:519][ 55]LogRenderer: Forcing update for all mesh draw commands: SkyLight real-time capture change
[2026.01.12-15.30.15:531][ 55]LogUObjectHash: Compacting FUObjectHashTables data took 0.64ms
[2026.01.12-15.30.15:534][ 55]LogChaosDD: Creating Chaos Debug Draw Scene for world Map_Transition
[2026.01.12-15.30.15:534][ 55]LogStreaming: Display: FlushAsyncLoading(664): 1 QueuedPackages, 0 AsyncPackages
[2026.01.12-15.30.15:535][ 55]LogStats: SeamlessTravel FlushLevelStreaming - 0.000 s
[2026.01.12-15.30.15:562][ 55]LogWorld: Bringing World /Game/Maps/Map_Transition.Map_Transition up for play (max tick rate 300) at 2026.01.12-15.30.15
[2026.01.12-15.30.15:562][ 55]LogWorld: Bringing up level for play took: 0.027264
[2026.01.12-15.30.15:562][ 55]LogWorld: Sending NotifyLoadedWorld for LP: LocalPlayer_2147482468 PC: BP_GamePlayerController_C_2147481819
[2026.01.12-15.30.15:562][ 55]LogNet: Verbose: NotifyLoadedWorld Begin
[2026.01.12-15.30.15:562][ 55]LogNet: VeryVerbose: GetFunctionCallspace RemoteRole Remote ServerNotifyLoadedWorld
[2026.01.12-15.30.15:562][ 55]LogNetTraffic: Sent RPC: BP_GamePlayerController_C /Game/Maps/Map_Transition.Map_Transition:PersistentLevel.BP_GamePlayerController_C_2147481819::ServerNotifyLoadedWorld [39.4 bytes]
[2026.01.12-15.30.15:562][ 55]LogNetTraffic: VeryVerbose: Sending: FOutBunch: Channel[5] ChSequence: 324 NumBits: 315 PacketId: 0 bOpen: 0 bClose: 0 bIsReplicationPaused: 0 bReliable: 1 bPartial: 0//0//0 bHasPackageMapExports: 0 NetTokensPendingExport: 0
[2026.01.12-15.30.15:562][ 55]LogNetTraffic: Verbose: UNetConnection::SendRawBunch. ChIndex: 5. Bits: 315. PacketId: 13134
[2026.01.12-15.30.15:562][ 55]LogNet: Verbose: NotifyLoadedWorld End
[2026.01.12-15.30.15:562][ 55]LogWorld: StartLoadingDestination to: /Game/Maps/Map_EmptyPlane
The crash call stacks aren't always the same, here's two I've seen:
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0xffffffffffffffff
ntdll
Dolly!Chaos::FEventManager::UnregisterHandler() [D:\UnrealEngine\Engine\Source\Runtime\Experimental\Chaos\Private\EventManager.cpp:42]
Dolly!UNiagaraDataInterfaceChaosDestruction::BeginDestroy() [D:\UnrealEngine\Engine\Plugins\Experimental\ChaosNiagara\Source\ChaosNiagara\Private\NiagaraDataInterfaceChaosDestruction.cpp:333]
Dolly!UObject::ConditionalBeginDestroy() [D:\UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\Obj.cpp:1295]
Dolly!UnhashUnreachableObjects() [D:\UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:6158]
Dolly!UE::GC::PostCollectGarbageImpl<1>() [D:\UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:5773]
Dolly!UE::GC::FReachabilityAnalysisState::PerformReachabilityAnalysisAndConditionallyPurgeGarbage() [D:\UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:5970]
Dolly!CollectGarbage() [D:\UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\GarbageCollection.cpp:6216]
Dolly!FSeamlessTravelHandler::Tick() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\World.cpp:8824]
Dolly!UEngine::TickWorldTravel() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp:15563]
Dolly!UGameEngine::Tick() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\GameEngine.cpp:1873]
Dolly!FEngineLoop::Tick() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp:5829]
Dolly!GuardedMain() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Launch.cpp:190]
Dolly!GuardedMainWrapper() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:123]
Dolly!LaunchWindowsStartup() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:277]
Dolly!WinMain() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:335]
Dolly!__scrt_common_main_seh() [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288]
kernel32
ntdll
and
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0xffffffffffffffff
Dolly!UNiagaraDataInterfaceChaosDestruction::BreakingCallback() [D:\UnrealEngine\Engine\Plugins\Experimental\ChaosNiagara\Source\ChaosNiagara\Private\NiagaraDataInterfaceChaosDestruction.cpp:1922]
Dolly!UNiagaraDataInterfaceChaosDestruction::PerInstanceTick() [D:\UnrealEngine\Engine\Plugins\Experimental\ChaosNiagara\Source\ChaosNiagara\Private\NiagaraDataInterfaceChaosDestruction.cpp:2492]
Dolly!FNiagaraSystemInstance::TickDataInterfaces() [D:\UnrealEngine\Engine\Plugins\FX\Niagara\Source\Niagara\Private\NiagaraSystemInstance.cpp:1875]
Dolly!FNiagaraSystemInstance::Tick_GameThread() [D:\UnrealEngine\Engine\Plugins\FX\Niagara\Source\Niagara\Private\NiagaraSystemInstance.cpp:2605]
Dolly!FNiagaraSystemSimulation::Tick_GameThread_Internal() [D:\UnrealEngine\Engine\Plugins\FX\Niagara\Source\Niagara\Private\NiagaraSystemSimulation.cpp:1348]
Dolly!FNiagaraWorldManager::ExecuteSimulations() [D:\UnrealEngine\Engine\Plugins\FX\Niagara\Source\Niagara\Private\NiagaraWorldManager.cpp:1755]
Dolly!FNiagaraWorldManager::Tick() [D:\UnrealEngine\Engine\Plugins\FX\Niagara\Source\Niagara\Private\NiagaraWorldManager.cpp:1615]
Dolly!FTickFunctionTask::DoTask() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:349]
Dolly!TGraphTask<FTickFunctionTask>::ExecuteTask() [D:\UnrealEngine\Engine\Source\Runtime\Core\Public\Async\TaskGraphInterfaces.h:697]
Dolly!UE::Tasks::Private::FTaskBase::TryExecuteTask() [D:\UnrealEngine\Engine\Source\Runtime\Core\Public\Tasks\TaskPrivate.h:519]
Dolly!FNamedTaskThread::ProcessTasksNamedThread() [D:\UnrealEngine\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:791]
Dolly!FNamedTaskThread::ProcessTasksUntilIdle() [D:\UnrealEngine\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:691]
Dolly!FTaskGraphCompatibilityImplementation::ProcessUntilTasksComplete() [D:\UnrealEngine\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:1604]
Dolly!FTickTaskSequencer::ReleaseTickGroup() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:1035]
Dolly!FTickTaskManager::RunTickGroup() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:2129]
Dolly!UWorld::Tick() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\LevelTick.cpp:1743]
Dolly!UGameEngine::Tick() [D:\UnrealEngine\Engine\Source\Runtime\Engine\Private\GameEngine.cpp:1883]
Dolly!FEngineLoop::Tick() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp:5829]
Dolly!GuardedMain() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Launch.cpp:190]
Dolly!GuardedMainWrapper() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:123]
Dolly!LaunchWindowsStartup() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:277]
Dolly!WinMain() [D:\UnrealEngine\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:335]
Dolly!__scrt_common_main_seh() [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288]
kernel32
ntdll
Hey! This lives on the PickableActor, which is spawned on the server, its the issue of ownership, as Server owns it and the client side wants to fire audio component play, I transferred the call execution to the playercontroller client RPC, which is the owner on the client side.
I'm not sure if the mesh is smoothed, but I know that the character itself isn't, which creates a jarring discrepancy from the perspective of the player, since their camera is being teleported.
I can tell you that you shouldn't put any visual stuff as a child of the capsule
It should always be parented to the Mesh
For that very reason
Do you happen to remember where the mesh location is smoothed for the locally controlled client?
I only found where it happens for simulated proxies and for clients from the listen server point of view
I've looked through some of the pins but I'm having trouble finding what you're talking about. Could you point me in the right direction?
This is in regards to extending the CharacterMovementComponent to support more movements
If anyone cares, no, RPCs aren't queued or cached. If a RPC is sent and a new peer joins later, he won't get that RPC.
My issue was caused by expecting I had stopped my actor from ticking, but since I wasn't the authority and the player that had authority let the actor tick, it also forced my copy of the actor to tick.
In the editor though, the authority will NOT force your copy to tick.
It's also not happening in every situation. I didn't debug this enough to figure it out.
Multicast RPCs can be queued in very specific scenarios
generally when the actor isnt available on a client yet
but is about to
afaik
that's about it
I don't think it does. Mesh smoothing is done in the CMC's SmoothCorrection function, which is only called on simulated proxies or remote autonomous proxies. It even has an ensure that would prevent it from being called on local auto proxies.
Yeah, that's what i found too, but i do remember hearing about smoothing for the controlling client before
If you find anything that talks about it, share it cause I'd love to see how other people do it
I guess you could interpolate the mesh component position between the pre correction position and post correction position. But this would probably interact badly with root motion (??)... not really sure.
Yeah, I'm trying to get the camera component to lerp towards the new position after being corrected, since my game is first-person, and the mesh is rooted to the camera component
They will all make their own connection to the signalling server. In there, they'll each be identified by the component StreamerId
when extending the CharacterMovementComponent, is the idea to override Getters like GetMaxSpeed() GetMaxAcceleration() so that we can adjust simulation parameters deterministically based on boolean state flags?
No, not without having a look. Been in Mover land for too long. Don't have a PC atm (moving).
guys, is it expected behaviour that notify is not firing on listen server when adding a tag to container, client is firing; But notify is firing on server/client when setting a container variable
Yes and no.
The problem is how OnReps work in Blueprints.
In C++ they don't call for Servers. The reason they call for the Server in Blueprints is that they are sort of "Property Changed" notifiers there.
But the whole thing is coupled to the Setter. The Add node doesn't trigger it.
Best thing you can do is probably set the container with itself in that case.
Yeah, but that doesn't even matter that much. It's more the K2 node that is the Setter I believe
So maybe Epic should in Add gameplay tag func make array dirty? or it would not work in BPs anyway?
thats what i was doing in c++ but I only tacked cpp replication
Idk what trigger the OnRep logic exactly
push replication or whatever
Could be that it needs to do that but might be a special function call in the K2 node
Yeah it's not about push replication
You are getting the onrep on the client after all
Something inside the Setter triggers the changed notifier.
Got it
Again, in C++ OnReps don't call on the server to begin with
I know, you have to manually call func
You can have a Single-Player game and use the OnRep as a Property Changed notifier in Blueprints in theory. Not that you should
but its magic automated in bps
Is Struct Property replicated as whole or only its child values per change?
Unless you implement a custom net serializer for your struct (just making that distinction for anyone else who might read this and not realize)
UE documentation mentions a Remote RPC alongside server/client/multicast. I've never seen this before, is this something new and from what version of UE?
iirc it's contextual based on who calls it to be either way
It's new in 5.5. I have not tried using it yet personally
From what I remember its possibly related to the experimental server meshing (cant remember its proper name).
MultiServerReplication ?
That could be it yeah.
I feel like it was related to that
I could be wrong
from my understanding it's like you have an identical Server and Client RPC, you can use Remote and it will be call on the other side
but the use case seem niche
It could very well be just a convenience like that
Might not be tied to anything in particular
Though they wouldnt have added it unless they had a reason to
In the MultiServer paradigm I wouldnt be surprised if it has something to do with like "local" authority for a particular server instance in relation to another instance next to it.
🤷
Server instances need a mechanism to talk between each other without a Player involved.
Might be related tothat
"If I am a Slave instance, send this to the Authority, if I am the Authority, send it to Slaves"
🤷
Tracking down the commit that it was introduced in might give clues
remote object is kind of the term here
basically every single TObjectPtr has code now that considers remove objects
How would you check if a controlled actor is controlled by the listen server?
GetNetMode() it is.
IsLocallyControlled()
with IsNetMode(NM_ListenServer) if need be, or just an authority check
IsLocallyControlled just check if the actor is controlled by local controller.
I need to check if the character is owned by the listen server.
all characters will return authority on server machine.
To put it into context, I am dealing with interaction on server side.
With lag in mind, I will tolerate extra interaction radius when interacting character is owned by a client.
But for server, I want the radius to be checked as is because server have no delay.
if (InteractingCharacter->GetNetMode() == ENetMode::NM_ListenServer)
{
}
Not sure if this is even right 🤔
Perhaps I don't think clearly...
i can probably do the opposite. Check if the controller is owned by a client, otherwise it's the server.
Get Remote role or something.
if (InteractingActor->GetRemoteRole() == ENetRole::ROLE_AutonomousProxy)
{
}
maybe this?
Why even bother
I'd use the same leniency on the server, it just doesn't matter
IsLocallyControlled just check if the actor is controlled by local controller.
So what do you think that does when the local controller also has a net mode of ListenServer
:p
right right
I'm getting hit too much at the gym lately.
my test still early and I never get into the stage for a playable demonstration but you don't come across any issue when the character is at the edge of the interaction distance?
I don't want to have a scenario where the player is at the edge of the interaction radius, have the interaction data prompted as it was about to leave / enter the interaction radius and server go sike, you are off by a few units so you don't get the item.
No I meant I wouldn't bother removing the leniency for the listen server
Might as well keep it the same for everyone
@dark parcel
// Called on server.
if (ACharacter* InteractingCharacter = Cast<ACharacter>(InteractingActor))
{
if (!bInteracted)
{
const UAGInteractionComponent* InteractionComponent = Cast<UAGInteractionComponent>(InteractingCharacter->GetComponentByClass(UAGInteractionComponent::StaticClass()));
float _distanceToInteractingActor = (GetActorLocation() - InteractingActor->GetActorLocation()).Size();
float _interactDistance = InteractionComponent->InteractionRadius;
if (!InteractingCharacter->IsLocallyControlled())
{
// If interacting character is owned by client, allow tolerance for the interaction radius.
_interactDistance += InteractionComponent->ClientInteractionRadiusTolerance;
}
// Check distance between the fragment and interacting character.
if ((GetActorLocation() - InteractingActor->GetActorLocation()).Size() <= _interactDistance)
{
}
}
}
Thank you for the help btw, as this function is called on server, I can just check with IsLocallyControlled as you say.
Is there a proper way to use ans in mp? I PIE with 1 instance in Client Net Mode, I expect ANS end to be called 2 times but its being called 11 times instead. I have no idea why and how to solve this.
I have no issue with ANS in multiplayer. Perhaps show what you have.
UAnimInstance::Montage_Play called 2 times but ans end called 11 times
Can we get the ANS logic?
Also if you want to call this once per notify why are u using ANS instead of Anim Notify
Oh you want begin and end, nvm.
So the ANS pnly calls set state. I cant see any code that link it with your combat component.
If the reload weapon is the issue, show the ANS for that.
reload weapon probably has the same behavior, I tested this with another ans end and it has the same issue.
When I put a debug point on notify begin or notify end they being called more than they need to be called.
Go to your montage and open the detail panel.
Screen shoot it
Theres montage tick type or something like that.
Or something that is called que.
Try swapping what ever you have right now, see if it helps.
I gtg sleep, if that dont work. Hopefully someone else spot the issue.
neither tick type or que is in asset details of montage.
good night
Im sure its somewhere there, if not check the doc and figure out where to change it.
Also just because u running 1 instance of client, there is still the server.
Yeah try changing the montage tick type. I know it calls more than required.
Iirc shouod be branching.
But swap what ever you have right now.
Found on Google from forums.unrealengine.com
This is the best resource I've come across for extending the CharacterMovementComponent: https://youtu.be/urkLwpnAjO0?si=Cpfou99a1LZs50Zm
https://discord.gg/uQjhcJSsRG
In this video I am introducing a series I will be making which explores the character movement component and how you can extend it in depth.
0:00 Intro
1:00 What is the CMC?
2:00 Do you need a custom CMC?
5:35 What does the CMC provide?
7:10 Outro
the framework unreal gives out of the box is great. in Unity it took me like 3 months to make the same framework from scratch
That said, I understand why Unity doesn't
Cmc is a dinosaur, not great for games with a lot of characters.
Does unity even have multiplayer out of the box? Thought you have to download plugin or roll your own.
You're right. Its not out of the box, but they have proprietary solutions that you use to roll your own. More involved than unreal but much less than doing multiplayer from low level libraries.
NetCode for gameobjects is probably what you're thinking of
found montage tick type defaulted as queued, setting it to branching point fixed multiple runs.
Thank you a lot ❤️
so is
UGameplayStatics::GetPlayerController(GetWorld(), 0)
reliable to get host PC in ListenServer case?
not sure if I tagged, did not mean to do it
What is best way to create loading screen with readyup/wait for players. It means if all players accept after map load, screen is removed and game starts
Look into AGameMode, as it supports the concept of Match state.
Loading screen is just a widget you slap to the viewport.
You can choose to remove it when ever you want. Look up Lyra common loading screen.
Loading screen is just a widget you slap to the viewport.
It's not
Loading screens in Unreal are deceptively more complicated than what they friggin' need to be.
Sure - you can probably throw a widget on the screen and add it to the root and all that. But that has issues (that elude me right now, busy at work). The most common approach, that has been pretty successful, is hooking into UE's movie player. I know - doesn't make a whole lot of sense. But one of the big reasons is because when it gets created and destroyed and when it gets called. Also it is on a different thread if I recall.
Widget by default get destroyed on level change.
By making the UUserWidget a shared ptr, it stops them from being destroyed and GC. I havent copy anything else from lyra and havent play with the movie player.
But my loading screen can be removed and added at anytime. Atm i wait till my map finished load and for my cosmetic data to load.
I may be wrong but I think exi says, even lyra loading screen isnt truly async?
I probably just havent encounter future issues yet.
For hard travels, I don't think you can use widgets, you have to run a "movie" or image on a separate designated thread.
Depends on what you mean by cant. If you mean the widget get destroyed then no, you can prevent that.
Infact i am hard traveling soo far. Havent got the need to server travel yet.
Aren't widgets still rooted in the "world?" I thought that everything basically gets destroyed during hard travels, causing a synchronous load on the game thread.
If you make it a shared ptr it will prevent the widget from being destroyed and gced.
If its a raw ptr then yeah they get destroyed on world change.
Is the widget still displayed and running during the synchronous load?
Yes
Hmmm, that's interesting. I'll have to try it.
Survive both level. I spawned mine in subsytem and make it shared ptr.
Async load level then open level (hard travel)
Only fade it out after conditions are met in the new world.
When a client joins a multiplayer match, does the player's state get spawned before or after the level's actors have spawned?
On the Server side, the PlayerState is created as soon as the PlayerController is created.
On Clients, its arbitrary because its created through replication.
ok tldr I need some way to defer spawning the player server side until functions client-side complete, like loading a sublevel. An actor is handling the sublevel loading manually, and not all levels require a sublevel and the actor.
I'm suspecting replication should handle the sublevel to the client, so I suspect currently with the sublevel not yet loaded then the server is spawning players before it's loaded, which I could handle via the gamemode searching if the actor exists and waiting until they've completed their task before spawning players
Or spawn players in a temporary "spectator" pawn until things are ready for everyone.
I could do that, I just need some way where actors spawned in the level can tell the gamemode that things are ready
I have an actor which does that (gametype, which not to be confused with gamemode, handles how gameplay occurs including spawn rules) but in my current code its not finding the actor which it needs to wait for
oh, the issue is because the gametype actor is in a different always loaded level, so the ugameplaystatics::GetAllActorsOfClass isn't finding the actor
BeginPlay() -> Server RPC
what should I choose for a stuff like shrinkable bluezone that covers the whole map and resize over time
Subsystem or Actor with few components ?
Responsibilities of the bluezone system:
1: Dealing damage to players
2: Bombing a random point in available playzone
3: Generating a random airdrop point
4: Spawn airdrop plane that move towards airdrop point, when it is reached drop an airdrop package
If it needs a visual representation, an actor. If it's just a map thing, a subsystem is probably fine. You could do both. Have the subsystem spawn the actor.
Map = minimap / map overview.
My current approach
void AArmaGameMode::BeginPlay()
{
Super::BeginPlay();
BlueZoneManager = GetGameInstance()->GetSubsystem<UBlueZoneManager>();
BlueZoneManager->Initialize(this);
ZoneVisualizer = GetWorld()->SpawnActor<ABlueZoneVisualizer>();
BlueZoneManager->SetVisualizer(ZoneVisualizer);
}
Seems fine.
Though I'd probably have just thr server spawn it and have it replicate.
In case you want to transfer any data about it.
ZoneVisualizer is replicated just for visual representation
Yes, but that subsystem is going to spawn one on both server and clients. Unless the subsystem is only created on servers...
Yeah subsystem is only on server
it does all other stuff like
-- Global state management (current zone phase, timers, damage)
-- Damage calculation and application to all players
-- Zone shrinking logic and timing
-- Random point generation for bombing/airstrikes
-- Airdrop scheduling and coordination
I need to validate one thing.
Does Multicast runs locally if actor does not own connection ? 🤔
Correct
Anybody here who has got far enough to be hosting dedicated servers - are you opting for the -nothreading option?
I think traditionally it has been used to allow for more servers to share a single machine, but it implies that the server would need to run at a lower tick rate, plus I'm unsure how well things like HTTP background tasks work in that scenario.
you are smarter than GPT 😆
depends on the game. if you heavily use threading you might have to keep it on
many games are made to run on a single core or even be on a shared core. all depends on how the game was made and how difficult it is to run
even with threading on there are ways to force a program (like your server) to run only on assigned cores
I'm not really asking for advice, just to get an idea of what people are doing. By default UE spreads things over a small number of threads, and obviously on a server the render thread can be ditched which reduces the count further, but it's not 1. So I'm curious how people are approaching this.
I profiled my server on 5.3, and it was pretty much single threaded anyway. The other threads had v little activity.
Usually a MT server costs to much so games works with single threaded servers
heyy guys, do i need to set input mapping context to work on multicast if i want to switch them when enter in a vehicle? i tried to ask google gemini but he said input mapping needs to run only on owning client, but when i'm trying to do how he said nothing works, with multicast works fine but when my car starts to go, my second player from passengers seat starts to changing his location when vehicle is moving
i tried to make this event, but i don't understand why it shows Enhanced Input Local Player Subsystem is not valid
players possess the vehicle right? i'd switch the input context in the pawns SetupPlayerInputComponent function which gets automatically called on the client
yes, player successfully possess the vehicle, this event is inside my car blueprint and works fine
if i call this event after possess node, all works fine, but i don't understand why gemini said to use run on owning client because is better
you mean to switch them inside player controller blueprint?
no it'd be inside the vehicle class.. in c++ i'd use SetupPlayerInputComponent() but im not sure about blueprints.. maybe client restart? i just know you dont need to use an rpc
Especially a multicast to setup an input of a client. That make 0 sense.
so input switch needs to run only on owning client, without server?
yeah input context is completely local so it doesn't exist on the server... server only cares about the data sent from whatever those inputs are doing locally
ok i will try again thanks
omg, i just changed the possess node after call Client_SetupVehicleInput node and now works fine😅 , and i spent 3 days on this thing😵💫
Hi guys! I have a strange problem. I develop a listen server multiplayer game in 5.4 and when the players arrived in the Lobby everything is fine ,they can control the character but when we go to the game map, the client can not control the character, the character controller is None, the client doesn't see the host character when the host moving around it. I use seamlesstravel and bdelayedstart. What could be the problem? I've tried almost everything. GameMode and GameState is the same, in the character Blueprint the auto possess player is Disabled.
if you run a timeline on both server and client to set transform of a UStaticMeshComponent, why both desynced?
generally both should have the same transform for the mesh! but they don't 🤔
the issue was server first set transform and than client is trying to set it also, in result client get stuck cause server is again applying new target scale...
solution was to set the UStaticMeshComponent replicated and let the server set its transforms
what replicates? what changes? what times the timeline? what does the timeline actually do? does anything else change the transform?
and yeah of course if they are both fighting over setting it the last one will apply... if you need a separate local only value make a separate thing
replication is not going to send at a perfect framerate either so you can safely assume it will jitter without local interp
this was started by both server/clients
void ABlueZone::TimelineProgress(float Value)
{
NewScale = FMath::Lerp(StartScale, TargetScale, Value);
ZoneSphereMesh->SetWorldScale3D(NewScale);
NewPosition = FMath::Lerp(StartPosition, TargetPosition, Value);
ZoneSphereMesh->SetWorldLocation(NewPosition);
}
edited some spelling mistakes, very late for me so I gotta go
"server first set transform and than client is trying to set "
they are separate machines... what else does the server do to send the result to the client? what is actually "synced" at all besides the timeline starting?
yeah it was started in beginplay
yeah this is what log says at least, first server started than client started
I would suggest using a visualization like vislogger
instead of logging transforms... that is very hard to read
at least for me personally
actor was replicated, so any change made in the actor server replicates
that is the context you left out that makes what is happening here a lot easier to figure out
remember: we can only see what you type into the messsage
or is that what you changed after the original message? either way I can't assume the transform is replcated based on the first question but oh well
with this stuff It's really dependant on what the goal is imo... For example arguably you don't need to know about the true end position if the start position + start time is known and decently synchronized on both sides (accurate server time etc)
Yeh I logged, server : 500, 500, 1000 client : 500, 500, 1000 in the same frame and then server sets new value in next frame and client skip the next frame change, in result we have difference
its important for both to have same transform values, cause if client is outside from zone on server it recieve damage and on client side it still not outside of zone cause the client has different transform values
I don't know what "the client" is in relation to a random static mesh
static mesh is visually represent as a wall for client
why is the wall moving? is it the zone edge?
yes
that would have helped to know earlier because I think that kind of thing is going to change very slowly over time and in a consistent way
you only really need to send when it starts and the client just needs to represent where it is going visually imo but if it changes speed/direction often it might be worth keeping realtime
it moves to a random point and scaled down
red circle is server transforms, which don't match to the client transforms
all they need to do is share the same known min/max size and their time along it
for late clients it also needs to be synced
I don't recall saying this is an rpc (in the sense it's only sent once ever)
clients also can receive world time from the gamestate (via requesting it or replicating it down etc)
this is not needed though since there will only really be 1 of these and it being ~100ms off is not the end of the world
🤣
my current approach to keep it synced while minimal rep load
I am sure it can be further improved, but it works perfectly at least
I think I have to move this new system to the gamemode sybsystem, and use instance AInstanceStaticMeshActor for visual effects
AInstanceStaticMeshActor->UInstancedStaticMeshComponent supports runtime scaling/repositioning?
one more optimization, these don't needs to be replicated, they will be the same as targetposition and targetscale in the end
FVector NewPosition;
FVector NewScale;
replicated initial state and synced network clock
CenterPosition and StartTime is enough
I'm using ServerSnapshot as the initial state for late clients
USTRUCT()
struct FBlueZoneSnapshot
{
GENERATED_BODY()
FVector Position;
FVector Scale;
int32 PhaseIndex;
float Timestamp;
float ShrinkProgress;
FVector BomberTargetPosition;
bool bIsRedZoneActive;
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);
};
I would like to further optimize those replicated vectors, is it possible to apply bit packing on them? its a crazy idea but if it is possible and will work it will be a game changer!
these
UPROPERTY(ReplicatedUsing = OnRep_TransformState)
FVector TargetScale;
UPROPERTY(ReplicatedUsing = OnRep_TransformState)
FVector StartScale;
UPROPERTY(ReplicatedUsing = OnRep_TransformState)
FVector TargetPosition;
UPROPERTY(ReplicatedUsing = OnRep_TransformState)
FVector StartPosition;
Why do you need to replicate progress and scale, that's deterministically derivable from StartTime and the synced clock
I tried to make client locally progress but it was problematic, a small ping drop will desync the progress with the server progress
and about synced clock I read the article https://vorixo.github.io/devtricks/non-destructive-synced-net-clock/
looks like the system will need big changes to apply this
USTRUCT()
struct FPackedVector
{
GENERATED_BODY()
uint32 PackedX : 24; // 0-16,777,215 cm (167km) map support
uint32 PackedY : 24;
uint32 PackedZ : 16; // Usually 0 for blue zone
// Unpack to FVector
FVector Unpack() const
{
return FVector(
PackedX / 100.0f, // Convert cm to meters
PackedY / 100.0f,
PackedZ / 100.0f
);
}
introducing custom vector for this specific task
void Pack(const FVector& Vec)
{
PackedX = FMath::Clamp(FMath::RoundToInt(Vec.X * 100.0f), 0, 0xFFFFFF);
PackedY = FMath::Clamp(FMath::RoundToInt(Vec.Y * 100.0f), 0, 0xFFFFFF);
PackedZ = FMath::Clamp(FMath::RoundToInt(Vec.Z * 100.0f), -32768, 32767) & 0xFFFF;
}
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
bOutSuccess = true;
Ar << PackedX;
Ar << PackedY;
Ar << PackedZ;
return true;
}
and finally
USTRUCT()
struct FOptimizedZoneUpdate
{
GENERATED_BODY()
uint8 Flags;
// Only send what changed
UPROPERTY()
FPackedVector Position;
UPROPERTY()
FPackedVector TargetPosition;
UPROPERTY()
FPackedScale Scale;
UPROPERTY()
FPackedScale TargetScale;
// Phase index (0-7 fits in 3 bits, but using 4 for safety)
uint8 PhaseIndex : 4;
// Shrink progress (0-100%, 7 bits = 128 values)
uint8 ShrinkProgress : 7;
bool HasPositionUpdate() const { return (Flags & 0x01) != 0; }
bool HasScaleUpdate() const { return (Flags & 0x02) != 0; }
bool HasTargetUpdate() const { return (Flags & 0x04) != 0; }
bool IsShrinking() const { return (Flags & 0x08) != 0; }
bool IsRedZoneActive() const { return (Flags & 0x10) != 0; }
void SetHasPositionUpdate(bool bValue) { Flags = bValue ? (Flags | 0x01) : (Flags & ~0x01); }
void SetHasScaleUpdate(bool bValue) { Flags = bValue ? (Flags | 0x02) : (Flags & ~0x02); }
void SetHasTargetUpdate(bool bValue) { Flags = bValue ? (Flags | 0x04) : (Flags & ~0x04); }
void SetIsShrinking(bool bValue) { Flags = bValue ? (Flags | 0x08) : (Flags & ~0x08); }
void SetIsRedZoneActive(bool bValue) { Flags = bValue ? (Flags | 0x10) : (Flags & ~0x10); }
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
bOutSuccess = true;
// Always serialize flags
Ar << Flags;
Ar << PhaseIndex;
Ar << ShrinkProgress;
// Only serialize what changed based on flags
if (HasPositionUpdate())
{
Ar << Position;
}
if (HasScaleUpdate())
{
Ar << Scale;
}
if (HasTargetUpdate())
{
Ar << TargetPosition;
Ar << TargetScale;
}
return true;
}
};
free code, let's go
uint32 ABlueZone::PackPosition(const FVector& Pos) const
{
// Pack position with 1cm precision
// Map is 800000cm (8km), so we need 20 bits per axis (0-1,048,575)
// We'll use 21 bits to be safe (0-2,097,151)
int32 X = FMath::Clamp(FMath::RoundToInt(Pos.X * 100.0f), 0, 0x1FFFFF); // 21 bits
int32 Y = FMath::Clamp(FMath::RoundToInt(Pos.Y * 100.0f), 0, 0x1FFFFF); // 21 bits
int32 Z = FMath::Clamp(FMath::RoundToInt(Pos.Z * 100.0f), -1024, 1023) & 0x7FF; // 11 bits
// Pack: 21 bits X | 21 bits Y | 11 bits Z = 53 bits total
// We'll split across two 32-bit values
uint32 Packed = (X & 0x1FFFFF) |
((Y & 0x1FFFFF) << 21) |
((Z & 0x7FF) << 42);
return Packed;
}
error C4293: '<<': shift count negative or too big, undefined behavior
🤔
this is because you manipulate int32 and put value into an uint32
oh and also << 42 can't be possible for a 32-bit integer
even the comment talk about two 32-bit "We'll split across two 32-bit values"
yeah I want int64 , thanks
uint32 ABlueZone::PackPositionX(const FVector& Pos) const{
// Pack X and part of Y into first 32 bits
// X: 21 bits (0-2,097,151)
// Y_low: 11 bits (lower 11 bits of Y)
int32 X = FMath::Clamp(FMath::RoundToInt(Pos.X * 100.0f), 0, 0x1FFFFF);
int32 Y = FMath::Clamp(FMath::RoundToInt(Pos.Y * 100.0f), 0, 0x1FFFFF);
uint32 Packed = (X & 0x1FFFFF) | ((Y & 0x7FF) << 21);
return Packed;
}
uint32 ABlueZone::PackPositionY(const FVector& Pos) const{
// Pack remaining Y and Z into second 32 bits
// Y_high: 10 bits (upper 10 bits of Y)
// Z: 11 bits (signed -1024 to 1023)
// Remaining 11 bits unused
int32 Y = FMath::Clamp(FMath::RoundToInt(Pos.Y * 100.0f), 0, 0x1FFFFF);
int32 Z = FMath::Clamp(FMath::RoundToInt(Pos.Z * 100.0f), -1024, 1023);
uint32 ZPacked = (Z < 0) ? ((~(-Z) + 1) & 0x7FF) : (Z & 0x7FF);
uint32 Packed = ((Y >> 11) & 0x3FF) | (ZPacked << 10);
return Packed;
}
this kind of packing into 1 32 bit doesn't make as much sense to be as two 16 bits
depending on the ranges
most integer types in unreal are serialized around the idea of them being a lower range of values
from what I can tell from the source
but at this scale it won't matter much to shave off 4 bits
yeah I switched back to snapshot packing which is more simple and only takes one packed struct with all data needed for replication
that's good because it will all arrive at once
and gives super smooth update
If you're using NetSerialize then there are already some custom ways to serialize vectors, if I remember right
As opposed to the default Ar << MyVector
you can searchfor NetSerialize
we normally do like FVector_NetQuantize& ReplicatedLocation = ReplicatedLocations[i]; ReplicatedLocation.NetSerialize(Ar, Map, bOutSuccess); if we dont need precision
theres FVector_NetQuantize, FVector_NetQuantize10 and FVector_NetQuantize100
*
* 2 decimal place of precision.
* Up to 30 bits per component.
* Valid range: 2^30 / 100 = +/- 10,737,418.24```
for example
I will do it next time when I will need it for sure
these can reduce rep sizes
we have done in the past, where we exposed normal FVector for gameplay
// server sets it and calls onrep.
FZoneSyncData NewSyncData;
NewSyncData.PhaseIndex = NextPhaseIndex;
SyncData = NewSyncData;
OnRep_SyncData();
void ABlueZone::OnRep_SyncData()
{
UE_LOG(LogTemp, Warning, TEXT("OnRep_SyncData called - Phase: %d, HasAuthority: %s"),
SyncData.PhaseIndex, HasAuthority() ? TEXT("Yes") : TEXT("No"));
}
it only logs called by server, no idea why
but made it not replicated, then handle the rep via a quantized and set back to the normal property
this way to the end user, its just an FVector
you really should avoid server calling OnRep_ like that
you should make intermediate functions
that OnRep and server called, like a shared path
i really hate people doing OnRep_Blah on the server side path
its ambiguous
for dedicated server setup it also matter?
yes
cause the issue is, OnRep == Client callback when property changes
if server ends up calling it, its really hard to debug
it becomes a nightmare
i can look at my callstack and be like "Thats server side"
but if i see OnRep_ to me its client side
but if server is calling OnRep then thats not client side..
Adding an intermediate now, if it fixed, it will make my day 😄
the onrep only calls by server
// Pack X and part of Y into first 32 bits
// X: 21 bits (0-2,097,151)
// Y_low: 11 bits (lower 11 bits of Y)
int32 X = FMath::Clamp(FMath::RoundToInt(Pos.X * 100.0f), 0, 0x1FFFFF);
int32 Y = FMath::Clamp(FMath::RoundToInt(Pos.Y * 100.0f), 0, 0x1FFFFF);
uint32 Packed = (X & 0x1FFFFF) | ((Y & 0x7FF) << 21);
return Packed;
}
uint32 ABlueZone::PackPositionY(const FVector& Pos) const{
// Pack remaining Y and Z into second 32 bits
// Y_high: 10 bits (upper 10 bits of Y)
// Z: 11 bits (signed -1024 to 1023)
// Remaining 11 bits unused
int32 Y = FMath::Clamp(FMath::RoundToInt(Pos.Y * 100.0f), 0, 0x1FFFFF);
int32 Z = FMath::Clamp(FMath::RoundToInt(Pos.Z * 100.0f), -1024, 1023);
uint32 ZPacked = (Z < 0) ? ((~(-Z) + 1) & 0x7FF) : (Z & 0x7FF);
uint32 Packed = ((Y >> 11) & 0x3FF) | (ZPacked << 10);
return Packed;
}```
you dont want to be backing your vectors like this
since it should called by clients/server both when a server changes the property
this only logs has auth yes
void ABlueZone::OnRep_SyncData()
{
UE_LOG(LogTemp, Warning, TEXT("OnRep_SyncData called - Phase: %d, HasAuthority: %s"),
SyncData.PhaseIndex, HasAuthority() ? TEXT("Yes") : TEXT("No"));
}
but why this weird packing
UPROPERTY(ReplicatedUsing = OnRep_SyncData)
FZoneSyncData SyncData;
I don't have it anymore
what you using instead?
clients are doing this locally now
I was doing it for replication purpose to make the packets smaller, but now clients are simulating the timeline locally
I was doing all that custom serialization to minimize this load
void ABlueZone::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// OPTIMIZATION: Only replicate to simulated proxies (clients)
DOREPLIFETIME_CONDITION(ABlueZone, TargetScale, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, StartScale, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, TargetPosition, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, StartPosition, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, NewScale, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, NewPosition, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, bTransformRep, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, BomberTargetPosition, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(ABlueZone, ServerSnapshot, COND_InitialOnly); // Only for late join
}
now using this synced with the game time
void ABlueZone::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ABlueZone, SyncData);
}
USTRUCT()
struct FZoneSyncData
{
GENERATED_BODY()
// Phase timing
UPROPERTY()
int32 PhaseIndex = -1;
UPROPERTY()
float ServerStartTime = -1.0f;
UPROPERTY()
float Duration = 0.0f;
// Geometry
UPROPERTY()
FVector StartPosition = FVector::ZeroVector;
UPROPERTY()
FVector TargetPosition = FVector::ZeroVector;
UPROPERTY()
float StartScale = 0.0f;
UPROPERTY()
float TargetScale = 0.0f;
};
Hey all.
I have a weapon system.
Its a weapon actor attached to the player.
I'm having an issue, where the server tries to replicate the weapon actor, before the player/ owner.
(even with the use owner relevancy or whatever)
This appears to be, because the server thinks the client knows about the owner, but just doesn't. (since at the end of the day, its a distance check)
Is there anyway to change this, so the server/ client both know there owner is valid?
Or, do I just need a begin play loop, waiting for a valid owner?
(Also, specifically just the clients, server always has a valid owner, not like the owner var just isn't set.)
Hello, I'm new to Unreal and Multiplayer and have been having an issue with my RPCs in my Listen Server game.
I have a function that spawns a debug sphere in front of the player.
UFUNCTION(Server, Reliable, BlueprintCallable)
void Server_SpawnDebugBall();
UFUNCTION(NetMulticast, Reliable)
void NetMulticast_SpawnDebugBall();
UFUNCTION(BlueprintCallable)
void SpawnDebugBall();
void AFourManScrambleCharacter::NetMulticast_SpawnDebugBall_Implementation()
{
SpawnDebugBall();
}
void AFourManScrambleCharacter::Server_SpawnDebugBall_Implementation()
{
NetMulticast_SpawnDebugBall_Implementation();
}
void AFourManScrambleCharacter::SpawnDebugBall()
{
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
FVector SpawnLocation = ItemSpawnPoint->GetComponentLocation();
FRotator SpawnRotation = ItemSpawnPoint->GetComponentRotation();
AActor* SpawnItem = GetWorld()->SpawnActor<AActor>(SummonItem, SpawnLocation, SpawnRotation, SpawnParams);
}
I have a key-input that runs Server RPC in my C++ code. While I'm playing as the server, it will spawn the ball for both the server and the client. But when I press the button as the client it only spawns on the client
As well I tried hooking it up through blueprints instead. Of the three methods on the right, the top one is the former I had just mentioned. The middle one, (which you can see implemented in the bottom left), will spawn two balls in front of the calling player, and the bottom one, which just directly calls the Server RPC function, will work correctly, spawning a ball in front of the appropriate player on both the client and server.
Can anyone help me understand how these variations are happening?
when it comes to equipment / itmes that you can equip, would it make sense to "pool" these actors? seems like it would make sense in the way i understand the benefits of pooling. i suppose same would go for item drops in general, like if you were to "drop" an item, this is current an actor, but not sure if there's a way to make it not a full blown actor , as in most cases, it's just pointing to a single int32 value which is just an index to the actual item to pickup. if i made them non-actors somehow (and stil could interact the same way), then i'd think pooling would make sense
i've also considered the issues of equipables being pooled as they would be replicated actors, and having those just sitting not used also seems like it could be unnecessary, but yea curious on what somet akes on pooling things like item drops or equipment like weapons that would be effectively spawned and despawned potentially frequently (equip / dequip, etc, or dropp item -> pick up item)
To me personally.
Pooling doesn't make sense for stuff like that.
It also very much depends on the game.
You say, your items are an index to the actual item.
But, it may not be like that for some games.
and, then like you say for replication.
That just an extra actor that exists for no reason.
Pooling I feel like only makes sense, where an inventory is sorta locked.
Think looter shooters.
You don't have like 30 guns.
You have like 5 static ones.
Pistol, machine gun, melee, grenade, idk. 😛
You could also conceal the pooling/ loading in the unequip.
Sure, that still the "issue" of entire actor creation and shit.
But, thats 1 gun, compared to like 100 bullets, from a machine gun, or something.
that makes sense, will most likelly avoid the pooling for equipables. for item drops tho, im thinking of instead of spawning the item, have a single actor item drop manager or something w an item struct that can replicate the Item id and it's location... which in my head i think would work, but not sure about if multiple were spawned at once or something how it would handle that but maybe i can do soemthing like that for items. but could prob just keep them actors too (if single items). loot chest/storage boxes would remain actors as they aren't something quickly destroyed
The way I kinda see it.
In more dynamic games, a weapon/ tool, could be 50 different things, or just do nothing at all.
While most shooter games (arma, looter shooter), you kinda only can shoot a million bullets.
But, a survival game, could have shovel, pickaxe, sword, full auto gun, primitive crossbow, bow and arrow, nothing.
Theres so many possibilities, you'd be pooling like 50 extra weapons/ actors.
I do agree, that some sort of item drop manager could work better, especially with such basic item drops like you said.
Could also instanced static mesh it, and lookup the drop, based on the instanced index.
yea 100p when you describe it like that, it would be a nightmare pooling all the different possiblities lmao. i also like the ISM approach or even a simple niagara to represent it via sprite, could put that on the itme manager, then just do a "distance check" to the location to pickup the item, as i most likely will not be using collision on these, that would prob do more harm than good. and distance check could just pick up items by closest / most relevant
Yeah, it very much depends.
I could never use just a basic int32 var, for my items. lol
lmao, well it's just an item id which points to the actual struct w the info needed, but yea in my case, majority of items are sprites so easy to represent them in world w just an index
Oh, I see. 😛
I thought your items were legit just a int32, for an index on array, or some DataTable. lmao
Why have a int point to the item, and not just the item in the dropped item.
Out of curiosity?
Is that just how you designed your game, or did you have some performance, or like networking in mind?
tbh i just thought it would be easier to replicate and send around a int32 and then do the heavier strcut work later when needed rather than it's full item strcut, but it may very well be unnecessary but all my items have an ID which points to the struct in a datatable. in fact, i most likely convert it in the pick up logic of the actor version rn, immediatley , so it is probably unecessary lmao, but again, that variable is just replicated so i thought it would be a bit more efficent, and i wouldn't need all the extra info other than it's visual representation
im def always thinkinga bout performance, but given that im using zero new tech (no nanite, lumen) on forward rendering, and have essentially zero shadows/lighting, i prob have plenty of room lol
and all my charcters/items are sprites, so dont use skeletal meshes at all
biggest bottleneck is probably just the size of the world
and im not currently using world partition (at least i don't htink i am)
I tried like 5 different methods for my complex item replication.
None of them worked.
So, it was either low level, custom replication channel.
or, RPC spam.
I chose RPC spam. 😛
loll whatewver will get the job done and keep perfomrance maintainable is all we need, but ciurous what you mean by RPC spam
i have some functions that i set to reliable after realizing GAS abilites are reliable by defualt (at least as far as i understand them)
i dont use GAS tho ( i did for a month, never again... unless...)
RPC spam.
RPC for item add, item remove, item move, item drop, item changes.
Recently did custom serialize shit, so I can pass var changes around as bytes, rather then 1 RPC per possible var.
Its the only way I could really find to do it.
Got some smart people here, but all the methods they suggested would not have worked.
(This is only like 50% of my RPC's, for my item system.)
ohhhh yea, that's exactly what im doing, easily the worst part of the user experience for my game is moving items around, but i just coudlnt think of any easy way to do some sort of client preiction or making things feel smoother
all reliable lmao i love it
i never used reliable casue i thouht it was "bad" then like i said , once i realized how GAS worked, i was kinda pissed casue i could've had so much easier logic by setting some things to reliable. of course, they are "gameplay critical" things (that's the term i've heard)
Yeah.
If you need it to happen.
Such as item moves, then reliable makes sense.
For instance, player movement isn't reliable.
Cuz, while it could be seen as "critical", it also interpolates, so whatever var it recieves, will account for the lack of other RPC's it sends.
RPC's also help, for the 4 different ways my items can replicate.
Your calling the _Implementation
Don't do that
Oh! So I just call the "NetMulticast_SpawnDebugBall"?
Hi, can someone explain why the 1st controller Controller_0 doesnt spawn a character but the 2 conneccted clients do please? Even with the breakpoint Controller_0 never even triggers the Set Actor Location, I did consider destroying the Pawn and then trying to spawn a new one and assigning the Owner of the new pawn to the ConnectedController but feels a bit odd to destroy a character just to create another.
Nvm I forgot I overrode CHoosePlayerStart which was returning nothing....
Reposting this, cuz now its hidden behind all these other messages. 😛
I have a weapon system.
Its a weapon actor attached to the player.
I'm having an issue, where the server tries to replicate the weapon actor, before the player/ owner.
(even with the use owner relevancy or whatever)
This appears to be, because the server thinks the client knows about the owner, but just doesn't. (since at the end of the day, its a distance check)
Is there anyway to change this, so the server/ client both know there owner is valid?
Or, do I just need a begin play loop, waiting for a valid owner?
(Also, specifically just the clients, server always has a valid owner, not like the owner var just isn't set.)
Thankfully its not exactly a critical issue right now, so i'm not in a rush to care about/ fix it. 😛
for extending the CharacterMovementComponent: when networking one off events like a dash, should we extend the SavedMove struct to auto replicate, resulting in larger bandwidth per frame, or should we just send a one time ServerRPC to replicate?
serializing something like a dash can be a single bit that says if it's in the current structure or not... this is not going to be a bandwidth concern if you put any thought into how it is sent
right that's what I was thinking, for some reason the tutorial i was following used an rpc. maybe he just wanted to show how you could do it for some reason you needed to
using an rpc will basically mean doing it outside of the cmc by turning off corrections during the ability etc (if it ends up causing corrections)
but you can try that if it seems easier
for the serialization, are you saying you could have a bool like bWantsToDash that indicates whether or not any additional dash variables are stored in the networked struct?
no need for a loop of any kind here really... you can just have both beginplays check for the presence of the other and maybe a local trackimg thing to see if they initialized with X thing
that or basically having a single bool in the serialized thing representing if the dash has data in it etc... replicating a boolean is absurdly cheap. The cost to avoid here is sending new floating point values if you don't need to (or at least can avoid it in the common case)
thank you
but honestly you might be able to spam extra fvectors in there and never really care if bandwidth is never under pressure so profile it I guess
I thought of that.
I guess I wanted it to be 1 sided coding.
The weapon manages itself, and the player just spawns it.
If that’s the only logical method, then that’s what I’ll do.
or just change it to be that the weapon replicates as a subobject (component/or new uobject) of the player pawn
and then have the actor created locally when it arrives to just serve as visuals/collision etc
(this is of course a big change to make and not always nicer but to me it would reduce confusion)
what happens if an actor in world call ForceNetUpdate(); when it is loaded for late join client?
I assume it would replicate stuff regardless of net update rate/prio? Are you not seeing it arrive on the client?
Can you not do that with just direct actors?
I barely touched replicated sub objects. 😛
I'm honestly not sure if forcing an update matters for late joiners
yeah, it forced only defaults to be replicated, any custom replicated property is ignored
seems like it needs to serialized forcefully
yeah it not matters
I was doing it cause to test it to see if the actor will sync the late joiner in the current state of the actor
well... I guess it depends on what is interesting about the weapon to send down
Not sure I follow?
It’s just easier to put it all in an actor for my brain.
Rather then some comp on the player, and some fake actor weapon.
oh absolutely lol, I'm definitely going to agree it is easier to understand on a human level to have it just be a thing you can click on in the editor that says it has x and a mesh
I am not sure actors can "require" other actors to show up first in normal replication
I'm kind of surprised them being attached doesn't influence it or something (assuming they are)
So if anyone knows more than me free free to chime in but I don't really use this approach so I am unfamliar
The issue I guess is.
The server doesn’t check if the client knows of the actor.
So, at the end of the day, even if there attached, it still does a distance check, for replication.
Cuz, it influences it by using the owners relevant function.
But, of course if the client doesn’t have a valid owner, it doesn’t care for that.
apologies if I misunderstand... is the distance check happening too early and making it appear when it should not or not appear at all?
so the relevancy is getting stuck?
I wonder if you can make it use the attach parent for relevancy
The issue is.
It does use the attach parent.
But then just becomes a distance check.
And is purely a server only thing, so the server doesn’t know if the client knows of said actor, just that it’s within the rep distance.
Hence the issue.
The weapon replication is received/ calculated first, before the player, cuz the server doesn’t actually know/ check that the client knows of the player
So what happens? does the weapon appear at world origin for a split second?
Could you not just have it hide itself until the parent shows up if you know it has a parent? Not sure
ofc if you intend to ALSO have weapons that don't actually have any parent on the server (dropped on the floor) you would need to consider that state too I guess
I haven’t checked that honestly.
But, not sure.
The issue isn’t showing, it’s that’s the owner ref is invalid, so begin play fails.
Hence my potential thought of looping for valid.
you can keep the logic in the weapon
just have the character appearing find any weapons it can see attached to itself and call the weapons init thing
Right, yeah.
That very well may be what I need to do.
I was just hoping to keep it a bit fully self contained.
I just like that.
Even for the super basic “player finds weapons”
Unless someone else sees this.
I’ll just end up doing that. lol
it is not self contained unfortunately
if you want you could make a simple interface or something to hide the weapon from the character
fwiw there might be a nicer setup here, I'm mostly just guessing on this working and you might find inside of the AActor beginplay it might not see attachments yet etc
a delay one frame in a loop is very sad but sometimes can avoid headaches with stuff you can't listen for
Oh, no an interface, or reference isn’t the issue.
Just more personal design method of self contained stuff.
I don’t like having required secondary code, or multiple copies of code.
So far UE replication has been fucking my personal design method. lol
Maybe the weapon actor can override it changing what it is attached to?
to react to the owning character appearing etc
Oh, that’s valid.
I didn’t think of that.
not to skip calling super:: here, but to just know when it happens
I’ll need to check for a func when I get home.
Yeah.
Thankfully I don’t plan on doing other shit with the weapons.
It’ll always be equipped.
that trick actually works to make late clients sync with the current replicated state by using the server world time
FBlueZoneSerializedSyncData NewSyncData;
NewSyncData.CurrentPosition = LevelCenterPoint;
NewSyncData.CurrentScale = FVector(Scale, Scale, Scale);
NewSyncData.TargetPosition = LevelCenterPoint;
NewSyncData.TargetScale = FVector(Scale, Scale, Scale);
NewSyncData.PhaseIndex = -1;
NewSyncData.ServerStartTime = DoTimeTravelInServerWorld(); //replicated
NewSyncData.Duration = 0.0f;
NewSyncData.ServerShrinkProgress = 0.0f;
ZoneSyncData = NewSyncData;
void OnRep_ZoneSyncData();
now if the bluezone in any phase, late clients will join the current phase, duration, scale, location synced
and the best thing its now one time notify, and client simulate their state locally based on the synced data they recieve
The hard part is making sure the time is closely synched but for something that moves slowly it being slightly off might be perfectly fine. The cool thing here is the amount of data is just the start and stop
https://www.forrestthewoods.com/blog/tech_of_planetary_annihilation_chrono_cam/ Planetary Annihilation is an RTS game that takes this concept to the extreme where even unit positions and things are sent as a "curve" with a timestamp
yeah all of 7 phases are slow , the final 3 phases are fast enough but I think it will not be an issue
if it will be, I will slow them down also 😄
LogTemp: Warning: [CLIENT] Received zone sync data - Phase: -1
LogTemp: Warning: [CLIENT] Setup - Progress: 0.00, Duration: 0.0
LogTemp: Warning: [CLIENT] In shrink delay - starts in 0.0s
LogTemp: Warning: [CLIENT] Starting shrink
LogTemp: Warning: [CLIENT] Starting timeline - Progress: 0.00, Remaining: 0.0s
LogTemp: Warning: [SERVER] === Phase 0 Announced ===
LogTemp: Warning: [SERVER] Starts at: 11.1 (current: 6.1, delay: 5.0)
LogTemp: Warning: [CLIENT] Received zone sync data - Phase: 0
LogTemp: Warning: [CLIENT] Setup - Progress: 0.00, Duration: 120.0
LogTemp: Warning: [CLIENT] In shrink delay - starts in 5.0s
LogTemp: Warning: [SERVER] Timeline started
LogTemp: Warning: [CLIENT] Starting shrink
LogTemp: Warning: [CLIENT] Starting timeline - Progress: 0.00, Remaining: 120.0s
late client 1
LogTemp: Warning: [SERVER] Timeline Progress 0.15, Duration: 120.0
LogTemp: Warning: [CLIENT] Received zone data on join
LogTemp: Warning: [CLIENT] Setup - Progress: 0.16, Duration: 120.0
LogTemp: Warning: [SERVER] Normalized Artifect - Progress: 0.17, Duration: 120.0
LogTemp: Warning: [CLIENT] Starting timeline - Progress: 0.17, Remaining: 101.5s
one more thing I think I need is to make server just lerp from start to target without timeline
what do i do if i want to see logs from both the client and server? right now im only seeing logs from the client and I'm running with 2 players in viewport while playing as Listen Server.
where are you looking at the logs? is this a single process PIE?
nevermind the issue is with my code not unreal
if you are asking about text formatting this how you can do
FString RoleString = HasAuthority() ? "server" : "client";
UE_LOG(LogTemp, Warning, TEXT("Fire executed on: %s"), *RoleString);
what settings do you use to test multiplayer code? do you run width a dedicated server?
when you run as client it automatically creates a dedi server for you and client connects to it
than you can click late client to add more clients
which ever environment you want to support.
If you are going to use dedicated server then play as client,
for listen server, play as listen server.
If you want to support both, then you use both.
use GetDebugStringForWorld instead
that is local role only
just because you have authority does not mean it is the server (locally spawned things would have authority etc)
it is still useful to see local role but it would make more sense to consider that together with the local netmode from GetDebugStringForWorld
yeah GetDebugStringForWorld is a perfect thing
the one downside is in some cases it might be too early for it to see the debug string but that is quite rare
that's a good note
is world time used as a synced clock between client and server
even though they are not at the same time at the same point
basically it is not quite close enough for some things so the alternative is to replace it or have a simple rpc back and forth to constantly update it with simple math (running ping average that deltas the local one)
it depends on what the timer is used for though because incoming replication data is always in the past (well, from it)
BTW, there is one. 🙂
The OnRep for the attachmentreplication, given I only have issues for the client side.
neat, I hope that works
It does.
Already tested
I’m trying to make a sprint mechanic in my game. Sprinting costs stamina, and the way I have it right now is that it consumes stamina in the sprint phys function, and if there’s not enough stamina it exits sprint to another movement mode. However, I noticed that clients consume stamina about twice as fast as the server, and I think it's because of replaying moves. I wanna just not consume stamina if we’re replaying moves, but I don't know how to know if we’re replaying moves from the phys function. Should I not be changing variables in phys functions at all? Should I be doing that in a different function? If so which one?
@boreal flicker #multiplayer message
Maybe this will help you
GetServerWorldTimeSeconds is the built in function you want. That is synced across all instances. No need for custom solution for most cases.
it won't be close enough in some case unfortunately but it will work for simple stuff that doesn't need accuracy
definitely easier to try that first and then change it if you find jittering stuff etc
sorry to bother yall again, I'm misunderstanding something about the CMC. I thought that on autonomous proxies, we run movement logic then build a saved move, which we then compress and serialize into NetworkMoveData, which gets sent to the server and rerun on the same movement pipeline. My confusion stems from how the server takes the NetworkMoveData and reruns the code. Is it true that when the server recieves the NetworkMoveData, it doesn't rebuild a saved move and use PrepMoveFor() to update the CMC state, but instead relies on manual setting of CMC state from NetworkMoveData?
were u able to fix this?
how to fix bugs with other player location when a car is moving? movement is set to None, collisions are disabled, attach actor to component are all snap to target, weld simulated bodies tried to enable tried to disable, nothing changed, and why works fine on driver screen? passengers screen only have this problem
driver is server?
yes, passengers too, i just divided them with a bool, if is driver seat -> posses node, if not -> switch camera input only
all this is inside run on server event
are you attaching to socket?
this inside OnRep_IsInVehicle, inside player character blueprint
yes, sockets inside car skeletal mesh, i tried to attach them with a scene component location, but same problem
try ignoring the vehicle collision channel when attach to vehicle
and disable physics simulation
where to put this node? inside EnterVehicle which is running on server?
before attaching to vehicle
disabling physics of the character?
first try on server if not work do it on multicast
yes
im not using multicast at all
for disabling physics/collisions try with a multicast