#multiplayer

1 messages · Page 277 of 1

pliant cypress
#

Thank you. sometimes i couldn't read properley or understand on sight. Commonally during Typos

silent valley
#

There's a GetServerTime that stays in sync across clients that is useful for this.

verbal ice
#

AGameStateBase::GetServerWorldTimeSeconds()

thin stratus
#

The problem will be that just one time won't be enough.

#

Or rather, seeing it as one truthful value isn't enough.

#

It becomes more obvious if you exaggerate the individual pings of two clients.

#

If one client has a ping (RTT/2) of 1.0 seconds and the other of 0.5 seconds, then the position of the Pendulum will be 1.0/0.5 seconds behind for the specific client. So they already see different pendulum positions if you were to overlap their views.

If the client with 1.0 seconds ping now starts walking when the pendulum is not blocking their way, the client may dodge the trap locally, but the move will take 1.0 seconds to reach the server. At that point, the server's pendulum will already be 2.0 seconds ahead of what the client saw and reacted too.

To keep it simple, let's assume the Pendulum needs roughly 2.0 seconds from center to outer edge. And let's further assume the first client started walking when the pendulum is at the outer edge from its point of view. At that exact moment the pendulum is already 1.0 seconds ahead on the server and on the way back to the center. 1.0 seconds of time for sending the server move, and the server will walk the client right into the pendulum that is now in the center on the server.

And since client two has a different ping, you can't adjust the time to only match one client.

So the tl;dr of this is that you will need to take the individual clients ping into account. Or you need to make it client authoritative if you don't care about cheaters.

silent valley
halcyon ore
#

Isn’t there any entire website dedicated to how not well in-sync the network time is?

thin stratus
thin stratus
wooden yarrow
#

Is it possible to replicate physically simulated actors welding in 5.7? (by welding I mean "weld simulated bodies" option in attach actor to actor node). I tried new physics prediction and it seems to work okay, but the welding still doesn't. In lego fortnite it's possible to assemble moving objects so I suppose there's some way, maybe not attach actor to actor but something else. Anybody knows?

tardy fossil
#

i'm pretty sure lego fortnite uses UClusterUnionComponent under the hood.. not much documentation about it besides the comments in the source code but i think its usable in blueprints

wooden yarrow
wooden yarrow
tardy fossil
#

hmm i seem to recall a modular vehicle component example adding the components at begin play with the "Add Component To Cluster" node..also i think it takes an array of bone id's which for static meshes was a single entry of 0

#

and pretty sure you want to add the components as authority only for networking

#

but i've never used it personally so there might be more to it lol

crisp shard
#

do you need to replicate the whole component to get a single variable on it to replicate ?

#

on the player state*

wooden yarrow
#

And the array can be empty, it means everything in the GC is added to the cluster union, otherwise you can add only selected GC parts, identified by their bone ids

#

And it replicates if Physics Replication Mode is set to one of the new modes

#

Pretty cool stuff!

brazen anvil
#

I have a Actor Component that takes Data Assets that provide values on how an item is held, how much it sways, if you can aim, etc. This AC can be added to any item and then when you equip the item animation will update based on the data assets that AC has set. Does it make sense to keep this AC on every single item or would it be better to put it on the character and when an item is changed just update the DA that the AC references?

knotty bane
#

I have an issue with using Listen server, when the host dissconects i destroy the session, afterwards clients cannot join or create a session due to them being still in an session as what i see in the logs: [FOnlineSessionSteam::JoinSession] Session (GameSession) already exists,can't join twice, added my disconnect logic and made a mutlicast to see if that changes anything wich it didnt, any suggestions?

halcyon ore
#

Just destroy it before doing a search for a new session. (or when the main menu widget loads, or etc)
Cuz, if this is meant to happen when the host disconnects, it would never work?
Cuz, the host would be long disconnected, by the time the multicast works?

knotty bane
halcyon ore
#

I believe "disconnect", and "session" are 2 separate things, but I could be wrong. 😛
But, I just destroy the session when my main menu loads.
Works fine, and has no issues.
No need to handle session in the active lobby, cuz various factors can/ will just skip that (aka, unintended disconnects, lag with your current method, or etc)

knotty bane
halcyon ore
#

Any website, or understanding of when you should do a major version, that forces the game version to match to play?
Should you do it any time an RPC is changed, and when a replicated asset is added/ removed?

nova wasp
#

etc

#

some things kinda bake their "settings" into the serialization but some don't

#

I would say it's better to be safe than sorry here

#

sometimes I have had situations where we wanted to fake a version id to connect anyways given we knew it was mostly okay but that was mostly for debugging

halcyon ore
#

Is there an obvious way to know when this happens.
Or, just gotta know?
Such as, adding a new replicated var would probably change this bitStream?

nova wasp
#

I feel like you are trying to gauge when it's okay to accept a different version but I think there are too many things

#

basically changing the "shape" of the serilization where it reads

  • something different unintended
  • it reads MORE than the original message sent (adding a new thing that the sender didn't know about)
    will break
#

as the project gets going I think the amount of shape changes will decrease over time

#

I feel like games reject different versions connecting for a reason though

#

if you deploy a server side only code-only fix that doesn't affect replication shape at all it might be okay etc

halcyon ore
#

How about stuff like un-replicated variables?
Would that change the shape, simply be existing.
(like if I add a new one)
or, does the shape only change from things being marked for replication

nova wasp
#

it would depend on how it is read and sent

#

the only things that change the shape would be the things that end up in the serialized packet

#

and HOW each side READS AND WRITES said packet

#

let's say you have a user that upgrades from version 1 to 2

version 1
int32 OGVar

version 2
int32 OGVar
int32 NewVar

#

They receive a packet describing the state of version 1

#

they read the bits of OGVar and all is well, but NewVar ISN'T THERE and the reader overflows the packet buffer if they are reading it sequentially

#

this can depend on a lot of things like bitmasking and delta serialziation or whatever

halcyon ore
#

But, wouldn't that only happen for replicated vars?
I'm just talking about an un-replicated var.

Or, would the literal order of var decleration mess with it?

nova wasp
#

the non replicated variables should not affect replication

#

unless they change the order somehow from shifting things around

#

but idk how actor channels or iris orders members (it might be stable)

#

you can read the source or use network insights to see the shape of each packet

halcyon ore
#

Oh, ok.
Didn't realize that.
Just working on shit, and haven't messed with any of the new debug tech. 😛

nova wasp
#

network insights is like 5 years old now afaik

halcyon ore
#

Most of my experience is on UE 4.05.1, so. 😛

nova wasp
halcyon ore
#

Modding. 😛

#

Well, was

#

Moving onto actual game dev.
But, most time was spent on 4.5.1

halcyon ore
#

So, curious for anyone who sees this.
and, maybe I just missed the entire old convos of it.
Cuz, someone told me it happened/ affected to base Unreal Engine as well.

That, apparently bool, and/ or default value replication was super buggy and glitchy around the UE 5.2 - 5.5 range.
Specifically in the capacity of:

Default = false
Some player ROS changes it to = true, perfectly normal all the time
But, if a player ROS then changes it back to = false.
The clients just wouldn't receive that false bool replication?
Same with ints, and supposedly every type.
(not involving structs, or special stuff, just a normal bool var)

This surely seems impossible that base UE was affected by such as drastic, and "bad" issue?
Just replication not working as designed, with all the value checks, and the fact that var changes are reliably sent to clients.

thin stratus
#

Also not sure if that's still the same with Iris by now

pliant cypress
#
void AHitScanWeapon::Fire(const FVector& HitTarget)
{
    Super::Fire(HitTarget);

    APawn* OwnerPawn = Cast<APawn>(GetOwner());
    if (OwnerPawn == nullptr) return;
    AController* InstigatorController = OwnerPawn->GetController();


    const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash");
    if (MuzzleFlashSocket && InstigatorController)
    {
        FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh());
        FVector Start = SocketTransform.GetLocation();
        FVector End = Start + (HitTarget - Start) * 1.25f;

        FHitResult FireHit;
        UWorld* World = GetWorld();
        if (World)
        {
            World->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility);

            if (FireHit.bBlockingHit)
            {
                ASoldierCharacter* SoldierCharacter = Cast<ASoldierCharacter>(FireHit.GetActor());
                if (SoldierCharacter->HasAuthority())
                {
                    UE_LOG(LogTemp, Warning, TEXT("Damage being applied"));
                    UGameplayStatics::ApplyDamage(SoldierCharacter, Damage, InstigatorController, this, UDamageType::StaticClass());
                }
                if (ImpactParticles)
                {
                    UGameplayStatics::SpawnEmitterAtLocation(World, ImpactParticles, FireHit.ImpactPoint);
                }
            }
        }
    }
}
#
void UCombatComponent::Fire()
{
    bool bIsValid = bFireButtonPressed && EquippedWeapon && EquippedWeapon->IsMagEmpty()==false && !(SoldierCharacter->GetSoldierMovementComponent()->GetIsSprinting());
    
    if (bIsValid)
    {
        ServerFire(HitTarget);
        StartFireTimer();
    }
}

void UCombatComponent::MulticastFire_Implementation(const FVector_NetQuantize& TraceHitTarge)
{
    if (!EquippedWeapon) return;

    if(SoldierCharacter)
    {
        EquippedWeapon->Fire(TraceHitTarge);
    }
}

void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget)
{
    MulticastFire(TraceHitTarget);
}

void UCombatComponent::OnRep_CarriedMagazine()
{
    Controller = Controller == nullptr ? Cast<ASoldierPlayerController>(SoldierCharacter->Controller) : Controller;
    if (Controller)
    {
        Controller->SetHUDCarriedMagazine(CarriedMagazine);
    }
}
void ASoldierCharacter::BeginPlay()
{
    Super::BeginPlay();
    if (HasAuthority())
    {
        OnTakeAnyDamage.AddDynamic(this, &ThisClass::RecieveDamage);
        UE_LOG(LogTemp, Warning, TEXT("Damage Binded"));
    }
}

void ASoldierCharacter::RecieveDamage(AActor* DamageActor, float Damage, const UDamageType* DamageType, AController* InstigatorController, AActor* DamageCauser)
{
    UE_LOG(LogTemp, Warning, TEXT("RecieveDamage Called"));
    if (Attribute) Attribute->TakeDamage(Damage);
}
#

the issue is character is not taking any damage from hitscan weapon, so i cannot see my blood screen on the UI.

nova wasp
#

first of all you should not use the actor damage system.. it is getting removed eventually (annoying, but making some simple component or interface should be simple enough)

#

"issue is character is not taking any damage from hitscan weapon I have NO idea which one of these functions is firing or what is in them

#

I cannot compile or run code just from looking at it

halcyon ore
thin stratus
halcyon ore
#

Huh?
How so?

#

To me, it seems so wildly broken, that I wonder if you miss-understand what I’m saying?
Seems crazy to me that basic type replication is broken “since forever”

thin stratus
#

The thing I mean is this:

  • Replicated Actor Blueprint
    • Add Boolean Variable
      • RepNotify
      • Instance Editable
      • Default Value: False
    • Override BeginPlay
      • SwitchHasAuthority
      • Set Boolean Variable to False
      • Add PrintString to the OnRep function of the Boolean
  • Place an Instance of the Blueprint into the level
    • Set the exposed Boolean on the Instance to True
  • Press Play
    • With 2 Players, ListenServer

Expected Result: Server and Client will call the OnRep and print the PrintString, because the Instance has the Boolean True and the Server sets it to False on BeginPlay.

