#multiplayer

1 messages · Page 292 of 1

charred island
#

FVector impulse = delta_t * velocity + transform.GetLocation() - owner->GetTransform().GetLocation();

    comp->SetPhysicsLinearVelocity(velocity);
    comp->AddImpulse(impulse, NAME_None, true);
#

where velocity comes from the authoritative sim

#

(along with transform)

#

but this is incomplete, due to how my setup works. the general approach will probably still be the same, but i dont have a consistent coordinate system between clients because i bake parts of their motion into kepler equations.

#

because of that it currently only works when they're in the same "orbit" bubble

meager spade
#

wouldnt mover solve this

thin stratus
#

Mover is just the movement simulation. The backend is the more important part

cinder quartz
#

I'm using a Timeline to handle aim down sights logic for a project, which involves variable speeds for aiming- Issue is, when running the Timeline Playrate update function on server, it doesn't seem to get broadcasted back to client so the duration is flattened to 1.0 seconds and thus does nothing

#

Apparently making it reliable fixed it??

meager spade
#

i wouldn't use timeline to be hones

#

also server really shouldnt be running it? why does server need to run the aim down sights timeline?

#

does server really have to zoom in?

cinder quartz
#

Well the aim down sights does move the physical transform point from where the bullets come out of

#

I am noticing a few issues with it since it's tied to a boolean input so if you have a better alternative I'm happy to hear

nova wasp
#

if they both do the roughly the same thing on both sides from starting or stopping aiming the actually useful inforamtion is when it began

cinder quartz
#

Ahhh I see what you're putting down...

nova wasp
#

also for a co-op game etc it might not even matter much aside from sim proxies (I add this caveat every time but this advice is still relevant for sim proxies at least partially)

cinder quartz
nova wasp
#

then don't do it on the server that way

#

the client can just report they started aiming and shooting as a series of "commands" and the server can more or less accept them as long as they seem okay or even play them back

#

client prediction for shooting is more or less the standard for every fps game out there

#

how the server does things on their side or simulated proxies is a secondary problem... shooting should at least be partially predicted in almost every fps game

Even if it's they can predict shooting and aiming but not the final damage etc

cinder quartz
#

Right... For one I think it's fair to predice some stuff like, if the server knows the player was aiming when they sent a shot, then it should spawn it from the aiming location and whatnot

#

Also tested my implementation of replicted camera pitch under high ping, and even with packet losses at 10% it's decently reliable

#

Only issue is moving the camera too much seems to cause issues and stuttering at high intensity scenarios

#

@nova wasp Sadly I think I will need a more detailed explanation here. Not exactly in a great spot...

nova wasp
#

why introduce randonmness from the server and replication rtt here

nova wasp
#

that is a tremendous amount of information to send instead of just

  • which weapon is equipped
  • where you are aiming
  • if it is aiming or not
#

if that's just for simulated proxies, sure

#

remember: our goal is to worry about information

#

the actual "instructions" to get a similar result

#

replicating random arbitrary things is good if you can't easily describe their states with other more simple things

#

but for something this simple it does not make sense to me

#

unless they can really like, move the gun around in 1000 different positions that can't be described in a simple way

cinder quartz
nova wasp
#

depends on what "the data" is

cinder quartz
#
void ADulceWeaponActor::ShootProjectile()
{
    // Set SpawnParameters for the projectile we're shooting.
    FActorSpawnParameters SpawnParameters;
    SpawnParameters.Owner = Owner;
    SpawnParameters.Instigator = GetInstigator();

    FVector TargetLoc;
    FTransform OriginTransform;

    // Run this only if the weapon is owned by a player (So it shoots where they face rather than a predefined point)
    if (bIsPlayerOwned)
    {
        // Establish parameters for the line trace.
        APlayableClass* PlayerPawn = Cast<APlayableClass>(GetInstigator());
        FVector Start = PlayerPawn->Camera->GetComponentLocation();
        FVector End = Start + PlayerPawn->Camera->GetForwardVector() * 100000.0f;

        FCollisionQueryParams Params;
        Params.AddIgnoredActor(GetInstigator());
        
        FHitResult Hit(ForceInit);
        
        if (GetWorld()->LineTraceSingleByProfile(Hit, Start, End, FName("BlockAll"), Params))
        {
            // If Line hits anything, make TargetLoc that position.
            TargetLoc = Hit.Location;
        }
    }
    
    OriginTransform = ADulceWeaponActor::GetProjectileOriginTransform(TargetLoc);

    // Here we spawn the actual Projectile Actor.
    AActor* Projectile = GetWorld()->SpawnActor<AProjectileBase>(OriginTransform.GetLocation(), OriginTransform.Rotator(), SpawnParameters);

    // Establish Shot Times to ensure we may fire as fast as we want to.
    LastShotTime = GetWorld()->GetTimeSeconds();
    NextShotTime = LastShotTime + ShotCooldown;

    // Run a timer only if weapon is Auto.
    if (FireMode == Tag_WeaponFireModeAuto)
    {
        GetWorldTimerManager().SetTimer(TimerHandle_Shoot, this, &ADulceWeaponActor::ShootProjectile, ShotCooldown, true);
    }
}

This is the function I have for spawning projectiles, for now.

#

In this case the data would be where the bullet should start from, where it faces. It could send them with some delay but they would try to go where they're meant to go at least.

charred island
#

what scheme can i use to replicate a variable from a client, back to the server, then back out to all clients other than the origin?

nova wasp
#

or just... don't do anything in the onrep if you can see it's not intended for you

charred island
#

i'm assuming that works the same way

nova wasp
#

yes

#

that is just how BP represents it

charred island
#

ok, thanks

nova wasp
#

woops I cut off the line I wanted to show...

#

note that this relies on network ownership

#

so this will generally only apply to things like your possessed pawn and other owned actors etc

#

you can also use netgroups I guess but that is not needed here imo

#

also COND_SimulatedOnly might even make more sense

nova wasp
#

which is not so great for prediction (if is replicated)

cinder quartz
#

Right right... This one replicated but I did an update

#

Client function does calculation, and a server function that does the actual spawning.

nova wasp
#

If you wanted to you could actually spawn a local "fake" actor and interpolate between the real one and the fake one if they are slow enough (how unreal tournament works)

#

this way the responsiveness is immediate but the results are still server authoratative, which is nice but will mean ping still matters

dark parcel
#

That's what I end up doing, but I haven't interpolate yet.

nova wasp
#

to me a big part of the decisionmaking is how cohesive the hit has to be relative to the visuals

#

if you need a perfect visual of the thing going from point A to B it changes what I think about a lot to be more "delayed" and done as a single "start from here to there"

#

but if the sort of like, result can be offset and survive you can get away with not caring as much

#

also sim proxies as always are a different problem generally and can be faked a LOT

#

I personally don't really see the point of an entire new actor for a simple bullet unless it is very complicated and has many rendering things attached

cinder quartz
#

I do it because, mostly

#

I'm learning and cannot figure out a better, cleaner way

nova wasp
#

that's fair, I'm not saying you have to figure out everything in one go

cinder quartz
#

I am still grasping on stuff like, how to exactly do prediction and such

nova wasp
#

it's really just... doing the same thing on two sides

#

and having a way to deal with what happens when the diverge

#

a very open-ended problem that can get really really complicated but generally we can get away with "close enough" in normal replication

cinder quartz
#

Yeah I understand the concept of replication, keeping two machines handling as similar numbers as possible and filling the blanks when needed to make up for lag, packet losses etc

#

What I struggle with is the actual coding all that in part

nova wasp
#

one problem here is that you are relying on random external objects to be replicating and those are not going to ever show up in the order you care about... unreal does not order replication for random properties like that even if they are on the same object
they can show up in random frames

#

having a single holy property that represents more than one thing about the firing state might help reduce the complexity here with random stuff showing up

#

remember: the information is what matters here

#

in order to make a bullet fire on both sides you don't need to replicate a bullet... you can replicate THAT IT WAS FIRED

#

sometimes it is useful to have the actual "in-flight" thing be tracked as a separate thing if it is very slow though for sure (or can change direction somehow)

dark parcel
#

Any ideas on how to effect movement in networked CMC? Thinking of having a black hole ability that sucks nearby objects.
Would it be as simple as applying impulse / force by the server?

cinder quartz
nova wasp
#

client can already visualize the fired bullet

#

server could if you want be the only side that actually does damage to things

#

simulated proxies get either some kind of onrep saying they started firing (burst counter style etc) or just an rpc

cinder quartz
#

I still have to touch on simulated proxies

cinder quartz
#

Well I have a new issue after running into bugs
I'm not getting the correct Player State to assign ownership so a lot gets messed up..

nova wasp
cinder quartz
#

I am using the Pawn Get Playerstate node

#

I am am waiting until well after the actor plays and input takes effect

cinder quartz
#

The player pawn

nova wasp
#

This is unspecific and doesn't describe the when or where this happens

#

on the server? the client? what callback on the pawn?

#

"waiting until well after" ?

cinder quartz
#

So once the Player Pawn spawns, and the player can apply input to it

#

I have a basic function that tries to fetch and print the PlayerState assigned to that pawn

#

This is a Local function, not on server, only client

nova wasp
#

this is a very specific question

#

is it after every single time they press a button? once early on?

cinder quartz
#

It's just called at an arbitrary point after spawn for testing purposes

#

Because I realized that the player state was not grabbed correctly

nova wasp
#

at that point they should indeed have a playerstate set

cinder quartz
#

Since when the player spawns an. it's supposed to assign the Owner to its own playerstate for score tracking purposes

nova wasp
#

but you have to be 100% clear on how your getplayerstate works in order to understand when it is safe to call it fwiw...

basically sometimes it will try to get it from a cached member ptr, which might be set AFTER the playerstate triggers some callbacks

#

for example APawn::SetPlayerState might be called after the playerstate begins play

#

If all else fails and you can't figure out a good callback to use a 1-frame delay is possible but should be a last resort (and not a random delay with no retry, that is a massive mistake I see way too much)

cinder quartz
#

I tried all that

#

It just doesn't get the player state no matter how, where, when I do it.

#

The correct player state is visible in the outlier, so it exists

