#multiplayer
1 messages Β· Page 704 of 1
then I guess do a hasAuthority check?
You can workaround it, it's just silly that it works differently in each domain
still sounds unnecessary though, you're right
two takeaways:
- update repnotified vars only on server, 2) hasAuthority check if required to run repNotify only on clients
++ BP's onrep also get called when the variable doesn't change ie: setting the number 7.f twice to a float var π€·ββοΈ (I thought this wasn't the case, got me all surprised actually)
lol fabulous
does anyone build games with BP at all?
it's a tool
It's certainly used. Just IMO has a low ceiling when talking multiplayer in particular
Yeah, I am currently using owner of the actor component as outer. What do you mean by crashes, is it fine replicating UObjects from server to clients or should I rather choose another method?
no I mean full games.
I'm building one right now...not seeing too many issues
I am mindful of this however, + lots of unity MP experience
It's definitely been done I think yeah
it's definitely irritating that I don't have access to PlayerArray in GameState for like the first 2 seconds
have a read through that if you haven't already
Galaxy in Turmoil runs most of its logic in BP's and it's a multiplayer game...
it doesn't scale very well, but it runs okay
It's got mostly negative reviews
mhm, yeah it didn't do very well x'D
but anyways, it's an example that it's indeed possible
Def possible, just... tedious
And yeah scaling up becomes an issue, doesn't matter if it's a simple game though
Like lots of players or high-complexity game etc.
we're going blazing fast with BPs
Yeah that's probably fine tbh
oh also BP multiplayer got some gotchas
such as/
because of UE initialization code
waiting for PS and whatnot
things that aren't exposed in BP's
Thank you, will take a look. One thing I didn't see when skimming through, is changing outer to another actor (if I move the UObject to another owner). Can I go with UObject::Rename(..) or rather duplicate and discard old one?
I haven't tried moving them between outers, but I'm pretty certain it would break under some situations, especially if data about that object is still replicating on that channel when it's destroyed.
interesting..
it's cool, doubt we'll run into anything major
BPs for board games seem fine to me π
oh you will in the UI for sure
Ah, thanks
The difficulty in BP is coding around the inherent race conditions you get from the networking system, they're quite easy to get around in CPP because you can override a lot of engine behaviour - but in BP a lot of that is not exposed.
^ correct ^
can't remember all the examples
but for example GS replication
your PC is alive in the client and the GS isn't yet anyways
so u have to wait for it
Basically you can never rely on an actor to be around when you access it, so it boils down to a lot of events etc.
in BP's you can do this with a simple waiting loop or sm
but yeah the correct way to do it is to hook on begin play and propagate existence
incredibly tedious
in C++ you can use other hooks that ease your job
such as?
as the non-virtual setplayerstate
that cannot even be overriden in C++ π
well one example is onrep_playerstate in the character (i believe it was)
It could be anything really
but yeah these are just implementation details...
if you get any of these just come here and ask
it's tough for starters
2 second delay works for me now...probably will switch to propagating event from PlayerState in the future
It's one of those things you can only get your head around once you start experiencing it really
don't
why
rather than 2 second delay, loop it
loop the delay until is valid
it's an atrocity, I know, but it's safer
like, a while loop? how would I write this?
Think just finding a good mix of bp - cpp works fine
and what am I actually waiting for?
It can be useful (and this is commonly the approach in CPP also), to create just a core system you can access from anywhere at anytime - and it contains some global events you can bind to
is there any online BP editor I could use to show you?
E.g. "PlayerStateReceived", "GameStateReceived" etc etc
probably just a diagram would do
Ive found it nice for most base classes created to just define as much as possible in C plus plus and then extend outwards from blueprint
can I use the PostLogin event?
@near bison enjoy π€£
How can I do isValid on a playerStateArray
uh what do you want to do with the ps array?
ah u want to check if every member in the array is there,right?
then instead of doing isvalid
do array.length == quantity
but how do I know the quantity before hand?
well it's predefined for now
but might be different well into the future
it's a board game
just loop the array and check if the content is valid?
Presumably you want whatever it is to respond to players being added/removed dynamically
Which will happen
If players leave, join in progress etc.
right, there is no a BP handler for that afaik, but you can do postlogin
but that's not for PS's
I think GS has overrideable functions for players being added/removed no?
Can't remember if they are BP event funcs
i cant find a player added node in GameState
sheesh x'D
Oh lel, yeah it's CPP only
should I use delay or a while loop here?
virtual void RemovePlayerState(APlayerState* PlayerState);```
Would be useful to have an event by default tbh
if u want to check for quantity, use a delay + length check
yes well james, at least they are virtual x'D
but how long do I delay for?
this thing but isntead isvalid
u get the array and do length == whatever number
Just an example of what I meant by having a central object that has events:
{
Super::AddPlayerState(PlayerState);
if (UHT_WorldEventManager* WEM = UHT_WorldEventManager::Get(this))
{
WEM->NotifyPlayerArrayUpdated(this);
}
}
void AHT_GameState::RemovePlayerState(APlayerState* PlayerState)
{
Super::RemovePlayerState(PlayerState);
if (UHT_WorldEventManager* WEM = UHT_WorldEventManager::Get(this))
{
WEM->NotifyPlayerArrayUpdated(this);
}
}```
??
the if branch
what would you have in the notify player array updated body?
i find it a pretty nice idea, might steal it π
{
check(IsValid(InGS));
checkSlow(InGS->GetWorld() == GetWorld());
ConditionalBroadcastNetworkReady();
OnPlayerArrayUpdate.Broadcast(InGS, InGS->PlayerArray);
}```
aaah I see a delegater π
Then you can do fun stuff like this:
{
Super::NativeOnInitialized();
if (!IsDesignTime())
{
UHT_WorldEventManager::NetReadyExecute(this, UHT_WorldEventManager::FOnNetworkReady::FDelegate::CreateUObject(this, &UHTG_DropzoneUI_WavePanel::NetSafeInitialize));
}
}```
And not have to worry about UI trying to access missing stuff all the time
It should be tbh
the fact that I have to do this
Might dump this somewhere
is so dumb
worth a blog post for sure! I'll link it around if you do, I know some people that will be happy about that
can you tell me where u are executing that code?
gamestate
when all the players are connected, I want to shuffle their turn order. that's why I'm calling a simple function on gamestate
ah! aaah! okay
not exactly the problem i was trying to solve
but it works aswell in that case
π€£
well, yep
and only once this turn order is setup, will I fire an event
that enables everybody's UI
ez. lol. game the system
gtg now! good friday
thanks @pallid mesa and everybody else π
James, if you remember, ping me when you post that stuff! π
thanks!
Malformed_Packet: Received packet with 0's in last byte of packet
What does this mean?
I'm using online subsystem steam
It's very difficult to debug server issues on Linux
This error cannot be searched for sadly
Errors should be searchable
not sure if this is going to help you, but I can find the error string in a unit test, and in Engine/Source/Runtime/Engine/Private/NetConnection.cpp
I used the search string
Received packet with 0's in last byte of packet
If the missile is a REPLICATED ACTOR then the clients will see it too when it spawns on the server.
No, online multiplayer
Oh yeah, that part is working now π One thing thats occured now is that the missiles disappears right before impact for clients, I think it has something to do with the replication culling... could it be too huge numbers maybe?
The launcher (which is a replicated actor) spawns missiles (which are replicated actors), whos movement may or may not need to be replicated (depends on if they move in such a way that can't just be predicted by their initial transform and velocity)
How many missiles are you talking?
How you do it will depend on if it's a couple missiles or hundreds or thousands
you generally don't destroy replicated Actors server side right away
hide them, turn off their collisions, turn off their tick, and set their lifespan for a few seconds
I feel like im doing something wrong but how do I set a class to use a certain player state? Trying to have a certain player state for each character
Aah, Im firing 4-8 missiles, but I'll try to add a higher cull distance value to test it out @dark edge - I gotta do the same thing for my characters as I want their gunshots to be heard across the map π
APawn::SetPlayerState in C++
CLOSE_CONNECTION_DUE_TO_SECURITY_VIOLATION(this, ESecurityEvent::Malformed_Packet, TEXT("Received packet with 0's in last byte of packet"));
Whenever I try to connect to my dedicated server, I get this warning printed and the connection is lost.
Has anyone seen this
if an actor contains a camera component that is active, but has no player as its view target, is this a large amount of wasted resources? are resources wasted by the server only, or does this also hurt clients?
the logical solution is only activating the cameras when a client is set as the view target. but I seem to be having an authority issue that prevents clients from activating/deactivating cameras unless they are set to auto-activate.
activating the cameras on the server does not activate them for clients, according to print strings. but activating them on clients has no effect.
Honestly I wouldn't care about this too much if spectating can happen to often in my game, as the overhead of activating/deactivating would be higher than leaving them as is(at least that's the case in our game)
So you are saying after you set the cameras to auto-activate, still they are not activating? not being set as view target?
they are working fine for clients if set to auto-activate. which is fine by me, except thereβs a lot of cameras and iβm worried about the performance costs
the only cost for not used cameras is their transform updates and tick, if anything runs on it
Which isn't a big deal?
you should not be worrying about performance until you have something that works
and then only if the performance is terrible
later on, you use profiler, see whats costing a lot and try to optimize it
Fair enough, makes total sense to me
generally, no
that helps. thank you!
Are your projectiles pretty predictable or no?
Problem with spawning a replicated Actor that spawns 6-8 other replicated Actors is that it all works nicely on empty test level
then it breaks when there are couple of hundred replicated actors around
evaluating Actors for replication takes time and CPU on server
Yeah, they hit pretty predictably now π
and then you get a short lived Actor, like your missiles, and it just doesn't get its turn to replicate to clients before its lifetime already expired on server
and then clients don't see missiles
That's why a replication graph is needed for such cases, right?
as long as server can provide good predictable target information at the time it spawns whatever launches the missiles
If their movement is decently predictable then just replicate their firing
same for your gun bullets
you can have that information replicated inside the launcher actor, and have the clients spawn missiles locally themselves
Be warned, if you have air drag in your projectile calculations it WON'T be predictable compared to a pure ballistic trajectory.
i use a custom push model for replicating 85% of my Actors
none of my pickups or interactable actors are actually replicated, i have a network manager actors with fastarrays replicating few hundred actors each
So you spawn most of the stuff locally on the client
i have a network manager actors with fastarrays replicating few hundred actors each
I have seen this mentioned quite a few times. Never used FastArrays myself, but should look into them at some point
they are still netaddressable
as i need a pointer to the actor replicated as part of the fastarrayitem struct
but we spawn entire level locally on clients, then network it afterwards
I see, they are netaddresable from the fast arrays
no, they are net addressable because all machines spawn them in exact same location with exact same name, and IsFullNameSupportedForNetworking returns true
we also add a small... "hack" to make the engine behave as if they were loaded from the level, instead of spawned at runtime
Would you recommend going down that route for a multiplayer game with procedural levels or is it a lot of trouble?
i would, you can't replicate few thousand actors
and even if you could, relevancy behavior of destroying non relevant replicated actors would bury you
In our case the only actors that would need to be replicated are doors etc, things that move.
All the level geometry can be derived from the seed
we spawn 50k actors procedurally on larger levels
around 3000 of those need to replicate during gameplay, and that is where network managers come in
we also spawn them from seed, ofc
there are a few traps along the way
Ours is a top down tile-based system, using WFC for map generation. So really, we won't be doing generation on the client but just replicating the tilemap and every machine interprets it into meshes etc.
you can't replicate any of the procedurally spawned actors to clients until clients have completed procedural generation
when you set bNetStartupActor and bNetLoadOnClient true
unreal will assign them static NetGUIDs (last bit in the guid is static/dynamic)
unreal then also expects that when it sends a NetGUID for such an Actor that client, which has loaded a level at this point, has that Actor already and can Ack the NetGUID
if client didn't spawn the Actor already, they will still be NetAddresable, but you won't be able to open the ActorChannel
as in ServerOpenDoor(ADoor* MyProcedurallySpawnedDoor); would work just fine
but if you relied on the door to replicate its open state, client would be able to pen the door, but not see it opened
Does this sound gross or ok? This is the current model.
On travel to a new map (nothing is actually loaded, we have 1 persistent level and that's it)
- Server generates tilemap.
- Server and client interpret tilemap into meshes etc. Most of the level is there by now, besides actual actors that do stuff.
- Server spawns replicated actors (doors, enemies, interactables)
it works, but can be improved
All of this is hidden by a "travel" phase. The gameplay loop is sorta like Diablo with it's town -> dungeon -> back to town paradigm but it's spaceship -> surface -> back to spaceship
if you used the same seed to spawn the replicated Actors generating their name as they are spawned with FActorSpawnParameters
setting bNetLoadOnClient and bNetStartupActor to true
and letting the clients spawn their own versions of those replicated Actors
with IsFullNameSupportedForNetworking returning true for those Actors
So what do I end up with, a replicated DoorManager and CharacterManager and BulletManager etc?
instead of 30 replicated doors and 100 replicated characters etc?
and IsNetRelevantFor on those Actors returning false until client RPCs that it finished spawning the level
you could have clients spawn the replicated Actors themselves, and just have them replicated after that
I don't really see what advantage that gives me though, there's no hurry in the spawning really.
with us, the level takes 10-15 seconds to spawn on a fast PC, if we had to replicate those Actors, it would be minutes
but generally
(generic case)
if you had a FFastArraySerializer with FFastArrayItem that has a TWeakObjectPtr<AMinorReplicatedActor> and a TArray<uint8> ActorState as members
and that AMinorReplicatedActor (or interface) had a PostReplication function in it
you can wire a PostReplicatedChange/Add in FastArrayItem to call that function on the Actor the struct has a pointer to, passing in that ActorState as an argument
and have those MinorReplicatedActors be responsible for encoding and decoding their state from an array of bytes
which would in turn allow you to turn their replication off, or in your case set them dormant
and when they'd need to replicate something, they'd encode their ActorState, update their FastArrayItem and MarkItemDirty in the replicated NetworkManager that has the FastArray
and the replication callbacks from FastArrayItems would cause those Actors to update on clients
Yeah that sounds like a crap ton of work lol. Maybe we'll hire that out if it gets to that point.
i got it working in 2 days, without having done it before
and it had side benefits, like with few network managers, you can configure their NetPriority and NetUpdateFrequency to be higher
making the replication feel much much more reliable
I have a problem where The client can see the host's full head/gun rotation, but the host can't see the client's head/gun rotation, the clients bullets(which are shot from the rotation of its camera) are never able to shoot upward or downward because the host sees the clients head as not moving up or down, how do I fix this?
So if I get what you're saying, this is replacing the regular replicated properties system with network managers that replicated some state as bytes to be interpreted by whatever actors.
even unreal a significant network load
you don't have to use array of bytes
depending on how many different actors you need done this way
you can have a fast array for each actor type, if you have few enough
then you don't need to encode or decode anything
ActorState is the payload though right? That's what's being replicated around?
yes
and i run several different fastarrays inside network managers
one fastarray handles interaction, one handles damage/death, one replicated gameplay tags, 4th replicates buffs
and a more complex actor can actually use all 4 of them, each replicating one aspect of that actor
as there are like 300-400 different actor classes we replicate in this manner
Wow, seems like you created your own replication system...hands down!
the TArray<uint8> is the form that can generically handle any data, so it was easiest to use as an example here
Seems like this would mesh with Subsystems pretty decently
sure, but you don't actually need a subsystem, as network manager here has only one resposnibility
and splitting that responsibility with a subsystem just muddles the code
If your BuffNetworkManager also did all your Buff logic it'd be pretty close
yeah, but i don't have a BuffNetworkManager
All roads lead to ECS i suppose
i have a NetworkManager that has 4 FastArrays
the callback logic is inside the FastArrayItem structs
How do you do movement then?
things that replicate movement replicate normally π
they don't run via network managers
replicating several hundred moving Actors is doable
replicating several hundred moving Actors while you have several thousand non moving replicated Actors cluttering the NetBraoadcastTick is not
If we ever get replicated Subsystems there might be an interesting endgame there. I really like just having lots of dumb data on objects and letting a manager do all the logic. It seems like the manager would also be the optimal place to handle the networking as well.
Our projectiles work like that, they're just data in a subsystem.
only subsystem i see happening replicated is a GameStateSubsystem
it wouldn't be too difficult to create either
you need an ActorChannel to replicate it, and none of current available subsystem Outers are Actors
the only one that makes sense, and can guarantee it will be around is GameState, with GameMode not being replicated
could in theory pull it off on ALevelScriptActor, too
unreal has a nasty habit of swapping the Outer on a replicated subobject to be the Actor that replicated it via its channel
so while you could in theory put AWorldSubsystemReplicator Actor on the level, and have it gather and replicate all instances of WorldSubsystems you have running, client side those Subsystems would end up being A - Additional instances in addition to client run ones, and B - that WorldSubsystemReplicator, and not the World would be their Outer
I suppose a component on GameState would make more sense then a subsystem
which is still not insurmountable, provided you stop those Subsystems initializing on clients
you would not be able to access them via GetWorld()->GetSubsystem<T>() without additional hackery
but they would work
(like manually inserting them into World's subsystem collection during the AWorldSubsystemReplicator::OnSubobjectCreatedFromReplication
Anyone ever ran into a situation where a replicated server spawned AI thinks it's in the air on the client (spamming true/false)
but stays false on server?
default walking mode is navmesh walking
you probably have MovementMode NavMeshWalking on server and regular Walking on client
so server correct teleports it onto the NavMesh, which is typically 30 UU above the actual floor
and then it starts falling to the floor
and CMC doesn't really do much replication directly
ok?
so set your MovementMode to NavMeshWalking on client on say, BeginPlay
its one of the most expesive things in the netstack
and it should fix it
oh, its sends plenty of RPCs, but its entire replication is wired over the Character
the thing is
if your familar with networking
when you spawn on authority
which is server
you don't actually have a net load client version
to be "out of sync"
to set a "different" walking mode on
i agree it should be in sync
as your relying on the "replicated" actor
Just curious about this. In this sort of situation with a net static actor. How do you differentiate an on rep being once the actors come back to relevancy or has been in relevancy? Because with a dynamic one or with net load on client off it will always retrigger the begin play, right?
net load on client just means the client has a copy on net load which calls "client begin play"
It also causes the client version to be removed when youβre out of range
meaning any "states" shouldn't be init on begin play
Because static net actors stay
no, static actors will just do a full replication when they become repevant
But theyβll just not be replicated
dynamic actors are destroyed when not relevant and respawned when relevant again
which in turn causes BeginPlay to happen "again", but not really as its not the same instance as before
@severe nymph you got navmesh generated on client?
that is the second thing i can think off can cause this behavior
@chrome spear after the first replication of the Actor (which happens before BeginPlay) PostNetInit is called
So, can you tell in the onrep if itβs a full replication or not from net driver or something? In a situation with a door where you have animations onrep, for instance, you can use the begin play to skip the animations and just dodge the onrep with a HasActorBegunPlay c
we use timestamps, and synced network clocks
so we can tell if the change happened recently, or half an hour ago
Ah okay, I just actually did that myself recently haha so thatβs good to hear
Iβm not sure if youβve tested out level streaming or world partition in ue5 p2 but when level streaming is enabled, the client actor begin play happens before its onreps not after
So you donβt have any of your replicated variables in begin play
all replicated variables are set, and all OnReps are called prior to BeginPlay
doesn't matter
Both are called in the same frame so onreps always come late
The values are all defaults and null
PostNetInit is what calls BeginPlay on replicated Actors on clients
For static actors it doesnβt get called, it doesnβt seem
and the initial replicated variables come in same package as instructions to spawn the replicated Actor, so one can't happen without the iother
static Actors are not spawned on clients
there is a difference
Iβve had to put in a time stamp to check if the onrep is directly after intialization
got like no idea why this is happening, been looking through the code but not finding anything useful sadly
[2022.04.02-00.33.54:519][136]LogSecurity: Warning: STEAMID:7777: Malformed_Packet: Received packet with 0's in last byte of packet
[2022.04.02-00.33.54:519][136]LogSecurity: Warning: STEAMID:7777: Closed: Connection closed
Anyone seen this before? All I'm doing is open steam.id_of_server and the server has this. My server is on linux.
Yes but the functionality changes between level streaming and a normal map. With world partition disabled it works as expected
Enable world partition and your onreps happen after begin play
there is a bug i think
Yeah, I think so
with streaming levels that are set to AlwaysVisible
basically, the visibility of the streaming level doesn't replicate correctly
So Iβve had to use time stamps just to check whether or not the onreps that occur within x time are first rep or not as it is
So I assume thatβs fairly similar in concept to what youβre doing normally
@winged badger i've tried with it on and off
same behavior
I've also rebuilt it
LogBlueprintUserMessages: [BP_Ai_Male_C_0] Client 1: true
LogBlueprintUserMessages: [BP_Ai_Male_C_0] Server: false
LogBlueprintUserMessages: [BP_Ai_Male_C_0] Server: false
LogBlueprintUserMessages: [BP_Ai_Male_C_0] Client 1: true
LogBlueprintUserMessages: [BP_Ai_Male_C_0] Client 1: false
LogBlueprintUserMessages: [BP_Ai_Male_C_0] Server: false```
Is there an generally agreed approach for βinstanceβ style dungeons in multiple open worlds? In single player Iβd just load the player to another level/map. But is there a way to do this on a dedicated MP game?
@winged badger you talking about client side navigation?
yes
Is there a way to handle this while/before the game mode creates the pawn?
The thing is that with net load on client nav mesh disabled
and only a server copy of the ai
the client shouldn't be doing any CMC corrections on Server controlled AI
@winged badger
From what I was told, no (without super complex networking code) In multiplayer sessions, the server only loads one map and all players have to be there. A good solution that most games do is to put the dungeon below the map and teleport players there
Yeah, thatβs what I assumed as well. Thanks
Np
That's literally what we're doing. Home is in a spaceship. Dungeon is on the ground.
I have a problem where The client can see the host's full head/gun rotation, but the host can't see the client's head/gun rotation, the clients bullets(which are shot from the rotation of its camera) are never able to shoot upward or downward because the host sees the clients head as not moving up or down, how do I fix this?
What variable drives the look/aim rotation?
if your server has NavMeshWalking set, and client either has normal Walking, or doesn't have a NavMesh, this is what happens
the character movement and this:
Actor spawns on client on same position as on server (30ish UU above ground), next CMC Tick, the Actor starts falling on clients, as its in the air, as far as its local CMC is concerned
next server update correction happens, server update causes it to teleport it back on the navmesh
and it start falling again
movement updates from server don't arrive every Tick, and in between client CMC does its best guess, in this case best guess is that it should be falling
So the ControlRotation is what's driving it. That isn't replicated to other clients. Try GetBaseAimRotation
im not sure how getbaseaimrotation would help here
anyone know anything about overlap events on servers? they seem inconsistent
nevermind, I figured it out, tysm
What's the scenario?
basically anytime I have my overlap events use switch has authority to make sure that it's only the server that's firing them, it just seems inconsistent for when it detects the overlaps, it will work sometimes but sometimes it won't, i don't know if this is relevant but the hitboxes are attached to bones of a skeletal mesh so they're constantly moving with the animations of the player model
I mean how fast?
Could be tunneling
Turn on CCD
CCD?
continuous collision detection
make sure you turn it on for both bodies you need to collide
where sometimes the overlaps will trigger when they shouldn't
yes that's not the issue
it's that it works sometimes but not others
this is an example of the issue where it triggers when it shouldn't
i've had this problem for a long time, been trying to find a fix
i just asked because I've just had a hard time with overlaps running on server
for example in this game there is a slide tackle mechanic
there are hitboxes attached to the players feet
if overlap only runs on server it doesn't fire usually
basically when the hitbox overlaps the ball it runs a custom event
Move the overlap box for the goal back a bit.
that gives it some impulse
i did that, but that's a workaround
not a solution
i can't move it back that much
It's probably a tick order thing.
basically it might be triggering overlaps 1 frame ahead of what's being rendered
how fast is the ball moving?
fuckin fast at times
Yeah i'd drill down and do some testing to make sure it's never physically ahead of where it's showing
is ball moved by Physics?
yes
i was thinking the problem is something along what you said, where it's processing the overlap ahead of physics
That smells like a tick order thing yeah
It's more that the physics is ahead of the rendering
how can I mess with the tick order
yeah that makes sense
Could be some physics settings you can tune though if this isn't it
hmm ok i'll try this
Make a testing setup that's less complex so you can rule things out
good idea thanks
Iβm still a bit lost to what you mean
The client cannot have different properties for a server spawned replicated proxy
Itβs a server authority spawned character class
With its walking mode set to Nav mesh walking as βdefaultsβ
The Nav mesh is generated on server βas the cmc is sending transformsβ
And the nav mesh is net load on clients by default
If the character is placed in the level all is well
If itβs spawned by authority the client is falling spams
Iβve also debug printed walking mode with navmesh enum output on both the client/server
normal walking doesn't result in "isfalling" spams
navigation is on both client and server
Do anyone knows why this can happen? the pawns are detroyed on each other screen after some time
and EndPlay is called only on client with Reason = Destroyed
the Channel close reason is 170, strange
i fixed, it was relevancy problem ...
I have a problem where the client is constantly moving slower(and laggier) than the host is, they use the same player character
Is there anything that could be causing this?
has anyone done any large scale multiplayer experiences hosted on AWS, of up to 80~100 clients. (previously we have done smaller scale ones hosted on our own servers supporting ~30 people). Is 100+ clients a feasible thing for the default networking system to handle?
What's the correct class to add all my UI to player for multiplayer games?
Do you mean like floating names above heads, or all on screen UI?
Sounds like some form of state based replication that calls HUD and adds it. Really depends on the button, what it's for and why it needs to be shown.
It's a settings button
I jsut want it on my client when the client loads up
Why is this so hard? and no, I'm not going to replicate anything for this
UI should be local only.
Then your issue isn't a multiplayer one. Add a widget to screen from where ever you manage your UI. AHUD is usually a good place for this.
I mean it is a multiplayer one, but that's the next step. I was trying to add my entire UI in my playercontroller so far
AHUD? Do I need to create a new HUD class?
Spawn the widget in your pawn or player controller on beganplay?
i tried that @lavish minnow . you can't spawn widget like that in player controller
AHUD is a local only class spawned by the player's local controller. It's a good place to keep UI, because it cannot network, but everything still has global access to it through the local controller. One AHUD instance per player, per machine.
you mean you want the server to trigger the appearance of the widget?
I don't, and I never will do that @lavish minnow (at least until the need comes up)
this looks like what I'm looking for. Thanks
Is this ok or do I need to feed in OwningPlayer in the HUD class? does it implicitly resolve?
That's fine. Owning Player only matters with multiple players on same machine.
It'll run through the framework to find the local player for you and set it.
Fortnite with 100 players is the usual example, that yes it's possible. It all comes down to optimization. Replication Graph will be important to hit that number for sure.
how to get player state in HUD class
Get a class that holds a PS reference and get it from it
so PlayerController, Pawn
etc
you could just get the owner
HUD Owner is always the player controller
i guess it's referenced in PlayerOwner
ok great.
now, I am trying to print something from local player state in my HUD. however, it does not give me the correct result. Basically, I get only one of my connected clients printing
Lol ok...looks like it's because PlayerState is not set on time
Playerstate requires time to replicate. If you have C++ access, it can be good to drop some delegates in GameState on the Add/RemovePlayerState functions.
I'm using Blueprints only
Can I not have an event on PlayerState?
But is the problem that I can't bind to that event because playerstate is not available in the first place?
This isn't gonna work is it
PlayerState Beginplay could, probably. Make a GameState delegate and have your PlayerState call it with passing Self through it.
Beginplay will never run on any system before a GameState is valid. So GameState is a great place to keep your core UI bindings that you have to rely on a replication chain for.
idk if you can override this on BP tho
I don't see an OnReP_PlayerState in my pawn
C++ π
There is pretty much no BP access to the core framework stuff. Easy to override in C++, but BP only requires a little bit of workaround.
guys
please help me find an equivalent solution in BP, I'll be ever so grateful
I think this is the only problem I'll encounter in BP, starting state and setting up with UI
everything else is predictable/workable
Delay(10 minutes)
^
I have an event dispatcher in my playerstate that I call on beginplay
GameStateDelegates, Make two. PlayerStateAdded, PlayerStateRemoved, Call them in PlayerState's Beginplay and Destroyed events.
but how can I bind to that in my AHUD class? Because I don't know at that point the PlayerState right? The cast will fail
Game State. Not Player State
is gamestate available from the get go?
^
missed that, nice
just curious but what are u trying to access on your PS ? π
why u holding that on PS, it needs to be persistent across levels ?
then you can just hold it in your PC
No.
but why? i want my turnnumber to be replicated
Array of PlayerStates in the GameState.
?
You can replicate things in your PC
Pawn
etc
etc
why not playerstate?
You use player state for things that needs to stay across levels
does it matter though?
Depends on the game. If it's all players, I'd just drop an array of playerstates in GameState.
dont I already have access to array of player states in gamestate, GetPlayerArray
PlayerState is also used for player relevent data that all players need to know about that doesn't belong on Pawn.
I meant an ordered array in the order of your turns.
would not use PS at all if its for all players, if it's Turn Numbers like the Round Count or smth just GameState is sufficient
yeah but for it's UI Stuff actually so it's more an PC stuff
than Pawn or PS
Player Controller really has no business holding anything UI related most of the time.
He's literally talking about an HUD Class
that is holded by the PC ?
so ?
Well lets just fucking network all UI through the GameMode then. It spawns the GameState.
nah, all UI stuff should be client only
ok guys I hav a good solution. works fine for now.
hear me out:
PlayerController is a networking and input handling class. It has no business messing with UI.
that's exactly what i said
we can say the same for PlayerState
GameState
etc
in game state I call an event when all player states are ready.
I bind to this event in my HUD class. BOOM. works like a charm.
magic
PlayerState is a class meant to hold data per player. GameState is a class meant to hold data about the game.
persistent/relevant data
but yeah ok
anyways π
i don't see at any point why you would need to hold a non-persistent UI data on player state, it does not even need to be relevant but anyway
Out of curiosity. Where would you store a player's current level's score that doesn't move to the next level?
PC
And how are you planning on letting Player 2 know what Player 3's score is?
bad idea
btw. @kindred widget
This is the most useful statement I have ever come across on this channel:
"Beginplay will never run on any system before a GameState is valid. So GameState is a great place to keep your core UI bindings that you have to rely on a replication chain for."
I can literally bind whatever events I want via this
that's not because your "Blueprint Tutorial Series" on youtube told u to put everything related to your player on PS that this is a good thing
mmm, but how to replicate those. are you gonna replicate the variable itself
I come from a Unity background building mp games with 2+ years experience.
Tbf all these seem like unnecessary abstractions to me lol
was not talking to u tho
You still haven't answered the question. How are you going to tell Player 2 what Player 3's score is?
yeah i get it i get it, just saying that i dont like what unreal has done with all of these abstractions.
didn't they prune GameMode and GameState to GameModeBase and GameStatebase. We need more like that
ShooterGame stores kills and deaths on the playerstate, the gamemode or gamestate then iterates through all of them on match end to generate a score
it's not on the pc, there's some variables on it for internal tracking i think
btw if I ever have bots, will they also be using playerstate?
If their set to request them.
you can yes
PlayerState has a IsBot function you can call to test if it's a player or AI
ok. Right now I am hardcoding playerstate.length == ExpectedPlayerCount. If I have bots I want that to add to playerstate too
and there's a setting, I think in the ai controller to make it have its own player state
guys, I fixed blueprints for multiplayer with this one sequence. do I call tim
I can bind whatever events I want now anywhere because I have my playerstates ready
wow
that's indeed Timothy
this should be out of the box in BP. I think it is for C++
I. need. more. events. to. bind. to!
theorically using Jambax idea you get rid of this problem
specially since it's a subsystem that you'll be able to access everywhere
doing it blueprintable won't be much effort
it just requires some C++ here and there + the subsystem
it's fine. i don't think i'll have the problem anymore with the above setup ^
I'm just gonna safely wait for all clients to connect and their playerstates be ready before I do anything in game
just gonna add a "Waiting for all clients to connect..." UI before the event fires
ez. why complicate anything
π
anyway blueprints for mp sucks. not gonna reinvent the wheel XD
btw just out of curiosity, if a client disconnects and reconnects, his state is taken care of right? (if all the needed vars are replicated?)
How is this handled
when a client disconnect their player state stays around for some time
so indeed you can support reonnections i believe implementing OverrideWith
but not sure to what extent that exists in BP's π
i'm losing hope
can I not build a production ready game iwth BP
I'll probably tackle this when we get there
hopefully isn't too hard
you cant in fact, just with a few workarounds π
but i would still use cpp if i was u π (when u got time. don't abandon your current project to learn cpp)
so you can explore the engine source code and understand how things does this and that out of the box !
How do I wait to spawn players till all clients are loaded in to the level?
C++ only multiplayer hud.
Hello, I wonder if it is possible to set multiplayer inventory (I have one variable containing pickuped items) and own HUD for all the clients without adding a lot of extra classes (atm all logic - interwaction, hud is in Character class).
When there is one person on the server its working just fine, but when its 2+ -> everyone share the same hud (i have hud prompt for interaction and when one person wants to open the door everyone have this prompt) and when i try to pickup item item is picked up but nobody have it.
All tutorials that I was able to find use BP for this logic ;-;
I really dont want to change much the logic i already have ;/
I would really appreciate it if somebody could answer me some question on pm
AController::InitPlayerState is the function that spawns and initializes a PlayerState for the Controller. It's virtual so you that's probably what you're looking for.
Also it happens before there is a pawn spawned and possessed.
Is there an event I can listen to on the server after a variable has replicated to all clients successfully?
There is no way to know that, unless you add a server event on client that fires when a particular variable replicates
Can I do something like this? @bitter oriole
So in repvar, once it successfully replicates, (on the local player) call an event
Yes, if you really need that
@bitter oriole may I walk you through my use case, you can suggest your best approach after listening to mine
I guess
Is there a way to wait for all clients to load level before beginning play?
No, but you can have each client send a "I am ready" event to the server that calls a "real begin play" event once everyone is there
@bitter oriole
- in GameState, wait for all clients to load (by checking length of PlayerArray),
- Function to set turn order of all players (this is a board game),
- In function, get all PlayerStates, set a RepNotify'd var called TurnNumber,
- In TurnNumber repNotify (on player state), enable my UI on HUD
Okay, sounds good
That's it..works most of the time, but got this error once
Blueprint Runtime Error: "Accessed None trying to read property GameState". Blueprint: KTHUD Function: Check if My Turn Graph: CheckIfMyTurn Node: Return Node
I'm setting the GameState way before calling this function though
You can only call server events on player controller, player state, possessed pawns, and objects they own
But HUD does not exist on Server right? I'm calling this from HUD
Obviously HUD cannot have server events
How would you tell when the client is βreadyβ?
But neither can game state
Depends on your game
@bitter oriole can I not bind to a GameState event from HUD?
You can only call server events on player controller, player state, possessed pawns, and objects they own
Other objects cannot have server events
Dunno if that's your issue here
No it isn't, I can still bind to events on Game State in my HUD. GameState is replicated
Okay, but consider this: You cannot have a Server event in GameState
Just checking if you tried doing that
What are you talking about though? The event I'm listening to is client sided
i.e GameState pushes out an event on multicast for all clients to listen to
Okay then, so it just sounds like your KTHUD is reading game state before it replicates, then
I suspect this too
Do I need an event dispatcher for when game state is ready? :/
Does HUD load first?
There is never any guarantee on timing
You can poll it on Tick, or use another event
Looks like I'll have to use an event, sigh
hahahah but the question is, how do I even listen on that event if the GameState doesn't exist yet?
lol
Where can I reliably acccess GameState without race conditions again?
If Pawn exists does that mean for sure that GameState exists?
Tick, get game state, is valid
Delay better. I think
Why would it be better?
tick on every frame π¦
Being afraid of Tick is a disease
Yes but I have to bind to a function after. I wouldn't wanna do that in Tick right?
You could do the binding and then disable Tick
I'm calling Delay right now in BeginPlay, so that the handlers don't get registerd again later
Why disable tick though? What if I need it for later
Delay is almost never a good solution
why?
Disabling tick sounds worse to me
What if I want it for something
Also how do I disable*** tick?
i'm assuming you only need to bind your listener once, and that you don't currently use Tick, so in this context I'm suggesting something like "wait on tick for a valid game state, bind your stuff to it and then either check if you're bound alreayd, or disable tick"
Delay in multiplayer is terrible because you're assuming a given time is going to be enough
Just use tick
I am very averse to using Tick, sorry.
And this will work fine
My problem is not here anyway
Like I said, this stuff is a disease
nah
tick leads to more problems the way I see it, I don't wanna accidentally keep registering listeners and then having memory leaks
I've had it happen before
Having any logic to register an event listener frame per frame is a bad solution
Even if there are checks in place
Right now you literally have a tick that ticks only 10% of the time
So I'm not sure how you think it's somehow different
because it safeguards me against memory leaks
You literally can't leak memory in Unreal
Even in C++ it takes some serious stupidity
Anyway, not my code, not my problem
it doesn't matter anyway
tick 10% of the time doesn't sound too bad π
Do I have access to the variable that just changed in OnRep?
The value will be changed before the OnRep is called. I don't think BP has the ability to pass in the old value.
So bad.
Can you help me solve my problem if I quickly mention my use case?
- in GameState, wait for all clients to load (by checking length of PlayerArray),
- Function to set turn order of all players (this is a board game),
- In said function, get all PlayerStates, set a RepNotify'd var called TurnNumber,
- In TurnNumber repNotify (on player state), enable my UI on HUD
You haven't explained what the problem is in those four statements
I can't do the last step
Do you guys have any tips on what to troubleshoot if I'm trying to host my game with Advanced Sessions Steam API, and my friends can't see the server? When they host on the other hand it's fine. They're both situated in Netherlands, not sure if that has anything to do with it, but yeah
I've tried disabling my firewall and exiting my editor while testing
First off. Start by putting the function in GameMode. GameState should never have this logic as it's a server authoritive thing. GameState's functions should be things that even clients can call, maybe filtering functions for game state's data, etc.
Regardless of the upper point. You'd need two OnRep for this to be solid. One OnRep for the Player's Turn, and an OnRep for the GameState's CurrentTurn. Both should call HUD, or have bindings that a widget or HUD can use to show/hide things based on if CurrentTurn from GameState == Turn from the PlayerState
@kindred widget
You mentioned this right? Does this apply for ALL begin plays? Including HUDs, playerstates etc?
Every single Beginplay applies to this. GameState sets a value in the current World. The World holds whether it is ready for beginplay. When GameState starts up, it will get all current actors in the world and broadcast Beginplay to them. Or more accurately I think it has World do this, and then World sets it's HasBegunPlay value to true and from then on every time World spawns an actor, it calls BeginPlay on it directly after it's done spawning.
Including HUD right?
Every Actor
HUD is not an actor though right?
AHUD, it's an Actor spawned by the Player Controller locally for the client.
ok thank god
People name some of their widgets Hud. Not to be confused with AHUD which is an actor.
So is this the right one? (The one that waits for GameState)?
Yep. Blueprint.. very stupidly removes class prefixes. Mildly annoying.
Next question: how do I check and bind events/do whatever I want ONLY on my local client in any of these networked blueprints?
For example HUD, print "Hello" ONLY on my local client?
That is a very easy and a very hard question to answer at the same time.
HUD for instance is local only. It has no networking. If you get HUD on a machine, it belongs to that machine and has no version on another machine.
Then why is my "Hello" printing on all clients?
Client 1: hello
Client 2: hello
Client 3: hello
is that an Unreal thing? Showing logs of all clients on 1 client's screen/
What event did you print Hello on?
It's more of a PIE thing. Prints run on all viewports. What you're seeing is each client printing once.
But how is it printing on all clients if HUD is only on 1 client
HUD is on every client. One per client, non replicated
One AHUD per player, per machine.
so in this case, how do I get only the HUD belonging to me? and not the others? in OnBeginPlay?
A Dedicated server has no players, and has no HUD. A Coop game with three people has one machine, but still has three HUDs
This is what I meant by easy but difficult to explain. π
No I got what you're saying, the other 2 connected players have Actors spawned on my local machine
No, not in your case.
You're misunderstanding the prints in this case.
For example, put a print in your Pawn's beginplay.
If you have 3 clients on a Listenserver, you'll see 9 prints.
AHUD will have 3 prints, Player Controller will have 6 prints
You're seeing a print from every version on every machine when testing in PIE.
using dedicated, not listenserver
So why did Pawn print 9 with 3 clients? Shouldn't it print only thrice because pawn is locally owned only?
In that case, you'll see 12 prints for Pawn, Still 6 for Player Controller and 3 for HUD
Like I said, you're seeing a print for every version of that actor on every machine you're simulating.
When you have 3 players, every machine has to have a version of that Pawn. So...
Server, Client1, Client 2, Client3, all have a version of Client 1's Pawn.
Server, Client1, Client 2, Client3, all have a version of Client 2's Pawn.
Server, Client1, Client 2, Client3, all have a version of Client 3's Pawn.
12 prints
But I thought Pawn is something that's only locally owned, Why would BeginPlay print for Client2 and Client 3 on Client1's machine?
Beginplay runs on every machine the actor exists on.
Ok so just to be clear, when there are other players in game, their objects are also considered Actors, in essence
Do I have that right?
ok. this I'm aware
Pawn is a class that can be possessed by a PlayerController for input.
Usually a Character in Unreal games.
Ok so, 6 for playerController because:
Server, Client1, all have a version of Client 1's Controller.
Server, Client 2 all have a version of Client 2's Controller.
Server, Client3 all have a version of Client 3's Controller.
Correct, cause other clients do not have a version of other client's controllers.
Fantastic
Ok so, 3 for HUD because:
Client1, all have a version of Client 1's HUD.
Client 2 all have a version of Client 2's HUD.
Client3 all have a version of Client 3's HUD.
Yep.
So now I'm confident that my event handler in HUD is being bound only once, even though it's in BeginPlay. so that's good.
If you're ever in doubt, test by disabling the RunUnderOneProcess setting. It'll make clients run in Standalone mode.
Let's tackle the next problem, if you don't mind
Prints are process specific and PIE simulates all machines under one process so to speak. So in PIE, client 1 can see Client 2's prints, etc. In Standalone, it separates that out.
If we solve this I'll get a very good grasp of what to do to avoid these nasty race conditions
So now, in my GameState, I am looping through all PlayerStates and setting their Turn Number
When I know my turn on my local client, that's where I decide whether to enable or disable their own HUD.
So naturally for ease of use sake, I want to hook into OnRep of TurnNumber in PlayerState so that I don't have race conditions
Personally. Like I said before I would just drop a delegate in the GameState for OnCurrentTurnChanged, and one in the PlayerState for OnPlayerTurnSet.
Make Set functions for your Turn variables in both classes and call these delegates after setting the value.
Have a function in AHUD that GetGameState->GetCurrentTurnNumer == GetLocalPlayerState->GetPlayerTurn. If this is true, show your widgets, if this is false then hide your widgets.
Have HUD's Beginplay GetGameState, and GetLocalPlayerState, and bind those two delegates and then also call the function you made that does the check.
Now, regardless of what happens in whatever order, your HUD will set things to display correctly.
So, the OnRep_CurrentTurn works fine, because there are no race conditions well into the game.
I'm looking into what you said with OnPlayerTurnSet
Already have the function you mentioned in my HUD
Now my problem actually lies in this part:
Have HUD's Beginplay GetGameState, and GetLocalPlayerState
What if I don't have the LocalPlayerState in my HUD begin??
Same thing. You bind to the GameState's PlayerStateReplicated thing.
Maybe. Personally, if this was me, I would make a throw away widget for it. Initialization is fucking annoying. You know that Local PlayerState will arrive at some point. I would just plaster a widget up that says "Waiting for game to start", or whatever. Tick whether the game is ready. Then make a call to whatever to bind your delegates. Once that's done, you can throw this widget away, which will stop it's tick.
Should I use a delay instead of Tick?
Same thing in the end.
Ok so now my flow is:
When all player states ready, I get local player state in HUD and set it in a var
Blah blah, delay is probably faster cause bp tick, something something performance, cause doing stuff the hard way is better, use timers, cause they're so much neater, etc etc. I'd just tick it. They're very simple fast checks that not even a phone would recognize in BP.
But the problem is: now has my TurnNumber finished replicating or not?
Now you want me to have another delegate in PlayerState correct?
Doesn't matter if the turn number has replicated or not. That's why you both bind and call the update function.
Only thing that matters as far as initialization is that you have a valid GameState, and LocalPlayerState on that client that you can bind things to.
After that, replication will take care of the rest just from calling that function post binding and on each binding.
I can guarantee this, all good. I think both exist now for sure.
Actually, wait what? I tried playing like 10 times. Like 3 times local player state wasn't there
Guess I have to do this then? lol
hahahah
told you
it's ok, this ^ of mine works all the time
Just delay until player state is available locally.
Working 100% of the time.
Done.
Now what's the final step?
How do I hook into when TurnNumber is correctly replicated on my client?
onrep
Try this out. It's a fairly simple setup.
Yep, I've done all of this.
This should be all you need in HUD. Replace the prints with calls to show or hide the HUD.
Question is ,when do you Call OnPlayerTurnSet in PlayerState?
How do you know when the PlayerTurn has successfully replicated?
The OnRep.
Default Value for turns should probably be set to something you'll never use for turn number, like -1.
Done done
So I think what's happening now is:
(since it isn't working)
My OnRep fires the call BEFORE my player state is bound in HUD i presume?
Yep I can confirm that's what's happening @kindred widget
Which is fine.
Sometimes it won't. That's why you call the update function after the binding calls. No matter what happens, at some point in time, something will update this to the correct state.
No but my button isn't appearing. So clearly the order matters doesn't it?
Which update function?
Second part of the sequence
If you set this up like these images, and cannot see the button, then for some reason your client has been told it has a different turn number than the current game's turn number
Yeah I missed the second part of your sequence
Implementing it now
lol this...is so weird
I am calling SetLocalPlayerState() (to a local variable) and THEN in the second sequence calling UpdatePlayerUI for turn
Why is the function saying the localplayerstate is invalid???
Does sequence not run...sequentially?
so I have collision hitboxes attached to different bones of a skeletal mesh, I'm wanting these collision boxes to trigger overlap events, the problem is that it seems like the hitboxes do not move with the skeletal mesh on the server, so when I have the overlap events run only on the server, it doesn't work as it should, it's like the hitboxes don't move with the animations even tho they are attached to the skeletal mesh. Does this make sense to anyone? This is the conclusion I came to but i'm not sure if it's right
i wonder if there's a way I can make the server factor in the movement of the animations so the hitbox moves accordingly
Anyone have thoughts on a good time to write client persistent stats to disc on a multiplayer game? The most obvious route I think is on round end, but if that leads to map change there could be instances where client is still writing on map change. Do servers wait for all clients to confirm they are done writing?
Well if you're storing it client side it doesn't matter right?
But if server calls change map, and client is still writing to disc async, there may be some risk there?
Destructible Object on Multiplayer.
Anyone know how to delete an item after is destroyed? I need solution for LATE JOINING into the game, every new player can see this object and interact with it. I have no issue with other object such as bullets or pickup items when client late join. But i cant hide/destroy permanently Destructible Object ( even GetWorld()-> DestroyActor(this) do not work)
Wouldn't have thought so, if it's a just a single RPC that says "pls write this to disk". Users can change maps while writing to the disk.
Ok cool! Thanks
You'll need the actor to be replicated in order to destroy it
Hi guys! I have a small problem and I'm kinda stuck. I'm trying to automatically change the map when the round is over. Server side running on a dedicated server(so the host,player, can change the map). I've seen some docs about travel and seamless, but I saw that you can change one map, not more. I have multiple maps for 1 gamemode. Right now I'm using reset game. Thank you!
Just use the ServerTravel feature to move to the new map
And be sure to enable seamless travel
I know that, but after the next map is changed, the round will be over on that map and then I need another map. That's why I'm asking. I have 7 maps for that gamemode
@winged badger btw
Disabling client navigation fixes the issue
But the issue is I need this for ai auth only spawned characters
that just sounds... wrong
we have client side navmeshes and autonomous proxy predicted movement with pathfinding
we had that jitter issue, but only because CMC on clients started in wrong movement mode
Easy mock-up
Blank thirdperson template
Slap in map
Set navmesh walking on the aibase
Project settings βclient navigationβ
Toggle it on and clients will print βfallingβ
In animbp
Be sure to enable ai controller possession for placed and spawned in world
Test βas clientβ
The mode will reset when you change maps
Or at least, the MatchState will change. You may need to handle your custom logic in the various overridable functions in the GameMode class, though I'm not sure how many of them are exposed to BP.
How can I make sure things that are being executed in repnotify also work in singleplayer? Should I just set it or is there some cool trick I don't know of?
So disabling at project level isnβt an option
Need to find out why navmesh walking on server spawned AI is doing this
Shouldnβt have to use βwalkingβ
Yes, but itβs the same mode for every map.
That's fine, I use the same mode for my maps also
did you even try to manually set NavMeshWalking on CMC on BeginPlay for that AI?
@winged badger I'm printing it out
Btw just wondering do Player Controller Begin Play fire on map travel with seamless travel enabled?
that means no
Should do yeah
BeginPlay -> GetMovementComponent -> SetMovementMode (NavWalking) and reenable client nav
Some people told me it wouldn't because they are brought into the new world as is
LogBlueprintUserMessages: [BP_AIBase_C_0] Client 1: Navmesh Walking```
@winged badger
which is not even remotely the same as printing out DefaultLandMovementMode
wtf
Hmm I could be wrong actually, I don't use BeginPlay much tbh
Have to give it a try
they will always call BeginPlay if class has changed
is CMC's saved move expected to be replicated to other clients? for some reason I can see sprinting animation only on owning client and on server but not on other clients
I can't test rn but let me know if you figure anything out :o
server spawns them as "navmesh walking" for "movement mode" server and client prints navmesh walking as "class defaults"
but client still loads as walking
thats retarded
its not, thats just between autonomous proxu and server
welcome to unreal, its full of landmines
so do I have to replicate the bSprinting variable by myself with UPROPERTY(replicated) then or is there anything else to do with FSavedMove to replicate it to simulated proxies as well?
well in my case sprinting variable is used in anim BP so i need that variable
just don't try to replicate it inside the anim BP π
it won't work at all as far as i know
but i can destroy it, i use the same logic as with pickup item. Just for some reason when i late join with new client only destructible object is re-spawned ;-;
how is it spawned?
its on the scene from the beginning of the game, i can destroy it and every client (that is at this moment in the game) can see its destroyed and fading away
but when i late join, new client can see and interact with it
in that case ULevel should handle the destruction
/**
* Stored information about replicated static/placed actors that have been destroyed in a level.
* This information is cached in ULevel so that any net drivers that are created after these actors
* are destroyed can access this info and correctly replicate the destruction to their clients.
*/
USTRUCT()
struct FReplicatedStaticActorDestructionInfo
{
GENERATED_BODY()
FName PathName;
FString FullName;
FVector DestroyedPosition;
TWeakObjectPtr<UObject> ObjOuter;
UPROPERTY()
UClass* ObjClass = nullptr;
};
UPROPERTY(Transient)
TArray<FReplicatedStaticActorDestructionInfo> DestroyedReplicatedStaticActors;```
so im thinking you did something unspeakable there @bleak cargo
maybe, cuz its my first time using UE4, and its hard to find any tutorials in c++ only for multi
making single was pretty ok, but with multiplayer, everything gets super messy...
@winged badger I even tried setting in constructor
did you turn client navmesh back on?
@bleak cargo so its part of the level - static Actor, and you're destroying it with destroy, you don't do TearOff, you don't turn its replication off? Is it replicated?
they be jumping π
i can't see any of that, nor do i have any idea what that print is
its sooo funny to see them hopping around π€£
the print is "cmc is falling"
spamming between true/false
THANK YOU! I found the issue! i forgot to check one option in the BP
LogBlueprintUserMessages: [BP_AIBase_C_2] Client 1: Navmesh Walking
LogBlueprintUserMessages: [BP_AIBase_C_2] Client 2: Navmesh Walking
LogBlueprintUserMessages: [BP_AIBase_C_2] Client 3: Navmesh Walking```
are they jumping or jittering?
huh?
their feet should ne on the green plane, not the floor
your just telling me something I already know
lol
they are "falling" or "jumping"
and they will never "walk on" the green mesh
they approximate the floor
it works correctly with client navigation off
if the server is the "only thing" nav walking
youre not giving me much useful information here
video
1 sec and I'll zip the dang thing up
i w9ont download or open it
video here
what?
you can pathfind with normal walking
you need client side nav mesh to get "navigatable radius"
NavWalking is more performant, but they walk in the air
I'm not going to rpc to the server for that
I draw and trace the arc with client side logic
but not for FPS, TPS or VR
look
I've been doing this a very long time
I appreciate you trying to help
but your wasting my time
have a good day
i don't know how to debug this with blueprints
c++ data breakpoint on MovementMode
callstack to see what causes the change
again I'm a senior unreal dev I have access to source and can look there too
I simply posted the video to appease you
because i felt you were calling me a liar
you did give me distinct blueprint only impression
c++, data breakpoint the movement mode, examine callstack
which is offensive
assumptions are for "a-holes"
ever hear that?
if you check out my git you'll see I'm not simply a blueprint warrior
but its cool
again... thanks for "trying"
my point was "this is whats happening" and instead of looking at what was presented you "made assumptions" you knew better
"I have projects .... thats impossible... that seems wrong"
etc
your ego dude
your animation blueprint is throwing conclusions off
check it