Actual Result: Client won't call the OnRep as at the time of receiving the data it will compare the Boolean value to the Archetype of the Blueprint, where the Boolean value is False. And since that equals the received value it won't call the OnRep.

#

@halcyon ore

halcyon ore
#

No.
Not that at all.
I did recently see that.
But, that’s not what I’m talking about.

thin stratus
#

Right, then I don't know of any other bug of this degree.

halcyon ore
#

Yeah, that’s what I expected.
Cuz, what this person is reporting as a whole engine/ UE issue is.

Replicated actor, replicated bool

Spawn at runtime.
Server changes to true, all normal
Server changes back to false
Any new relevant clients are fine.
but any clients currently relevant during the change, just have a 50/50 chance of not receiving the false change, and being stuck on true.

#

No special instance stuff.
Just as simple as GameMode spawning an actor on startup, and changing the bool every 1-2 minutes has the issue.

pliant cypress
# nova wasp "issue is character is not taking any damage from hitscan weapon I have NO idea ...

UCombatComponent::Fire calls for server RPC in case the fire is being called from client. Then the server would call fire from the EquippedWeapon which has only job to spawn casing, muzzle flash etc but hitscan weapon is a child class of weapon so it overwrites the fire mechanics and do the line trace with some extra extent to detect the hit bone/actor. Then the applydamage would be called.

Take damage is binded in character which calls Take damage from attributecomponent containing code for COD style health system when hit, timer will start and if player get hit again, it'd start again but if player is not hit and timer complete, the regeneration of health start

nova wasp
#

what part of this works? what part of this doesn't? does the rpc reach the server? does the linetrace hit?

#

showing the code is great but I can't just guess what part of these 200 lines isn't doing what you want

#

debug it

pliant cypress
pliant cypress
#

FIXED

nova wasp
#

I think you are doing fine but putting in a decent effort to debug it first will save a LOT of time

pliant cypress
#

So I'm looking at it now.

blazing spruce
#

In blueprints, If I mark an event reliable that guarantees the event itself will be called but it doesn't guarantee that any subsequent events or functions called by this event get called, right? They would have to be marked reliable themselves as well to guarantee its called? So in BPs I cant guarantee any function actually gets called I would have to make it an event to mark it reliable, yeah?

exotic wasp
#

reliability only matters when going over the network

#

if you call a function or event locally it's always going to occur (it would be impossible to make a program otherwise)

exotic wasp
#

IMO, if you have RPCs triggering RPCs, might be best to evaluate design

pliant cypress
# pliant cypress So I'm looking at it now.
void AHitScanWeapon::Fire(const FVector& HitTarget)
{
    Super::Fire(HitTarget);

    APawn* OwnerPawn = Cast<APawn>(GetOwner());
    if (OwnerPawn == nullptr) return;
    AController* InstigatorController = OwnerPawn->GetController();


    const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash");
    if (MuzzleFlashSocket && InstigatorController)
    {
        FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh());
        FVector Start = SocketTransform.GetLocation();
        FVector End = Start + (HitTarget - Start) * 1.25f;

        FHitResult FireHit;
        UWorld* World = GetWorld();
        if (World)
        {
            World->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility);
            DrawDebugLine(World, Start, FireHit.ImpactPoint, FColor::Red, false, 5.f);
            
            if (FireHit.bBlockingHit)
            {
                ASoldierCharacter* SoldierCharacter = Cast<ASoldierCharacter>(FireHit.GetActor());
                if (SoldierCharacter)
                {
                    UGameplayStatics::ApplyDamage(SoldierCharacter, Damage, InstigatorController, this, UDamageType::StaticClass());
                }
                if (ImpactParticles)
                {
                    UGameplayStatics::SpawnEmitterAtLocation(World, ImpactParticles, FireHit.ImpactPoint);
                }
            }
        }
    }
}

when i fire, the player hit itself instead of player at which gun/weapon is aim at. then i tried to use FCollisionQueryParams in which ActorIgnore i added GetOwner(), then it made all player character to ignore the line trace.

exotic wasp
pliant cypress
exotic wasp
#

if you don't do that you're pretty much guaranteed to hit yourself unless it's on a different layer

pliant cypress
exotic wasp
#

did you add the other actor to the ignore list?

pliant cypress
exotic wasp
#

that shouldn't ignore the other player then

#

so something else is causing it to not collide

pliant cypress
#
            FCollisionQueryParams QueryParams;
            QueryParams.AddIgnoredActor(GetOwner());
            World->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility, QueryParams);

this is my code when i added Ignore Actor

#

Also, i have 2 mesh

pliant cypress
#

but the weapon is attach is single mesh based on IsLocallyControlled

exotic wasp
#

how are you calculating start and end?

pliant cypress
# exotic wasp how are you calculating start and end?
    const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash");
    if (MuzzleFlashSocket && InstigatorController)
    {
        FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh());
        FVector Start = SocketTransform.GetLocation();
        FVector End = Start + (HitTarget - Start) * 1.25f;
exotic wasp
#

what is Hit target?

pliant cypress
#

HitTagret is being calculated in Tick calling CrosshairTrace function which is doing LineTRace per frame

#
void UCombatComponent::CrosshairTrace(FHitResult& HitResults)
{
    FVector2D ViewportSize(0.f, 0.f);
    if (GEngine && GEngine->GameViewport)
    {
        GEngine->GameViewport->GetViewportSize(ViewportSize);
    }

    FVector2D CrosshairLocation(ViewportSize.X / 2.f, ViewportSize.Y / 2.f);
    FVector CrosshairWorldPosition;
    FVector CrosshairWorldDirection;

    bool bScreenToWorld = UGameplayStatics::DeprojectScreenToWorld(UGameplayStatics::GetPlayerController(this, 0), CrosshairLocation, CrosshairWorldPosition, CrosshairWorldDirection);
    if (bScreenToWorld)
    {
        FVector Start = CrosshairWorldPosition;
        FVector End = Start + CrosshairWorldDirection * TraceLength;

        GetWorld()->LineTraceSingleByChannel(HitResults, Start, End, ECollisionChannel::ECC_Visibility);

        if (!HitResults.bBlockingHit)
        {
            HitResults.ImpactPoint = End;
        }
    }
}
exotic wasp
#

so your linetrace end is dependent on that line traces end?

pliant cypress
#

yes

#

this function is called inside tick

exotic wasp
#

that does not make sense

pliant cypress
#
// Called every frame
void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    if (SoldierCharacter->IsLocallyControlled())
    {
        FHitResult HitResults;
        CrosshairTrace(HitResults);
        HitTarget = HitResults.ImpactPoint;
    }
}
exotic wasp
#

you are trying to linetrace from your gun to shoot something, right?

pliant cypress
pliant cypress
#

yes

exotic wasp
#

why does it trace each frame?

pliant cypress
#

to change the color of crosshair

#

which i'll add once i found a texture of crosshair

#

and interactions (future interactions such as door, etc)

exotic wasp
#

does this cross hair trace work correctly?

#

like I'm fairly certain the end point of the trace isn't being calculated right

#

it should just be Start + RotatedUnitVector * length

pliant cypress
pliant cypress
#

gotcha, line trace again messed up

pliant gull
#

does anyone know what is the best way to replicate a actor component in the player controller to the HUD/user widget

#

currently I have the onrep trigger a delegate to broadcast to the huds but since HUD is on the client it doesn't recognize the delegate as bound and doesn't send( if I understand it correctly)

#

I thought maybe replicate from the player controller to itself so I can access it client side for whatever I may need. although I'm not sure if this is a good idea or seen as a bad way of doing it

nova wasp
#

is it bound or not

#

the player controller is a fine place to replicate things if they are intended for things that are only for you and the server

#

you can't see other player's player controllers as a client

#

a HUD should just represent game data

#

how the game data gets there is not the hud's problem

#

the onrep of course would only do anything to the hud when the hud is actually there

pliant gull
nova wasp
#

do you bind anything to it?

pliant gull
#

yea

#

it works for listen server client just not joining client

nova wasp
#

can you gaurantee that the binding occurs BEFORE the onrep?

#

if the binding can come later the first binding must also trigger the whatever the onrep was supposed to do

#

debug it

nova wasp
#

I am not sure what you are doing here between other players or what changes the onrep

pliant gull
#

not between player controllers

#

just one player controller and his hud

#

independent from each player

#

if that makes sense

nova wasp
#

and what is the onrep?

pliant gull
#

the onrep just calls my delegate to be broadcasted with the updated variable as argument

nova wasp
#

what order does the hud and onrep happen in relative to one another on each side?

#

in multiplayer stuff you cannot make assumptions about order much

pliant gull
#

well my character walks up to an NPC presses a button which sends rpc to adjust the variable and onrep broadcasts delegate

nova wasp
#

if the onrep happens before it can be bound on the local machine the binding later can just also pretend the onrep just happened if the data is already there

#

pretty common pattern

pliant gull
#

the delegate is bound on beginplay

#

like 0.5f afterwards via timer or whatever it's called

#

and isbound returns true

#

upon begin play

nova wasp
#

never use timers to "fix" netcode...

#

if that's for the button itself that's fine but you need to not rely on this randomly being .5 seconds

#

you have still not answered my question about the order of the binding relative to the onrep

pliant gull
#

I'm not quite sure what you mean by that question

nova wasp
#

just add a print statement or something... sheesh

pliant gull
#

I have done that

#

the delegate gets bound on beginplay

#

the onrep gets called during play

#

which broadcasts the delegate

nova wasp
#

so what's the issue then? I am confused

#

is it not actually bound later on?

pliant gull
#

when broadcasting it returns not bound

#

isbound()

nova wasp
#

I don't see how you bind it

#

going off of your description piece by piece is extremely difficult

#

show the declaration of the binding, the thing that binds it, and proof something actually binds it and the onrep is called on the client

#

use GetDebugStringForWorld(GetWorld()) to get a nice log that changes for each client/listen server

#

you need to bind the hud's delegate locally on their machine of course (well, world in the editor)

pliant gull
#

I have PC->OnMoneyUpdated.AddDynamic(this, & namespace::functionname) which is proceeded by an if statement checking isbound returning true. done in the player HUD

nova wasp
#

"I forget?"

pliant gull
#

I'm not at my pc

nova wasp
#

I don't really think I can help much without seeing the actual code here, sorry

pliant gull
#

okay no problem

nova wasp
#

at least I can say consider using AddUniqueDynamic to make sure it's not repeatedly binding but this should not be an issue here

pliant gull
#

on begin play this returns =bound for both server and client. when called during play returns false

#

but I can send full code at later time

nova wasp
#

Well, do you unbind it? is it actually the same playerstate?

#

Also I am confused

#

you said this was in the controller

#

this is a playerstate

#

remember: I can only read what you show me so leaving stuff out makes this harder

pliant gull
#

yea this is old picture but same thing copy pasted into player controller

nova wasp
#

I am not interested in seeing old information and imaging what it looks like...

pliant gull
#

yea sorry I'll try to post proper code when I can

nova wasp
#

I feel like the mystery here is why it's suddenly not bound

#

does something unbind it?

pliant gull
#

no

#

it should remain bound throughout the game

nova wasp
#

does the object that representsd the bound delegate get destroyed?

pliant gull
#

my understanding is the player controller on the server does not know of the HUDs existing. so my thoughts were that because the delegate is bound in HUD it doesn't work

nova wasp
#

why would the server controller care about the hud?? (for non-local players)

#

you need to bind this on the local machine's player controller when they have a hud ready

#

the server of course has all player controllers on it

#

the hud only exists for you locally

pliant gull
#

yea

nova wasp
#

but everyone has a local player controller

#

if you are only binding this on the server this of course will... only work on the server I think