nova wasp
#

you have not given specifics on how you do it so I can't help much

#

which node is this? is it a typical pawn?

cinder quartz
#

I'm trying to but my pc only seems to work in 10 second intervals

nova wasp
#

oof, that's rough

#

internet issues?

cinder quartz
#

My pc has about 4 to 6 different issues across hardware / software

#

It's a laptop with a busted screen, so now I gotta keep it plugged to a monitor...
Of course, the only way it can fit on my desk with this setup is by making the heat exhaust face directly at my face.
because of course.

#

I am thankfully getting a replacement this week after battling to get the last piece I needed, so just a little longer...

#

@nova wasp OKAY I think I found the source of the problem finally.
So the method I used for the player state was rooted in the PlayerController, right? Since it's all defaults.
So it turns out that while Play in Editor creates 2 Player States, it does still create just 1 controller. And since it cannot have more than one player state, one player state is unusued thus a lot of odd behaviour starts to happen

dark parcel
#

That's unheard of

cinder quartz
#

I'm not sure what even is the reason or cause for this

dark parcel
#

can't tell without seeing anything.

#

though a pawn would have a reference to it's own player state.

#

it will be null if you try to access it when player state is not replicated yet but otherwise you shouldn't get error.

cinder quartz
#

So for starters the Outlier shows 2 pawns of the Playable class, 2 player states, but just one controller

nova wasp
#

keep in mind only YOUR controller is replicated to you

cinder quartz
#

So this creates a very weird set of rules

dark parcel
#

each pawn have their own player state...

nova wasp
#

the outliner can be changed to display the various PIE worlds and you have not described the pie settings

quasi tide
#

You need to select the world the outliner is showing

dark parcel
#

while client only know their own controller.

#

so if there are 2 players in the game. As client, you will have 2 player states in your world.

nova wasp
#

(the gear in the top right of the outliner)

cinder quartz
#

I'm aware of that yeah...

dark parcel
#

1 for your own character, the other for who ever's playing.

dark parcel
#

if you know what which object exist in what machine, there wouldn't be an issue.

cinder quartz
#

Okay so for starters when I check the Outlier while in PIE

#

While it is set to update

#

I only see 1 playerController

#

This is the server outlier btw

#

Wait...

#

I just realized it

#

So not only the controllers are not aware of eachother, but they also always share the same name on the client?? No ID before getting to server?

#

I feel so dumb now... That explains too much

nova wasp
cinder quartz
#

Right no matter what the client's will always be newer

nova wasp
#

so try to make sure it's like, actually the one you expect

cinder quartz
#

Ah, fair yeah

#

I am having some issues on one thing now still

#

So I have this setup in the player actor. The PlayerState should get assigned correctly since I fetch it from the variables of the Pawn... But it doesn't properly work here, at all. When trying to read the Owner state in the Actor spawned it just throws an error

nova wasp
#

why would it be set on beginplay?

cinder quartz
#

Yeah I did some checkups...

#

Tried to do it on Server instead but that may not be as reliable

#

So probably OnRep_PlayerState instead

#

To like be 100% sure it's accesible

#

I might have to do that in c++ cuz idk if it's doable in bps, I'm just testing here

nova wasp
#

onreps do not run on the server to be clear

#

I would suggest asking to see if the playerstate is set and using it if it is

cinder quartz
#

And if it isn't just try again until is?

nova wasp
#

waiting for a callback ideally like APawn::SetPlayerState calling OnPlayerStateChanged

#

if all else fails repeatedly trying with a timer is possible, but it is very nasty

cinder quartz
#

I can imagine...

nova wasp
#

the playerstate BP does have an OnPawnSet event

#

but otherwise this is an example of why multiplayer in bp is really just a bit of a struggle because a lot of these callbacks don't exist

cinder quartz
#

Yeah and it does not seem to actually work on the automatic possess that happens when running the game

#

Yeah I was mostly hoping to nai ldown the logic to carry over to C++ anyways...

#

I feel BP's just faster enough I can cut down the time spent and focus on understanding stuff a bit better. Granted, I am learning- Just not fast enough to not run into issues

#

I did run into a major issue with this method that causes a crash regarding accessing the ASC though

nova wasp
#

yeah it's absolutely fair to try to do stuff in bp first

cinder quartz
#

It's funny though, I think I am starting to get along with Unreal and the next walls shows up. Kinda fun to always have something new to learn

nova wasp
#

the key is to have the sort of ability to reason about what happens and NEVER guess

#

some stuff is hard to track down but as long as you can track down how something happens by just rooting around and using the tools at hand it's a lot easier instead of just hoping for a tutorial etc

#

you don't need to understand like 100% of it but having a rough idea of the general order things happen in the frame is crucial imo

cinder quartz
#

I also find most UE tutorials a bit lacking tbh

#

Lots of repetition mixed with less ideal practices

#

And tweaking PIE settings makes me find so so many bugs too

#

Like I have a lot of them caused by forced packet losses rn

nova wasp
#

like the number of people that don't just profile their frame one astonishes me... you don't need to know about 100% of it if it's not hurting your project but like it's insanely useful to know the general order stuff happens in

cinder quartz
#

Ngl I sm still trying to get my head wrapped around the profiler in general

nova wasp
#

are you aware of like actual real world packet loss scenarios here?

#

the 5% the editor has for "bad" is like beyond insane

#

like disconnect tier packet loss

cinder quartz
#

It's a very unorthodox way to visualize.

nova wasp
#

insights is the least confusing profiler I have ever used

cinder quartz
#

Yeah I'm aware the values used are generally extreme, and a full on disconnect will have a failsafe attached to ensure the game can go back to normal if recconected

nova wasp
#

I guess maybe the unity setup is a bit easier to just use instantly and insights does have some "oh you pressed a key and it hides everything" footguns

cinder quartz
#

Well I try to grasp it

#

It definetly needs study

nova wasp
#

and i say this not because you have to make your game run at 1000000 fps as much as just

#

using it to simply see.. what happens and where

#

you can for example see when packlets for networking are actually sent and read and what that means for when your onreps happen etc

cinder quartz
#

I get you, optimization is a very important step of a commercial release

#

And involves understanding what you're making

dark parcel
#

Why do you even pass player state around?

cinder quartz
#

Yeah I have realized as much

dark parcel
#

a pawn have reference to it's player state.

#

in both server and client.

cinder quartz
#

Yeah I figured as much, just wasn't sure how to do it since I never did it before

nova wasp
#

the rpc from the client with their own local things that might be set there is weird, yeah

#

it's not a bad idea to have a sort of rpc between the client and server to sort of ack that they are actually ready

#

but passing in pointers that the server should have around locally is not meaningful

cinder quartz
#

Right, I mostly thought about doing it that way since I knew they existed in server, but wasn't sure what the better way to access them was

nova wasp
cinder quartz
#

I actually changed it to this method instead.

#

Which I suppose in theory should work since the Controller is just as good a way to access a PlayerState

dark parcel
#

Beginplay will never be reliable. You can't expect that the controller and the player state to be already replicated.

cinder quartz
#

Yeah I saw that when running a test on simulated lag

dark parcel
#

even without lag you are probabbly lucky if it work.

#

and with tiny lag its already a guarantee to break.

cinder quartz
#

What's your suggestion?

#

I had OnRep_PlayerState as my next step

dark parcel
#

You can run it on OnAcknowledgePossession.

Your controller and player state should be ready by then.

#

OnAcknowledgePossession is called by server to client.

#

basically when the server already done the possession, it tells the client to run that function.

#

You can do some initialization there.

#

but this is for weapon?

On my end, I just have a ptr to an item for the weapon.

OnRep_Weapon -> CreateMesh()

#

the visual actor (the sword / the gun) isn't replicated.

#

server just inform clients and proxies in client, what item they are equipping.

#

spawning the visual stuff can be done locally.

cinder quartz
#

Well it is for a weapon in the sence of the physical actor that handles spawning the projectiles and unique logic and whatnot

#

But it's important that I pack this sorta stuff in the player since the player state holds the ASC and inventory data, so is needed to initialize most mechanics...

#

Is it safe to assume the PlayerState is ready as soon as the controller is?

dark parcel
#

Equipment should be hold in the equipment component.

#

sure it can talk to another component, equipping bits will be the responsible for equipment component.

cinder quartz
#

Well I just have the inventory data in the player state since I was gonna need to handle pre-match item management

dark parcel
#

yea that don't matter.

#

you can have the ASC and the inventory data in player state, not an issue.

#

my ASC and inventory is also in the player state.

#

equipment is in the pawn though.

#

the owner shouldn't matter, the system should work agnostically. It should work for player or A.I all the same.

cinder quartz
#

Oh yeah, you mean physical items?

#

I have them as actors with references in the player pawn

#

The actor per se isn't meant to be replicated, but the bullets it spawns are.

#

I don't need to worry about fancy spectator mode stuff so I just went for what worked

slate phoenix
#

Hello everyone,

I have an inventory system, and it is component-based. This component is attached to my PlayerController.

After packaging the game and starting the server, I join a world. However, sometimes the hotbar and inventory UI do not appear at all, sometimes they appear with a delay, and sometimes they show up immediately.

What do you think could be causing this issue?

kindred widget
kindred widget
nova wasp
#

if this is some random marketplace plugin we can't see what it is doing

slate phoenix
#

It works normally in Pie or standard standalone mode, but when I connect to the server and try it, sometimes the UI doesn't appear, or sometimes it appears late.

nova wasp
#

if I had to guess my assumption would be something is not aware of the order of replication objects appearing that changes unexpectedly in a built game

it could also be async loading etc

#

debug it

#

and check logs too in the case it never appears

queen escarp
#

hi, Whats the best way to manipulate movementspeed in MP, changing players /Npc movementspeed (slow, sprint) Etc ?, i remeber someone said u should now change the CMC Walk movementspeed but i dont remeber why probably cuz on desync issues ?

dark parcel
# queen escarp hi, Whats the best way to manipulate movementspeed in MP, changing players /Np...

https://discord.gg/uQjhcJSsRG
In this video I setup a new project and create a custom character movement component. I also implement movement safe sprinting which works at any ping.
https://github.com/delgoodie/Zippy

