#multiplayer
1 messages · Page 286 of 1
the point is you need to disable collisions/physics before you attach to vehicle
i already have these nodes
before attaching
i tried with Set Collision Enabled node but nothing changed
these are on server
first set the bool to true so it will call the onrep before you attach to disable collisions/physics , and than attach
changed it, nothing fixed🥲
remove these from server call
move them to onrep
onrep will called on server/clients both
removed them, still nothing
change attach rules, target, world, relative
weld simulated bodies enabled?
you have physics disabled on character, this should not matter
still nothing fixed, i can't understand why
actually when rotating wheels left or right in movement, the car is still laggy for driver too
do i need to use attach actor to actor maybe? im using to component right now
no, still nothing with actor to actor too
if i run the game with a server client too, on first client and on server all is ok, but on second client have this problem, idk why🤷
on client 1 screen, the character is moving his location and rotation when the car is moving and turning around
when do you attach? is it multicast event?
no, i don't use multicast, i have only run on server event inside car blueprint, and a repnotify inside player blueprint
this is what remained inside run on server event, disabling collision and movement i switched full insie onrep
this is inside player blueprint
Answering your question "how to debug", I would let there be only Attach node on server, and see if it works (without other Posses, replicate, notify etc)
try to attach only and see if it works
with possess node is working too, the possess node i use only for driver, not for passengers, but when i try to drive my car, my passengers are changing his location and rotation depend of speed of the car
and this problem i can see only from passengers screen, on driver screen i see all passengers are in their right position
disable camera rotation for the character which is rotating
is rotating the player location and rotation, not camera
when the car is moving
car is moving and the character camera is overriding the vehicle rotation for the character
in result your character don't follow the vehicle rotation
but why this is happeing only on passenger screen?, on driver screen i see all passengers don't have these problems
because passenger is not posessing vehicle, it is using its own movement stuff
but i need to rotate the camera around when im a passenger too🤷 😅
how can i look around when im passenger if i will disable camera rotation?
is that correct if when i enter the car, my capsule collision is remaining in that location when i entered the car?
in this case disable usepawncontroll rotation or something like that which effect character
i don't know if this is true what i made but i think i fixed my problem with set component tick enabled node
but this created another problems, when trying to enter exit, sometimes not working🥲
just disable these, when you enter vehicle and enable when you exit vehicle
CharacterMovement->bOrientRotationToMovement = false;
CharacterMovement->bUseControllerDesiredRotation = false;
Target->bUseControllerRotationYaw = false;
Target->bUseControllerRotationPitch = false;
i tried this, for now i don't see any problems anymore, but i don't know in future😅
if it works it works , good luck
thanks
@nocturne quail what about suspension is not working smooth when vehicle is moving, do you know how to fix this?
wheels suspension?
this problem is only when running on Play as Client, when As Listen Server all is ok
yes
I never encounter this kind of issue
you can record a small clip to show the issue
anyone here know steam sessions? (I have my game hosting and joining on Lan. And I believe I have it hosting proplerly but connecting on steam is not working.) Love to bend your ear or show you a video>
I think this is because of the vehicle physics body or bad wheel configurations
but why this is happening only on play as client? when play as server or standalone this is not happening
hmm, no idea than
🥲
There are some people knowing steam sessions.
You connect from same pc yo the same pc via steam?
no two seperate pcs
Question for Iris users, can you make a custom UDataStream class?
My usecase would be sending scripts from the server to the client that it needs to execute before doing anything else
My full plan is to stop replication of anything to players until they receive and execute those scripts, which are required for gameplay purposes
This would happen after they connect, and I figured that data stream class sounds useful for this
I have a level with an actor which loads a sublevel. Currently, clients join the level and the sublevel gets loaded as expected, however upon making the level visible it looks like based on the logs, trying to make the sublevel visible is causing the client to disconnect under MissingLevelPackage?
LogPlayerController: Warning: ServerUpdateLevelVisibility() ignored non-existant package. PackageName='/Temp/Game/maps/gameMaps/baseSubmaps/LaserMaze/LaserMaze_HalfGeometry_LevelInstance_4', FileName='/Game/maps/gameMaps/baseSubmaps/LaserMaze/UEDPIE_0_LaserMaze_HalfGeometry'
LogNet: UNetConnection::Close: [UNetConnection] RemoteAddr: 127.0.0.1:52037, Name: IpConnection_3, Driver: Name:GameNetDriver Def:GameNetDriver IpNetDriver_2, IsServer: YES, PC: UserPlayerController_1, Owner: UserPlayerController_1, UniqueId: NULL:AndyLaptopV4-6EC795694A30C4DFDA34FA8ED45D974B, Channels: 171, Time: 2026.01.20-00.40.07
LogNet: UNetConnection::SendCloseReason:
LogNet: - Result=MissingLevelPackage, ErrorContext="/Temp/Game/maps/gameMaps/baseSubmaps/LaserMaze/LaserMaze_HalfGeometry_LevelInstance_4,/Game/maps/gameMaps/baseSubmaps/LaserMaze/UEDPIE_0_LaserMaze_HalfGeometry"```
Server side the sublevel is already visible, and client side I can see the sublevel loading in. The client appears to get disconnected after the sublevel on their end has finished loading
Update, I think my issue might be I'm calling the level load/visible bp node on client by accident actually it has to be replicated???
the issue does seem to be with makign the level visible on clients, or perhaps the level on the server isn't being replicated to clients
I can set to LevelStreaming.DefaultAllowClientUseMakingVisibleTransactionRequests to true which I think would fix the issue but I think a proper solution would be to have the server correctly replicate the streamed level to clients rather than them loading the level manually
actually setting this cvar causes the sublevel to not become visible
To make level instance working in MP i had to work with unique name overrides
More specifically spawning at runtime new level instances
What do you mean by this? Set a unique name in OnConstruction so that the streaming level instance is different than on the server? (btw the actor loading the sublevel is in bp rn but shouldn't be difficult to move to cpp)
I cant check code right now but im talking about the struct/class param when you spawn a dynamic level actor
Isn't expected functionality of the player state supposed to be that it's restored if a player disconnects and reconnects? In my testing that is not the behavior, as the replaced built in score value at least got reset to zero Actually I think I have code which does this, as the game supports switching teams whihc should reset hte player score to zero
Anyone know why 3 characters would spawn in the level but only 1 controller is spawned please? I have no idea where to even start debugging this as I thought the player controllers were automatically created upon creation of the characters ?? Oddly enough each character can be controlled by the 1 controller (IE... They each jump individually when i press the jump key), Any help is appreciated, Thanks!
As a further addon info here is the print string which pops up from the Top Down Controller. As you can see it doesnt print out Client 1 : and Client 2 it still shows "Server"
found back my code
void AERGenerationManager::OnReplicatedLevelParamsReplicated()
{
FERRequestLoadAsyncLevelParams Params = FERRequestLoadAsyncLevelParams();
Params.Id = ReplicatedLevelParams.Id;
Params.LevelLocation = ReplicatedLevelParams.LevelLocation;
Params.LevelRotation = ReplicatedLevelParams.LevelRotation;
Params.LevelScale = ReplicatedLevelParams.LevelScale;
LoadAsyncLevel(ReplicatedLevelParams.LoadedLevel, Params);
}
void AERGenerationManager::LoadAsyncLevel(TSoftObjectPtr<UWorld> LoadedLevel, FERRequestLoadAsyncLevelParams& Params)
{
//if (!HasAuthority()) { return; }
FTransform Transform = FTransform::Identity;
Transform.SetLocation(Params.LevelLocation);
Transform.SetRotation(Params.LevelRotation.Quaternion());
Transform.SetScale3D(Params.LevelScale);
ULevelStreamingDynamic::FLoadLevelInstanceParams LoadLevelInstanceParams(GetWorld(), LoadedLevel.GetLongPackageName(), Transform);
LoadLevelInstanceParams.bInitiallyVisible = true;
const FString UniqueName = LoadedLevel.GetAssetName() + "_" + FString::FromInt(Params.Id);
LoadLevelInstanceParams.OptionalLevelNameOverride = &UniqueName;
bool bSucess = false;
ULevelStreamingDynamic* StreamedLevel = ULevelStreamingDynamic::LoadLevelInstance(LoadLevelInstanceParams, bSucess);
StreamedLevel->SetShouldBeVisible(true);
ER_GENDVLOG("Requested level: §% spawn in progress (Success: §%)", *LoadedLevel.GetAssetName(), bSucess);
}
is there a way to boost the net tick for start of game
its taking a while to send all replicated actor cause its kinda throttling, but at start of the game, we dont need it to throttle
an external actor exists in world plays Particle if it has no authority and set a timer to deactivate it after 1.5sec delay, if a client leaves before it gets Deactivated, will it crash?
Just replying to my own message as I found out that this option exists so you can see whats on the server world in the world outliner you can switch what world is being displayed in it by choose the "Choose World" option and then seeing whats active in each world. I am still having the issue with the clients not displaying any print strings.
the timer will run for the client that just leaves, and will reach to deactivate the particle for the client that don't exists any more
FTimerHandle DeactivateTimer;
GetWorld()->GetTimerManager().SetTimer(DeactivateTimer, [this]()
{
Particle->Deactivate();
}, 1.5f, false);
if you spawn 3 charactes, only those will spawn controller if they are actually possessed
in your case you are the only one which is possessed
and if you start the game with 3 clients, this will spawn 3 controllers casue each of them is possessed
When i view the Server world in the outliner i see all 3 cointrollers
controllers are only available for local client and server
you can't see other people controller
Wouldnt the server be able to see all of them ?
Yup which i can see in the pic.
Im not understanding why this is printing out on the clients though
When i press jump on each client they jump but the message prints which it should ONLY print if the Input System is not valid i would guess.
put a delay test
its possible the system is not yet init fully when you try to access it
beginplay only calls once when game starts
You can see it here what i mean where should i add a delay before the connection?
your jump key calls at current time where your inputs are valid
it has nothing to do with multiplayer, its a basic call cycle in unreal framework
beginplay calls only once at the time when you press play button
set it to 1sec
nope still same output
hmm, than I have no idea why its not valid
Ok when i press on each of the Server, Client 1 and Client 2 they all report their jumps respectively in the print string
Client 1 : Jump , Client 2 Jump and Server Jump
This has had me stumped for a while now because im not sure why it prints not valid but then the jump action works.
jump is replicated by default
but if the input mapping wasnt valid it wouldnt know the button was pressed woudl it ?
try to override the OnPossess event and print there
this is the onposses.
What object is this?
Ok i tried the input system on possess and i added this as well
Its the top down controller.
So i should do this in the Game Mode ?
Nope, game mode only exist on server.
Your binding must happend on target machine. Which are clients and listen server if you suppott listen server.
I bind my keys on OnAcknoeledgePossession but thats not blueprint exposed.
You probably end up with 3 widgets on server with this code.
Server has everyone controller.
If you play the game with 3 players, there will be 3 controller. You end up spawning the widget 3 times on listen server.
If the server has everyones controller why does it not have the input system connected?
Input system is local
Ok that makes sense.
Well i mean everyone is running their own instance and code.
So that would explain why I get Input Not OK because the input system is local to the local machine and it deals with it.
Not sure with how you get input not ok and in what context.
There should be an event you can use to bind keys
I would guess the server is spawning 3 clients (characters) but it cannot access the Input System local to each player as it only has access to it,s own.
Which seems to make sense.
But it has a socket connection to the controller to each pc for communication right?
Communication between server client goes through actor chanel.
Which utilize RPC and replicated variable. Thats about it.
Im dumb.... The node says Enhacned LOCAL input system...
I really appreciate the help 🙂
Its bit of a minefield trying to work out multiplayer but i think once you know how it works and how to do things it,ll become a lot eaier.
Tldr most of thr time begin play isnt the right place to initialize stuff ib multiplayer.
Mostly to do with race condition.
I did read that too as begin play can fire different times for different players
If thats true or not i dont know
Well ofc. They just fire when ever the actor spawn to the world.
And you need to understsnd everyone has their own instance (world)
Each player run their own code.
true and internet connections are not consistent and some low end pcs/connections will take more time to connect to trigger begin play ?
When server spawn replicated actor, it will tell clients to make copies of that actor.
When that actor spawn on player 1 world.
Plsyer 1 computer will call begin play.
When that actor spawn on player 2 world. Player 2 computer will call begin play.
When you want to do some action only for the character that you control. Dont forget to use IsLocallyControlled.
So IsLocallyControlled will only perform that action on the local machien ?
Like you dont want player 4 actor spawning in your world. Calling begin play and bind the keys.
You only want to bind the key for the character you possesed.
that makes sense,. Thank you
Would you happen to know about ChoosePlayerStart I have the default pawn set up in the game mode and am trying to use this function to determine where each player starts as you can see i remove a start position location from the array but Im finding that sometimes the players are trying to spawn on the same location and i coouldnt see a way to add a tag like "Occupied" to it to prevent a player spawning on it.
You can make this much simpler. Just scramble the start position.
I think the node is called shuffle.
Then you just go from start to end.
I have in the Game Mode this to get all the positions (I figured Begin Play in the Game Mode would mean that the server's Begin Play would always trigger before any connected clients as it owns the world essentially) but i could be wrong in that thinking
Cache it and shuffle it.
And you dont need to call random (and you still have the issue of picking the same number)
Thats why i thought if the server deleted one available spawn option when its selected by a player then by process of elimination there would be less and less options remaining in the server?
How do you want to go about this? Do you want to guarantee that the player dont spawn in the same place?
yes
Then i would just randomize the array. Go from start, then increment the index per spawn.
When reach the end, just get all the plsyer start and randomize again.
This way no one will spawn at the same place unless all the spawn location has been used.
Ok so use a local var SpawnIndexCounter and everytime it selects a spawn point then increment this by one until it equal to the length of the player start rght?
I thought removing an option from the array would work in a similar way but maybe it doesnt.
Yeah but not local variable. They are function scoped.
Just make one in the game mode.
Yes you can do it this way too.
Grab an array -> shuffle -> get index 0, remove.
Repeat.
When length is 0 just repopulate the array.
Actually your idea is better.
so this will return an empty start if the counter is equal to the length of the array else it,ll increment the counter by 1 each time and use that to select an element ie...0,1,2
ok that looks like its working 🙂
not sure why the other way did sometimes fail.
@fiery wadi actually your idea is better. No need with index and check. Just shuffle the array then remove as you spawn.
I think my way might have been failing sometimes due to timings and the player was connceted whilst there was still 3 options in the array
thank you so much for the help !
i,ve been stuck on that for about 2 days xD
heyy guys, how to get vehicle RPM node? my blueprint class is Wheeled Vehicle Pawn, the component is default auto created Vehicle Movement Component, but to get the RPM it asks to change component to ChaosWheeledVehicleMovement, i tried but i cant remove the old component
i just added this chaos movement component but can't remove vehicle movement component
i tried to change blueprint class but can't found this chaos vehicle
the plugin is enabled
that is not multiplayer question, post whole screen in #ue5-general , I guess its inherited from class so it can not be removed
@fallen fossildo you know how to change?
i already tried
there is no any chaos wheeled vehicle class
no I don't, unless its inherited u can't remove it. and I never used chaos plugin
maybe ? #chaos-physics
i fixed just by adding a cast to chaos wheeled vehicle from simple vehicle movement component😅
well, it can fail xD
add these to your vehicle class
for cpp and optionally for blueprints
FORCEINLINE const TObjectPtr<UChaosWheeledVehicleMovementComponent>& GetChaosVehicleMovement() const { return ChaosVehicleMovement; }
UFUNCTION(BlueprintCallable) FORCEINLINE UChaosWheeledVehicleMovementComponent* GetChaosVehicleMovementBlueprints() const {return ChaosVehicleMovement.Get();}
why?
ok will try thanks🙂
also should be in your
UCLASS()
class AMyVehicleBase : public AWheeledVehiclePawn
advanced vehicle template also use AWheeledVehiclePawn
its a good start to make vehicle system based on this class
It depends on Class,
Casting only works if Class inherits from Parent class, then it can be casted, otherwise it fails.
There is also concept of casting pointers Parent pointers to child classes.
but if classes do not share stuff like A->B, then it will fail ;d
but again, I never used chaos car, so I can't tell class hierarchy
i don't know i made a cast and all works fine without any fails
then I guess its parent is that class somewhere ;d
maybe😅
i don't know what changes epic games made on UE 5.7🤷 😅
I don't know about Iris, but we used a derived AOnlineBeaconClient to send scripts etc when clients joined, outside of the usual actor replication system
That would also work but I'd rather use data streams if it's possible
Since AFAIK they run outside of the usual channels and don't affect regular replication bandwidth
(might be wrong)
I also see UChunkedDataStream which would be awesome for sending files
The name of a level must be consistent between client and server. Usually if it's a level baked into your game the name is already unique and there's no issue
If you're dynamically placing levels at runtime then you need to load the level on both client and server and ensure the name is unique and matching
The level an actor is part of is used to describe its "name" more or less
They have the minimalapi specifier
Can't derive from them?
I believe so, yeah
Snipe the vtable, be a man
is there a more complete documentation on unreal net driver config ?
i found several config marked properties that still commented with @todo documentation.
hey! Iam trying to solve a puzzle which way is the best to keep save data for dedicated server for loading a players profile. I did a system that check player id and after login to a server it checks it have a profile. The thing is not always showing widget at first join .Which drives me cause it happens with the second login - widget appear and creating a profile happens. So the thing is how i can push that to be always reliable or make a class structure to have that perfect in slot. Tried different things and code is not the problem i think timing is crucial but cant get place that stops me to fix this issue It must be a message from the server to client to check if he have valid profile to his ID.
So i think i should change structure a bit to have things more controllable. Someone maybe have a graph where the logic of identification should be? Now i have gamemode + player controller and rpc that handle that + save object that data is pushed when certain conditions are met.
So the player state and game instance are now i focus but would like to ask how to do that better (dedicated server)
last piece left to me and iam really annoyed why i cant push condition to first join somehow engine wont react. LOL
We have the main logic in GameMode::Login. Use the PlayerUID from the PlayerController to lookup the relevant savedata binary object (if it exists).
Serialize the savedata into the PC, and allow replication to handle the transfer to the client as necessary.
Thank You very much for that tip iam not good since iam c++ starter but that actually helped me to fix the issue All the best!
it logs TestActor is invalid on clients!
How to deal with such condition without using delay?
bTest = false;
OnRep_Test();
TestActor = nullptr;
void ATestClass::OnRep_Test()
{
FString RoleString = HasAuthority() ? "server" : "client";
if (TestActor )
{
UE_LOG(LogTemp, Warning, TEXT("Valid on: %s"), *RoleString);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("In Valid on: %s"), *RoleString);
}
}
TestActor is also a replicated variable
Very high risk and Safety convernes , sending executables between clients is uuh :d
what do you mean without delay?
OnRep shoudl already have valid replicated variable 🤔
we are talking about TestActor is null cause its sets to null directly, if I set it to null with a 0.01sec delay its fine
Im confused, is OnRep function assigned to replication ?
Where you put delay? :d
How you replicate?
What do these scripts do?
standard onrep terminology
is TestActor object replicated ?
TestActor varialbe is replicated and the class it belongs is also replicated
ATestClass is also a replicated class
TestActor belongs to ATestActor
You never set the value of test actor though other than making it null?
it was set and on server it is valid
Where?
ATestClass by server
We are talking about ATestActor right? I only see it set as null.
yeah setting it to something is not related
If server set ATestActor to something.
Aint no way the client on rep gets null.
Show the actual code setting it.
Also setting it to null probably triggered OnRep on client where ATestActor is null.
will post the whole flow from setting it to an object and than to null in a minute
BeginPlay()
TestInteractionComponent->OnInteract.AddDynamic(this, &ATestClass::OnInteract);
void ATestClass::OnInteract(ATestActor* NewTestActor)
{
if (!IsValid(Character) || !HasAuthority())
return;
if (!bTest)
{
SetbTestTrue(NewTestActor);
}
else
{
SetbTestFalse();
}
}
void ATestClass::SetbTestTrue(ATestActor* NewTestActor)
{
if (!bTest)
{
TestActor = NewTestActor;
bTest = true;
OnRep_Test();
}
}
void ATestClass::SetbTestFalse()
{
if (bTest)
{
bTest = false;
OnRep_Test();
TestActor = nullptr;
}
}
void ATestClass::OnRep_Test()
{
FString RoleString = HasAuthority() ? "server" : "client";
if (TestActor )
{
UE_LOG(LogTemp, Warning, TEXT("Valid on: %s"), *RoleString);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("In Valid on: %s"), *RoleString);
}
}
show declaration of
OnRep_Test and TestActor
OnRep usually was used by rpc system, not manual call like yours, so there is some confussion
everything is fine with declarations
only on listen server
Well, my understanidng is u used OnRep like RPC for server
you need to manually call it on server in C++
? UPROPERTY(Replicated, ReplicateUsing=OnRepFunc)
i was pretty sure, this is the convention among unrel devs, thats why I just want to peek declaration, not change them
what's with OnInteract early returning if it isn't authority? This will only set the value on a client, and a listen server host has authority
interaction only happen on server
Isn't that just to bail out, only allow interaction on authority?
seems fine
That will only fire on actual replication on clients. If you want the server to run the same code you need to manually call it. In BP it fires on both
if I do this everything works fine, setting it to null on next frame
void ATestClass::SetbTestFalse()
{
if (bTest)
{
bTest = false;
OnRep_Test();
GetWorld()->GetTimerManager().SetTimerForNextTick(this
{
TestActor = nullptr;
});
}
}
well on the server you should be calling the OnRep after setting values
Are you getting the weird repnotify right away or after the actor has existed for some time?
right away
You sure you're not just firing the onrep on begin play or anything? Can we see the full cpp?
TestActor is not repnotify, its just normal relicated
also if OnRep_Test is for bTest and not TestActor, then you can't really rely on that
bTest is set to false on server on beginplay without calling on rep, since its not needed there
why not? I can just benifits from it its normal
because the OnRep function is dealing exclusively with TestActor
you can't guarantee the client will receive both values simultaneously
I know, I felt into this some day
hmm, so I need to move bTest to TestActor and setting it by server under ATestClass ?
well it would be a good start to test the OnRep on the actual value it's dependent on, yeah
That's your problem
race condition, it'll be much worse with latency.
why do you even have a bTest?
what does that boolean represent?
lets say
seat in the plane, and TestActor is a pilot
So I need the pilot ref to be valid if the seat gets empty, so plane actor ATestClass can do stuff to TestActor before its sets null
what state does that boolean represent?
You probably have redundant state here
I think you have a problem like if you had a bHasGun and AMyGun*, it's redundant
whether or not the pointer is valid IS the state
this represent if the plane seat is occupied..
if false -> eject the pilot on server/cient [onrep]
if true -> attach the pilot to the seat on server/client [onrep]
TestActor* can also represent that same state
in both cases the pilot should not be null, and it should get nulled only if the onrep calls on all
if TestActor* is not null, then the seat is occupied
yeah it can, but it will be an extra route which is not what I want, I am already interacting with the plane, Plane already have the pilot
It's not extra, you have redundant state.
that's true but the issue is when the seat needs to be un occupied
and the plane still need the pilot to do custom stuff with it
Just have the plane store who's the pilot and who's sitting in the seat
anyway, that's your problem, good luck.
I am doing it exactly the same, in the end the issue is still the same.... I can't set pilot to null if the onrep has not done its job yet
setting the value to something else after calling OnRep on server sounds like code smell but maybe it's just me.
Show current code
entire cpp file
variables replication do not happen instantly, after set, it can take some time (unless rpc used)
strange statement
not sure how RPC is related and how it can take no time / less time if RPC is used.
currently its not usable, I am re designing the whole class
but true. Changed values on server are not instantly sent
so wdym by unless rpc is used it take less time / no time?
latency will always exist.
its not latency, its that state replication awake parameters
rpc will usually be faster as it'll fire either immediately or at least that same frame (don't remember), while replication can take a bit. This isn't counting latency.
sure, there is net update etc. But it won't be instant.
instruction / data will always need to travel through the net.
instantly or not instantly has nothing to do with the issue, its frame related stuff... when onrep is called right after this the test actor is set to null, this means the for clients the onrep calls on next frame where the testactor was to null on the previous frame
Your previous problem was a race condition since your onrep was on one variable but you were reading the state of another. Once you get the class re-written we'll see what the next problem is.
the another variable was not yet changed when onrep was called, we can read the state of any variable in the onrep, they are not limited to the variable for repicated with them
the bool can replicate and fire the repnotify BEFORE the pointer is replicated
race condition
that was your problem
don't do that
is the problem only on server ?
im confused where is it, on clienr or server
you mean it was not set correctly on the first place?
void ATestClass::SetbTestTrue(ATestActor* NewTestActor)
{
if (!bTest)
{
TestActor = NewTestActor;
bTest = true;
OnRep_Test();
}
}
but it logs valid on both
Which replicated variable triggers OnRep_Test()?
bTest
that's your problem
lol I Made seriazlizaion for ubojcet cause I wanted to send orders in same way for everythign
if I made the seat dependent on ptr, I will not be able to access it when it want leave the plane
what?
You're not making any sense
This is to represent who's sitting in the seat, correct?
Yes, that's why I need it to be valid inside onrep, if I use a multicast it works fine but than for late clients it will be trouble
just haveing the pointer will be enough data
pointer is WHO is sitting in the seat, and also represents if anyone is sitting in the seat
you don't need bSeatIsTaken and APersonSitting*
just APersonSitting* is enough information
than to reinvoke onrep it has to be set null
set it null when they get up
that's the whole point
a seat only cares about who (if anyone) is sitting in it
OnReps store previous values... just saying
set it null when they get up , onrep is getting them up
That way you can detect the valid -> invalid edge and tell the previously valid char to stand up
so the parameter passed as the testactor will still be valid even if the variable sets to null?
void ATestClass::OnRep_Sitter(ACharacter* PreviousSitter)
{
if (PreviousSitter)
{
PreviousSitter.StandUp();
}
if (Sitter)
{
Sitter.SitInChair(this);
}
}
PreviousSitter will only be valid if Sitter == null?
PreviousSitter is the old value, if you give your Onrep a parameter of the same type as the replicated type, it'll send it the previous value.
so you have the pre and post replication values
hmm interesting, will test it now
Thanks very much
this now seems to working fine, when the APilot EndPlay gets called, PreviousPilot should still be available for one time access?
void ATestActor::OnRep_Pilot(class APilot* PreviousPilot)
{
// seat entry
if (Pilot && Pilot != PreviousPilot)
{
Pilot->AttachCharacterToSeat(this, EVehicleSeat::Pilot);
}
// seat exit
if (!Pilot && PreviousPilot)
{
PreviousPilot->DetachCharacterFromSeat(SeatTwoExit->GetComponentLocation(), false);
}
// (character swap)
if (Pilot && PreviousPilot && Pilot != PreviousPilot)
{
PreviousPilot->DetachCharacterFromSeat(SeatTwoExit->GetComponentLocation(), false);
Pilot->AttachCharacterToSeat(this, EVehicleSeat::Pilot);
}
}
Did I say executables :p I wrote a Luau plugin, it's perfectly safe. Best they can do is crash the player's game, oh well.
I do need them to run before the clients start processing anything though since mods can have custom character roles etc
Is VaRest a good plugin for API usage? I’m currently using it for API calls, but I’m not sure about it.
Do you have any solid plugin recommendations?
Or what would happen if I use Unreal Engine’s built-in HTTP / HTTPS system instead?
When using VaRest, I create objects but I can’t clean them up properly.
Because of this, I’m getting crashes.
I'm overflowing the net bunch size (64kb) on the player controller during initial replication. Network Insights shows a few components, but none of them are very big. ~300-400 bits. Do I need to do something to see everything in that bunch?
that's what I'm trying to use insights for
have you considered making some library functions or objects to be replicated as such "Script" ? not particullary script but some transformed version of it into such abstract stracuture?
I don't know your goal, but I could tell you more about this a bit
Networking the scripts and all isnt an issue, I can send the data over the network
i just need to prevent networking for anything else until the scripts and map have been sent to the client and initialized
Scripts are just .luau files
Iris can do it, I just need to figure it out
I don't know how joining session works 🤷♂️ sorry
play standole and f1 or "
And write stat net u will see
how many have actor
I experienced the same ping issue as well.
I was spawning the blocks as Actors (around 50k blocks) and I was getting about 300 ping!
After switching to HISM, my ping dropped to around 25.
You can check it the same way by typing stat net.
I will have to try that. I ended up logging inside AActor::ReplicateSubobjects. Found one component replicating 44kb of debug data and another replicating 23k.
anyone know a way to prevent net corrections from character capsule collisions? especially with other characters.
If you are getting excessive corrections, you are usually doing something wrong.
I'm having a 2 brain cell moment.
Where the heck does the engine handle control rotation reaching server?
I would've thought it was the set control rotation?
Actually, NVM.
Even if I knew that, doing it that way would cause issues. 😛
just walking into another character causes a net correction. this is the out of the box behavior in unreal engine. do you know a solution?
ofc that is without ignoring pawn collision.
I don't know exactly the right question to ask to fix my problem. I suspect that once I know the question I'll be at the solution anyways. Only one of these created widgets shows up. I've tried every function in the Player node (Players are a subclass of the Character class) that can return a Player Controller object and none of them change that.
Thats not how widgets work. 😛
Yeah that's what I figured the answer was gonna be.
Each 1 client has to spawn it themselves.
Simply passing in others PC's isn't how that works.
Then, whats your add node?
There is that other one, for split screen IIRC
Leading directly off the create widget node.
The stuff coming from above is printing out a ton of stuff from my failed debugging attempts, ignore that.
Oh, well then IDK. lol
Out of my depth.
IDK how you even test 1 screen multiplayer with UE, i've never dabbled in that.
Sorry 🙁
Augh.
I'm not following this, make do you actually want to do?
Btw the default character class already have get controller method.
Just be aware though while server have a copy of everyone controller. Client only know their own controller.
widget is local, they are not reachable by anyone else but the local machine.
Make a textbox hover above my characters' heads.
involving controller but own's local controller not gonna work.
That's it! I don't know why it needs controllers at all!
are you following a tutorial?
So do you want a name tag or something?
a text that show up for each player's name?
It's a popup telling a player how well they did in a rhythm game.
so a pop up msg?
Like "good," "ok," "great," "perfect," etc.
are you making this text component at run time, or each character already has one and you just want to set the text?
I have all the logic for scoring and input handling, I just need these freaking components.
lets say they hit 5 beats in 1 seconds
At runtime, that's the issue.
do they see like 5 "good" in sucsession
Run time or not shouldn't be an issue.
just different approach.
Only one at a time. You only get one try per window, if you're too early or too late your inputs lock until the next window.
You'd think so, wouldn't you.
To be clear, that is hostility towards Unreal, not you.
imo it's a pretty trivial problem.
so what issue do you have atm, attaching the text component or displaying the msg to players (networking)?
I THOUGHT it would be. Because I thought what I'm doing should work!
I still don't know why it doesn't!
This is the whole thing.
That is too low resolution, I will split it up.
There is no networking.
It is local multiplayer.
The problem is that it doesn't show up for anyone except player 1.
I don't know the exact problem from static image (refering to the part where you show the widget).
Split screen?
I don't either. I cannot find where it's happening. Every test I have run indicates success.
Nope. One screen.
All 4 of these characters are accessed in that loop. I checked.
And no, there aren't 4 of the same widget on the one player. I checked that too.
The player's mesh. The players are what's being looped on.
Np, take your time.
Can you show it in picture
Like, the mesh itself?
You can see it in the first of these images.
It's that one launching off the top and going forwards.
The whole thing is visible here but I didn't want you to hurt your eyes squinting at this.
@stiff pine
no issue here
print string the player array element, make sure it's not the same object.
Maybe one of yall can help. When I add a basic static mesh into my level, my num Network Actors increases. Does this mean they are replicating?
If you tick off NetLoadOnClient, does it still increase?
I am not doing anything special, those 4 nodes does the job. Does the socket actually exist on every mesh?
It decreased, but now my client doesnt see anything. Hm.
It's the same mesh. And this happens even if I leave the socket as None.
It working properly for you concerns me.
Makes me wonder if there's something insane going on in the MinigameCharacter, which I did not make.
sounds like it doesn't find the socket and just attach to world origin
I've tried slapping the camera all over the place and I've never been able to spot them.
. . . do widgets backface cull by default?
And why would it work for the one player? Like I said, they are the same mesh.
if you are rendering screen space then it should always be pointing to the camera
Actually wait these shouldn't be able to backface cull, yeah.
it may not work on any of them probably
just stood in world origin is my guess
That player with the display can move, and it moves with them.
Also spawn locations are random.
#multiplayer message
Maybe make a function just to test, and work outside your array. Just Get All actor of those character and add the widget component
I'm not sure I follow. Doesn't Get All return an array anyways?
yeah but since I can't debug from here, that's probably the next test I would do.
Fair enough. Lemme check.
Well, I have new information. Not sure if it's helpful, but it's new. Nothing changes if all I do is switch out the Player reference for a Get All Players node, but I noticed that in your code, you have nothing attached to the target of the Add Widget Component, whereas in mine I'm attaching the player.
Detatching the Player from that makes NONE of them appear.
Nothing. Loop still runs 4 times on 4 different characters but there is no visual representation whatsoever.
well I'm attaching it on the last node with Attach Component To Component. Basically attach the widget component to the head socket in the character mesh.
also are you using Screen position? I have mine set on screen instead of world.
You mean here?
No visible changes from previous approach.
If I detach that target from Add Widget Component, the one that does appear for Player 1 disappears too.
you are not attaching to any socket
I know. I set it to the default to remove another point of uncertainty. It just moves the center of the widget to the center mass of the player. Still moves with them.
Just for the sake of idiot-proofing, is there some why I could have set up the widget itself that would cause this behavior?
I tried it with one of the default Unreal widgets, so I assume not.
I found them in the debugger. I cannot figure out where they say where they're rendered though.
I also cannot find them under the players. I can only find them like this if I filter for their class.
More information that might be useful but I'm not sure how to interpret it. That name does not change all 4 times this node executes, and none of them show up in the debugger after it gets out of the loop.
This is going to make me lose my everloving mind. I don't understand what the problem could even be! It won't throw errors and everything I can think of to validate ends up valid, save for the fact that they just don't seem to exist!!!
I went and modified the dang code that SPAWNS the players to make adding these components the first thing they do and it still doesn't work.
It's the EXACT same behavior! The first player gets one, the others get nothing, and I can't find ANY of them in the dang scene tree.
can you just run a draw debug string for each player as a sanity check? (their locations in the world at the time of this being called)
I suspect the widget is doing something internally different
I want to see what "just moves the center of the widget to the center mass of the player" actually means
how does it know which player?
Already have. Multiple times. I've also run sanity checks on every single gosh dang connection in the loop to make sure it's not missing anything. I have checked the NAMES of the players to confirm they're unique. I have checked the names of the WIDGETS to confirm they're unique. The closest thing to something useful I have found is that the Widget Component that gets attached to the player has a weird name ending in -1, and it's the same name every time. I have not managed to turn that information into anything useful yet.
Beats the everloving frick out of me, but it's always player 1.
show the code
you said "just moves the center of the widget to the center mass of the player"
you made that
It's already here, unless you want the endless permuations of print statements I've gone through.
One sec.
That's all that happens.
Spawn positions of the players are randomized, but the one with the label is always Player 1.
There, I have it changing at runtime to display the name of the player it's attached to.
The node that creates these gets reached 4 times. The player object that it gets attached to are different all 4 times. No errors are thrown. And yet, this is the result.
I have positioned the camera all around the scene to make sure the others aren't hiding somewhere. I have tried changing individual names manually on the spawned components after the loop finishes to make sure player 1 doesn't have 4 identical widgets attached to him for some reason. I have tried using different widgets, which yields the same behavior of only Player 1 getting one. I am running out of ideas to sanity test.
At this point I'm sure it's going to end up being something elementary that I don't know about but I just cannot find it!
Idk if you tried already, but might be worth testing. Did you try to use world space widget component instead of screen space?
I know screen space widgets have issues with local multiplayer, but i do not remember if it was only for the case of multiple viewports
It turned out to be something that is almost certainly a 5.6 bug. Creating widgets using something that has a controller as a target results in the widgets belonging to everyone but the first player being collapsed in a manner that cannot be altered or circumvented by any methods I'm familiar with. You have to spawn them targeted on something random that isn't a player, and then bind the component to the player socket.
Apparently the developers of 5.6 never considered that someone might want to make a local multiplayer game that wasn't split-screen.
If that sounds stupid and convoluted, that's because it is. It took me 5 hours and the help of many people to find that.
The reason we're pretty sure it's a bug is because 5.7 has a project setting that is genuinely a toggle for the exact behavior I was experiencing.
I added Custom UObject Permission Manager into player state.
Everything is replicated, but my understaning is that It does not trigger
PostNetReceive on PlayerState, cause its using its own channel? 🤔
Depends. If it's a replicated property of the player state, that property changing would trigger PostNetReceive. But if it's not, then no - you would need to implement PostNetReceive on the object itself.
Save yourself trouble, use an actor component instead.
Many of those functions are native to UObject, so all objects can implement them,
yes, its ActorComponent
but I found the isseu
somehow compiler did let me start project without setting LifetimeReplication for my structs
....
Its not replicated, PostNetReceive is never triggered at all :/
UCLASS(BlueprintType, Blueprintable)
class UCommandPermissionManager : public UActorComponent {
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Replicated)
FCityCommandInfo BuildPerm{true, UCmd_Core::StaticClass(), "Build"};
// ... More commands
virtual void GetLifetimeReplicatedProps( TArray<class FLifetimeProperty>& OutLifetimeProps ) const override;
UFUNCTION(BlueprintCallable)
void SetPermissionAllowed( const ESharedCommandsUI type, const bool IsAllowed );
virtual void PostNetReceive() override;
void NotifyPS() const;
UCLASS(BlueprintType, Blueprintable)
class MINICITYBUILDER_API ACityBuilderPlayerState : public APlayerState {
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Replicated)
TObjectPtr<class UCommandPermissionManager> CommandManager;
yea not defining the lifetime function wont cause any compiling errors
UCommandPermissionManager::UCommandPermissionManager()
{
SetIsReplicatedByDefault(true);
}
Found real issue.
I though marking uproperty as replicated is sufficient oh
but its always pointer, so maybe that was problem
nice
What's the desired result here?
You want a widget to appear at XXXX for each YYYY when ZZZZZ happens.
It was specifically that they need to stick to XXXX of each YYYY. And YYYY are players. YYYY being the players ended up being the cause of this insane behavior.
use the word pawn
just have each pawn have a widget component, what's the problem?
Soo, did Autheur suggestion fix it?
I'm not sure if that's specifically the issue which is why I'm being vague. It also might be controllers.
they can just exist in the BP and have their widget swapped out whenever
Yes.
@dark edge something to do with local multiplayer.
I don't see any reason why any of this has to rely on controllers at all
Yeah. 5.6 does not seem to have properly accounted for the concept of a local multiplayer game that doesn't use split-screen.
It doesn't, but the things I was using as a target when creating the Widget Components had controllers, and that appears to have been causing the components to be collapsed.
But basically some widget r hidden for split screen. Im guesing when not owned by the player.
Have to tick some bool in the project setting.
Force something widget for split screen.
That does NOT exist in 5.6. That's the most condemning thing.
So how do you fix it? Upgrade the engine?
why are you creating them at runtime anyway, just plop one in your pawn bp
then you can dynamically shove widgets in them
Well yes, but since I can't do that right now, the workaround is spawn the components targeted on something random, and then attach them to sockets of the player meshes.
If that's the problem then yeah it's totally different
Since you r not doing split screen anyway, i find giving widget controller kinda redundant.
Just shove all widget for player 0
We only need them in this level, and this is a minigame collection. If our solution to everything was to attach new components to the player blueprint whenever one minigame needs it, the character would rapidly gain bloat. But yes, I am aware that in most cases this is the correct solution.
I wasn't! I was for a while but I stopped after my initial conversation with you when I saw that your functional version didn't do that.
So if u dont plug controller on creating widget it work?
If you don't plug something that has a controller. The targets on these component creation nodes are the players, which are pawns that have corresponding controllers. I don't know exactly if it's them being pawns, or having controllers, or something else entirely, but what I DO know is that if those connections are replaced with a random actor in the scene that doesn't have anything to do with multiplayer, it works. Right now they're targeted to the dang skybox and it works just fine.
Ignore the fact that this is an abomination. I'm very aware of how terrible this approach is, I was only doing it as a sanity check.
My man just use Get instead looping with break.
Does that get a direct reference instead of a copy?
copy of what
Its a copy of the address so its the same thing.
a pointer?
The only reason I'm doing this blasphemy is because I couldn't figure out a better way to get a direct reference out of an array.
if it's pointers it doesnt matter
get by copy of something out of Players (should be pawns) is the ADDRESS of a pawn, not hte pawn itself. It won't make a new pawn
You are getting a copy of the memory address, which is just an intger.
The underlying value it points to is the same.
Really? The node description specifically says that changes made to it will not propagate back to the original.
you need to understand the difference between a pointer and an object
If it would've worked this whole time, I made this whole disaster for nothing.
I understand it in C++.
I wasted so much time.
BP calls them references but they can be null so pointers are more accurate
I'm on my 5th rewrite of a system for my game, started 10 years ago. It happens.
If the dark blue means a pointer, the Get (A Copy) node does the exact same thing in terms of return value as the For Each loop, which does NOT give you the warning.
Greetings Multiplayer Posse
Question : the OnlineSubsystemEOS plugin has a README with dire warnings that it is an experimental plugin ( though the plugin doesn't have the experimental tag in the editor Plugins view ).
What is the general consensus : fine to use for prototype at least I presume, but is it ok to build on in the long run? What is the 'correct' path for production?
Not done much session related work since 2020, so I'm a bit rusty and can't get it to work.
How I host the game:
public void HostGame(APlayerController hostingPlayer, IDictionary<string, string> arguments, FPrimaryAssetId map)
{
UCommonSessionSubsystem sessionSubsystem = GetGameInstanceSubsystem<UCommonSessionSubsystem>();
ActiveHostRequest = sessionSubsystem.CreateOnlineHostSessionRequest();
ActiveHostRequest.MapID = map;
ActiveHostRequest.ModeNameForAdvertisement = "BazaarMayhem";
ActiveHostRequest.UseLobbies = true;
ActiveHostRequest.OnlineMode = ECommonSessionOnlineMode.Online;
ActiveHostRequest.MaxPlayerCount = 4;
ActiveHostRequest.ExtraArgs = arguments;
sessionSubsystem.HostSession(hostingPlayer, ActiveHostRequest);
}
How I look for sessions:
[UClass]
public partial class UEmberSearchSessionRequest : UCommonSession_SearchSessionRequest
{
public string LobbyId { get; private set; } = null!;
public void InitializeFrom(string lobbyId)
{
APlayerController playerController = GetTypedOuter<APlayerController>();
LobbyId = lobbyId;
OnlineMode = ECommonSessionOnlineMode.Online;
UseLobbies = true;
OnSearchFinished += OnSessionSearchFinished;
UCommonSessionSubsystem sessionSubsystem = GetGameInstanceSubsystem<UCommonSessionSubsystem>();
sessionSubsystem.FindSessions(playerController, this);
}
[UFunction]
private void OnSessionSearchFinished(bool succeeded, FText errorMessage)
{
APlayerController owningPlayerController = GetTypedOuter<APlayerController>();
UCommonSessionSubsystem commonSessionSubsystem = GetGameInstanceSubsystem<UCommonSessionSubsystem>();
foreach (UCommonSession_SearchResult searchResult in Results)
{
// Always empty
}
}
}
Config:
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
[/Script/CommonUser.CommonSessionSubsystem]
bUseBeacons=false```
The session sets up right, I can join it with `open 127.0.01` in PIE, but it fails to find sessions when doing standalone. Anyone see anything that I've missed? 😄
Hi! I have a WidgetBP that autogenerates Childs and saves the references from it to an Array.
I need to init a change to a specific Child from the Server-Side.
The Server also has an Index that equals the ChildWidget index.
How can I do this? I dont get it to work.
Blueprint Runtime Error: "Accessed None trying to read (real) property UI_Cells in BP_GridManager_C". Node: Call UI Cell Has Changed Graph: Grid_WriteCell Function: Grid Write Cell Blueprint: BP_GridManager
Blueprint Runtime Error: "Accessed None". Node: Call UI Cell Has Changed Graph: Grid_WriteCell Function: Grid Write Cell Blueprint: BP_GridManager
I do have the Widget Blueprints added as reference object into my variables. But it says "Unknown" in the Debugger
Widgets do not exist on servers unless its a playing listen server, in such cases you need to do workarounds such as replicating structures with data per widget instance etc.
Widgets don't network
don't do networking within a widget
What are you actually trying to do here, what's the actual gameplay purpose?
Well I try to Display a Grid in 2D and want just say something line tetris. But I Need a way to Reflect changes of every cell in my Grid to the ui
I just started with unreal 4 days ago so im still a big noob
(The Server side Logic works) and gets written to a struct Array that reflects each cell
you can make an array with structures to represent rows/collumns, then have all clients update their widgets based on that replicated variable
Might be complicated if you are just starting out though, replicating widgets is harder than normal in game replication such as actors, components etc.
I do have the struct replicated and the Grid Displays. ( I Test as Client in the dropdown)
So I got everything working beside updating the Ui
are you replicating in the widget? widgets dont replicate, you can use a component that replicates inside the game state maybe
I have the bp gridmanager that holds the struct and does a repnotify.
The Widget just has an ref var to the Grid Manager
Then the error must be somewhere else. Make sure you have a valid reference to the actor and that the grid manager bp also replicates. If its a grid manager with no components at all in it, make sure to also check "Always Relevant"
Im back at the PC now and open the Project, then i can give more detail
It was on replicate but not always relevant
I already started reworking it based on this image i found.
So Right now i do in the OnRep function: Get All Actors of Class -> ForEach -> Call Event in BP_PlayerController.
I hope that is even the right thing to do
OMG I got it working
(atleast a print string from the widget blueprint)
i have no idea if this even makes sense but to get it working after i did the call from my BP_GridManager to the BP_PlayerController i did this
that should just be a repnotify probably
OnRep_MyCell
But where?
the cell you're in is state, prefer to use repnotify for responses to state
What's the context here, you want the widget to update when?
in my BP_Gridmanager i have a random int so i use it as an index to change a bool isBlocked in my "Struct Array" to true.
This struct already is RepNotify.
BP_GridManager is Spawned per player. So i test in Client Mode to get it right
What's the actual thing you're trying to do here? This is a grid of what, and CurrentCell represents what?
It's this ugly grid thats defined in gridmanager and gets build as a widget.
I try to do some chaos tetris, block stuff - i dont know for sure what its gonna be.
I'm just learning tbh
The Struct hast infos like CellType (Block, Bomb, Empty)
And i want to change celltype right now from empty to block. And then i want to change the color of the cell
From my OnRep for the struct i go to the BP_PlayerController you saw what happend there on the other pic.
You can also make a dispatcher on the OnRep call and have your controllers bind to it
Above implementation is wrong since each PC should call it locally when the rep happens
How would I do that?
I would suggest looking up how dispatchers/delegates work, will be very handy once you understand it
Oh would I just bind the Event dispatch from my UI BP Directly in the onrep of my bp Grid Manager
the on rep would call a dispatcher which your UI would be binded to, yes
I think I tried that First but had all the unknown class errors
looping over controller in the OnRep make no sense.
server have everyone controller but clients only know their own controller.
If an actor isn't marked as replicated, but is placed in a map by default.
You can still at least replicate its reference around, cuz its a stable/ static name or whatever.
But, you can't do RPC's through it right?
any idea why this crash happens?
that's not even close to enough context to have any way of guessing what happened here and I don't even know which verison you are on
we can only see what you show us
on 5.4, I don't have any more context also
its just crashed
if it's a client callstack with no dump that's fair I guess but it would help to include that in the first post
we can only see what you show us
seems like onrep is called twice somewhere but I have double checked and its not called twice
like RegisterNetGUID_Server calls twice in the call stack
is it this check? Failed to validate ObjectLookup map in UPackageMap. Object '%s' was not in the NetGUIDLookup map with with value '%s
anything related in the logs?
Yeah exactly but how to find which object it is complaining for
will crash it again now, I think in logs there was no usefull information, but I will try t crash it again cause its not crashing all the time that's why I'm very worried
if you can crash it on command just attach a debugger (I recently found out about using -basedir to use cooked content from the ide easily, very useful)
no need to guess
could try turning on LogNetPackageMap for more info
*as well here is -BaseFromWorkingDir which is the same as -basedir, just takes the IDE's Working path *
I think I found that onrep is called twice
but if this is the case, why its not crashing always?
this with a typo fixed
Hey there, I have a component on my PlayerState that needs to execute some logic in InitializeComponent but only for the copy of the local player. The logic is a form of replication guard so that import stuff triggers only after all the import stuff has replicated.
Is there a way to properly detect that the code is currently executed on the local player's copy of the component, in the case I start playing in PIE with 2 players?
I was trying to go the ROLE_SimulatedProxy / ROLE_AutonmousProxy route but because the component is part of the PS, it is always ROLE_SimulatedProxy. I also cant compare playerstate's by accessing GetWorld()->GetFirstPlayerController()->PlayerState == ComponentOwner as the PCs playerstate might not be replicated yet (cant really wait for OnRep_PlayerState I think?).
@swift bay Player state have method to get the controller that created the player state.
to get the player state that is owned by the local player, simply.
That controller isn't replicated yet unfortunately
Controller is the one that makes the player state it should be valid.
However it would be invalid on non local player state because Clients only have a copy of their own controller.
if you are in CPP, there's another method
GetOwningPlayerController
if (GetOwningPlayerController())
{
if (GetOwningPlayerController()->IsLocallyControlled)
{
do stuff
}
}
absolutely no need for LocalOwnerRole check or NetMode. Get rid of those.
Ye these are currently there to prevent unnecessary break points (and the dedicated server I guess).
I'll check the GetOwningPC, maybe that works. Just stepped through all 4 calls of PS->GetPlayerController() but none returned the PC. Should I use a different method to do my logic than ::InitializeComponent() ?
Don't you want the init code to run, regardless if it's listen server or dedicated server?
I would get rid of those NetModde and LocalRole checks.
You can filter with HasAuthority
When is the code run? Why InitializeComponent?
Try begin play of the player state for sanity check.
I'll try BeginPlay then and get back to you
this could be because of this I think
LogAIPerception: Warning: UAIPerceptionComponent::OnRegister: Perception Component is being registered with BP_Bot_C_0, they are designed to work with AAIControllers!
LogScript: Warning: Script Msg: A null object was passed as a world context object to UEngine::GetWorldFromContextObject().
LogScript: Warning: Script Msg called by: DemoMap_C /Game/DemoMap/UEDPIE_0_DemoMap.DemoMap:PersistentLevel.DemoMap_C_0
well I can't reproduce the crash again, if it crash next time will see
I upgraded to 5.6 and im having some issue with crouching. When simulating network latency (100) the issue I have is that if I crouch & uncrouch fast, there's a little correction at the end of the uncrouching which looks very unnatural. If I play with 0 latency it never happens. I assume it's because the server capsule still didn't "update" so locally you get corrected. Any idea how to fix this? I was thinking of uncrouching only started once server gets there (like the net sync node you have in the gameplay abilities) but there's no such node outside of gameplay abilities.
Why are you doing it on triggered?
use started
Triggered runs every frame.
Btw there shouldn't be correction with 100 ms or 500 ms.
Crouching is already handled in the cmc.
you can use pressed/release triggers in the IA
there can be gotchas with "Started" but that only really matters for things like delays, actuation amounts, and key chords
Yea I'm using Pressed/Released triggers
Then I have no clue why it only happens on latency
then if you are, I would only use triggered and use action value to determine
but is probably not the issue, and I can't say I've seen it happen that often with the default CMC
well you probably should only use triggered
I can show a quick snippet of what its doing
because you'll get triggered and completed at the same time on release
don't depend on capsule for crouching, this is a bad practice to start with, only do it if your character recieving damage hits using capsule
since there is a release trigger
better do it using character body physics whilch will be smooth
that's safe to ignore
I have a custom character class which has no capsule at all, instead I am using a sphere root as a root for the class
Watch Crouching issue by Steeljardas and millions of other Screen Recording videos on Medal. #screenrecording
mute it since music in background lol
yeah did you make the change yet?
I depend on it due to things like not being allowed to uncrouch in certain areas, etc
triggered -> branch on action value -> true exec on Crouch, false exec on UnCrouch
don't rely on inbuilt things, they are done very badly
which areas are you talking about?
When I put print in it's only triggering once for both started & completed
If there's a ceiling above the character for example, you can't uncrouch
you can just give a tag to any area and when you crouch, check if you are not in this area that's all
your example didn't use "started" though, it uses "triggered"
you can do it with character physics also, no need to depend on capsule
this is typical missty anti-advice
plenty of multiplayer games uses the capsule for movement
it's not necessary at all
Sorry I meant to say:
- I changed to Started / Completed and it still happens, when I print it still only shows a single print in the action value (True for when I press and False when I release). If it was getting double triggered it would print mulitple times instead of only once per action no?
I also tested triggered/completed and you were right, it's triggering twice when I release, so i switched to started but still same issue
CMC works with the capsule component.
I'm not sure why you didn't do it this way if you are using those IA triggers
but sure, it won't really change the outcome
use CCMC 😄
what's that?
I can do it that way, it's the exact same as started/completed essentially no? Don't think it changes anything in that regard
But I think the issue will be the same
Custom
Why did you mention gameplay ability system? Is the input event not the only place where you crouch and uncrouch?
yeah, though using the action value was pretty handy when you simulatenously want to support hold and toggle crouch
Yes, I mentioned it because I thought it was server correcting the local player so I thought about using the net sync node that you ahve in GA's to make client prediction wait for server but yea you guys are saying it's not server correction so im not too sure what could be causing it
And yea I don't use it in abilities
they are not relevant.
Client movement prediction data is stored in FSavedMove
crouch is already in it by default.
that does make sense
also if you are feeling the animation is not smooth, it can be because you upgraded to another engine version, try reimporting the crouch animation
unless you're doing a true first person system, I'm not sure why you'd have crouch transitions driven by animation
I don't think it's animation issue, if I crouch slowly (as in hold it crouch and onyl uncrouch after a little bit) it works flawlessly
it only has issues when uncrouching quickly after crouching
and it does look more like the transition than any sort of server correction
put a cool down, you can't uncrouch if courch is not yet finished
Hi guys!
I'm taking a multiplayer C++ course on Udemy. There is something that drives me crazy, and I don't know whether this is how the industry does it or whether something is off. The tutor is using A LOT of guard initializations (I don't know what to call them) with ternary operators, e.g.:
MyHUD = MyHUD == nullptr ? Cast<AMyHUD>(GetHUD()) : MyHUD;
I understand that this can help when developing multiplayer games, since initialization can vary a lot between server and client, but this syntax seems really misleading because we have no clear information about whether the pointer is going to be initialized. As a result, later, when we check the pointer, if something doesn't get called, we may not even know why. Personally, I'm trying to find the correct places to initialize these pointers, and it seems to be a much better and more “professional (?)” approach.
What is your take on this? Maybe someone from the industry can explain how it looks in practice.
did you implement anything specific for the view transition?
HUD initialisation is predictable anyway since the client spawns it
frankly, I find that a bit ugly
could be but why is the transition slower with latency than with no latency how is it relevant
It really depends on the intention. Not really a yes or no question.
it should take just as long except starts 100 ms later
yea that's one of the solutions I've thought about but feel like it'll feel kinda bad to uncrouch and then it only becomes responsive after "xx-xxx" ms
Exactly my thoughts. I usually find a way to initialize those pointers in some init functions with NetMode if checks.
correct way is to put an anim notify in the end of the crouch animation to set iscrouch to true, and when you press uncrouch check if iscrouch is actually true
this way you will make sure to correctly uncrouch and will not spam the server also since if the bool fails locally don't request the server to uncrouch
HUD's also a bad example, very seldomly would gameplay code need to be aware of it since HUD elements should be event driven anyway
well is this relying on something default in the CMC or did you do something to implement the camera height between crouching and standing?
.< I wanted to avoid change from the default crouch / uncrouch as much as possible but yea if I can't fix these issues I guess i'll have to do something like that
It's using the default cmc stuff
@frosty harbor Can you describe these "correction"? Are you just having animation glitch and assumed it's correction or the client actually get Corrected?
You know how to debug movement correction?
All I ever did was add the animbp to play the animation when crouching
You don't even need the animation to see the crouch in action. Just visualize the capsule component.
@frosty harbor p.NetShowCorrection
https://medal.tv/games/screen-capture/clips/lYhnVCnxuaGeV8MvE
Basically when I crouch -> Uncrouch quickly / instantly, there's a "up" then "down" "correction" at the end. but ONLY when I have latency. If latency is 0 this DOES NOT happen.
If I Crouch -> Wait 1-2 seconds -> Uncrouch no issues arise.
Watch Crouching issue by Steeljardas and millions of other Screen Recording videos on Medal. #screenrecording
if you don't get any red debug sphere then you are not corrected.
And I do not know how to debug but i'll give it a look
I don't even think this is network related.
All crouch does is just changing the capsule component height INSTANTLY.
if you want smooth camera transition, you do have to implement that your self.
from what I see, this isn't even network related.
you might want to check what drives your camera.
back in 5.5.4 what I did was add the camera to a springarm and it made the transition smooth but that got messed up when I upgraded to 5.6
I also had tried all those timeline methods for smooth transitions but there were always some issues
He is also doing it for example in PlayerState in OnRep_Score function but with Character pointer.
void AMyPlayerState::OnRep_Score()
{
Super::OnRep_Score();
Character = Character == nullptr ? Cast<AMyCharacter>(GetPawn()) : Character;
if (Character && Character->Controller)
{
Controller = Controller == nullptr ? Cast<AMyPlayerController>(Character->Controller) : Controller;
if (Controller)
{
Controller->SetHUDScore(Score);
}
}
}
It seems ugly for me too so my take is to Initialize Character and PlayerController pointers in PlayerState with OnPawnSet delegate once
from the video I feel like this is collisions blocking each other
set the capsule to ignore camera collision
Code smell to me.
why is character being initialized every time a score is replicated....
I have nothing againts trenary operator, I used them all the time. But why are controller and character is set when a score is replicated is beyond me.
Yea I have it on ignore
where do you use this RelativeLocationZ? Or where is the code that drive the camera?
I also really like ternary operators, but this guard initializations is too much for me. I wanted to get some opinion
yeah I consider this a bit of an anti-pattern. the HUD element displaying the score should just register a delegate for when the score changes and use that to update
in this case I would just a create a new character with only character mesh and try to reproduce the bug
it can differ slightly if you want to use MVVM, but this isn't something that would be directly on the player state either
Ok, that's what I thought. It's just my first touch with multiplayer and I thought that maybe that's how we do it in multi
doesn't matter multiplayer or single player.
You want to keep dependency one way or minimum.
Great. Thanks. So it's not me that is insane in this case 😅
You can ignore the variables, those are just old variables I forgot to delete when I was testing stuff way back then related to camera
Crouching alone shouldn't move your camera
all it does is changing the capsule half height
well if the camera is a child of the capsule then it should change in height (maybe) but it would be instant.
The camera is a child of the mesh, which is a child of the capsule
It's bound to the head bone
I see
damn so the animation part was right
I guess the issue is something along the lines of the player already asking to uncrouch before crouching animation even begins on server
generally attaching the camera to 3p animation is how you make people motion sick
im doing true first person with spine bending and stuff so needs ot be attached to head bone
still stands though, it's subjective but I've always found true first person games to have a layer of jank to them
hmmm
I guess the only way to do it really is to add a cooldown before the uncrouch can happen
you gotta make sure the transition is smooth to what ever method you decide to do.
actually nvm cooldown wont fix it since its latency issue
like if it's tied to the head bone, then you want to make sure the animation doesn't go from going down then snap back up when doing the uncrouch animation.
I don't think it's latency issue.
if you play as listen server u have no issue?
It doens't happen at 0 latency at all, only when I have latency so has to be latency issue
try to disable correction at all and test again to find if this is latency issue
I think it's along the lines of player asks to crouch / uncrouch at nearly same time before server even started crouching
hence the latency
I disabled corrections in CMC but nothing changed, unless there's another way to disable corrections for everything
its a bug in your code this is confirmed cause we don't have this issue, I just tested with 5.4 and in 5.6 this works the same way
I don't really touch anything related to crouch other than the input action as I showed above and in the animbp for the animation
by the way why did you updated to 5.6? consider never ever updating unless you need a new cool feature from the new engine in your project
thats all I do for crouching in ANIMBP too
Needed it because of metahuman , they no longer support anything below 5.6 + Fab assets have a lot more compatibility with metahuman than other skeletons
in terms of armors and stuff
hmm legit reason
in your anim bp when you set iscrouching to true/false , your character crouch/uncrouch smoothly ?
yea it does
I just noticed my camera smoothly adjust to the character crouch position.
stole the code from lyra Camera Mode.
try with a new character class, attach camera to head head socket and just do crouch/uncrouch
if this is smooth, you have problem in your previos character class
so it is confirmed they have issue with camera adjustments?
With SteelHard/ I have no idea.
as for Crouch, all it does it just changing the capsule height.
it doesn't do anything to the camera out of the box.
maybe they are adjusting camera manually, we don't know yet 😄
are you doing camera adjustments when character crouch?
well seems like he is using the head bone.
Crouching just changes the capsule height, nothing else.
i can spam it, and it's still fine.
The adjustment is based on the animation itself since its following the head bone
Since this only happens under latency and never when I have 0 latency I think it's just some issue between triggering uncrouching too fast after triggering crouch, locally we're already uncrouched but on server the animation for crouching just began due to latency so it kinda bugs out is my guess
if you add smoothing on the crouch / uncrouch transition, do you still get "corrected"?
Dunno, depends on how you do it. I remember people doing these timeline based transitions but those touched the capsule which I wanted to avoid doing.
Yea if I add a delay of 0.5+ it works just fine
before the uncrouching happens
if i do 0.5 it literally does not work
has to be specifically 0.501 minimum lol
it does feel kinda meh not uncrouching right away tho
Could it be because on server the capsule still hasn't updated / crouched yet due to latency & same for crouching? Dunno its just weird
especially now that it literally requires me to wait a very specific 0.5s before uncrouching for it to not happen
Client will always be ahead.
It simulate move on it's own machine (Crouching, proning, w/e).
At the same time sending the move data to server.
Server replay the Move Data see if it's valid, if not valid correct the client.
Meanwhile client went ahead with it's move every tick. The only time it get snapped is when the client receive correction.
I'm looking into Lyra way of doing crouching but I can't seem to find which animbp they're setting up the animations in for crouching
Not fully answering the question because I'm not at a PC to go look, but basically Lyra's animation setup is that there's one main Anim BP, which then dynamically references child Blueprints using the Anim BP interfaces feature.
Those child Blueprints handle all the anims that change when you equip a different weapon..
There's a base class for those child BP's that has some logic in it .. I think it's probably in there, since there are different crouch anims depending on the weapon you're holding
that sounds quite convoluted
found it but yea since camera is not attached to the head bone its a different thing
.<
Is it possible for a property to replicate before the owning actor is finished constructing ?
I would think no, without looking deeply into it
"finished constructing" as in running OnConstruction?
Not sure what i've been drinking but for a moment thought the InputComponent was setup in the native constructor
Doesnt make sense
Having an issue with ASC and a possible race condition
subobjects should at least require their parent object (in the REPLICATION sense) to be present beforehand
Its called both in SetupPlayerInputComponentand ÒnRep_PlayerState, yet sooometimes it fails still
There's no gaurantee a replicated object will be there for either of those imo
properties are completely capable of being skipped in either case in the bunch afaik
You are generally going to want to account for the fact the playerstate might not be there yet pretty much everywhere
ended up having 3 different paths checking that everything else was ready, so any order of replication would work
Generally speaking if you can't think of a nicer way the most simple "dumb" fix is to just set a timer for next tick every time it's missing (or a very short delay) to consider the "initialization" steps required to trigger your "start the game" flows
but this is only appropriate really if
- you KNOW the object will show eventually or you know to cancel retrying if you need to give up
- you actaully re-try instead of just delaying once and praying
It's a bit of a headache for obvious reasons so it might be convenient to have 1 place that kind of acts as the arbiter of "init state"
for Lyra's init states for example are just a tagged if statements
that let you define different "steps" of readiness depending on who cares about what
hmmmm
i'm not a fan of any timer solutions, but man sometimes the way around them are painful
perhaps i should just join the dark side
Appreciate your help and time , as always, Mega!
I found that latency heavily affects how long the delay has to be before the uncrouching, how the hell is latency even affecting the animation or whatever is going on this makes no sense
If I use 0 latency, nothing happens, if I use 20 latency I can get away with this only happening if I instnatly release the crouch button, even holding it for 0.1s is enough for this to not happen, but if I use 100 latency I need 0.5s delay for the issue to not happen
For those not aware of what Im talking about, I'm having an issue where after uncrouching the camera moves up then down when I release it too fast, however, it only happens when there's latency and the higher the latency the longer I must hold "crouch" for for this issue to not happen.
A video showcasing the issue:
https://medal.tv/games/screen-capture/clips/lYhnVCnxuaGeV8MvE
Watch Crouching issue by Steeljardas and millions of other Screen Recording videos on Medal. #screenrecording
It's not recommended to use delay nodes with CMC, the input predicting nature doesn't handle delays in its simulation
The crouch state is getting reconciled there
Crouch in bp flips the bwantstocrouch boolean, from bp the result gets handled next frame
Those factors with latency will have weird results since CMC has its own update frequency
it was the only way I found to avoid the snapping at the end of the uncrouching when doing it quickly
this way it doesn't uncrouch right away
but yes this is a terrible solution
It doesn't even work as intended because 0.5s is for 100 latency, anyone above 100 latency will still have this issue
I want to find the root cause so I can try to fix it but I just cant find what could be causing the issue
For context, the video was recorded WITHOUT this delay system by the way, it was just simple crouch / uncrouch
@hoary spear is your ASC lives in player state?
When the pawn is possesed, client would have valid controller and player state.
From memory I think I handle input binding and init ability actor info via OnAcknowledgePosession for client and doesnt seems to ever fail.
So I kinda confirmed that the issue is because it's doing the animation locally then does it again on the server
seems like this happens because hte crouch then uncrouching are BOTH happening before the crouch on server even begins
unreal specifically mentions this issue you can get if you rely on GAS to send your movement abilities and CMC to send moves separately. Does anyone know their recommended fix? is it to send the movement abilities through the CMC pipeline and manually replicate them server side?
Yes it does actually !
Hmmmm, I called InitAbilityActorInfo on OnRep_PlayerState. What is the race conidition on your part?
Well it seems ASC isnt always ready when the playerstate replicates
So my hotfix was a asc onrep function 😅
To init ASC, we call InitAbilityActor info right? that's what set the owner and other important bits.
Hmmm 🤔
Cant recall calling that one
Just woke up with the kids, so cant walk throigh teh code atm...
Apparently 2 year olds dont like coding, inherently 😅
Ill look into it once i got the chance tho!
Yes - that's the function you call
they will soon like roblox 🥹 .
ASC->InitAbilityActor is what essentially sets the Owner of the ASC (In your case the player state) and the Avatar Actor (The pawn you are controlling).
But... i cant call that if ASC is not replicated yet ?^^'
Nvm, its ptobably locally avaliable , being a subcomp and all
Just me not referencing it correctly at before the BindAScInput gets called
In my case it's called during InitPlayer, which in turn is called from OnRep_PlayerState
but this seems insufficient
It is also called during PossessedBy, for the server side 🤔
For server it's called in PossesedBy
For client it's called in OnRep_PlayerState.
🤔
what sort of race condition do you run into?
Seems the InputComponent isn't ready
this could be a unique in-editor playtest bug tho
almost as if OnRep_Playerstate is called before client is done possessing
void AAGPlayerCharacter::OnRep_PlayerState()
{ // ** Called On Clients ** //
Super::OnRep_PlayerState();
// ** Init Ability Actor Info for the client ** //
InitAbilityActorInfo();
// Bind gameplay tag event in Interaction component.
if (IsLocallyControlled())
{
// Tell server to add startup abilities and abilities from data assets if locally controlled
Server_AddCharacterStartupAbilities();
Server_AddDefaultAbilitiesFromDataAssets();
// Bind gameplay tag event in interaction component. (Client).
InteractionComponent->BindGameplayTagEvent(GetAbilitySystemComponent());
}
//** Add Input mapping context **//
SetupDefaultInputMappingContext();
}
The idea of calling Init actor would also be that the Avatar Actor is readily available.
Is the OnRep_PlayerState the ones in the character? I don't think I have issue binding input in the OnRep_PlayerState.
how can Input component not be valid 0o?
is the input component the Input subsystem, or something else?
Im confused too, but i guess the input component is created on client possession, which apparently can be after playerstate has replicated ?
But that doesnt make all that mich sense to me either
This is the fun part about replication order etc i guess 😅
so I'm new to GAS, and want to program this ability where if the input is pressed down, we charge a variable, and if the input is released, we uncharge that same variable. basically something where if you hold the key it'll go up but then if you don't hold it'll go back to zero.
does this look like the correct implementation, given that I'm too lazy to code a "wait for input" solution?
It feels like I'm maybe missing a better way to do it but idk
also for my inventory system which is currently client side, do ya'll think it's worth it to overhaul it to be server side before release
for context it is co-op and probably not gonna be huge so I'm not sure cheating will really a crazy concern, but still idk feels better to not use rpcs a lot just to share items between other players
If its already working, id consider just postponing it untill it becomes a problem
wonder if it's already tested with multiple clients.
If an item is dropped to the floor, like who gets it if multiple clients simultaneously grab the item? It would be like jesus performing the bread and fish miracle.
My inventory comp are server auth, but design is the biggest motivation, not cheating.
hehe yeah im not sure how they'd solve it
perhaps they circumvent it completely, idk
If anyone can please have a look at a thread I opened, still havent been able to find a way to fix the issue >.< https://www.reddit.com/r/UnrealEngine5/comments/1ql9oyr/crouching_uncrouching_issue_in_multiplayer_with/
you cant do much about that, especially in BP only
welcome to networking issues
There should be a big warning when engine is launched for the first time saying that if you want multiplayer + custom movement you should learn how to do it in CPP 😛
not an issue, I can do it in c++
I just have no clue what the fix would be
mh, maybe write a "small" discord message explaining your issue so people here doesnt have to scroll on your big reddit post
Well the issue is basically:
Due to latency, when a player crouches / uncrouches really fast, both of them happen on the client before the server even begins the initial crouching which ends up in causing a visual issue where the camera moves up & down after the uncrouching is finished already locally. However, if I have 0 latency I can spam crouch/uncrouch and it never happens.
If I crouch + hold crouch for a little bit then uncrouch it's also fine (because the server crouch already begun as well before the client uncrouch finished).
For a visual representation of the issue you can check this short clip, easier to understand:
https://medal.tv/games/screen-capture/clips/lYhnVCnxuaGeV8MvE
My camera is bound to the player head bone since I'm doing a true FPS with spine bending.
5 Views - Watch Crouching issue by Steeljardas and millions of other Screen Recording videos on Medal. #screenrecording
couldn’t you use the waitforinput task that exists in GAS already?
Yeah I’m just lazy, it takes time to set that up
Is anyone familiar with the issue I'm talking about here?
It essentially boils down to the 2 different network pipelines for GAS vs CMC
you have corrections using cmc?
I plan to, unless you think I should disable them
if you will have corrections it means you have not implemented the movement correctly
well you can still get corrections even with perfect movement code due to dropped packets or ordering issues no?
and you don't need to disable it
you can't solve dropping packets issue, its not related to your code its a natural issue
but you do some client side predictions to make those corrections smooth
Sounds kinda like a delayed server correction?
right, i get that, but the issue i'm talking about here is that GAS uses a gas rpc to sync client ability activation with server ability actviation, whereas the CMC has its own servermove rpc. if you use them both separately, then you get jitter due to ordering issues like unreal points out, so I'm wondering what the recommend fix is. For example, not using the gas rpc and communicating solely through the severmove rpc.
why you want to use them both on the first place? trying to sit in two boats at the same time?
why do i want to use both as in why do i want to use both CMC and GAS?
both rpcs, you can do some refactoring to rely only on one rpc
yeah that's what i was thinking of doing, I was just kinda looking for some confirmation.
yeah you don't need both rpcs to use for same reason, choose one that fits best for you
okay thank you
Could be but not sure how I could ever fix this
just the camera, there's no changes visually when I watch from 2nd client
Seems i get the same thing with my raw implementation of "sprint"
it's very glitchy with the server corrections
yea I have no clue how to fix something like this ngl. I thought about making some sort of queue where even if the user asks to uncrouch it will only process once server crouching sends a flag
but I'm not sure how to do that since you generally run these things from the owning client since its an input
depends if it reallly matters that much
1000ms isnt really realistic support in my eyes
no no
that was an exaggerated test
even with 10ms it happens
the higher the latency the longer i must hold crouch for it to not happen essentially
so less latency = less likely to happen unless i instantly release CTRL
Guess you could block release untill server confirms
also depends on the game and the criticality of the implementation ofc
I thought about blocking it yea but im not too sure how to have the server crouch add a flag whenever it begins
since its a locally predicted mechanic handled by the cmc
I tried turning crouching and uncrouching into gameplay abilities and crouching would add a loose gameplay tag ot actor when it had authority (thus server) and uncrouch would only work when actor had that tag
but the issue was that it wasn't working because the tag was only added on server so i guess the client wasn't picking it up
not too sure what the issue was anymore since i tested it a while ago
A mockup would just be a bool dictating the server state
and you'd only be allowed to change crouch state if the server state matches your 'predicted' state
I use GAS in my project, but saw Mover and NPP recently and wanted to know if implementing them together is possible? From what i understand so far is that GAS and NPP have different prediction systems and there isnt really a bridge between them. I wonder if for my project this would be a problem since i use GAS mainly for the attribute system anyway and use only a few abilities like equipping items etc. No need for fancy root motion stuff since its a 2d game.
If someone with experience using the plugins could help me it would be nice, its my first multiplayer game and i am still learning and i wanna try the new plugins and see what they are capable of.
just use your custom crouch logic, have an enum which have states, stand, crouch, prone and update this using server and replicate the change using onrep
than inside onrep notify animation class to crouch anim, set capsule height to half and optionally play a sound
on uncouch do reverse of it
you don't need to use built in crouch if its not working correctly
its just a huge pain in the ass having to do a custom crouch because of all the height checks on terrain and stuff since our game will use that kinda stuff
its not that hard, when you want to uncrouch, first do a line trace upward, if hits anything with a blocking tag just return else uncrouch
like you can give a tag to any lhing which can block crouch/uncrouch