pliant gull
#

yea but from the server how would I bind to the HUD if it doesn't know it exists

nova wasp
#

you wait for it to exist by overriding/binding to various hud related things

#

LOCALLY

#

it would be easiest to just do it in the beginplay of the hud itself

pliant gull
#

which is exactly how it is

#

in the begin play of HUD I bind it

nova wasp
#

which I cannot see and you have not described...

pliant gull
#

snippet

#

anyways I can post full code at later point I'm sorry I can't now

nova wasp
#

you said "the delegate is bound on beginplay" which I suppose makes sense to be the hud but I am having trouble tracing through the 40 different messages to piece this together

hoary spear
#

Help us help you, kinda thing

pliant gull
#

lol

#

ye I'm trying

#

I'll redo

#

in the playerHUD on begin play, the HUD binds to a delegate located in the PC which is then checked Isbound and returns true. in playtime, I call adjust component via RPC. now In playercontelllerwhich and successfully adjusted the component. Onrep is called. which broadcasts the delegate which fails cuz Isbound returns false.

#

it works for the server not for the client

hoary spear
#

So its not bound on the client

pliant gull
#

yea when called during play it returns not bound

nova wasp
#

"adjust component via RPC"

#

with no details on the rpc

hoary spear
#

I think this is a simple race condition

#

Server vs client thing

nova wasp
#

yeah which is why I asked multiple times to see if the onrep was before the hud beginplay or not (the binding I suppose)

pliant gull
#

it's after

#

I understand that calling an onrep on nothing wont work

hoary spear
#

Calling the onrep keeps it local to the caller

pliant gull
nova wasp
#

also initial onrep might not happen if its unchanged

hoary spear
#

E.g. if server calls on_rep -> the function executes om the server

#

If client calls on_rep -> the function executes on the client

nova wasp
#

onrep on client can be called manually by you if you want but otherwise it is from replication only

#

it's fine to locally call an onrep as a way to make sure it gets called

pliant gull
hoary spear
#

What also confused me when i first got i to mp was that i somehow imagined delegates being bound across client/server.

But client and server have seperate sets of these delegates, and must be bound accordingly.

nova wasp
#

no...

#

it is time to read the pins

pliant gull
#

I have. maybe my most recent statement is false but when the onrep is called it's running on server. it says server:delegate not bound

#

not client:delegate not bound

hoary spear
#

Then its not bound on the server

nova wasp
pliant gull
hoary spear
#

You normally dont

pliant gull
hoary spear
#

You need to do it through a replicated actor

nova wasp
#

then you aren't replicating anything

hoary spear
#

E.g. playercontroller

nova wasp
#

I think at this point I need people to fill out a form proving each log they have fires on both client and listen server or something

#

the reason it's not firing though if it is on a valid replication property on a replicating object could be that it doesn't think the notify is different etc

#

read the page I linked

pliant gull
#

I already have

pliant gull
nova wasp
#

maybe it's time to read the page again

hoary spear
#

Onrep only calls on difference, doesnt it ?

hoary spear
#

Right right

#

Rep always is an option

nova wasp
#

if this entire time this wasn't actually a replicating property I am going to say don't refer to it as an onrep

#

also you don't NEED to bother with notify always... the actor can just call the onrep function itself locally on beginplay etc

#

that way you can kinda "respond" to the initial state

#

you can even override onrep functions from parents if they are virtual in c++

pliant gull
#

yea i believe the onrep is called initially just to get something but I may be mistaken.

nova wasp
#

since you have said both that it does fire and that it doesn't fire I think I'm going to go do something else for a bit until you can actually show what is happening

#

I get it if you aren't around the computer or whatever but I can't really help like this

pliant gull
#

well I never said it doesn't fire I said it always fires on server but yes I'll post codes when I can and thank you for the help and sorry for the trouble

nova wasp
#

the reason I asked right before this about the order it happens on both sides (client and server)

#

was to see if it also fires on client at all

#

I ask these questions because I want to help

pliant gull
#

yea just I had no idea it had to fire on the client

nova wasp
#

like I said in multiple ways before

#

the server is a separate computer

#

the server does not see your hud on your client

#

the client is a distinct physical machine

pliant gull
#

I know

#

I have read the compendium

nova wasp
#

so in order to use the local hud it kinda needs some kind of callback from either replication or just reading local data as-is

#

I think it might be interesting to make a simple article/post on how to make a widget work in multiplayer stuff because it seems like an extremely common problem for new people here

hoary spear
#

Indeed it is

nova wasp
#

long story short the widget exists LOCALLY on the machine and just reads incoming replication data or does things in response to it on real gameplay objects

#

in most cases

#

the widget itself won't be replicating etc

pliant gull
#

yea

#

that's why I first asked because I knew something wasn't right because otherwise this would be working to instead replicate the variable to the controller itself instead of sending it to the widget

hoary spear
#

I tend to push mine through the playercontroller, albeit i dont reaaaallly like the design after a while

nova wasp
#

if the player controller is getting too crowded you can always make a replicated component on it

#

or the playerstate etc

hoary spear
#

Yeah thats true

#

That would clean it up a tad tbh

torn hull
#

Hey, when I'm replicating a variable that's an object reference, am I only sending the address to that object? I'm not sending the size of the object itself, right? This object is replicated in its Blueprint.
(First screen is from the object, and second is from the character blueprint)

chrome bay
#

For obvious reasons you're not actually sending a memory address

torn hull
chrome bay
#

essentially yeah

pliant cypress
#

i am getting this very unsusual kind of behavior

#

which i am not able to understand from why this happening

#

like i just opened ue and it start happening

#

it was working finely befor

#

i did clean rebuild

#

the weapon was expected to collide the floor and stay on it

#

not to dissolve itself inside it

#

If the player picks the weapon, it should pick it up for the weapon fps mesh on local but on Tp mesh for Simulated proxies

vocal current
#

I can't remember if attachment replication is something you can turn off or not (one of those things where I'd have to be in front of a computer to go check, but I'm watching baseball at the moment 😁). But if you're making the attach call on the server, then that will probably replicate down to clients IIRC. So whatever you attached it to would be what it ended up being attached to on clients. Though if you did turn it off, you'd have to make sure that the logic that attaches purely client side, is run when someone joins in progress.

Tbh if you have shadows in your game you'll probably want both a first person and third person mesh for your weapons. (So that you correctly see the shadow of the third person weapon attached to your third person character in the shadow)

ocean swallow
#

I think this is the third time I've asked this question. I use OnlineSubsystemSteam for multiplayer. My engine version is UE5.6.1. I used the method in this video to fix the connection issue. https://youtu.be/Pk_Ki8rV8Wo?si=NaNsplMx2GE_1Qzn
Now I can only join the game through friend invites. The search function doesn't work. However, there's another major issue: if anyone quits the game, the server crashes. The crash log is in crash.log. I've followed other people's suggestions and modified it to the current Blueprint method, but it still doesn't fix the problem.

  1. Enable OnlineSubsystemSteam AND SteamSockets
  2. Replace the NetDriver definitions in your DefaultEngine.ini file with the one below!

UPDATED - 7/16/2025

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefi...

▶ Play video
#

The game map and the default menu map use different controllers, and the picture shows the controller of the menu map

ocean swallow
#

Does anyone else use UE5.6 + OnlineSubsystemSteam?😭

royal monolith
#

does anyone know why I have this issue with replication:

If I have a character BP enemy that turns into a ragdoll when I shoot it, after I shoot it a couple times once it's already a ragdoll, it's position won't replicate when it moves around from being shot, but if I grab it and move it around it will replicate perfectly

if I have an actor BP, with the same exact logic, it will replicate perfectly
is there a specific difference between character bp and actor bp when it comes to replication?

all the checkboxes and settings for replication are exactly the same in both BPs

tardy fossil
#

maybe the actor has the mesh as the root component where the characters root component would be a capsule

#

the fully simulated ragdoll would detach from the capsule

knotty bane
#

the error indicated something with the netdriver

knotty bane
#

but why its different from when using an actor bp i cannot say

ocean swallow
chrome bay
#

There are multiple ways to do it, but the way I've done it is a custom movement mode that makes the capsule follow the ragdolling mesh on the Server, and replicating extra info about the meshes rigid body state to clients, and feed that into physics replication locally.

exotic wasp
#

how do you usually handle gameplay relevant replicated ragdolls? like interacting with one to loot it or something

chrome bay
#

I replicate data from a few rigid bodies form the server and apply it to clients. Not much too it really

#

If you just pipe the rigid body states into physics replication and switch to predictive interpolation mode, it pretty much does it all for you

#

Don't need it to be perfect, just close enough

mystic estuary
olive quiver
#

How do you replicate widgets?

I am tryna make a health bar like in League of Legends where everyone can see everyone’s health above their head and the bar is also coloured for if they are on team red or team blue.

I am having an issue where every player can only see their own bar updated and the other players just have the widget set to default, so the text block just says insert text.

Anyway around this?

dark edge
#

you replicate the data the widget uses

#

Locally, on all machines, you color the widget based on the units team compared to the local players team

#

A healthbar depends on 3 things.

  1. The units health
  2. The units team
  3. The local player's team
#

assuming you want your team to be blue and the enemy to be red

olive quiver
#

I have already replicated the data for the health bar(as of now it’s just the team because I wanted to focus on one thing before I added health)

But I don’t know how to use that data properly, I am trying to update all the widgets for the characters with the data I have about them, the team, but I’m stuck to be honest.

dark edge
#

show code

#

I'm assuming this is a widget component that displays the widget in 3d space

olive quiver
#

Im not at my PC right now, but even if I was it’s a massive spaghetti mess. I call so many things from so many places I don’t think it would help that much.

Could you just tell me how you would do it(if you know how of course)?

dark edge
#

Simplest approach is just to have the widget know about the unit it's meant to show the hp of, and be fed that information on begin play.
Then the widget can tick and read its units hp and such and update itself. There's certain optimizations about not wasting work ticking if your hp isn't changing but get it to work first before trying to make it work efficiently

#

From the POV of the widget it's like this:

Tick -> if MyUnit is valid -> update self based on MyUnit.Health

#

it has to be told what MyUnit is from elsewhere, you'd do it in begin play of the unit, just pass a self ref to the widget components widget

olive quiver
#

I am doing that already, and on begin play it’s doing that and working fine, the problem is that when a widget changes and updates(like a health bar does) that change isn’t reflected to the other clients.

The server can see it all fine and on the server side it works perfectly but it’s not replicating to all the clients, the widget just stays how it was when it was first initialised.

dark edge
#

widget is the end of the chain

#

nothing depends on it

#

first make sure that data is getting replicated correctly

#

widgets don't replicate, the only way you and i see the same widget is if it was constructed and updated based on the same underlying state which lives somewhere else

#

I'm guessing you're either not replicating something you should be, or your widget isn't caring about the right unit

olive quiver
#

Okay, I was (trying) to replicate the team state(I have it as an enumeration), but I guess it’s not working properly then.

Do I need to make an on rep notify event for my team variable on the player state which then calls a function in the widget?

dark edge
#

don't worry about talking to the widget at all right now

#

later you can handle that

#

don't tell the widget anything besides who it cares about, have it poll and get data on its own to make sure it actually works.

#

Tick -> if MyUnit is valid -> do stuff based on MyUnits health -> do stuff based on MyUnits team -> ??? -> profit

vocal current
olive quiver
#

Okay, thanks for your guys advice.

I am thinking that(when I get back to my PC), the first thing I should do is bind my widgets bar full colour a function that gets the enum for my team variable from the player state and updates the bar accordingly. Then later try and make it a bit more optimised.