0:00 Create New Project
1:02 Setup File System
02:50 Create Custom CMC
04:43 Saved Move Class
08:37 Compressed Flags
13:35 Client...

▶ Play video
queen escarp
dark parcel
#

you can turn off correction entirely but that will cause deprecancy in location.

#

and ofc anyone can cheat.

queen escarp
#

hm

thin stratus
cinder quartz
#

So I have this slight issue.
I'm trying to set up a Timeline for an Aim Down Sights' zoom effect in an online coop game, but the Event Possessed is not cleanly applying the timeline length to client. Even using Multi events called from Event Possessed won't work

nova wasp
#

I would have to see which one you are actually mean

cinder quartz
#

yeah one sec

#

So I tried to add this Event On Possess to test it out. Everything works, BUT when I get to the Set Play Rate for the timeline it only works correctly in the Server player and only there.

nova wasp
#

does this get called on both?

#

I think no (at least possess is server only in this case, idk what is calling set play rate)

#

remember: I can only see what you show us here

#

is the timeline not the value you expect on the client?

#

why is there an rpc telling you to use a replicated value? there's no way that will always be the intended final value if it was just changed...

cinder quartz
#

I tried making OnPossess call an event to: On Local, Server, and Multi that does that Set Play Rate logic, none worked to fix it

nova wasp
#

why can't this just be an onrep or something

#

if this is about a replicated value changing

#

also if ADS time changes rapidly this will not work well... ideally it should be locally derived from prediction etc

cinder quartz
#

ADS time only changes on one shot events at occasional times.

#

In an ideal out of testing scenario each weapon would have its own assigned ADS time

#
// Called when the game starts or when spawned
void AProjectileBase::BeginPlay()
{
    Super::BeginPlay();
    AActor* ProjectileInstigator = GetInstigator();
    InstigatorASC = UDulceAbilitySystemGlobals::GetAbilitySystemComponentFromActor(ProjectileInstigator, true);
}

While we're on the topic I had this snipped of code in my projectile actor but, for whatever reason it can only get the Instigator's ASC in the Server version, not Client.

nova wasp
#

debug it and find out?

#

either the instigator is not there somehow or it could not find the asc from that call

#

for example this silently allowing null is probably bad

cinder quartz
#

Hmm okay

#

Maybe something with the Init too

cinder quartz
#

I did the method for when the ASC is stored in the pawn rather than in a state

cinder quartz
#

@nova wasp Well I tested most of what I could think of, I fixed plenty but the core issue is, in the C++ code, on begin play, fetching the ASC from Instigator doesn't work

#

But doing the exact same in BP makes it work just fine. Huh.

nova wasp
#

find if it's happening to early etc, then maybe consider moving it to another callback or something

#

why doesn't it find the asc? just add a breakpoint or an ensure

cinder quartz
nova wasp
#

I'm not sure how exactly it is created here and if it will show up from replication or just exist already from being a default subobject etc

#

I am not 100% clear on how subobject init works with replication either

cinder quartz
#

I'll share how I declare it, sec

#
//.h
protected:
      // Stores the ASC of whoever this projectile belongs to.
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated)
    TObjectPtr<UDulceASC> InstigatorASC;
void AProjectileBase::BeginPlay()
{
    Super::BeginPlay();
    AActor* ProjectileInstigator = GetInstigator();
    InstigatorASC = UDulceAbilitySystemGlobals::GetAbilitySystemComponentFromActor(ProjectileInstigator, true);
}
cinder quartz
#

@nova wasp y'know what I'm just gonna bruteforcei t.

#

Rather than pull my hairs at making a pointer variable I will just use a Get function

nova wasp
#

don't replicate things you write on every machine

cinder quartz
#

Huh

#

I think I see the point now...

nova wasp
#

replicated = let replication modify the value

#

unless you are the authority or it's a non-replicated object

cinder quartz
#

Would it be better to make only the server bullet get the ASC then?

nova wasp
#

no, both of them should have it

#

I am not saying "don't use the asc"

#

I am saying don't add "replicated" for no reason

cinder quartz
#

Ah... I was a bit confused then.

#

Thanks for clearing it up

nova wasp
#

note the replicated here refers to the property itself

#

not whether the object it points to is replicated

cinder quartz
#

I started to get cleaner info when going from 2 to 3 players too. Didn't realize each client had its own index for player states and the only absolute one was Server.

#

So then that's used so one change is broadcasted to server and other machines automatically?

#

And so it sees no use if the value is set on Begin play and thus consistent gets updated by itself

cinder quartz
#

On Replicated UPROPERTY

nova wasp
#

replication does not mean it goes TO the server ever

#

replication is ONLY from the authority to clients (for replicated properties)

#