Is that a good first step?

vocal current
#

Yeah that'd be a good way to prototype it. Plus you'll know right away if the team enum is not replicating for some reason

dark edge
olive quiver
#

What do you mean exactly by unit?
Im new to multiplayer so I’ve never heard that terminology before,

If you are talking about each player then every player has a team which is stored on the player state, although to be fair I move it around quite a bit it’s starting to get a bit messy 😂

serene copper
#

Hello 👋
I hope someone can help me out as I cannot find a solution to my issue.

I have a packaged game on Steam which has co-op elements.
I am currently running into an issue where I am not able to normally start up a round in coop with 2-3 players.

Loading into the lobby works fine for host and clients. As soon as I start the gameplay map, either all players or all except the host receive a "Fatal Error" message and the game crashes.

I think it used to work fine but does not work anymore nowadays, even though I believe I have not touched anything regard the multiplayer logic in BP.

Could someone help me out? It would be greatly appreciated!

#

I launch the game here when the host presses the launch button.
Image 2: Here is the Server Travel logic.
Image 3: This is the game manager in the new map which then does logic stuff.
Thanks!

dark edge
#

I thought you were talking about a MOBA, where there's creeps

olive quiver
#

No, it’s just the players

dark edge
#

yeah so anyways, it's that simple.
Somehow get the widget to know what playerstate or pawn or both it cares about, and let it pull data to update itself. Get that working.

#

Then later you can worry about doing it in response to dispatchers etc.

olive quiver
#

I’m tryna do it now actually but I can’t get it working.

I am trying to just do something basic but it’s not working.

My current system is just when I press 1 update the team and have it replicate but the server is the only one that is seeing a consistent change but on the server it’s updating all 3 widgets even when it’s one person pressing the key.

I made a blank project to test the absolute basics and I got it working there but it’s just not transferring 🤦

olive quiver
#

Bro, it’s literally the biggest mess ever haha. It’s over a few blueprints as well

#

I just made this, with the health being replicated and there is a wiudget that just binds to healkth.

So far, for this part it works 100 percent fine, but when I try and integrate it to the actual health bar... it doesnt exactly work

#

The first one is from the player character, I dont hold the team on the character but rather the player state so thats why I call to the player state. The secvond is what gets called on the player state. The thirtd is ther bind I have on the widget. The fourth image is how we send the player state to the widget. I have two widgets because I did them as world and put them back to back but thats just a stylistic choice it makes no difference here

dark edge
#

in your widget BP, give it a playerstate or pawn reference and set it from outside. From then on you don't have to talk to it at all ever

#

Also this is bad

#

the widget doesn't care about player state 0

#

it cares about the player state that it's meant to represent the health of

#

anything with get player state by index or get player controller by index should just be deleted from your project, it's 100% barking up the wrong tree

#

why is get match player state REF an interface anyway?

olive quiver
#

The honest answer to that is I just did it and went with it, I didnt really look to much into it cuz it worked.

As for getting the player state, I thought if I got index 0 it meant get the player state of the thing we are in, but if thats wrong then how would you get the player state of the controller/character you are in? Can you just say get reference to self then drag off and search for player state?

Btw I fixed the issue and got it working, I moved the replicated team variable from my player state to my player character, I still sort of store it in the player state but when I update it in the player state I also update it in the player character. I also found that my re notify event wasnt actually firing every time I updated my variable so a made a custom event that changes my variable and fires the necessary events. This probably isnt the best wayb to do things but at least now its working I can start optimising

thin stratus
twin vessel
#

How do i get the current size of a FArchive?
(I need to get the size at the beginning and end of a NetSerializer to log how many bits i serialized)

thin stratus
olive quiver
#

So between these two I need to use the one on the right? its kind of obvious now I am looking at the side to side cuz ones marked as replicated

thin stratus
#

Yes, but it has nothing to do with the replicated part.

#

Imagine, in real-life, you have 5 people standing in a row.
You ask all of them to place their phone onto the table, one next to the other, but in a random order compared to how they are standing.
While they do this you aren't allowed to look.
After they are done you have two options.

  1. Ask a specific person to take the first phone.
  2. Ask a specific person for their phone.
#

GetPlayerState(0) is option 1. it will give you the first phone/PlayerState in on the table/in the PlayerArray, but you can't be sure that it's the phone/PlayerState of the person you asked.

Using the PlayerState variable (or a getter of the class) directly, is option 2.

olive quiver
#

who stores this list then? it makes sense that there is a list but where is it? is there some behind the scenes global list of all the player states?

thin stratus
#

Yeah, for PlayerStates specifically you have the GameState's "PlayerArray".
While it contains all PlayerStates, they aren't necessarily in the same order, because the PlayerArray isn't actually replicated. It gets manually filled due to each PlayerState replicating down to the individual player. So the order can differ.

#
class APlayerState* UGameplayStatics::GetPlayerState(const UObject* WorldContextObject, int32 PlayerStateIndex)
{
    AGameStateBase* GameState = GetGameState(WorldContextObject);

    if (GameState && GameState->PlayerArray.IsValidIndex(PlayerStateIndex))
    {
        return GameState->PlayerArray[PlayerStateIndex];
    }

    return nullptr;
}
#

If you can read a bit of c++, this is what that node does.

#

Gets the GameState. Gets the PlayerArray from it and grabs the matching PlayerState for 0 (or PlayerStateIndex). Or nullptr (nothing) if that index is invalid.

#

Using those GetPlayerXYZ(Index) nodes is always rather rare.

#

You usually want to make sure you stay relative to the actor you are in if possible.

olive quiver
#

That makes good sense, thanks for explaining👍

thin stratus
#

Let's assume you have a Weapon Actor Blueprint that you spawn for a given Player. Since your Weapon Actor isn't a Pawn or Controller, it has no PlayerState variable by default.

If you want to know the PlayerState of the Player that "owns" the Weapon, you usually want to forward either the Controller (if it's only needed for the local player), the Pawn (if it's needed for everyone), or fwiw just the PlayerState of the Pawn/Controller directly to the Weapon.

#

So you build that "link" yourself by just forward the relevant data further and further.

#

Weapon fires a Projectile Actor? Same story. Weapon can give the Projectile Actor the Pawn/Controller/PlayerState.

#

In most cases, for Multiplayer, you usually specify the "Owner" pin on the SpawnActor node.

olive quiver
#

to be honest my main point of confusion was I thought that when I got index 0 I was getting the local, I thought the list started at 0 from whatever you were on, so you would get the list in a new way relative to where you are. I know that doesn't really make sense nown I know how it works but I guess thats what learning is😂

thin stratus
#

And forward the Controller that way. You can then also use the "Instigator" pin for the Pawn for example.

thin stratus
olive quiver
#

Haha, I am just happy its working to be honest. This is my first time touching multiplayer so the fact it works is good enough(for now)

thin stratus
#

GetPlayerController(0) is something you will see a lot of beginners fall back to and tutorials plaster it everywhere. And then people don't know why they are starting to get the wrong PlayerController when they try to respawn Client 42 on the Server and the Server grabs its own PlayerController the whole time....

#

#multiplayer message

I looked into the exact shit that goes on when that node is used, in case you want to learn that.

olive quiver
#

there arent enough good multiplayer tutorials, they all basically stop after the very basics, none of them really explain sutff in great detail. To be honest I think youtubers dont want to cuz they probably dont even know themselves haha.

thin stratus
#

And that starts a domino effect.

wet pasture
#

Or can this also differ sometimes

thin stratus
#

Yeah, I mean I wrote that in the list I linked iirc

quasi tide
quasi tide
#

I do a tutorial every here and there and even then, it takes up a lot of my time that I simply don't have. Having to also plan a project around teaching someone? That would be extraordinarily long. Especially one that covers production level issues.

thin stratus
#

I know a lot of peeps like learning via videos and audio. I probably also like that more, but this format has a huge problem: You can't easily update it.

#

So if I were to make tutorials in the future, I would probably only do more written ones.

quasi tide
#

Written ones take more time for me 😅

#

I've been meaning to sit down and write one for the State Trees as well. But guess what? NO DAMN TIME

thin stratus
#

Yeah, I wrote a lot of documentation for NPP and Mover for my client.
Can't recall if I was allowed to transfer that into a blog post.
Will probably ask in the future.

#

by the time I will, NPP and Mover will probably be dead

quasi tide
#

So, if I were ever to do a tutorial on networking stuff - it'd only be concepts and potential pitfalls with the most basic of basics of projects.

thin stratus
#

Aka the YouTube tutorials oliver doesn't want.

quasi tide
#

Well - it'd certainly cover the networking of Unreal more than that

thin stratus
quasi tide
#

I'm talking about not doing rollback or perfect client prediction, etc...

thin stratus
#

Touché

#

What I would be interested in making one or more tutorials for would be "Gameplay System Designs".

#

So like, if one were to make Gameplay System XYZ, how could a few variations be structured to fit nicely into UEs framework and why.

#

Cause that seems to be one of the biggest problems for beginner and intermediate level. They might understand how to replicate a variable, but they can't connect the dots yet.

quasi tide
#

Just put everything in the GameState. It's all the state of the game after all.

#

Easy architecture

#

Good luck browsing 🥳

thin stratus
#

*Reliable Multicast everything.

quasi tide
#

Reliably on tick

thin stratus
#

I will never forget that one client I had (some VR ArcViz stuff), where they weren't able to spawn a chair anymore and they didn't understand why. Took a me a bit back in 4.idk to find the reliable RPC on tick that was causing nothing else to replicate anymore :D

soft vortex
#

I'm playing around with replication stuff and I'm seeing a property being replicated without use of DOREPLIFETIME macro. If I add Replicated in UPROPERTY, it seems to replicate without issues (if I remove Replicated, it doesn't replicate at all, of course).

#

I'm testing this with listen server, 2 clients.

#

Is that expected?

thin stratus
soft vortex
#

What do you mean by that?

thin stratus
#

At least iirc, Epic changed it so DOREPLIFETIME isn't needed anymore unless you want to do something specific.

soft vortex
#

Oh nice! You're right, just found that in 5.6 release notes: "Replicated UProperties no longer need to register themselves via DOREPLIFETIME in GetLifetimeReplicatedProps."

thin stratus
#

Ah, yeah you were faster than me.

soft vortex
#

This is great, thanks!

lost inlet
#

but I'm usually opting into push model these days

nova wasp
#

I'll say I honestly might still prefer to just getlifetimereplicated props

#

it's kinda nice how it has everything in one place arguably lol

#

but that is a good change

#

no need for the boilerplate if you aren't changing anything

hoary spear
#

Is there an event that i can hook into for when 'any' data was replicated in a UObject ?

#

or any BP property is replicated ?

#

PostNetRecieve and PostRepNotifiesseems interesting for this

hoary spear
#

Hmm nah that didnt work apparently. Never getting called

#

Hmm. Maybe it is

#

Im looking for a method that's called only if a replicated property is changed

hoary spear
#

I can use bp repnotifies but i was hoping to avoid that

lament flax
#

PostRepNotifies

#

is called

#

only for repnotify tho, not classic replication (i think)

hoary spear
#

I'd want something for just regular replicated properties aswell if something exists

#

the point is trying to avoid forcing the user to handle the repnotify updates themself

pliant cypress
#

i am using HasAuthority in most places such as ApplyDamage inside Fire and FinishReload (called via AnimNotify) due to which both system doesn't work and i don't want the clients to do work which can come handy with cheats

#

such as here

#
void AHitScanWeapon::Fire(const FVector& HitTarget)
{
    Super::Fire(HitTarget);

    APawn* OwningPawn = Cast<APawn>(GetOwner());
    if (OwningPawn == nullptr) return;
    AController* InstigatorController = OwningPawn->GetController();


    const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash");
    if (MuzzleFlashSocket && InstigatorController)
    {
        FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh());
        FVector Start = SocketTransform.GetLocation();
        FVector End = Start + (HitTarget - Start) * 1.25f;

        FHitResult FireHit;
        UWorld* World = GetWorld();
        if (World)
        {
            World->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility);
            DrawDebugSphere(GetWorld(), FireHit.ImpactPoint, 12.f, 12.f, FColor::Red, false);
            if (FireHit.bBlockingHit)
            {
                ASoldierCharacter* SoldierCharacter = Cast<ASoldierCharacter>(FireHit.GetActor());
                if (SoldierCharacter)
                {
                    if (HasAuthority())
                    {
                        UGameplayStatics::ApplyDamage(SoldierCharacter, Damage, InstigatorController, this, UDamageType::StaticClass());
                    }
                }
                if (ImpactParticle)
                {
                    UGameplayStatics::SpawnEmitterAtLocation(World, ImpactParticle, End, FireHit.ImpactPoint.Rotation());
                }
            }
        }
    }
}
lament flax
#

But idk how you read them to know if its a RPC, replicated var or other

hoary spear
#

My context is a quest system. Where i want a quest task's replicated property to sutomatically update the tasks UI through a delegate

#

Being subclassed and freely used in bp I was hoping for a method to allow for it to 'just work' with replicated bp properties aswell

exotic wasp
#

It really sounds like you just need a OnRep tho

exotic wasp
pliant cypress
#

And make sure those manipulated players are removed

hoary spear
pliant cypress
exotic wasp
#

With validate will kick even if a player has a accidental bad data send

pliant cypress
exotic wasp
#

Idk on you to figure that out

exotic wasp
hoary spear
#

Tmap doesnt replicate. Guess i gotta dive deeper and see if theres anything i can catch somewhere

#

Its purely for convenience that i wanna make this handled automatically

exotic wasp
#

You would probably want a fast array so you can get per element callbacks

hoary spear
#

Was hoping Cedric had some awesome wisdom to share on this topic

meager spade
#

i mean what kinda data is this

#

@hoary spear

#

its a bit vague what your trying to do

#

maybe a bit more context

crisp copper
#

does anyone know if spawning actors (a projectile) can work in a predicted gameplay ability. the only results i managed to get is 1. the projectile only spawns on the client, or 2. the projetile spawns twice on the client who fired it (but once on other clients). should i not use a gameplay ability for it? since i might not need prediction for it since that aspect is partially client authoritative (and is partially validated by the server)

meager spade
#

abilities dont do any prediction regarding actor spawns etc

#

if you want predicted projectiles then you should make functions to do that

#

this is not something supported in abilities out of the box

weak solar
#

Hey there! I can't seem to find crash dumps for our Linux dedicated server. I can find logs just fine, but no dumps. Is there something I'm missing?

meager spade
#

you ability can call functions to spawn projectile, but you should manage the "prediction" side of that projectile yourself. you could listen for the ability being rejected from server and destroy client side projectile, or accepted, etc.

weak solar
hoary spear
#

I want to know about it and handle some callbacks

meager spade
#

PostNetReceive

#

should handle it

#
    COREUOBJECT_API virtual void PreNetReceive();

    /** Called right after receiving a bunch */
    COREUOBJECT_API virtual void PostNetReceive();```
#

in pre you could get all the rep properties

#

cache the value or w/e

#

then in post see if that value changed

#

or w/e

hoary spear
#

Hmmm that might be it yes! Thanks 🙂

hoary spear
#

Hmm but these wouldnt trigger server side ever, right ?

#

I could just solve that elsewhere tho , should be fine

hollow gate
# thin stratus by the time I will, NPP and Mover will probably be dead

Npp isn't dying bro. Epic is supporting it. Publically encouraging others to use it. Makes no sense to have a talk in unreal fest this year specifically about NPP if they are not promoting it or it's out of support .
Mover is already in fortnite granted the chaos one but it's still same component, if it's in UEFN already it's not so "experimental" is it!. Do you have some insider info public isn't aware of , or this is personal opinion?

thin stratus
nova wasp
#

NPP always seems to be in this awkward state of almost not happening despite being used in mover

#

for example unless they fixed it recently it doesn't serialize correctly in iris

#

it has kinda changed hands multiple times as people leave epic here and there

#

at least since a few years ago

hollow gate
#

I swear i saw you say the same thing many many times. Might be mistaken 😅

nova wasp
#

it's a complicated problem of trying to make a generic prediction system that somehow meshes well with the rest of the random gameplay codebase

#

they have a lot of cool tooling at least

pliant cypress
#

i have a fire function which do line trace from muzzle socket. It works perfectly for the server but on client the logs are this

LogTemp: Warning: Hit : BP_SoldierCharacter1
LogTemp: Warning: Hit : Floor
LogTemp: Warning: Hit : BP_SoldierCharacter1
LogTemp: Warning: Hit : Floor
LogTemp: Warning: Hit : BP_SoldierCharacter1
LogTemp: Warning: Hit : Floor
LogTemp: Warning: Hit : BP_SoldierCharacter1
LogTemp: Warning: Hit : Floor

Note* weapon is doing automatic fire. Also, it should apply damage which isn't.

#

void AHitScanWeapon::Fire(const FVector& HitTarget)
{
    Super::Fire(HitTarget);

    APawn* OwningPawn = Cast<APawn>(GetOwner());
    if (OwningPawn == nullptr) return;
    AController* InstigatorController = OwningPawn->GetController();


    const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash");
    if (MuzzleFlashSocket && InstigatorController)
    {
        FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh());
        FVector Start = SocketTransform.GetLocation();
        FVector End = Start + (HitTarget - Start) * 1.25f;

        FHitResult FireHit;
        UWorld* World = GetWorld();
        if (World)
        {
            World->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility);
            DrawDebugLine(World, Start, FireHit.ImpactPoint, FColor::Red, false);
            if (FireHit.bBlockingHit)
            {
                UE_LOG(LogTemp, Warning, TEXT("Hit : %s"), *FireHit.GetActor()->GetActorNameOrLabel());
                ASoldierCharacter* SoldierCharacter = Cast<ASoldierCharacter>(FireHit.GetActor());
                if (SoldierCharacter && HasAuthority())
                {
                    UGameplayStatics::ApplyDamage(SoldierCharacter, Damage, InstigatorController, this, UDamageType::StaticClass());
                }
                if (ImpactParticle)
                {
                    UGameplayStatics::SpawnEmitterAtLocation(World, ImpactParticle, End, FireHit.ImpactPoint.Rotation());
                }
            }
        }
    }
}```


Fire function called like

Fire() -> RPC Server Fire() -> Set Combat State to Firing then EquippedWeapon->Fire same to OnRep.
thin stratus
#

Personal opinion would be that Mover is probably gonna be used. NPP on the other end I don't see evolving. We have a feed on commits for that plugin and since May this year, the only changes were either global engine changes or their attempt at getting the InputCmd to the SimProxies, which they reverted.

hollow gate
nova wasp
pliant cypress
# pliant cypress i have a fire function which do line trace from muzzle socket. It works perfectl...

for server, it do LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1
LogTemp: Warning: Hit : BP_SoldierCharacter_C_1

but for client, it hit server then floor

nova wasp
#

draw a debug line for both cases

#

compare the results

#

also comapre the current physics scene in both with the chaos debugger

pliant cypress
pliant cypress
nova wasp
#

not sure what else I could be referring to

#

you are asking to compare two things

#

compare them visually and the surrounding area

hollow gate
pliant cypress
nova wasp
#

the chaos debugger is extremely throughal and will show both the collision scene and the queries

#

so it should help

#

it's under debug

thin stratus
nova wasp
#

what does Chaos Mover do? is it the character constraint or just moving the cmc to tick inside of chaos?

pliant cypress
#

Gotcha

#

I'll check and report back

thin stratus
#

Aka it's part of the Physics Sim on the Physics Thread.

hollow gate
#

It means nothing for non physics gameplay. No game thread means making sims using it is not that simple. Something for the game thread is a must.

nova wasp
#

I am doing my own crazy stuff (Jolt/ and going COMPLETE fixed tick without any actors. every transform is smoothed in parallel during render frames etc)

#

but I have not gotten very far with reconciliation and rollbacks working well

hollow gate
#

Imagine GAS in another thread..

nova wasp
#

at this point I am getting a bit fed up with the complexity of full rollback and I kinda want to just do something simple

nova wasp
#

I don't do everything in parallel and I don't use any of the gameplay framework

#

the ideal is if you can simulate everything on both sides there is no need for complexity

pliant cypress
#

Megafunk, I couldn't find a good yt tutorial/video. Do you any for Chaos debugger?

nova wasp
#

but in practice it is absurdly difficult to get a stable sim in a 3d game

nova wasp
#

I'm sorry but you really should just google this

hollow gate
pliant cypress
nova wasp
#

my stuff is similar in some ways but the entire simulation is stored at once

#

besides a few rendering-specific things

#

the main complexity comes from animation and navigation stuff which is hard to make stable and where I kinda gave up on making it perfect

hollow gate
#

That is part of building the sim. Deciding what "state" (replicated dat) it needs , putting it in struct with cystom net serializer and that is prettt much all. From that point on , it's like singe player.
Example: mover, new mode = decide what replicated data you need, make struct , use struct in your mode and done. Can't get simpler than that

nova wasp
#

but with npp you don't NEED perfect results I guess

#

much like quake and all the others it's non deterministic, just very close

#

I can get detereministic physics already but the surrounding things are a bit too much

#

if I was making a 2d game it would be fairly simple to make a fixed point math setup that fits all cases and works on all platforms

#

but I need animation blending so... rip lol

#

so the idea is something where you have the predicton as a "good enough" approach and the server constantly sends new info

hollow gate
#

Valorant's way of dealing with the animations to get as "deterministic" result as possible ia pretty good. It's enough for riot should be enogh for us

nova wasp
#

yeah I don't need anything quite as fancy as encoding blends based on nodes

#

I just make my entire animation graph fully "immediate"

#

there are NO results based on previous bones if I can spot them

thin stratus
#

putting it in struct with cystom net serializer
Does that take Iris into account?

nova wasp
#

the animation state is ENTIRELY described in a single struct. this is restrictive because of course blends are insanely useful

nova wasp
#

unless they added that recently

#

so good luck lol

#

Iris serializers are immensly tedious but aren't that complicated ultimately

thin stratus
#

Well I know about NPP + Iris. We have that long fixed and working.

nova wasp
#

sweet

#

did you end up going with a polymorphic template?

pliant cypress
#

Btw, how do you guys hack your own game or do the anti cheat work? Like if I've a project and I want to find the vulnerability to exploit it and fix those bugs/patch them. How do you guys do that for multiplayer?

pliant cypress
#

Such as ESP, MaxHealth

nova wasp
#

I'm not an anti cheat engineer

pliant cypress
#

There's a GitHub I saw called UE-Dumper

thin stratus
hollow gate
pliant cypress
hollow gate
#

Correct me if am wrong

nova wasp
nova wasp
#

supporting future versions when iris is the default in a few versions most likely

thin stratus
nova wasp
#

if you don't have a slow netbroadcast /read you might not need to care

#

IMO they really should have a "I don't care if it's slow, give me a virtual callback" serialize setup as a fallback

#

but that said I rarely need to make a serializer

#

default struct serialziation is great

#