but yes if the client can just derive the value on beginplay from something they already know replication is pointless... might still be convenient though but the more random objects interacting from replication you have the weirder ordering will get (maybe it's not around yet etc, in the case of a replicated dynamic object ptr)

cinder quartz
#

Ah! So if I run a server function that modifies replicated properties it automatically updates it for every other object that also holds it on every machine.

nova wasp
#

yes, if it is replicated and the ptr points to a valid replicating or stably named object (this will not be validated and will silently fail if it isn't one)

#

the ONLY way a client can tell the server anything is from RPCs from client->server

#

aside from control packet internals which are kind of not for gameplay code etc

cinder quartz
#

Right. Thanks for clearing up that!

#

Think this time it will work

#

Nope....

nova wasp
#

I would personally just have the ASC cached locally if the pointer can be derived from the instigator

nova wasp
cinder quartz
#

I will show you more as soon as it loads

#

But honestly the issues are have are all around the snippets of code I showed

nova wasp
#

are you familiar with how to debug c++ code?

cinder quartz
#

InstigatorASC's reference is all that seems to be off

#

Yeah, gotta run in debug mode for something cleaner than logs and all

nova wasp
#

cleaner? okay I do not think you are aware of what I mean

#

put a breakpoint and step into it

#

see what it's doing

cinder quartz
#

Sure, reloading

nova wasp
#

this should be step 1 almost every time

#

when you show some c++ and say "It didn't work" I can't figure out what happened at all without any context or local memory showing what it is doing

#

but you can

cinder quartz
#

Okay collecting data

nova wasp
#
void AProjectileBase::BeginPlay()
{
    Super::BeginPlay();
    AActor* ProjectileInstigator = GetInstigator();
    if (ensure(ProjectileInstigator))
    {
        InstigatorASC = UDulceAbilitySystemGlobals::GetAbilitySystemComponentFromActor(ProjectileInstigator, true);
        ensure(InstigatorASC);
    }
}

for starters silently failing is very sad... ensures here might at least help make it annoying when something failed

#

if it is expected to not always have an instigator that ensure does not make sense, but if it is you want to fail early instead of breaking and pretending nothing happened etc

cinder quartz
#

Oh didn't know about ensure

cinder quartz
#

Okay something I found here...

#

I tried to look at the Instigator from watchers, and it's there with access to all varaibles

#

The instigator and all data matches up with the World outlier...

surreal fox
#

hey guys I'm still leaning multiplayer, I had a little doubt with RPC concept.
Lets say I wanna open door so in I use Open bool and set it to repnotify and in it's function I play door open animation. But here for some reason I also need to pass a variable's value at the same time (Char forward vector). But since repnotify does not have parameters how will I get that value while performing code in repnotify func?

nova wasp
#

a repnotify is only for that specific property

#

if you need more information then use some kind of struct for more information so you can handle it in one repnotify

surreal fox
cinder quartz
#

I'm honestly at a loss here

#

Not sure what goes wrong, how to fix it, or what to do.

#

I am not built for online programming

nova wasp
surreal fox
#

I had a thought of using multicast but it doesn't works for late joiners

#

or is there anyway that later joiner can match the current state of the game before loading the map?

nova wasp
#

yes, a repnotify

dark parcel
#

Don't use multicast for anything that needs to be in sync.

nova wasp
#

you could just have a second repnotify and pray they show up at the same time but a single struct with both will be more consistent

#

if making 1 new struct here is too difficult I don't really know why it is any different than adding arbitrary new properties to a bp

dark parcel
#

Also struct isn't complex, if you need to pack something together, use struct.

#

in networked game, the order isn't guaranteed either. So easy way to get data bundled together is with struct.

nova wasp
#

you could technically do something where the client requests information for each specific door but that is vastly more complicated than just using an onrep

surreal fox
#

thanks for the info

cinder quartz
nova wasp
#

why it didn't do what you expect

#

something made this return a nullptr

cinder quartz
#

I'm not sure what I'm looking for that's the thing

#

I don't understand any of this

nova wasp
#

this is assembly and it means it can't figure out where to put the breakpoint in regular lines

#

are you actually compiling and running from rider?

#

are you using debuggame editor?

cinder quartz
#

I am compiling and running from rider

#

And running on debug mode

nova wasp
#

your answer here does not match up with what I mean

#

I am talking about the buld target configuration

cinder quartz
#

This here...?

nova wasp
#

as I suspected...

#

you are running with optimized code that can't be debugged easily without disabling optimization

#

always use debuggame editor (when adding new C++ code that you need to reason about) (it will make your project far easier to debug but keep the engine mostly the same)

#

you really might want to read the pins in #cpp

#

debugging will be a lot easier and you should be able to see exactly what happens

cinder quartz
#

Ah....

nova wasp
#

it will run your game code a lot slower though but I doubt it's the majority of the frametime right now

cinder quartz
#

Btw, did you have the other links you shared on replication...?

#

I misplaced them after a pc crash

nova wasp
#

basically compilers will mangle the hell out of your C++ code in a way that means it's not the same as the code you see on the screen
so if you disable optimizations they will basically stick closer to "as written" and be something you can follow with a debugger much more easily without reading asm etc

nova wasp
#

any details? I can try to find them

cinder quartz
#

A blog post that talked in detail about sending events to server from clients and viceversa, had several pages about it, went over it in both bp and c++, dark mode with some red ish colors?

dark parcel
#

just go over the pinned material again, I'm pretty sure exi compedium and wizard multiplayer tips and tricks go over RPC.

#

but it's like dead simple.

Server RPC = Client telling server to run a function.
Client RPC = Server telling OWNING client to run a function.
Multicast RPC = Server telling everyone that has a copy of the replicated actor to run the function.

cinder quartz
#

So is the build time supposed to be this slow when running in debug for the first time?

cinder quartz
#

Right thanks.

#

Okay there we go

#

So it's running the getASC function, that's expected

#

It correctly grabs the instigator pawn

nova wasp
#

also consider adding {,,UnrealEditor-Engine}::GPlayInEditorContextString to the watch window

#

so you can see who this is easily

#

(server/client 1 etc)

dark parcel
#

@nova wasp sorry to bother you, it's something that I want to do as well.
Just love the documentation when it's pure text and doesn't show where to click exactly.

#

like where is the variables pane / panel?

nova wasp
cinder quartz
#

Eh weird...

#

And it's supposed to run multiple times over, once per client / server?

nova wasp
#

yes

#

remember the editor is pretending they are two different computers here in different uworlds

#

code will run multiple times

#

that runs on both sides

#

some sections will only run for the server and vice versa of course

cinder quartz
#

Okay wait I think I saw something

nova wasp
cinder quartz
#

How can I check back?

#

Like, check the previous tick

#

Or step of logic

nova wasp
#

you can move the execution cursor up up the stack but you can't really easily do that for the entire tick

#

you just.. try again generally

cinder quartz
#

I mean not tick itself

#

But the previous step

#

Oh. That's annoying lol

reef bison
nova wasp
#

this yellow cursor can be dragged back but be warned this will not always work well outside of simple stack local things

#

I do not really think it likes to deal with side-effects much but simple just if statements etc will generally be okay to redo

#

I'm not sure what restrictions moving the execution back really has in all honesty but I generally just... restart if I need to start from the top again

dark parcel
#

what am I missing

nova wasp
#

I'm wondering if our dlls are different somehow

dark parcel
nova wasp
#

what is the name of the module in your engine uses?

reef bison
nova wasp
#

if you have a custom source build you might be using a different name

#

I am also on the Rider EAP so it's possible I am using a newer syntax and forgot

#

{,,UnrealEditor-Engine}::GPlayInEditorContextString is the old way

dark parcel
#

Source build 5.5 iirc.

#

UEditorEngine maybe? let me test.

reef bison
#

if its relevant im on 5.7

nova wasp
#

there's also {,,UnrealEditor-Engine.dll}::GPlayInEditorContextString I guess? I have no clue what this syntax is lol

nova wasp
#

or just in the module list

#

which is going to be a nightmare in unreal but it will end in -engine

#

it might be YourProjectEditor-Engine as a source build

dark parcel
nova wasp
#

right click that window and enable "show module names" at least just for a second here

dark parcel
#

ahh I see, thx

#

yeah it's my ProjectNameProjectEditor

nova wasp
#

ideally Rider would resolve this module name for you but it's a bit horrible at that

cinder quartz
#

Any way I can specifically break at the Server version of the logic?

#

Since that is the one with issues

nova wasp
#

good question... honestly the simple thing is to just add a temporary if( HasAuthority) sometimes

or just a conditional breakpoint on something being null etc

dark parcel
#

k sorry for being annoying, I'm still not hitting the mark.

nova wasp
#

try the older fashioned way
{,,UnrealEditor-Engine.dll}::GPlayInEditorContextString

dark parcel
nova wasp
#

yeah I think it might be me using Rider EAP that uses this somewhat nicer syntax

#

it's super new

dark parcel
#

I'm one version before they implement the A.I auto complete (copilot?)

nova wasp
#

I mean it's simple to disable if you don't want it

dark parcel
#

I want it :S

nova wasp
#

I have it all turned off for now

dark parcel
#

and it sucks because I bought the prepetual lisence

#

still got 9 months to go

#

but the moment I unsubscribe, I can't update anymore.

nova wasp
#

the main big ticket thing that actually matters aside from AI stuff is they made debugging stuff generally faster

#

aside from that I don't really know how much you lose being on an older version aside from plugin support

cinder quartz
#

@nova wasp Okay so I watched it step by step, fetching the Instigator, the ASC- All exist, and are correctly referenced and can be accessed...
But server, still, for some reason, doesn't actually set it?

nova wasp
#

does the server hit this breakpoint and not do anything? are you considering the branches etc?

cinder quartz
#

The server hits the breakpoint and do nothing, it just grabs random data and does nothing with it if HasAuthority is true, before setting InstigatorASC

dark parcel
#

How do you set the Instigator?

cinder quartz
#

I inspected the data received and passed. The PlayerState, its ASC both exist in server, and appear in the watched data list.

#

HOWEVER once it finishes up confirming and fetching all the data, it fails to set it, only for Server.

dark parcel
#

but the issue isn't the ASC? you get null ptr on the instigator

cinder quartz
#

I also tried with 3+ players, and all clients correctly have the InstigatorASC set

#

I don't get Null in the instigator

#

But in the Property that is supposedto store a reference to the instigator's ASC

dark parcel
#

that sounds weirds, why do I get the feeling that you spawn something on the client and expecting something on server?

#

Replication doesn't work from client to server btw. Anything the client spawn only stay in that client machine that spawn it.

dark parcel
cinder quartz
dark parcel
cinder quartz
#

This is how the actor is spawned btw

#

On IA start it calls Local, which then calls Server

cinder quartz
dark parcel
#

and see where it failed / didn't get the expected result.

cinder quartz
#

Actually when I looked into that, it worked perfectly fine.

#

Like it returned the data...

#

@dark parcel The weirdest part of it all is that doing the exact same logic in Bp just works for some unholy reason.

dark parcel
#

I don't know what logic and how it got anything to do with the ProjectileBase BeginPlay

#

as far as I can see the BP you showed me just have the client to tell the server to spawn a BP_Dulce_Test something

#

Also what is Projectile Data here?

#

Can't pass around UObject unless it can be resolved (exist in both machine, through replication or statically spawned).

cinder quartz
#

Speed collision radius etc

dark parcel
#

hmm I would just read that from a Data Asset or something. Or make it a struct if its mutable.

#

anyway I am still not sure what the actual problem on your end. You haven't describe what actually went wrong.

#

other than "it works fine in bp, but not in cpp"

cinder quartz
#

So this is the reads from the function that handles getting my ASC.

#

And these are the results. For some reason, everything should work, but doesn't?

nova wasp
#

f11

#

look at what that function does

cinder quartz
#

If I do f11 here, doesn't it just advance to the necr curly bracket and end the begin play logic?

nova wasp
#

f11 steps "into" the current line's functions

#

oh wait, you already did

cinder quartz
#

hah, well I don't know what is wrong here

#

When I do the exact same logic, setting the variable in BPs on Begin play, it works.

nova wasp
#

is this still replicated?

cinder quartz
#

But now if I do it in c++

#

No, I removed the replicated flag

nova wasp
#

BP beginplay fires afterwards generally I think

#

but I don't think it should matter much here

cinder quartz
#

So that small delay is what matters

#

Therefore...

#

I should do OnRep_Instigator to set the ASC?

#

I'll try that and see what happens

nova wasp
#

this is not happening a frame later afaik

cinder quartz
#

Yeah I'm aware it's like

#

More so order

nova wasp
#

instigator should... generally be part of the initial bunch of the actor but an onrep would not hurt

#

my confusion is why it matters here because afaik it's generally just happening one after the other

cinder quartz
#

But I don't understand, why, or how the variable is not set SPECIFICALLY for the server

nova wasp
#

ah, what is the parent beginplay doing

#

I think actually the BP is before

#

AActor::BeginPlay called by the super would trigger ReceiveBeginPlay

cinder quartz
#

The BP begin play is actually a function that by default BeginPlay does so

#

They are technically different things.

nova wasp
#

yes, but they are called in the same callstack

#

the only difference being that I guess ActorHasBegunPlay is set right after the BP call?

#

and whatever else the parent between this and AActor does in beginplay

#

I'm not really sure if this line of investigation matters though, I'm mostly curious

cinder quartz
#

Yeah I get that... But

#

Nothing I see here tells me, why this works for the clients, but not the servers

#

Hm maybe it'd be better to simply expose this OnSpawn

#

And feed it into the actor

dark parcel
#

btw if you want to set something before spawn, use SpawnActorDefered

nova wasp
#

SpawnActorDefered will let you delay when BeginPlay happens until after you set some things

#

which is really useful for stuff like this

dark parcel
#
                    FRotator Rotation = (ProjectileTargetLocation - SocketTransform.GetLocation()).Rotation();
                    SocketTransform.SetRotation(Rotation.Quaternion());
                    AAGProjectile* SpellProjectile = GetWorld()->SpawnActorDeferred<AAGProjectile>(ProjectileClass, SocketTransform, GetAvatarActorFromActorInfo(),
                    Cast<APawn>(GetAvatarActorFromActorInfo()), ESpawnActorCollisionHandlingMethod::AlwaysSpawn);
                    
                    /* @TODO: Create and give the spawned projectile a gameplay effect spec */

                    
                    /* Gets the ASC that own this ability */
                    const UAbilitySystemComponent* SourceAsc = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetAvatarActorFromActorInfo());
                    const FGameplayEffectSpecHandle SpecHandle = SourceAsc->MakeOutgoingSpec(ProjectileEffectClass, GetAbilityLevel(), SourceAsc->MakeEffectContext());

                    FAGGameplayTags GameplayTags = FAGGameplayTags::Get();
                    UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(SpecHandle, GameplayTags.Damage, BaseDamage);
                    SpellProjectile->ProjectileSpecHandle = SpecHandle;
                    
                    if (Cast<APawn>(GetAvatarActorFromActorInfo())->IsLocallyControlled())
                        SpellProjectile->NetOwner = EProjectileNetOwner::ThisMachine;
                    else
                        SpellProjectile->NetOwner = EProjectileNetOwner::Server;
                    SpellProjectile->SetInstigator(Cast<APawn>(GetAvatarActorFromActorInfo()));
                    SpellProjectile->FinishSpawning(SocketTransform);
cinder quartz
#

Huh, that's good to know

#

And the way I do it in BP is literally get get ASC->Set a non replicated ASC variable.

nova wasp
#
    FActorSpawnParameters SpawnInfo;
    SpawnInfo.ObjectFlags |= RF_Transient;
    SpawnInfo.bDeferConstruction = true;

    Connection->PlayerController = GetWorld()->SpawnActor<APlayerController>(ANoPawnPlayerController::StaticClass(), FVector(), FRotator(), SpawnInfo);
    Connection->PlayerController->NetPlayerIndex = NetPlayerIndex;
    Connection->PlayerController->NetConnection = Connection;
    Connection->PlayerController->FinishSpawning(FTransform());

a random example from the engine

#

the important parts being bDeferConstruction = true and FinishSpawning after you finish setting things

cinder quartz
#

Is this DeferSpawn useful if only variables set are Owner/Instigator?

nova wasp
#

I suppose no

#

it should be present already

cinder quartz
#

That's the strange part then

#

I'm only grabbing stuff off the instigator

nova wasp
#

okay I am losing track here so apologies if you have to repeat yourself

#

but is the instigator valid in ALL cases?

#

and it just can't find the ASC? (on the server?)

#

you may as well add some logging or something with GetDebugStringForWorld etc or just branch on the authority to keep it simple

cinder quartz
#

Instigator and ASC are valid in all cases
The only singular issue is that the Server, specifically, cannot set InstigatorASC to the Instigator's ASC
And when I mean only the server I mean it. I tried with 3+ servers and logs showed that client 1 and 2 both could get their projectile's ASC assigned, but NOT the one on the Server

#

So it's less that it cannot find the ASC, but that it genuinely won't set it for some reason

nova wasp
#

like does this line of code assing the ASC pointer or not

#

does anything else write this member?

cinder quartz
#

Well for some reason it will work on the clients but not on the server.
The line will try to set InstigatorASC to whatever it can get from trying to grab the instigator's ASC

#

@nova wasp Doing OnRep won't work either. Of course.

nova wasp
#

what is "whatever it can get"

#

is it valid or not?

#

this is why I asked to see if it was actually set

#

I have shown direct examples of adding ensures

cinder quartz
#

Okay so it wasn't set

#

But it did get valid data at all points

nova wasp
#

prove it

#

add a check or ensure

cinder quartz
#

It got a valid instigator, then the player state

nova wasp
#

we want a valid ASC

#

does it get a valid ASC in all cases or not?

#

if it doesn't, find out why

dark parcel
#

find out by stepping into the lines of code.
Also when debugging, check whos running the code by checking the watch list Megafunk showed earlier.

nova wasp
#

You should be able to hit an ensure breakpoint and rewind execution to right before it asks for the asc

#

or if that's difficult you can just call the function again and step through etc

cinder quartz
#

Okay I tried something else with ensure and found something weird.
When running an ensure condition, by creating a Local Variable of the ASC before assigning it to the actual ASC variable... It won't even get the instigator...

#

...This is even weirder

#

The ensure says it runs, and is applied correctly.

#

But when accessed later in actor lifetime it returns nothing

#

Wait

#

I think...

#

@nova wasp I did it.

#

I actually did it.

#

I finally found the reason why and it's so so bizarre...

#

Turns out it was a conflict caused by calling Super::BeginPlay BEFORE running custom logic...

nova wasp
#

what custom logic?

#

super call order mattering isn't very bizarre if it actually matters

cinder quartz
#

Basically running Super::BeginPlay after trying to set ASC makes it valid and work as expected as soon as the actor spawns.

nova wasp
#

I'm assuming the beginplay is clearing something out that makes it work otherwise

#

I can't see what is actually going on here though so I have no clue why

cinder quartz
#

YEah fair. But would it be an issue to do it that way? Not familiar enough with this to know whether it's a bad long term idea or not

nova wasp
#

I don't know because I can't see what you are doing

#

there are plenty of situations where you need to interject before a super call depending on what they super call does

#

it's not strange to re-order things around a parent call

#

generally speaking the super being first is just... the default for no real reason

#

as it's just consistent

cinder quartz
#

Really wish I was better enough at this to give you a better explanation

#

I feel I'm talking in circles while you try your best to help me here, must be a headache

nova wasp
#

This is all probably overwhelming but I think you should really try to get into figuring out how to use the debugger like this more often to figure out how things happen in order etc

#

It's often quite difficult to track down WHY certain things happen in multiplayer but you can at least catch when things that are your own code happen in full detail

#

like, you went from not running in debug game to using a breakpoint on your own code pretty quickly

#

that is a lot of progress having not done that much before

#

this is the kind of thing most Epic C++ tutorials just assume you already know which for me was extremely frustrating but they kind of assume you have some knowledge of how to use debuggers etc

cinder quartz
#

Yeah I learned quickly most UE video stuff is misguided

#

Like I had to figure out how casting worked separate from every tutorial that used casting, for example

nova wasp
#

to help dispell the myths

#

the reason people go "casting is bad" is not because casting is particularly slow... pretty much every BP node is slow (by nature) and that one isn't doing anything super expensive

#

youtube tutorials generally assume it is because of a perf reason etc

#

the real actual mechanical reason is because it creates an ASSET REFERENCE to the object casted to. Because the BP MUST know about the actual asset it casted to

#

so if you cast to your character bp and the character bp has many art assets, those are loaded together (even if nothing ever executes that node!)

#

the simple solution is to just keep heavy art references separated in either child classes or just soft references etc

#

"use an interface instead" is just... it's not going to be any faster but it might help for organizational purposes and adding it to random other things

cinder quartz
#

Yeah I was familiar about that actually

verbal ice
#

Was there a helper macro to (de)serialize an array from/to an archive?

#

I feel like there was one

#

Or is Ar << Array fine

halcyon forge
#

I have a question about global time dilation and server. I am assuming this command is executed on the server and it does a multicast to pass the new dilation to the clients?

verbal ice
#

It's a replicated property

#

Doesn't use an RPC to update, just sends it to all clients

fiery olive
#

Hey, the game I'm working on is meant for playing with 4 players but recently has been crashing when all 4 players are playing at once. It also crashes at 3 players but takes a lot longer to crash than it does when 4 players are playing. Any ideas how to fix it?

gritty pelican
#

in 5.7 don't need to specify bUseIris = true in Target.cs?

#

I have the engine from the launcher and it seems like Iris should work in it

dark edge
fiery olive
dark edge
#

Try trigger it in debug to see what's up.

#

Who's crashing, the server or clients?

warm plover
#

So I have a problem, My On_Rep is firing when I add an item but not when I move an item within the inventory what could be the cause of this?

nova wasp
warm plover
#

my inventory items variable... not sure if its changed on the server or not.. Im trying to get my Refresh UI to fire and it wont

nova wasp
#

is it marked dirty with pushmodel?

#

I can't help with no context. You should be able to figure out if it is changed on the server via simple debugging and logging when it changes or just inspecting the outliner

#

in order to make a multiplayer project it is really crucial you understand what happens on each machine and can reason about it when things happen in a way you didn't expect

warm plover
#

thanks ill keep trying. Aprreciate you taking the time to respond

nova wasp
#

You could share any info about how you declare this if you want help

#

remember: we can only see what you show us

verbal ice
#

Might be tired, but do clients know if they're connected to a dedicated server or a listen server?

#

or do they not have that info

fossil spoke
#

@verbal ice They can check the NetMode

#

Actually

#

Thats incorrect

#

Sorry

verbal ice
#

yeah afaik that was local

fossil spoke
#

Im trying to remember how we handled checking that exactly.

verbal ice
#

Mainly asking because I want clients to request an auth ticket from the server if it's a player, to validate their identity

fossil spoke
#

Im pretty sure the NetConnection knows.

#

Just checking now

verbal ice
#

ty

nova wasp
#

they could maybe go netdriver->ServerConnection ?

fossil spoke
#

@nova wasp Was about to say that

#

Thats how we are checking it.

nova wasp
#

I'm not sure if it has the netmode on it directly on the client side or if you have to derive it from the url or something else
(the server connection's owning netdriver)

#

And if all else fails you could just toss in a quick simple replicated thing that says one or the other

#

oh well

verbal ice
#

Yeah but then it can be faked

nova wasp
#

faked how?

verbal ice
#

Server could just change that value to be wrong

#

No real reason to buuuuuut you never know

nova wasp
#

you don't control that anyways if it's on their machine?

verbal ice
#

I guess not

#

Depends how the net driver detects it

#

The less they can "easily" modify the better anyway

halcyon ore
#

By that logic, couldn't it still do that?
Like, SOMEWHERE it says its a dedi, or listen server.

verbal ice
#

Probably could

#

Doesn't mean I'd give them an easier way to heh

halcyon ore
#

If anything its easier.
Cuz the engine source is accessible, while your game source isn't.

Also, what does this even do, that faking it could be "bad"?

verbal ice
#

not the end of the world

nova wasp
#

is it useful for them to figure out if it's a listen server?

verbal ice
#

im just not going to have clients ask dedis for an auth ticket to validate their identity

#

no real point

#

I could but it'd be a bit of a waste

#

There would be zero benefits to spoofing your dedicated server's identity on Steam

#

as a listen server however, you could make players think you're someone else as the host

nova wasp
#

well

#

you might need some kind of identity provider thing I guess?

#

I'm not sure how to set that up or what your actual goal her is

verbal ice
#

Steam

nova wasp
#

it sounds like you want some kind of persistent data

#

between server hosts

verbal ice
#

Listen server host gets an auth ticket from Steam, sends it to the client who wants it, client can validate the host's identity with Steam

#

not persistent data I just want players to be able to verify that a listen server host is who they say they are

nova wasp
#

I would kind of assume that's the steam connection's problem

#

like, ideally they don't accidentally click on someone pretending to be their steam friend? I don't know

verbal ice
#

They could spoof as anyone, that's not the point heh

#

And you can also just find listen servers in the server browser

#

I'm making a Steam plugin from scratch using OSSv2/Online Services and I'm just trying to improve it over OSSv1

#

Considering so far I'm pretty sure I could go get a bug bounty for a bit of OSSv1 Steam heh

#

If I ever feel bored enough to

#

On another note, is there no way to disconnect a connection from within a HandlerComponent?

#

the packet handler stuff

#

or does calling Packet.SetError() cause a disconnect anyway?

nova wasp
#

on the unreal-level an error will disconnect afaik but I'm not sure about that layer

#

you would have to try it

verbal ice
#

Seems like it should, but the thing is since my calls are async, I gotta be able to kick a player from within the handler component without a packet

#

which doesn't seem possible

#

unless I just send a bogus error packet and it disconnects them (lol)

#

idk why Epic didn't make it easier to do so, sounds like something you'd want

#

okay did some digging

#

seems like this is the best way to guarantee it

#
LocalAccountId = UserData.UserId;
if (!LocalAccountId.IsValid())
{
    UE_LOGFMT(LogCrowbarAuthHandler, Error, "Received invalid SteamID from player, kicking.");
    Packet.SetError();
    Net::AddToChainResultPtr(IncomingPacket.Traits.ExtendedError, ENetCloseResult::NotRecoverable);
    return;
}
#

And I guess if I want to force drop a connection without an incoming packet, I can just create a new packet & mark it as error with not recoverable before sending it to the client

#

But I'll test that in a month when I have the plugin ready for dedicated server testing lol

verbal ice
#

that's annoying

#

god forsaken engine can't add a "disconnect connection" function in the packet handler

#

(╯°□°)╯︵ ┻━┻

#
void FCrowbarSteamAuthHandlerComponent::Incoming(FIncomingPacketRef IncomingPacket)
{
    // If we're in an unrecoverable error, mark the incoming packet as errored and unrecoverable.
    if (State == ECrowbarAuthHandlerState::UnrecoverableError)
    {
        IncomingPacket.Packet.SetError();
        Net::AddToChainResultPtr(IncomingPacket.Traits.ExtendedError, ENetCloseResult::NotRecoverable);
        return;
    }
#

this better work

#

why the fuck can't we grab the net connection that owns a handler component, from the handler component

#

it's stupid

#

I can grab it from a private delegate inside the packet handler

#

kind of

#

by grabbing the delegate's uobject

#

dirty as fuck but I guess it's all I can do without engine mods

#

not even sure actually

verbal ice
#
void FCrowbarSteamAuthHandlerComponent::DisconnectFromError(const FString& InError)
{
    // Only allowed on the server.
    check(Handler->Mode == UE::Handler::Mode::Server);
    
    // If we have a valid owning connection, we'll try to close it that way first.
    if (OwningConnection.IsValid())
    {
        Net::FNetCloseResult Result(ENetCloseResult::NotRecoverable, InError);
        OwningConnection->Close(MoveTemp(Result));
    }
    
    // We'll also set ourselves to an unrecoverable error state, that way we do not handle anything else.
    SetAuthState(ECrowbarAuthHandlerState::UnrecoverableError);
    
    UE_LOGFMT(LogCrowbarAuthHandler, Error, "Disconnecting connection with error: {0}.", InError);
}
#

went with this

#
// This is hacky, but we can try and fetch the net connection that owns this handler through a delegate.
// Since it's a private member we have to be even hackier.
FPacketHandlerLowLevelSendTraits& Delegate = PacketHandler_Private::Get_LowLevelSendDel(*Handler);
OwningConnection = Cast<UNetConnection>(Delegate.GetUObject());

and this to grab the owning connection

#

we'll see if it works

lusty sky
#

Isn't the client supposed to generate an auth session ticket and send it to the server ? And then the server confirms that tickets match the steam id?

tidal cloak
#

Hello, I have a question.
Assume there is two users in a session and lets say its level A. User A (host) and User B(client).
User A triggers servertravel goes to level B.
But User B (client) does not follow User A(host) to level b. User B goes back to initial starter map.

NOTE :
seamless travel is true (recommended by chatgpt)

this is the code snippet of servertravel.

FString URL = FString::Printf(TEXT("%s?game=%s"),
                                          *Map.ToString(),
                                          *GetGameModePath()
            );
            GetWorld()->ServerTravel(URL, false, true);```
dark parcel
#

@tidal cloak can you come again? You said user A was the host then after that User b is the host.

#

Which is it.

#

In any case only one map can be opened at a time.

#

If the game needs to travel to another map, simply have host call server travel.

tidal cloak
tidal cloak
#

But in my case connected clients goes back to starter map. And host travels to new map

quick flint
tidal cloak
quick flint
#

Hmm that's a little weird then.

User B goes back to initial starter map.

Sounds like User B is getting disconnected. You could check the log to see why this is the case.

tidal cloak
#

Then client goes to starter map

#

Btw using UE 5.7

quick flint
#

Try checking the server log, it often has more useful info regarding disconnects

tardy fossil
#

hey is there a way to make running multiple instances on steam work? or will steam just not allow that? i know if i launch the game from the exe while i have it running already it will launch the second instance, and i can press shift tab to get the steam overlay.. but the second instance can't see any servers

quick flint
tardy fossil
#

i have a feeling steam just hard limits online stuff to 1 instance per account

quick flint
#

Yes, as far as I know that's true

regal narwhal
#

hey. I have same issue. I m using non-seamless travel when the server player load savegame I call serverTravel functioanlity but It disconnects clients. Is it still best practice to use seamless travel for loading savegame?

thin stratus
#

You should be using seamless travel for your server travels though, if possible

kindred widget
#

The client would disconnect even without the savegame. That's what non seamless does.

verbal ice
#

That way it prevents listen hosts from spoofing their identity

left bear
#

any tips for moving a player w/ client authoratitive movement from the server (eg having an AI grab said player)? can turn off client auth but then there's some jitter, and can also have the client attach itself to the AI but also fighting jitter.

fossil spoke
#

If its like an in place body slam or something like that, you can easily just lock both Actors in place and just animate or move the Meshes instead of the entire Actor.

#

If its like a pull from a distance, you can think of it in terms of the Player character performs a Root Motion Source to the Enemy, simulating a "grab" by the Enemy.

thin stratus
#

Might also be worth noting that you'd want to attach to the MeshComponent and not Capsule, cause that one isn't smoothed potentially.

sand narwhal
#

Any tips on moving a lot of data from the game server to the clients? I'm talking about 50-70 Mb of procedural data on game init phase to generate the full level on clients.

I'm currently using replicated actors which works but I'd love to have a fire and forget similar to RPC to send the data instead to reduce the amount of resident memory used on the game server. Makes sense?

The only two ways I have in mind are:

  • replicated actors which means I need to synchronize a cleanup after all the clients have used the data
  • RPC with lots of data chunk (high risk of client disconnection from my perspective - 64 kb limit, max number of rpc sends per iteration, etc)
spiral timber
#

Would it be possible to have the clients generate the data themselves using the seed the server used?

meager spade
#

why does client need 50-70mb of data, even Minecraft doesnt do that.

#

if client needs FULL data to make the map, you designed the system wrong

#

our procedural maps == seed only, plus state changes

#

ie you send the data only of what the player sees (this is what minecraft does)

#

so if you need to send entire data in one go, somehting is wrong, and why is it so big?

kindred widget
#

That's a loooot of data. 😄 Like practically a decent sized map fully serialized and not compressed or anything.

nocturne summit
#

Hi, I'm new to multiplayer, and have many questions don't know where to find answers.
I'm wondering why many friendslop games are using 4 players? instead of 5 or 6 or 3? Is that a technical limitation?
Are they using one player's device as a host and other players join it? Do they need server for it? If publish on steam, does it have some kind of free server for it?😯

kindred widget
#

For the server part, usually one player is the server. Called a Listenserver in Unreal. Steam doesn't do servers. Steam manages being able to connect to a server, but doesn't host servers.

For the games like you're meaning, one player is host/server, other players join their game.

exotic wasp
#

but 4 people is a pretty easy group of people to get to consistently play coop

#

anything below that and it's too small, anything above that and you're trying to schedule 5 people together

#

systems like communication (voice) also break down in higher numbers

sand narwhal
#

Data is generated through Unreal PCG on the game server and includes a lot of stuff including foliage, game items, etc etc. I think part of it is the unreal containers that reserves extra buffer to account for growth (so I will remove part of it) but for the sake of the question, even if I remove 30 Mb, I still have 40 Mb to transfer.

kindred widget
meager spade
#

yeah PCG is very determenistic

#

its seed driven, as long as client has exactly what server has, and the correct seed, it will generate exact pcg

sharp mason
#

How can I client predict enemy death ? Player actions works well with GAS client prediction, but enemies that lives on server I don’t really know what to do, I need the death to feel instant because it use root motion to push it away, and if server does not agree with the death I roll it back, but the character movement don’t let me move it on the client, should I set replicate movement to false while the server don’t confirm the death ?

exotic wasp
#

i think every bit of guidance ive ever seen is to not predict client death

nova wasp
#

It's not out of the question imo

#

It's definitely preferrable to not have to

#

I would say it depends on what "death" means here as if it's mostly visual you could just predict it in the visual sense

#

"character movement don’t let me move it on the client" is going to require overriding OnRep_ReplicatedMovement and maybe basedmovement along with anything else that comes down

#

I suppose ACharacter::PostNetReceiveLocationAndRotation might be more direct but I forget if that covers everything

gilded vapor
#

Clients can play RM anims on simulated-proxies without changes (though they can still get net corrected)

#

GAS can't really locally predict abilities on simulated-proxies its kinda a strength and a shortcoming of it~~

oak flower
#

I'm learning about multiplayer security in Unreal Engine and trying to understand how client-side vulnerabilities are realistically exploited.

What tools or methods are commonly used to intercept or modify client-to-server data in Unreal Engine multiplayer games?

Also, is there any good educational material, tutorials, or research about this topic available online?

This is for learning secure server-authoritative design and testing vulnerabilities.

dark parcel
#

@oak flower client are running their own instance, they can pretty much modify the data in their instance.
Using kernel level anti-cheat may help but I wouldn't bother with all of it.

General rule of thumb, you want to trust the client as little as possible.

#

You can probably go long way simply by having a good design.

#

like don't just trust the player informing the server that they have shoot some object. Check in the server machine if the shot is possible.

short arrow
#

On the flip side vulnerabilities only really happen because the server just can't afford to do/check everything. That is why anti cheats are so important

oak flower
#

i understand, i'd like to learn "what is possible" to improve my multiplayer code, maybe intercepting an RPC

reef bison
#

players can modify anything they want in their client, you should consider basically any data coming from a client to be compromised

visual ore
#

hello all, i just started a project on ue5.7 and im looking at UObject replication for my nested inventory system, but i notice the plugin for it hasnt been updated since 5.5 despite the author still maintaining other projects, since he has no discord im asking here:
how is UObject replication handled in UE 5.7? have the features of the plugin been integrated into the base engine? if not, is there another plugin i could use, or might it work if i just rebuild the plugin in IDE?

dark parcel
visual ore
#

testing it now, however im not confident that i can diagnose it myself given my inexperience with replication

nocturne summit
kindred widget
# nocturne summit Thank you! So in this way, it doesn't cost anything right? And even the ran...

Listenservers don't cost anything, no. Cause it's all ran on the consumer's machine.

Steam in this case is just essentially a replacement for connecting via a direct IP address. Any online subsystem is, really. This is true if you're using Steam, Epic Online Services, Playstation Network, Xbox Live, or whatever else.

The only downside to this is that you basically cannot make anything secure, cause it's not ran by you as the dev. But that doesn't really matter for a non competitive coop or whatever game.

halcyon ore
nocturne summit
dark parcel
#

so in other word, it cost nothing for maintenance. You just have to cough up for $100 for the dev fee on steam to publish your game, which you will get back if you sell over $1000.

nocturne summit
#

Oh, and a small question. Is that either choosing listen server or delicated server, I could use a same game system? The difference only exist in connection? I could use the same replicate methods right?

dark parcel
#

Same method but there are some consideration depending on the context.

#

dedicated just mean headless server (it doesn't render graphic).

nocturne summit
#

Oh, so delicated server only calculate datas? And the graphics are all running on clients machines?

dark parcel
#

but yeah you can think of dedicated server as a console command.

#

are you not familiar with Left 4 dead?

nocturne summit
#

What about the maps, multiple players in a same map. That map update is also different instance in every client?

#

Yea a little, played long time ago

dark parcel
#

think of it like counter strike.

#

Host select the map, everyone has to play in that map.

#

Out of the box, you cannot do multi world.

#

like player can't just go to Dungeon A, B, C.
Nu-uh, it's like counter strike, where everyone has to play the same map.

#

And yeah, MMO made in unreal engine is a thing. But they don't use Unreal replication framework, they roll their own backend.

#

well... technically you can host a fleet of dedicated server.

#

where each server host a map. When traveling to other map, just migrate that user to another server that host the map.

#

sound expensive as f though.

#

looking at AWS pricing calculator, I decide to do listen server.

nocturne summit
#

I see, lol. Thank you very much!

sage lance
#

any idea what causes this? 5.4 steam sockets + lyra

devout violet
#

Yo, having a bit of a block using VOIP. The system is working fine in build, but I can't get any attenuation settings to apply. Everyone is just always heard 100% of the time. I believe I'm doing a fairly normal implementation, but it appears that the settings just don't apply for some reason. Any ideas?

(InitVoip gets called in Event BeginPlay on both Client and Server, and I did check that the attenuation itself does work fine with normal, non-VOIP sounds)

visual ore
# dark edge does it not work on 5.7?

got sidetracked, but i finished testing and all the functions seem to work properly with no issue,

for anyone following the same question as me: the UObject Replication plugin works fine on ue5.7

dark parcel
visual ore
# dark parcel Ain't a plugin. UObject can always be replicated through actor.
Fab.com

DOCUMENTATION -- DISCORD SUPPORTUObject Replication Plugin enables projects to replicate UObjects over the network in Blueprints, which is not supported by default due to C++ setup. The plugin will replicate your UObjects simply as replicating an Actor/Actor Component.Why should I replicate UObjects?They are lightweight to replicate, so they're...

dark parcel
#

but for your question "have the features of the plugin been integrated into the base engine?"
That's not the case. The authour of your plugin simply use what the engine already done.

visual ore
#

the base engine doesnt include blueprint exposition of the subobject replication?

dark parcel
#

not bp support

visual ore
#

right, this plugin does that

dark parcel
#

Yeah but it sounded like you are implying that this plugin somehow become a feature in the engine.

visual ore
#

i was asking if it had

dark parcel
#

I am just saying it's the other way around, the author simply expose functionality to bp.

ruby parrot
#

@sinful tree I made a rookie mistake... everything was working already after I changed it to your suggested concept here: #multiplayer message
it was working immediately... just replication didnt... because i forgot to tick replicate on the 3D object i was interacting with, it was turned on on the Actor Component alone... well thanks for the help 😄

worthy wasp
#

Mobile games networking architecture - games like Summoners War (genre) - are these using a dedicated auth server model? Or is thereanother light-weight way that pulls this off? My concern is the lack of support for multiplayer playerbase of 1000's/10's/100's even million playercounts? Who knows how many concurrent players there will be at any given time.

#

i'll safely assume that it is good standard practice to split to servers - where i have couple 100 per server - scaled dynamically. Think GLOBAL CHATROOM #66 - where theres N# of players per server... and a dedicated server appointed to this server. This seems the most scalable architecture i can think of - if i need to leverage DediServer architecture

thin stratus
worthy wasp
#

i was thinking of Ark architecture with this... even how old that is - i dont know how its increased over the years....

thin stratus
#

Idk what Summoners War is, but if you need something more lightweight that isn't even utilizing the "live" gameplay that a DediServer offers, then you'll have to code it yourself.

worthy wasp
#

ok

thin stratus
#

A Chatroom system is 100% nothing that should utilize unreal's networking. That makes no sense.

#

If the fights in that Summoners War game are asynchronous, then you most likely don't want to do this with Dedicated Servers. Idk what the gameplay is though.

worthy wasp
#

it was an example of what hte game really is - most of it is single player gameplay (few instances of GUILD/SOCIAL based gameplay) but sitll needs authoritative stance.

thin stratus
#

Yeah, then I wouldn't use a Dedicated Server at all.

worthy wasp
#

so i need to design my own authoritative stance - got it.

#

time to grab my Harry Potter wizard hat....

thin stratus
#

Last time I had to work on something like this we had a server written in Go. The player selected what units they played and where they were positioned. Backend knew if the player even owned those units. Go server then validated the placement, checked what level the player is in and simulated the fight. Then it send the client the instructions on how the fight went.

worthy wasp
#

you just answered my questions. ok

thin stratus
#

Idk if that matches the gameplay of that Summoners War stuff, but Mobile Games that are "singleplayer" with auth state are mostly similar, so this probably aligns.

worthy wasp
#

kind of - the game is turnbased with like 5 characters each. it could be a map/set of the turn & the results each character/enemy - so the client can just simulate the gameplay but it is directed by the authoritative stance.

thin stratus
#

Yeah, that's fine. Server still has to simulate it too, for rewards and such.

worthy wasp
#

crits/etc could be calculate dby the server/auth ... sent to player as results and the client just animates teh combat with the results already pre-determined.

#

yah

#

ok

#

this makes sense...

thin stratus
#

But this is mostly a "request -> response" kind of setup. Not really live gameplay.

worthy wasp
#

you're correct.

thin stratus
#

A socket connection to that (Go) server is probably enough.

worthy wasp
#

right on - i'll go this approach - i like it.

thin stratus
#

Idk how to scale that setup, but I assume a simple server application will run 10.000x better than a Dedicated Server.

#

It's probably similar to having some webservice with a database that receives some requests.

worthy wasp
#

i can setup to scale the server based on network bandwidth & CPU/MEMORY stats

#

that should be asily done.

thin stratus
#

Yus

worthy wasp
#

ty Cedric!

nocturne quail
#

what's the best way for ignition sound to play?
this is my current approach using a trancient component

void AVehicleBase::Multicast_PlayEngineEgnition_Implementation()
{
    if (HasAuthority()) 
    {
        return;
    }

    if (!IgnitionSound) return;

    if (TransientIgnitionComp)
    {
        TransientIgnitionComp->DestroyComponent(true);
    }
    else
    {
        TransientIgnitionComp = NewObject<UAudioComponent>(this);
        if (TransientIgnitionComp)
        {
            TransientIgnitionComp->RegisterComponent();
            TransientIgnitionComp->SetSound(IgnitionSound);
            TransientIgnitionComp->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);

            TransientIgnitionComp->bAutoDestroy = true;

            TransientIgnitionComp->Play();
        }
    }
}
#

will spawn sound at location makes more sense or it doesn't matter?

gilded vapor
#

SpawnSoundAtLocation is more performant (it doesn't require an AudioComponent) but its not attached

#

So its more of different use-case kinda thing~~

nocturne quail
rough dock
#

Could anyone help me out here? in a repnotify when the bomb is set to detonating it casts to the bomb timer widget to display the time text, but for some reason i cannot get the widget to access the float it always comes back as 0

#

trying to make things work even for players who join late

fossil spoke
#

@rough dock If this is running on a Dedicated Server, the Widget wont exist for the Server.

fossil spoke
#

Are you using a Dedicated Server or a Listen Server?

rough dock
fossil spoke
#

Use a PrintString node to check the value

#

The debugger is not always accurate.

rough dock
#

value is fine in repnotify but in the widget it reads 0

#

i can get the timer to work fine with a multicast but i cant get it to work with repnotify

#

and this code works perfectly fine too

rough dock
#

got it to work with this in the repnotify

sharp mason
sharp mason
nova wasp
#

as for how to do stuff like this

#

there are things you have control over and there are things that I would suggest not trying to replace

#

unreal gameplay data replication is always from the server/authority to other clients
this includes the creation/destruction of objects (with some ways to "tear off") and replicated properties

#

I would recommend against modifying replicated properties on the client locally to try to predict things if possible. It is going to break some assumptions unreal makes
But what you CAN almost always do is choose WHY AND HOW those replicated properties are used. Especially in C++

#

For example, let's think about actor transform replication (in the basic sense)

#

The actor's root scene component transform represents where it ACTUALLY IS locally on the client. Notice how the actor transform replication is a different property?

#

see: AActor::OnRep_ReplicatedMovement etc

#

This is good news for us because this means you have two separate things...

  • The replicated transform location: The server's most recent "idea" of where the actor should be on the authority which is a bit behind due to ping (which is why this jitters around a bit)
  • The actual final local transform of the object
#

If you look at AActor::OnRep_ReplicatedMovement or ACharacter::OnRep_ReplicatedMovement if this is a character (note it OVERRIDES the parent)

you can see they choose whether or not they want to apply this

#

You can too

#

In fact, you could even just call OnRep_ReplicatedMovement whenever you want to re-apply it

#

The important takeaway here is that you can override virtual Onreps to replace them entirely, change what they do, or even just call them whenever you like

#

You can even directly disable specific replicating properties of a parent class with certain macros if need be (I generally do this in order to replace them with my own better ones that fit the project)

#

I'm not sure how your enemies work though, @sharp mason

#

take note for ACharacter there is a secondary codepath for standing on a moving platform (based movement) but for simulated proxies generally they just get the regular OnRep_ReplicatedMovement with velocity and a few other replicated properties to see if they are crouching or jumping

#

In reality their position is actually quite jittery

#

But the Character will smooth the position of the mesh relative to the base to make it look better with a small amount of extrapolation mixed with interpolation. You can control this behaviour as well and it's important to note here as it could change how it looks

#

My general impression for what to do here would be that you want to basically have the client say "No, we are definitely moving this way" for a bit and have it ignore new server onreps for a moment

How you do this is pretty open-ended I guess... I don't really know what the data relationships are between these two things or what the knockback can and can't do

#

I would say definitely don't completely destroy the actor for "death" until it's legit 100% correctly dead... You can't really easily restore a destroyed actor torn off on the client so hiding it ahead of time would be superior imo

#

Also rolling back might get confusing... You can do this in a ton of different ways and even be more "permissive" if it helps

sharp mason
# nova wasp I'm not sure how your enemies work though, <@229205467405090818>

basically the player can kill enemies in specific ways that will trigger a root motion animation that send them flying away, what i first want to achieve if possible is that the simulated proxies block the server movement for a while, play the root motion animation, IF for someway (only hackers i think) it did not die, i just revert it back to its position (it will be "bad" visually but responsiveness on my pve game is more important)

nova wasp
#

you have good judgement there I think... I would say most of us have more to worry about making a game anyone would care to cheat in than cheating

#

As the enemies are flung away does their state influence the world around them? can they collide into other enemies or block anything on the way?

sharp mason
#

no they only collide with static objects like wall, so it dont go inside the wall, otherwise its pure cosmetic

nova wasp
#

If they don't have an influence on the simulation after being sent flying it might matter even less to make it perfectly match up with what happened on the server and peers

#

Which is helpful for simulated proxies of other players I guess as it means you don't have to be quite as careful if they could end up in different spots without it really mattering much

#

(It's fair to want it to be similar anyways, just saying it might not be do or die)

sharp mason
#

For now i am trying to understand what is blocking my rootmotion to move the character, i dont if PerformMovement just simply ignore it on simulated proxys, or its just the server overriding its position

nova wasp
#

well

#

for starters you need to consider the root actor transform and the visual mesh relative offset as separate in some cases

#

they might be way off depending on what is happening... make sure you visualize the true capsule location just to make sure

#

Of course we mostly care about the visuals here but it might help illustrate what happens

#

I'm not really sure what root motion does to smoothing honestly, I've never had to mess with that codepath

#

Can you visualize what happens when you apply root motion locally on the client first? I'm not sure how this is happening etc

#

I guess FWIW

#

it doesn't matter how it moves as long as it works... you can do basically whatever

#

if you override all of the places the server tries to re-apply the final position you can absolutely take over the location

sharp mason
#

what is currently happening that i am not understanding how is, on my client i start the animation early it moves the character instantly back, then the server is playing the animation too and overriding its position, so i thought ok i just need to turn off movement replication, i turned it off and now there is no root motion at all

nova wasp
#

well

#

did you turn it off on the client?

#

or the server?

sharp mason
#

i turn it off on the editor just to see what happens

#

so i think both

nova wasp
#

you probably only want to turn it off locally on the client when they predict the death

#

you still want them to replicate normally before that, riught?

#

remember: these are different machines in a sense

#

one downside though is that bReplicateMovement is replicated

sharp mason
#

oh yes but i tried the most absurd approach to see what happens, and what happened was not what i expected

nova wasp
#

you might want to override OnRep_RootMotion, OnRep_ReplicatedBasedMovement, and OnRep_ReplicatedMovement and add a new branch

#

so you can ignore the other things fighting over your new value

sharp mason
#

even with the on replicate movement false, those functions can still be called ?

nova wasp
#

well, you need replicate movement to be on before

#

note that bReplicateMovement is ironically itself a replicated property

#

I generally would advise against modifying replicated properties locally without having a way to restore the original value but you can if you want

sharp mason
#

Maybe i am trying to understand a problem that should not exist on a normal situation and i should give up , but for me its extremely confuse, set it to not replicate on editor, put the enemy on the map, shot him on the client it does not move with root motion, turn everything back on now root motion works but the server corrects it, like how is it no playing with no replication ?

nova wasp
#

Just leave that on for now... you don't want to disable replcating any movement

#

My guess is that root motion still works because of ACharacter::PreReplication

#

notice how it branches on either having IsReplicatingMovement or root motion

sharp mason
nova wasp
#

I think for now focus on making the client "take over" the enemy character more or less during the prediction of their death
You can figure out how to make that work well on the server and other peers later

sharp mason
#

I now have what i want the root motion is playing on client, but the server also trigger the animation and move it back again, kinda playing it twice, should i override OnRep_ReplicatedMovement ?

nova wasp
#

I think you should be able to just set SetReplicatingMovement to false on ONLY the client when they start pushing them for now

#

note that even though this is false it doesn't stop you from RECEIVING data

#

it only stops you from APPLYING the data from the server

#

the most recent received transform will always be there. It can be restored at any point you want

#

I'm not sure about the root motion parts though and I imagine you might need to pave over the server's idea of root motion if it's getting stuck right before hand

sharp mason
#

thats where i dont understand

nova wasp
#

okay, well

#

I guess we can see if that root motion is being removed somehow...

#

If I had to guess it would probably be UCharacterMovementComponent::SimulatedTick

#

In which case...

#

I would have to debug it to see

#

I'm not sure which branch is being taken or if something is overriding the root motion source

sharp mason
#

yeah i think i can take it from here, so i dont take you more time on it

nova wasp
#

You can mess around with having your own local boolean value that the client sets locally to override this

sharp mason
#

ok thank you

nova wasp
#

One crazy route you could take could potentially be copying a completely different object/state/component etc to serve to represent the predicted state but I don't think that will be necessary here

#

it's straightforward enough to override the state being applied here

#

I would say definitely take note that simulated proxies have a different codepath so... if you have a listen server they might need to just do this differently

#

the CMC is a lot of code but the simulated proxy side we care about right now is actually not that much... it's mostly some onreps as mentioned earlier

#

There are also things like OnRep_IsCrouched

sharp mason
nova wasp
#

If it helps you can actually ignore the server telling you to destroy an actor in certain ways

#

tearing off etc

#

this can be useful if you want to keep it around for visual reasons but don't need it on the server

nova wasp
#

ideally you keep the same mesh somehow

sharp mason
#

and then it do the root motion

#

you saved me a lot of time

nova wasp
#

glad I could help

sharp mason
# nova wasp glad I could help

now as you suggest i should override this guys OnRep_RootMotion, OnRep_ReplicatedBasedMovement, and OnRep_ReplicatedMovement, right ?

nova wasp
#

That's what I would do to try to control the places the server will try to apply state on top

#

there might be more

#

The server might change the replicated movement mode or if they are jumping etc as well

sharp mason
reef bison
#

since this is a death animation you probably dont even need to handle the smoothing when reactivating the server corrections

nova wasp
#

If you want you can replace them all with one holy onrep but it will require some more work

sharp mason
nova wasp
#

I would assume OnUpdateSimulatedPosition and or SmoothCorrection ?

sharp mason
nova wasp
#

but yeah I'm not clear on how root motion works so I will defer to their judgement

reef bison
#

SmoothClientPosition (return when the RMS is playing) and SmoothCorrection (teleport back to the previous position and return while the RMS is playing)

#

you dont need a custom root motion source for this, you can use a simple bool flag on the client. i was experimenting with different solutions so thats why i had one

sharp mason
reef bison
#
bool UTerraCharacterMovementComponent::HasActivePredictedKnockback() const
{
    for (const TSharedPtr<FRootMotionSource>& Source : CurrentRootMotion.RootMotionSources)
    {        
        if (Source.IsValid() &&
            Source->GetScriptStruct() == FRootMotionSource_PredictedKnockback::StaticStruct())
        {
            return true;
        }
    }
    return false;
}

void UTerraCharacterMovementComponent::SmoothCorrection(
    const FVector& OldLocation, const FQuat& OldRotation,
    const FVector& NewLocation, const FQuat& NewRotation)
{
    if (HasActivePredictedKnockback())
    {
        // The engine just teleported the actor from OldLocation (our predicted position)
        // to NewLocation (the server's lagged position). Undo it, the server should end up
        // in the same position once it catches up
        if (UpdatedComponent)
        {
            UpdatedComponent->SetWorldLocationAndRotation(
                OldLocation, OldRotation, false, nullptr, ETeleportType::TeleportPhysics);
        }
        return;
    }

    Super::SmoothCorrection(OldLocation, OldRotation, NewLocation, NewRotation);
}

void UTerraCharacterMovementComponent::SmoothClientPosition(float DeltaSeconds)
{
    // Suppress server position smoothing while a predicted knockback source is driving this
    // actor movement
    if (HasActivePredictedKnockback()) return;

    Super::SmoothClientPosition(DeltaSeconds);
}
#

fwiw i deleted all this code for knockback prediction so take it with a grain of salt