I have my own vector quantize thing becuase the built in ones aren't the right size for me

#

but it's simple stuff for the most part

thin stratus
#

The most annoying thing about the built in ones is that they don't have a conversion getter built in :D

nova wasp
#

also you can just make your own dumb as bricks "send as a uint32 and make a getter that makes it the real type"

#

there is RARELY a need for a custom serializer for pod types

hollow gate
nova wasp
#

delta serialization is optional

#

completely based on settings

#

atomic serialization is the ideal of course

#

you will still want to merge multiple properties into one struct for a real fast-paced game (gauranteeing the same frame read)

#

for example it even delta sends TArrays

#

you still need fast arrays for a nice callback though

#

also Iris lets you extend and add your own ID exports in 1 template and even sends gameplay tags over one

#

basically turning a giant amount of data (a string) into an id based on a negotiation

#

that is more advanced though

#

for a larger game with a lot of polling network objects using iris will be kinda required to not have godawful perf I think as repgraph is deprecated

thin stratus
nova wasp
#

and yeah delta on the individual property barely makes sense for anything but really huge structs and containers

thin stratus
#

Arrays is what it mostly makes sense for me.

hollow gate
#

Non deterministic replication is not ok for a prediction system.
As far as i know delta serialization in engine now can cause phantom states, as states on client that never happened on server due to mismatch in replicated deltas. I don't k ow if this is addressed in iris. I stayed away from iris and NPP because it doesn't offer any significant upgrades for a pvp past paced game that doesn't have 100 players. Something like a moba or valorant doesn't need iris at all

nova wasp
#

you can turn it off on a per-class basis

#

you have a fair amount of control over iris replication behaviour

#

and yeah with a low playercount you might be totally fine

thin stratus
hollow gate
nova wasp
#

if it helps unless you have a LOT of custom netserialize or somehow need repgraph the transition won't be too bad

#

it's mostly literally a cvar (well, or 3)

thin stratus
#

Unless you littered your code-base with NetSerialize overrides.

nova wasp
#

which is still useful because replays need those 🥹

thin stratus
#

Yaaa, DemoNetDriver rest in pieces.

nova wasp
#

it still works

#

it can work entirely alongside iris

#

which is absolute madness but it will work

#

it will cause a lot of subtle issues though lol

#

so if you need replays yeah... iris will not help you much right now

thin stratus
#

Yeah, I can't recall but I think replays are broken on our end. Don't know why anymore though. I vaguely remember that it crashed in NPP but we don't use replays atm anyway.

hollow gate
thin stratus
#

Bandwidth I can't tell, cause I never saw the traces for that. Performance increase mainly. But we also have some stuff in Iris multithreaded by now.

nova wasp
#

Iris multithreaded in main is only for the writing side

#

arguably it could thread reads but it would be fairly minor of a difference imo

#

the onrep callbacks cannot be threaded normally

hollow gate
nova wasp
#

I think I could add a simple parallel onrep read scheme that is an optional flag for when you know it's okay

#

but it would be... rare lol

thin stratus
nova wasp
#

curious what bandwidth part is the big offender?

#

are you sending full sized doubles?

thin stratus
nova wasp
thin stratus
#

So I think we are doing fine with what Iris offers.

nova wasp
#

Hot take: Unreal quantization would be instantly cheaper if you could define play area min and max
you would instantly be able to preclude a giant swathe of bits

#

it would only be reasonable for VERY specific types

thin stratus
hollow gate
#

Mover alone user 600bits min per client per update. With net relevancy and all other stuff you don't really replicate all 100 players at once but it can get bit high.

nova wasp
#

what exactly is it sending in the net profiler?

#

I've heard it's rough but that's a lot of bits lol

#

and no I do not mean stats, I mean the actual insights packet view

#
-DisablePython
-TraceAutoStart=0
-NetTrace=4
-tracehost=localhost
-trace=net,default,task

If you want a tl;dr on how to do that launch with this
edit: also if it doesn't show up in PIE stop and start an empty trace before playing... why does this help? I don't want to spend 2 days figuring it out to fix it lol

#

the first two are unrelated but still nice

hollow gate
#

Mover has couple of stuff in its replicated state, they add up. I wanted to kniw how iris helps with this. But it seems it does nothing. just for server pref when having big amount of enteties.

thin stratus
nova wasp
#

I would say you could compare raw transform sending in an empty project to compare

#

it should be fairly simple to turn iris on and off outside of mover

#

here's an example of me sending some float vectors and quaternions as floats

thin stratus
#

If Iris doesn't help your specific project, then that has nothing to do with what I meant.

nova wasp
#

I am hoping epic fixes the lack of correct serializers in npp instead of forcering everyone to do this

#

I think it would be fair of them to assume epic will resolve this on their end first

thin stratus
#

They probably will, yes.

hollow gate
thin stratus
#

I would need to trace bandwidth again to answer that. All I can say is that:

  • Our Mover is changed a lot. E.g. we aren't replicating MovementBaseLocation and Quat anymore.
  • We are running 100 player matches just fine in terms of Bandwidth. Mover/NPP isn't the only thing in the Game either, as one can imagine with 100 players.
nova wasp
#

as for bandwidth I am not sure I can compare them too closely

#

I am not familiar with actor channel network id sending/path export etc and if it packs the same way

#

I will say sending quats isn't THAT slow/huge (they can use only 3 numbers) but it is a bit silly to send an entire quat when you ONLY change the yaw

#

of a character rotation for example

thin stratus
#

Quat replication is the worst.

#

In most cases it's enough to send a packed FRotator.

nova wasp
#

in the above image you can see it literally being smaller than a position in this case

#

but yeah a rotator will probably beat it...

#

16 bit rotator is PLENTY

#

even for first person

hollow gate
#

A compressed short is what epic uses for rotation rep is 99.99% of cases.

thin stratus
#

But that's already the Iris NetSerialize for FQuat, right?

thin stratus
nova wasp
thin stratus
#

Mostly asking cause I wonder how the normal one looks like.

nova wasp
#

hell.. why am I even sending these lmao

#

I think I am just too scared of converting it to a euler rotation as it's a physics object here

#

so it being wiggled around is probably not going to end well

#

this is intended as full 100% reproducable state here

#

wait... could you not lookup table the most common raw rotations at certain angles?

#

argh... probably not enough to be worthwhile at the scale here

#

I've been trying some insane nonsense for positional replication involving cheesing the mantissa bits but I should probably leave rotations alone

tardy fossil
#

man i use custom net serializers so much.. i really hope they figure something out for that

nova wasp
#

for example if you want to have a thing that is marked by a bit for reading/writing you can just make it a nested struct and it will inherently be bitflagged away

#

which is of course not so nice in the resulting code sometimes

#

so yeah I am praying they make a MUCH less insane boilerplate Iris netserializer

mystic estuary
#

Hello, how can you identify whether a client has disconnected normally or not? E.g. is there any entry for me to see that the player didn't crash/lost Internet connection/something else?

I want to allow players to reconnect to the game without losing their progress, in case they do that within a certain time period. More specifically, I want to leave the player character pretty much standing where they got disconnected.

However, if they leave the game on their own through the ESC menu, it's considered as they're not willing to play anymore, so the character should get destroyed immediately.

lost inlet
#

I worked on a rejoin feature at a previous studio, and the main thing that helped out is the client sent an RPC when they voluntarily left

mystic estuary
#

Alright, I was thinking about it, but I wanted to make sure I'm not missing something that engine already comes up with. Thank you 😄

#

I assume you pretty much did that from the player controller, right?

#

Also, in that case the disconnect procedure is unchanged? E.g. the client is the one forcing the disconnect on their end, so no server instigated disconnect after the RPC?

nocturne quail
#

what can be the reason for EquippedWeapon is not valid in OnRep_EquippedWeapon() ?
but when i call OnRep_EquippedWeapon() with a .5sec delay everything works fine

void UWeaponManager::ServerSetEquippedWeapon_Implementation(AWeapon* NewWeapon)
{
    EquippedWeapon = NewWeapon;
    OnRep_EquippedWeapon();
}

void UWeaponManager::OnRep_EquippedWeapon()
{
    if (!IsValid(EquippedWeapon) || !IsValid(EquippedWeapon->GetWeaponItem()))
    {
        printf("EquippedWeapon is not valid"); // <--- this prints
    }
}
verbal ice
#

even if the property is replicated

#

the actor can replicate & spawn on the client before or after the property does

thin stratus
verbal ice
#

oh rep notifies are called when the property gets mapped?

#

dunno how I missed that all this time

thin stratus
#

You only really encounter this when spawning something and setting the variable instantly.

verbal ice
#

I do it quite a bit, I just generally have the other actor notify the owner on begin play clientside

#

guess I never noticed the rep notify gets called automatically, weird

nocturne quail
# thin stratus If the Weapon was just spawned, then the Variable can replicate before the Actor...

this is how I spawn it and after FinishSpawning calling SetEquippedWeapon

void UWeaponManager::SpawnAndEquipp(UWeaponItem* WeaponItem, bool bTargetIsOnHand)
{
    if (!IsValid(WeaponItem))
    {
        return;
    }

    FActorSpawnParameters SpawnParams;
    SpawnParams.bNoFail = true;
    SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
    SpawnParams.Instigator = OwningCharacter;
    SpawnParams.Owner = OwningCharacter;
    SpawnParams.bDeferConstruction = true;

    FTransform Transform = FTransform::Identity;
    if (AWeapon* NewWeapon = GetWorld()->SpawnActor<AWeapon>(WeaponItem->WeaponClass, Transform, SpawnParams))
    {
        NewWeapon->WeaponOwner = OwningCharacter;
        NewWeapon->SetWeaponDataItem(WeaponItem);
        NewWeapon->FinishSpawning(Transform);

        if (bTargetIsOnHand)
        {
            SetEquippedWeapon(NewWeapon);
        }
    }
}
thin stratus
#

Or I guess 1 nullptr 1 valid.

nocturne quail
#

@thin stratus I have to use delay or is there any other clean way to make sure the actor is valid on first onrep call?
its a dedicated server setup that's why manualy calling onrep

verbal ice
#

huh

#

on the server it should immediately be valid

verbal ice
#

and a delay wouldn't guarantee it either in extremely bad scenarios so don't use them that way

nova wasp
pliant cypress
#
LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor BP_SoldierCharacter_C_1. Function ServerFire will not be processed.

LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor BP_SoldierCharacter_C_1. Function ServerFire will not be processed.

happens when i called this on server

thin stratus
thin stratus
pliant cypress
#

yes

pliant cypress
#

for client, it doesn't print this

LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor BP_SoldierCharacter_C_1. Function ServerFire will not be processed.
thin stratus
#

Possibly on the other players character?

#

Given the _1 in the Actor name, I assume the Server is calling a Server RPC on the Clients Character.

pliant cypress
thin stratus
#

Although, outliner seems to indicate it's the Server's Character.

#

Can you confirm that this is being called on Server or Client ?

pliant cypress
thin stratus
#

Print the NetRole of the Character

pliant cypress
pliant cypress
#

Simulated Proxy

#

void UCombatComponent::FireButtonPressed(bool bPressed)
{
    bFireButtonPressed = bPressed;

    if (bFireButtonPressed)
    {
        UE_LOG(LogTemp, Warning, TEXT("%s"), *UEnum::GetValueAsString(SoldierCharacter->GetRemoteRole()));
        Fire();
    }
    else
    {
        ServerStopFire();
    }
}


void UCombatComponent::Fire()
{
    if (bFireButtonPressed && EquippedWeapon && !EquippedWeapon->IsMagEmpty() && bCanFire)
    {
        ServerFire(HitTarget);
    }
}

void UCombatComponent::ServerStopFire_Implementation()
{
    CombatState = ECombatState::ECS_Unoccupied;
}

void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget)
{
    if (SoldierCharacter == nullptr || EquippedWeapon == nullptr) return;
    CombatState = ECombatState::ECS_Firing;
    EquippedWeapon->Fire(TraceHitTarget);
    StartFireTimer();
}
thin stratus
#

RemoteRole of the Server's Character is expected to be SimProxy, as that's what other Players will have as a LocalRole on that Character.
LocalRole checked on the Server should be Authority.

#

Remote and Local Role are a bit confusing at the start, as the value changes depending on who looks at it.

#
Server Character
- Server
  - LocalRole: Authority
  - RemoteRole: SimProxy
- ClientA
  - LocalRole: SimProxy
  - RemotRole: Authority

ClientA Character
- Server
  - LocalRole: Authority
  - RemoteRole: AutoProxy
- ClientA
  - LocalRole: AutoProxy
  - RemoteRole: Authority
- ClientB
  - LocalRole: SimProxy
  - RemoteRole: Authority

Unless I mixed something up, that's how it should look like (given the Character's are possessed).

pliant cypress
thin stratus
#

Hm, if that fixes it then you are calling the RPC on the other Character after all.

#

Something is fishy.

#

How are you getting to UCombatComponent::FireButtonPressed?

pliant cypress
# thin stratus Something is fishy.
void UCombatComponent::FireButtonPressed(bool bPressed)
{
    bFireButtonPressed = bPressed;

    if (bFireButtonPressed)
    {
        UE_LOG(LogTemp, Warning, TEXT("%s"), *UEnum::GetValueAsString(SoldierCharacter->GetLocalRole()));
        Fire();
    }
    else
    {
        ServerStopFire();
    }
}


void UCombatComponent::Fire()
{
    if (bFireButtonPressed && EquippedWeapon && !EquippedWeapon->IsMagEmpty() && bCanFire)
    {
        if(SoldierCharacter && SoldierCharacter->IsLocallyControlled()) ServerFire(HitTarget);
        StartFireTimer();
    }
}

void UCombatComponent::ServerStopFire_Implementation()
{
    CombatState = ECombatState::ECS_Unoccupied;
}

void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget)
{
    if (SoldierCharacter == nullptr || EquippedWeapon == nullptr) return;
    CombatState = ECombatState::ECS_Firing;
    EquippedWeapon->Fire(TraceHitTarget);
    StartFireTimer();
}

void UCombatComponent::StartFireTimer()
{
    if (EquippedWeapon == nullptr || SoldierCharacter == nullptr) return;

    SoldierCharacter->GetWorldTimerManager().SetTimer(FireTimer, this, &ThisClass::FireTimerFinish, EquippedWeapon->FireDelay);
}

void UCombatComponent::FireTimerFinish()
{
    if (EquippedWeapon == nullptr) return;

    bCanFire = true;
    if (CombatState==ECombatState::ECS_Firing && EquippedWeapon->bAutomaticFire && !EquippedWeapon->IsMagEmpty())
    {
        if(SoldierCharacter && SoldierCharacter->IsLocallyControlled()) Fire();
    }
    else if (EquippedWeapon->IsMagEmpty())
    {
        Reload();
    }
}
pliant cypress
thin stratus
#

And that comes from a binding?

pliant cypress
#

Input binding

thin stratus
#

Do you haev any OnReps that trigger Fire?

pliant cypress
# thin stratus Do you haev any OnReps that trigger Fire?
void UCombatComponent::OnRep_CombatState()
{
    switch (CombatState)
    {
    case ECombatState::ECS_Unoccupied:
        break;
    case ECombatState::ECS_Firing:
        //Fire();
        break;
    case ECombatState::ECS_Reloading:
        HandleReload();
        break;
    }
}```

but i see that fire() don't need to be called on the OnRep since server is calling and working on client too
thin stratus
#

Yeah, so it's not the Server that calls the RPC

#

It's probably the Client that gets the property replicated and then also tries to call it.

pliant cypress
#

then it fixed

thin stratus
#

Yeah, make sure you don't accidentally call your RPCs on SimProxies due to OnReps.

pliant cypress
#

btw how can i make ADS? Aim Down Sight?

thin stratus
#

In theory, you'd do something like this for the Fire RPC stuff:

// LocalClient/ListenServer
// Only called by Input.
void UCombatComponent::OnFirePressed()
{
    if (SoldierCharacter->HasAuthority())
    {
        Fire();
    }
    else
    {
        ServerFire();
    }
}

// Server (Dedi/Listen)
void UCombatComponent::ServerFire_Implementation()
{
    Fire();
}

// Server (Dedi/Listen)
void UCombatComponent::Fire()
{
    if (!SoldierCharacter->HasAuthority())
    {
        return;
    {

    // [...]
}
#

That's without Client Prediction fwiw.

thin stratus
nocturne quail
#

circled in red are the places where weapon is invalid on client instantly

#

.05sec delay fixed it, which is the only solution works for me right now

thin stratus
haughty ingot
#

Do you reaaaaaally wanna fight that battle

thin stratus
#

Missty is just gonna be back with an even larger headache if they use a delay now.

nocturne quail
haughty ingot
#

Dump a 42KiB code file, nice

thin stratus
#
// Call only on Authority (in this case Servers).
void AFooBar::SpawnActor()
{
    if (!HasAuthority())
    {
        return;
    }

    ASomeActor* NewActor = GetWorld()->SpawnActor(..);
    SomeActor = NewActor;
    // Manual call for Authority.
    OnRep_SomeActor();
}

// Called on Clients and Server.
// Client can call this with an invalid SomeActor if the Actor hasn't replicated fully yet
// Client will call this a second time once the Actor is valid.
void AFooBar::OnRep_SomeActor()
{
    // Can be invalid on Clients.
    if (!IsValid(SomeActor))
    {
        return;
    }

    SomeActor->DoStuff();
}
#

That's how it is, so you just gonna expect and handle this.

nova wasp
haughty ingot
#

Who needs context? Dump code and wait for the answers to flood in

nocturne quail
#

posted the whole class to see how actually system works

thin stratus
nocturne quail
thin stratus
#

Yeah I'm aware. You said that multiple times now

nova wasp
#

so does it eventually onrep a valid pointer or not?

#

relying on the first onrep to always be what you want is not useful

thin stratus
#

I told you how it's supposed to work. Repeating to me that you use a delay to solve it doesn't change things.
Remove the delay. Put UE_LOGs into the functions and give us more info.
The OnRep should call with a valid Weapon eventually. You never told us if it calls more than once or not.

nova wasp
#

"it fails"... WHAT FAILS??

haughty ingot
nocturne quail
nocturne quail
haughty ingot
#

But, he said why

nocturne quail
#

how i'm supposed to know it?

haughty ingot
#

What is happening

#

Cedric I told you

nocturne quail
#

am setting
weapon = newweapon;
onreapweapon();

haughty ingot
#

I’m out

nova wasp
#

no pushmodel usage? not marking net dirty?

#

also I cant' see anything stopping the local client from setting equipped weapon

nocturne quail
#

yeah this is why I'm so confused, even testing locally the client fails to set it

nova wasp
#

why would you EVER want the local client to set a replicated variable?

#

you should make a separate variable if you desire having a local value

#

this kind of thing will be hard to deal with if the local client can just change it as they please

nocturne quail
#

I mean server is setting for client is failing instantly

nova wasp
#

leave replicated variables alone on a client

#

I'm sure there's some strange situation it is okay to do so but here it does not make any sense

nocturne quail
#

yeah and will be more problematic, I don't like delays in such cases

#

I can see there is no issue in the code flow, but it still needs delay likely something is not yet finished or the actor is not fully spawned or initialized

#

and that delay giving the actor some time to fully initialize before server can set it for clients

#

the weapon actor is like setting 50 variables in the ctor when it is spawned

#

this can be the reason?

nova wasp
nocturne quail
#

if you instancing this no pushmodel usage? not marking net dirty?, yeah the weapon is spawned from a replicated UObject data

nova wasp
#

try marking the network object dirty

nocturne quail
nova wasp
#

also you should try forbidding non authorities from calling SetEquippedWeapon

nocturne quail
#

this function is part of it

nova wasp
# nocturne quail it is already

No. You NEVER use a push model setup OR call ForceNetUpdate (at least in this massive code file you shared)... this would at least ensure unreal is aware of the replicated change no matter what asap

nova wasp
#

This is just the stuff I would try first at least

#

you are free to ignore me and go "ah, well I don't need that" I guess

nocturne quail
nova wasp
#

It's totally possible I missed something and it's something completely different

nocturne quail
#

yeah it is

bool UWeaponManager::EquipWeapon(UWeaponItem* WeaponItem)
{
    if (!OwningCharacter->HasAuthority() || !IsValid(WeaponItem) || !IsValid(WeaponItem->WeaponClass))
    {
        return false;
    }

    PickupWeapon(WeaponItem, false, EWeaponPosition::E_Left);

    return true;
}
nova wasp
#

EquipNotifyHandle is not protected by authority

nocturne quail
nocturne quail
# nova wasp EquipNotifyHandle is not protected by authority
void USurviveNotifies::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference)
{
    if (!MeshComp) return;

    AActor* Owner = MeshComp->GetOwner();

    if (!Owner || !Owner->HasAuthority())
    {
        return;
    }

    if (ASurviveCharacter* Character = Cast<ASurviveCharacter>(Owner))
    {
        CustomNotify(Character);
    }
}
nova wasp
#

also OnRep_EquippedWeapon depends on the anim instance being loaded and valid among other things (why?)

#

when most of it is not strictly anim instance related

#

this is very brittle and will silently fail if this is not there

nocturne quail
#

anim instance successed, the next check for weapon fails

nova wasp
#

instead of just hoping all callers protect by authority

#

also not sure you ever proved the onrep NEVER gets called with the correct weapon pointer

#

without the delay

nocturne quail
nova wasp
#

show the code logging it without being protected by random unrelated pointers

nocturne quail
#
void UWeaponManager::OnRep_EquippedWeapon()
{
    if (!OwningCharacter || !OwningCharacter->GetMesh()) return;

    UCharacterAnimInstanceBase* AnimInstance = Cast<UCharacterAnimInstanceBase>(
        OwningCharacter->GetMesh()->GetAnimInstance());

    if (!AnimInstance)
    {
        UE_LOG(LogTemp, Error, TEXT("AnimInstance is NULL or wrong type!"));
        return;
    }

    if (!IsValid(EquippedWeapon) || !IsValid(EquippedWeapon->GetWeaponItem()))
    {
        UE_LOG(LogTemp, Warning, TEXT("No valid weapon -> Unarmed"));
        OwningCharacter->SetCharacterPlayType(EPlayType::UnArmed);
        AnimInstance->UpdateWeaponState(nullptr, false);
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("Equipping weapon: %s"), *EquippedWeapon->GetName());
        UpdateWeaponsDisplay();
        OwningCharacter->SetCharacterPlayType(EPlayType::Armed);
        AnimInstance->UpdateWeaponState(EquippedWeapon, true);
    }
}
nova wasp
#

once again: our goal is to see EVERY time this onrep happens

#

not when every single one of 4 other pointers is there

#

if you are just baiting me gg I guess... I am trying to help

#

onreps do not care about your init order

#

onreps do not care about anim instances

#

onreps show up from packets early in the frame whenever they feel like it

#

for this kind of thing in my experience you will want to make this code resilient to the other things showing up in any order

#

which generally means them arriving will read the current value of the other things and then listen for it later

nocturne quail
nova wasp
#

I am not telling you to do one thing, I am telling you to both log this and not randomly early out and skip logging stuff

#

the "doing it the right way" can come after you figure out what is wrong

#

this stuff is hard and can be difficult to track down

#

I do wonder if setting the owner on the weapon is needed

#

I would also say the weapon being an entire actor is unneeded as well but that's kinda up to you... it has its benefits

nocturne quail
nova wasp
#

even after the weapon is replicated and the variable is set on the server AND never set different on the client AND you manually mark the actor holding the onrep net dirty as I mentioned earlier?

nocturne quail
nova wasp
#

so?

#

what does that have to do with replication?

#

you can send an int32 and spawn a skeletal mesh on the each client that receives it if you want... I don't see how that forces you to replicate a second actor at all

#

if it's just easier to add new things that way, sure

nocturne quail
nova wasp
#

more actors = more net objects = more network polling = more overhead and more complexity
but it is easier to add new behavior to things I guess and this should be working fairly okay if everything is set up okay

nocturne quail
nova wasp
nova wasp
#

and even if it does you can just check for everything when each new one shows up similar to how init states work in the modular gameplay framework

nocturne quail
nova wasp
#

please just use ForceNetUpdate (on the object with the onrep)

nocturne quail
# nova wasp why?

it was just my guess cause with other actors i don't have this issue

nocturne quail
nova wasp
#

sometimes waiting 1 frame is meaningful for rendering stuf I have found

#

note I when I say ONE frame I mean THE NEXT frame... not a random number of frames from a delay

#

a random delay is like... the last resort

#

or for example when your callback is from a function and the thing you need set is later in the scope. you have no reasonable way to wait on that without engine changes in many cases
this doesn't seem like one of those times

#

a TON of changes I have to make to gameplay classes is just adding new delegates to be able to react to things that are normally overrides in things

nocturne quail
#

I mean calling finishspawn will call beginplay of the actor and it will be synced if i'm not wrong

nova wasp
pliant cypress
#

Does anyone know a good article, documentation or video on

Client prediction and server reconciliation?

shut loom
#

I'm trying to implement a physics-based grabbing mechanic but can't get it to work. On the client (right window) it doesn't seem to do anything at all whereas it spazzes out but doesn't move the object on the listen server (left window). The input and Server_GrabObject are in the player character. The pickup object has Replicates enabled.

tardy fossil
#

i dont use the physics constraint component personally but i feel like the object's mesh component thats being picked up should be plugged into the "component 2" pin of "Set constrained components" node

shut loom
#

I forgot to connect the pickup component to Component2. But now when I grab it on the client, it works fine on the listen server but not on the client itself. And when the server grabs it, it also works on the server but not the other client

nocturne quail
hollow bridge
#

Hi, I'd like to have a knockback on a player without any jitter/rubberband. What is the right way?
Using GAS? Maybe SavedMov in CMC?

vocal current
# pliant cypress Does anyone know a good article, documentation or video on Client prediction an...

Not Unreal specific, but I often recommend this talk to folks that are looking to understand network replication in games.

https://www.youtube.com/watch?v=h47zZrqjgLc

In this 2011 GDC session, Bungie's David Aldridge discusses the programming that drove Halo: Reach's online networking.

Register for GDC: http://ubm.io/2gk5KTU

Join the GDC mailing list: http://www.gdconf.com/subscribe

Follow GDC on Twitter: https://twitter.com/Official_GDC

GDC talks cover a range of developmental topics including game des...

▶ Play video
#

The section about how armor lock works from a client/host perspective is relevant

pliant cypress
vocal current
#

I don't think it has source snippets, but it has concrete examples of features that shipped in a big AAA title, you're not going to get much more practical than that, unless you're looking specifically for details of how to do it in Unreal rather than more generally

nova wasp
mighty trout
#

getting this error for packagin on windows

spare lynx
#

I'm making a Ability system in unreal engine 5.6.1, i'm trying to create a cooldown system in cpp, anyone can help me?

dark parcel
spare lynx
dark parcel
#

not sure why you want to re-invent the wheel, so what exactly are you having trouble with?

spare lynx
# dark parcel What do you have problem with?

I'm trying from scratch again, i have the ability system. But I already tried to create a cooldown system, but the timer only existed on the server and not on the client, so the client could spam the skill. The netmode that needs to work is "Netmode: Client".

#

Ability system with cooldown

dark parcel
#

You kinda have to decide your approach. If you are going for Authority check then there would be the problem with delay.
If you don't care soo much about cheating, you can just let the client to book keep it's own cooldown.

#

you can still check on server, if the ability get casted faster than it should, if cheating is a concern.

#

Tldr, you can just keep the cooldown/timer on the caster machine.

spare lynx
dark parcel
#

you said the client spam the skill, so I am assuming the ability is client predicted. Which in this case, you should just have the timer solely on the client.

#

and if cheating is a concer, you can just check on the server if the time between last and current spell < cooldown.

spare lynx
#

So, how i would implement this?

nova wasp
#

run it on the client

#

¯_(ツ)_/¯

#

of course if you need the timer on simulated proxies for showing something visual they might need to either run it on their end as well or get given some visual cue/event etc

#

the answer here is vastly different depending on the actual needs of the project imo but since we have no context = I am going to guess

spare lynx
nova wasp
#

no thanks

#

if you cant give vague details like whether it is co-op or not why would you be able to reveal that it has cooldowns?

#

we don't need the elevator pitch.. just some surface level info I guess

spare lynx
#

It's a pvp game MVP for a tech test

nova wasp
#

not sure why it being for a tech test matters here... I guess you want something easy to make quickly?

spare lynx
#

With 4 abilities, and all will have cooldown, some of their will have area of effect and one will have a time of effect

spare lynx
dark parcel
#

Don't think AOE have anything to do with what we are discussing.

Depending on your design, you can just couple a cooldown/timer for each ability.

nova wasp
#

not sure how any of us are supposed to know what isn't working with 0 info on what you actually tried

dark parcel
#

You said the timer is run on server. Well I would suggest to run the timer on the casting player machine.

#

and the casting player simply just check if the timer / cooldown is not 0 to decide if it can cast the spell or not.

#

ServerActivateAbility

well I don't have 2 cent if you want server auth casting. Personally I just use GAS, it already have prediction option with rollbacks.

nocturne quail
#
    >UnrealEditor-Core.dll!FName::ToString() Line 3356    C++
     [Inline Frame] UnrealEditor-Survive.dll!UObjectBaseUtility::GetName() Line 423    C++
     [Inline Frame] UnrealEditor-Survive.dll!GetNameSafe(const UObjectBaseUtility *) Line 864    C++
    UnrealEditor-Survive.dll!UInventoryComponent::ItemRemoved(UItem * Item) Line 440    C++
     UnrealEditor-Survive.dll!UInventoryComponent::execItemRemoved(UObject * Context, FFrame & Stack, void * const Z_Param__Result) Line 957    C++
**FName::ResolveEntry**(...) returned 0x7FF8.
void UInventoryComponent::ItemRemoved(class UItem* Item)
{
    if (!IsValid(Item)) {
        UE_LOG(LogTemp, Warning, TEXT("Item is not valid."));
        return;
    }
    AActor* Owner = GetOwner();
    if (!IsValid(Owner)) {
        UE_LOG(LogTemp, Warning, TEXT("Owner is not valid."));
        return;
    }

    FString RoleString = GetOwner()->HasAuthority() ? "server" : "client";
    > UE_LOG(LogTemp, Warning, TEXT("Item Removed: %s on %s"), *GetNameSafe(Item), *RoleString);
}
#

any idea why resolving name to string fails?

#
FORCEINLINE FString GetNameSafe(const UObjectBaseUtility* Object)
{
    if (Object == nullptr)
    {
        return TEXT("None");
    }
    else
    {
        return Object->GetName();
    }
}
#

so the game is trying to resolve name at address 0x7FF8

#

interesting why if (!IsValid(Item)) also don't works at this point

dark parcel
#

unrelated but why do you have class keyword before the ptr? Don't we meant to only do that for forward declare?

#

Sorry to intterupt the ongoing question, is there an event that is called before Begin play? And if the server set something there, will the replicated actor on the client side guaranteed to have the modification?

nocturne quail
#

in the cpp

#

that class comes from .h

#

I mean i have this void ItemRemoved(class UItem* Item); when created the definition the class was added automatically

dark parcel
#

any hint on the call stack?

nocturne quail
#

cause its not crashing all the time

#

it crashes 1/20

#

other 19 times it prints the name of the item was removed

dark parcel
#

I am facing the same issue when I destroyed the item on the server and client needed to still have access to the item to clean up on it's own end.
Just yapping atm, but I got the band aid by just hiding the item and giving it a decent life time like 2 - 3 seconds.

thin stratus
#

If the InventoryComponent itself isn't garbage at that point, then this smells like a stale pointer.

nocturne quail
#

yeah IC is not garbage

#

seems like I have to cache the name of the item before removing it and pass that directly instead of passing the item

#
BeginPlay()
OnItemRemoved.AddDynamic(this, &UInventoryComponent::ItemRemoved);
bool UInventoryComponent::RemoveItem(class UItem* Item)
{
    if (GetOwner() && GetOwner()->HasAuthority())
    {
        if (Item)
        {
            OnItemRemoved.Broadcast(Item);

            Items.RemoveSingle(Item);

            OnRep_Items();

            ReplicatedItemsKey++;

            return true;
        }
    }

    return false;
}
#

it seems like i'm printing it before removing it

#

seeme like resoving FName to FString is a heavy operation

#

it takes long time and the item is removed before it resolves

dark parcel
#

code isn't async, that shouldn't be the case?

nocturne quail
#

nah, it crashes on server

#

have to figure it out first before moving to client side

tardy fossil
#

try doing a log print inside RemoveItem with Item->GetName().. maybe the pointer is already stale inside RemoveItem

nocturne quail
#

basically its same, in the end it will call GetName before reaching Items.RemoveSingle(Item);

tardy fossil
#

sounds like RemoveItem is getting passed a stale pointer

nocturne quail
#
int32 UInventoryComponent::ConsumeItem(class UItem* Item, const int32 Quantity)
{
    if (GetOwner() && GetOwner()->HasAuthority() && IsValid(Item))
    {
        const int32 RemoveQuantity = FMath::Min(Quantity, Item->GetQuantity());
        ensure(!(Item->GetQuantity() - RemoveQuantity < 0));
        Item->SetQuantity(Item->GetQuantity() - RemoveQuantity);
        if (Item->GetQuantity() <= 0)
        {
            RemoveItem(Item);
        }
        else
        {
            ClientRefreshInventory();
        }

        return RemoveQuantity;
    }

    return 0;
}
#

I think that IsValid(Item) protects against stale pointer

tardy fossil
#

set a breakpoint on the line calling the RemoveItem function and check if the values are all weird

thin stratus
#

The idea of a stale pointer is that it's valid in the sense of not being a nullptr, but the thing it's pointing to is not what it's meant to be.

nocturne quail
thin stratus
#

IsValid can still return true for a stale pointer.

nocturne quail
#

removing from inventory never crash, logging the name of the item which wants to remove crashed

thin stratus
#

Where are these Items stored?

nocturne quail
thin stratus
#

One thing you should try is to enable GC every frame (console var), to test if that makes the issue happen every time.
The note that it only happens "sometimes" makes me wonder if the order of what you are doing doesn't take into account that the GC could be nuking the object.

nocturne quail
nocturne quail
thin stratus
nocturne quail