#multiplayer

1 messages ยท Page 42 of 1

pallid mesa
#

Been working recently around MoveAutomous

#

and I wanted to check how it all looked in ue5-main, got surprised to see a new CVAR that happened to fix the notify issue

#

a bit unconvenient that it is a CVAR ๐Ÿ˜ฆ

#

but anyways... this is also set in Lyra's engine config

quasi tide
#

Maybe it was planned? Weird. I'd imagine it should be on by default and should be optional to be off.

pallid mesa
#

yeah

open grove
#

Helloo!
Currently using UE5, just loaded a new third person tenplate, attempted to use split screen using "Create Local Player" this doesn't seem to get any input from my second xbox controller. Both controllers work in the editor allowing me to move around. But it doesn't seem that a player controller for my second controller is being used/detected. Any help will be very appreciated ๐Ÿ˜„

prisma snow
#

Mmm any reason a server-executed multicast is only being fired on server (and not clients?)

#

I can ensure it is being called on the server

quasi tide
#

Clients aren't relevant

prisma snow
#

mmm this class is marked as always relevant

worn wagon
#

or it's a server only class like gamemode

prisma snow
#

it's basically RPCing some stuff to its client clones

#

mmm

#

The class itself is created on the server, but since it is marked as replicated, shouldn't it exist also on clients?

twilit radish
#

What are we talking about? Gamemode, player state, a custom actor?

prisma snow
#

A custom actor which acts as a helper so a subsystem can do networking stuff basically

#

This is part of some "old" code that I ported from 4.27 (a prototype I made) and it used to work there, so my bet is that something in the creation/spawning process is not correct and therefore is not existing on clients or smth

worn wagon
#

post code if you want more help

prisma snow
#

yeah I'll do, thanks

strange apex
#

Just a quick question, when i am hosting a lan server , it takes like 30 seconds to join as client 2, any way to speed that up ?

dry pebble
#

oh wow thank you! @thin stratus will this help you too?

thin stratus
#

Yes, thanks for the ping

dry pebble
#

@pallid mesa Also I read all your articles yesterday, they are amazing! Thank you for writing them. I have a question about your "A non-destructive and better synced network clock" - have you tested whether the slight difference in synced time between client and server would cause net corrections if gameplay mechanics were dependent on this time? E.g Reducing cooldown timers for GAS abilities by the RTT up to a certain ping?

rocky topaz
#

I have an issue with my vehicle replication, I'm working on a client authoritative mode but for some reason when I'm playing in a listen server it's state doesn't get replicated to clients (client to server and to other clients works)

chrome bay
#

Probably an oversight in the implementation

rocky topaz
#
    UFUNCTION()
    void OnRep_ReplicatedState();

    UPROPERTY(ReplicatedUsing=OnRep_ReplicatedState)
    FReplicatedState ReplicatedState;

    UFUNCTION(Server, Unreliable)
    void Server_ReplicateState(FReplicatedState NewReplicatedState);
void URacingTankMovementComp::OnRep_ReplicatedState()
{
    TankBody->SetWorldLocation(ReplicatedState.Location);
    TankBody->SetWorldRotation(ReplicatedState.Rotation);
    TankBody->SetPhysicsLinearVelocity(ReplicatedState.LinearVelocity);
    TankBody->SetPhysicsAngularVelocityInRadians(ReplicatedState.AngularVelocity);
}

void URacingTankMovementComp::Server_ReplicateState_Implementation(FReplicatedState NewReplicatedState)
{
    ReplicatedState = NewReplicatedState;
    OnRep_ReplicatedState();
}

OnTick :
    if (OwnerTank && OwnerTank->IsLocallyControlled())
    {
        ReplicatedState.Location = TankBody->GetComponentLocation();
        ReplicatedState.Rotation = TankBody->GetComponentRotation();
        ReplicatedState.AngularVelocity = TankBody->GetPhysicsAngularVelocityInRadians();
        ReplicatedState.LinearVelocity = TankBody->GetPhysicsLinearVelocity();

        if (!OwnerTank->HasAuthority())
        {
            Server_ReplicateState(ReplicatedState);    
        }
rocky topaz
#

oh and

#

DOREPLIFETIME_CONDITION(URacingTankMovementComp, ReplicatedState, COND_SkipOwner);

chrome bay
#
        {```
rocky topaz
#

I'm using this

chrome bay
#

Listen server does have authority

rocky topaz
chrome bay
#

Oh NVM, you are setting it

rocky topaz
#

the Server_ReplicateState just sends it to set it yeah

thin stratus
#

You aren't calling OnRep then though

#

For the server at least

#

or?

rocky topaz
#

yeah that's also on purpose

thin stratus
#

Ok

rocky topaz
#

calling OnRep on server makes it reset the location and velocity every tick

chrome bay
#

I ma personally against calling OnReps for server as it makes actual replication harder to debug - but yeah presumably you need to apply it

#

Also, I assume you have disabled replicated movement on the owner?

rocky topaz
#

yup

chrome bay
#

Realistically, you shouldn't need any of this btw - you can just set the owning actors' replicated movement data (which contains physics state)

#

Which will also be cheaper - component replication/RPC's have additional overhead

#

Not usually anything to worry about, but becomes a factor at scale or when properties are updating a lot

rocky topaz
chrome bay
#

Not necessarily, just ignore the updates on the receiving client

#

I.e. in OnRep_Movement guard against IsLocallyControlled or auto proxy or w/e

rocky topaz
#

I'm making a racing game and I want to let the player do whatever they want (cheating protection isn't required)

thin stratus
#

All he's suggesting is to use the already replicating movement

#

And instead of applying it locally, you filter the call

chrome bay
#

In fact, Skeletal Meshes even have a flag that does that automatically for the purpose of vehicles

#

Exactly what it's meant for

#

Why it lives on USkeletalMeshComponent and not USceneComponent or w/e is anyone's guess though. 10/10 API decisions.

rocky topaz
#

how would I change the behaviour of movement replication though?

#

overriding OnRep_Movement?

chrome bay
#

If it's a physics simulating skeletal mesh, you don't even have to do that

#

Just uncheck "Replicate Physics To Autonomous Proxy" on the mesh

rocky topaz
#

damn

chrome bay
#

It's a stupid fortnite API thing that ended up in vanilla engine

#

Because apparently nobody would ever make a physics-simulating static mesh vehicle

#

Genius

rocky topaz
#

btw I'm in class (granted, it's a Shader Programming class) but teacher was like "you should use a multicast"

#

:thonk:

chrome bay
#

no

thin stratus
#

:D why does that sound like you need that to exist for StaticMeshes for your pet project

chrome bay
#

bad teacher

rocky topaz
# chrome bay no

I know I was like no as well but he got on my pc and started doing it

quasi tide
chrome bay
#

Just such a dumb decision to put it there IMO

rocky topaz
chrome bay
#

If server + client have to execute it, I make another func and have the OnRep call that

chrome bay
rocky topaz
#

we have a "physics engine" and "network programming" teacher that never opened unreal

chrome bay
#

I kid

#

MP is hard, you need actual experience to teach it properly. No offence to the teachers.

rocky topaz
#

he was like "I'm sure Blueprints can be more performant than C++"

rocky topaz
#

he doesn't know shit it made me depressed

#

I went through all stages of grief on the first week of class with him

#

we had like 22hours of class where all he did was talk about politics and open youtube tutorials about how to make a blueprint

#

๐Ÿ’€

worn wagon
#

what kind of politics

quasi tide
rocky topaz
#

he was like "it's going to get bloody very soon"

#

(I'm in france btw, despite my strong wish to not be here)

chrome bay
rocky topaz
#

he told us things would change radically in the next two weeks like a month and a half ago

#

and now this week he was like "it's gonna happen first weeks of january"

#

๐Ÿ˜‚

quasi tide
worn wagon
rocky topaz
#

ikr, he's a politician actually

#

idk why they brought him here

#

school gave him like 100 hours of teaching

#

prolly 5000โ‚ฌ

#

I would bet my ass he didn't teach jack shit to anyone

#

5000โ‚ฌ down the drain

thin stratus
#

Just tell him to rethink both of his careerpaths

rocky topaz
#

unless it's some kind of money laundering scheme ๐Ÿ˜ฌ

latent heart
#

Complain, tell the school he has no idea what he's doing.

kindred widget
#

Just make sure to leave emotion out of it. Just lay out clean clear facts.

worn wagon
#

my not so well informed opinion is if you actually want to learn something properly and you don't need a degree or some kind of qualification for your career path, best to just find resources yourself than pay for college

chrome bay
#

Main point of note, is that when an RPC is received it's applied at the beginning of the frame. I had better/smoother results by applying client changes after the current physics tick - hence all the intermediatte data

thin stratus
#

"I learned more from some guy from the UK on Discord in 5 Minutes than from that guy in a school during the last 2 weeks."

latent heart
#

2 months*

chrome bay
#

Notice my incredible anti-cheat protection:
// TODO: Time / Cheat Verification

kindred widget
thin stratus
#

best to just find resources yourself than pay for college
Small note: It's probably best to pay a tutor for that

chrome bay
#

EAC got nuttin on dis

pallid mesa
quasi tide
#

I learned more from some guy from the UK on Discord in 5 Minute
To be fair - it is James and he is friggin' sweet ๐Ÿ˜….

rocky topaz
#

but yeah we did and he's getting fired next trimester afaik

latent heart
#

Get a refund.

rocky topaz
#

I was in an apprenticeship first year which paid for the school through a gov grant

worn wagon
#

You only need a degree if you're looking to join an existing company ๐Ÿ˜„

rocky topaz
#

ah nvm I misunderstood what you said

chrome bay
#

OH WAIT

#

They moved it in 5.1

#

It's in PrimitiveComponent now

#

good guy Epic

rocky topaz
thin stratus
rocky topaz
worn wagon
rocky topaz
chrome bay
#

Yeah must have been recent, I recall it only being in skeletal mesh for no reason whatsoever

thin stratus
rocky topaz
#

well this is weird

#

I removed all my replication stuff

#

and my server's state is still not replicating to the clients

#
    SetReplicateMovement(true);
    
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
    SetRootComponent(Mesh);
    Mesh->SetSimulatePhysics(true);
    Mesh->bReplicatePhysicsToAutonomousProxy = false;
prisma snow
#

Ok, so after debugging a bit I am still clueless so, here's my code:

In my subsystem, the helper replicated actor is created:

// MySubsystem.h
UPROPERTY()
AReplicationHelper* MyHelper;
// MySubsystem.cpp
void UMySubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    if (GEngine->GetNetMode(GetWorld()) != NM_Client)
    {
        MyHelper = GetWorld()->SpawnActor<AReplicationHelper>(AReplicationHelper::StaticClass());
    }
}

Then, in AReplicationHelper constructor I set bReplicates and bAlwaysRelevant to true.

The function that is multicasted from the server:

// .h
UFUNCTION(NetMulticast, Unreliable)
void NetCastLocations(const TArray<FUnitLocationNetUpdate>& UnitLocations, int32 ServerStepNumber);
void AReplicationHelper::NetCastLocations_Implementation(const TArray<FUnitLocationNetUpdate>& UnitLocations,
                                                                 int32 ServerStepNumber)
{
        // only server reaches this code
    if (GetNetMode() != NM_Client)
    {
        return;
    }

    // do my client-side logic
}
chrome bay
#

@prisma snow I think I know. U ready for dis?

chrome bay
#

It's unsafe to access ENetMode in A world subsystems initialize

#

I had to jump through repeated hoops for this

prisma snow
#

MMM

quasi tide
#

Wait - it is? I think I might be doing that ๐Ÿ˜…

prisma snow
#

I can ensure that the actor exists in both client and server

#

but that's it

chrome bay
#

Some really obscure UWorld lifetimes in PIE make it a PITA

rocky topaz
#

this is soo weird

chrome bay
#

So it's possible that both server + client are spawning their own

rocky topaz
#

why would the server's state not replicate to clients

prisma snow
chrome bay
#

You can get around it, 1 sec

prisma snow
#

Jambax for president

#

xD

quasi tide
#

This is how I'm doing my server only subsystem ๐Ÿ˜…

if (!Super::ShouldCreateSubsystem(Outer))
{
    return false;
}

UWorld* World = Cast<UWorld>(Outer);
return World->GetNetMode() < NM_Client;
chrome bay
#

This is the dumb code I had to use:

{
    const UWorld* lWorld = OverrideWorld ? OverrideWorld : GetWorld();
    check(lWorld);

    OutMode = lWorld->GetNetMode();

#if WITH_EDITOR
    // PIE creates some obscure UWorld lifetimes that makes NetMode access more difficult.
    // See https://udn.unrealengine.com/s/question/0D54z00007DW1CQCA1/why-are-uworldsubsystems-initialized-before-uworld-is-initialized
    if (lWorld->IsPlayInEditor())
    {
        UEditorEngine* const EditorEngine = CastChecked<UEditorEngine>(GEngine);
        const UPackage* Package = Cast<UPackage>(lWorld->GetOuter());
        if (!Package || Package->GetPIEInstanceID() == INDEX_NONE)
        {
            // This is a Transient UPackage used for PIE Client worlds.
            OutMode = ENetMode::NM_MAX;
            return false;
        }
        else
        {
            // We can get the UGameInstance/UNetDriver from here, *before* the UWorld properties are set
            const FWorldContext* PIEWC = EditorEngine->GetWorldContextFromPIEInstance(Package->GetPIEInstanceID());
            if (ensureAlways(PIEWC))
            {
                if (!PIEWC->PendingNetGame)
                {
                    OutMode = PIEWC->RunAsDedicated ? ENetMode::NM_DedicatedServer : ENetMode::NM_Standalone;
                }
                else if (ensureAlways(PIEWC->PendingNetGame->NetDriver))
                {
                    OutMode = PIEWC->PendingNetGame->NetDriver->GetNetMode();
                }
            }
        }
    }
#endif

    return true;
}```
#

Also then - I recommend moving the actor spawn to some post-world-initialized function

#

The problem is that subsystems are initialized before the world is actually initialied, but the order varies between editor vs packaged

#
{
    Super::Initialize(Collection);

    const UWorld* lWorld = GetWorld();
    check(lWorld && lWorld->IsGameWorld() && lWorld->PersistentLevel != nullptr);

    /* Can't actually do proper initialization until much later... */
    PostInitWorldDelegateHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &UHT_WorldManager::PostInitWorldInternal);

#if WITH_EDITOR
    /* Editor environment is even more fucking annoying */
    PostInitWorldPIEDelegateHandle = FEditorDelegates::PostPIEStarted.AddUObject(this, &UHT_WorldManager::PostInitWorldPIEInternal);
#endif
}

void UHT_WorldManager::Deinitialize()
{
    ManagerTickFunction.UnRegisterTickFunction();
    FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(PostInitWorldDelegateHandle);
#if WITH_EDITOR
    FEditorDelegates::PostPIEStarted.Remove(PostInitWorldPIEDelegateHandle);
#endif

    Super::Deinitialize();
}

void UHT_WorldManager::PostInitWorldInternal(UWorld* NewWorld)
{
    const UWorld* lWorld = GetWorld();
    if (lWorld && lWorld == NewWorld && !bHasPostWorldInitialized)
    {
        bHasPostWorldInitialized = true;

        FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(PostInitWorldDelegateHandle);
#if WITH_EDITOR
        FEditorDelegates::PostPIEStarted.Remove(PostInitWorldPIEDelegateHandle);
#endif

        // Handle Tick Registration now.
        if (!ManagerTickFunction.IsTickFunctionRegistered() && ManagerTickFunction.bCanEverTick)
        {
            ManagerTickFunction.Target = this;
            ManagerTickFunction.SetTickFunctionEnable(ManagerTickFunction.bStartWithTickEnabled || ManagerTickFunction.IsTickFunctionEnabled());
            ManagerTickFunction.RegisterTickFunction(lWorld->PersistentLevel);
        }

        OnWorldInitialized();
    }
}

#if WITH_EDITOR
void UHT_WorldManager::PostInitWorldPIEInternal(bool bSimulating)
{
    PostInitWorldInternal(GetWorld());
}
#endif```

What fun.
#

Sorry for wall of text

prisma snow
#

what a mess Epic games xD

chrome bay
#

yeah, that fixed it for me at least

#

I had the same problem essentially

quasi tide
chrome bay
#

I wanted to onbly have certain subsystems initialized on server for e.g.

rocky topaz
#

lemme put my messages back together

chrome bay
#

So had to do this shiz

{
    if (Super::ShouldCreateSubsystem(InOuter))
    {
        const UWorld* lWorld = Cast<UWorld>(InOuter);
        if (lWorld && lWorld->IsGameWorld())
        {
#if WITH_EDITOR
            // PIE creates temporary worlds for Net Clients which should never initialize subsystems.
            if (lWorld->IsPlayInEditor())
            {
                const UPackage* OuterPackage = CastChecked<UPackage>(lWorld->GetOuter());
                if (!OuterPackage || OuterPackage->GetPIEInstanceID() == INDEX_NONE)
                {
                    return false;
                }
            }
#endif
            if (CheckNetMode(lWorld) && CheckLevelName(lWorld))
            {
                return true;
            }
        }
    }

    return false;
}```
prisma snow
#

lol

rocky topaz
#

so I just set replicates movement and unchecked autonomous proxy replication but it's not working as it was with my implementation
(it wasn't replicating earlier because the blueprint kept replicating movement unchecked ๐Ÿคฆ๐Ÿปโ€โ™‚๏ธ )
the movement isn't going from autonomous proxy to the authority like, I flipped a car in the server and it started moving upside down when I was moving in autonomous proxy

chrome bay
#

Maybe i should just dump the whole class on git

prisma snow
chrome bay
#

tbh I think this is mostly PIE shennanigans and the hax it creates

#

The way the world is duplicated by editor GI is wierd

pallid mesa
#

thanks; the blog needs some love... there are loads of info being lost in discord, god bless the chat history... but discord in a way... killed the forums and dev-blogposts

rocky topaz
#

@chrome bay did you read my messages? ๐Ÿฅบ

dry pebble
quasi tide
#

/* Editor environment is even more fucking annoying */
๐Ÿ˜…

dry pebble
pallid mesa
#

So for example... I've shot my weapon at this angle at 10.33

#

The server will receive this information, and since clocks are synced, it will be able to rewind the victim's capsule to that point in time

#

meaning that you can trust that your 10.33 are equivalent to the 10.33 in the server

rocky topaz
#

welp I have no clue what's wrong with the default move replication and I don't have time to dive into it I guess I'll just go back to my old issue

#

when a struct field that's marked as replicated is modified on the server it's replicated to all clients right?

pallid mesa
#

you need to replicate the whole struct

rocky topaz
#

yeah the whole struct is

#

can you take a look at what I'm doing please? @pallid mesa

pallid mesa
#

and mark the fileds u don't wish to replicate as NotReplicated

rocky topaz
#

so this is my struct ```h
USTRUCT()
struct FReplicatedState
{
GENERATED_BODY()

UPROPERTY()
FVector Location;

UPROPERTY()
FRotator Rotation;

UPROPERTY()
FVector LinearVelocity;

UPROPERTY()
FVector AngularVelocity;

};

#

I have this in my header : ```h
UFUNCTION()
void OnRep_ReplicatedState();

UPROPERTY(ReplicatedUsing=OnRep_ReplicatedState)
FReplicatedState ReplicatedState;

UFUNCTION(Server, Unreliable)
void Server_ReplicateState(FReplicatedState NewReplicatedState);
#
void URacingTankMovementComp::OnRep_ReplicatedState()
{
    TankBody->SetWorldLocation(ReplicatedState.Location);
    TankBody->SetWorldRotation(ReplicatedState.Rotation);
    TankBody->SetPhysicsLinearVelocity(ReplicatedState.LinearVelocity);
    TankBody->SetPhysicsAngularVelocityInRadians(ReplicatedState.AngularVelocity);
}

void URacingTankMovementComp::Server_ReplicateState_Implementation(FReplicatedState NewReplicatedState)
{
    ReplicatedState = NewReplicatedState;
    OnRep_ReplicatedState();
}


void OnTick...
    if (OwnerTank && OwnerTank->IsLocallyControlled())
    {
        ReplicatedState.Location = TankBody->GetComponentLocation();
        ReplicatedState.Rotation = TankBody->GetComponentRotation();
        ReplicatedState.AngularVelocity = TankBody->GetPhysicsAngularVelocityInRadians();
        ReplicatedState.LinearVelocity = TankBody->GetPhysicsLinearVelocity();

        if (!OwnerTank->HasAuthority())
        {
            Server_ReplicateState(ReplicatedState);    
        }
    }```
#

and this is the body

#

my issue is that the Server's state isn't being replicated to clients

dry pebble
# pallid mesa The server will receive this information, and since clocks are synced, it will b...

Ahh yess for server side rewinding. I've implemented that before from stephen's course, it's very handy and syncing time is a great use case for that (and a day night cycle across servers). I was curious more about client side prediction cooldown timers for GAS abilities. The idea Eki was talking about where you minus the RTT from the server's cooldown. Some people said it wouldn't work because you can't get frame perfect time sync between client and server. Where you get a result that's accurate +/- 5 ms, but that difference is the difference of a few frames. And just being off by one frame can cause a net correction. Curious if you have insight on that?

rocky topaz
#

I really don't get it as there should be no reason the ReplicatedState of the pawn of my ListenServer wouldn't get replicated to clients

pallid mesa
rocky topaz
#

it's getting modified in the server itself so it should call the RepNotify

pallid mesa
#

it should be set that way in getfetimereplicatedprops

#

can i seeยฟ ๐Ÿ‘€

rocky topaz
#

I'm using DOREPLIFETIME_CONDITION(URacingTankMovementComp, ReplicatedState, COND_SkipOwner);

#

should it be COND_SimulatedOnly?

#

other clients aren't the owners of the server's pawn so it shouldn't be skipped with this either

#

๐Ÿฅน

pallid mesa
rocky topaz
#

I'm so puzzled

#

nevermind it works now by some kind of magic

#

wth

#
FReplicatedState NewReplicatedState;
        
        NewReplicatedState.Location = TankBody->GetComponentLocation();
        NewReplicatedState.Rotation = TankBody->GetComponentRotation();
        NewReplicatedState.AngularVelocity = TankBody->GetPhysicsAngularVelocityInRadians();
        NewReplicatedState.LinearVelocity = TankBody->GetPhysicsLinearVelocity();

        if (!OwnerTank->HasAuthority())
        {
            Server_ReplicateState(NewReplicatedState);    
        }
        else
        {
            ReplicatedState = NewReplicatedState;
        }```
#

I changed the tick to this

#

shouldn't modifying the existing struct in the server trigger a replication too?

pallid mesa
#

yes

#

I wasn't honestly seeing what was happening

#

oversight?

rocky topaz
#

so weird

pallid mesa
#

although the initial code was a bit confusing, i like it better now

rocky topaz
#

it's probably an issue coming from how a struct's dirty state is detected

pallid mesa
#

I was thinking that maybe your onrep wasn't getting called because the values where equivalent due to the predictive setting

#

but you unpiezed me after saying you were skipping the owner

rocky topaz
#

wait nevermind ReplicatesMovement was set

#

it might still not be solved

#

I had commented it in code but I forgot it's set to true by default

#

nevermind the issue is still here

#

I sooo don't get it now

prisma snow
#

@chrome bay I need to include UnrealEd in the module dependencies (public or private) to use your wonderful hack right?

pallid mesa
#

onreps on C++ only get called when the value differs

rocky topaz
#

oh yeah

#

well now we can be sure the value differs no?

#

the only solution I'm thinking of is a multicast gasps

#

but I really don't want to use a multicast

prisma snow
glacial pollen
#

Sometimes unreal really does not make sense.

rocky topaz
#

@pallid mesa do you give up?

#

welp I guess this means yes

#

wtf

#

turning the struct into a blueprint type fixed it?

#

or recompiling yet again

#

I have no clue

pallid mesa
#

I'm doing many things parallely and trying to assemble a chair x'D not the best time now @rocky topaz

rocky topaz
turbid sable
#

Could anyone confirm this?

From reading the docs, ownership of an actor is not really the same as the actor's netrole. If you, the player, controls a pawn, you'll have ownership of the pawn, but the netrole could still be authorative on the server, and proxy for your local client.

If the above is true, would anyone know the reason why calling a client RPC on a pawn controlled by a local player from the server fail? Testing in PIE as a local client, and I get no logs that should appear

chrome bay
#

Ownership essentially means "who is allowed to call Server RPC's on this actor", and is the "NetOwner"

#

A client can "own" an actor, but if it's a replicated actor created by the server, they do not have authority over it.

#

Authority != Ownership

#

Owner also dictates which connection will receive the client RPC, if any

#

Possessed pawns are by default also "owned" by the controller, so clients RPC's should arrive and execute

graceful flame
#

So if you were to place a blueprint actor in the world and within that blueprint actor there's some sort of overlap event. Does that overlap run on server? client? both?

chrome bay
#

both

graceful flame
#

Okay so if that overlap needs to affect your character, would it make more sense to add on to the character's capsule overlap event and check for that actor instead?

#

or I guess that's when it starts to become "it depends" as the answer because other aspects of the game will influence how it should be designed?

turbid sable
#

Went on a deep dive with the debugger and the reason why I'm not getting my client RPC seems to be due the following inside the NetDriver

    const FFieldNetCache* FieldCache = ClassCache->GetFromField(Function);
    if (!FieldCache)
    {
        DEBUG_REMOTEFUNCTION(TEXT("FieldCache empty, not calling %s::%s"), *GetNameSafe(Actor), *GetNameSafe(Function));
        return;
    }

Field cache is null, anyone know what could possibly be the reason for this?

weak linden
quasi tide
#

For trigger boxes, I only spawn them on the server.

graceful flame
#

But I'm liking the idea of @quasi tide to only spawn the box collider server side. You can save resources client side but not having anything to check and still have server side checking.

quasi tide
#

Sounds more like a design question.

I'd have the box collider change it personally. With the character exposing a method that allows something from the outside to change its state.

weak linden
#

I'd have the box collider change it personally. With the character exposing a method that allows something from the outside to change its state.

This is the way I'd go about it too IMO

graceful flame
#

Yea okay, makes sense. I'm at a point in my game where I've learned a lot and made a lot, but now its time to go back and refactor some of my older work to be more optimized.

weak linden
#

๐Ÿ™ I do love me a good refactor of "junk I made a year ago" session LUL

graceful flame
#

Since the level placed actor doesn't move the OnBeginOverlap event only runs when a character or something else that can move triggers it, whereas the character's capsule is pretty much always overlapping as they move around the level. So yes it makes way more sense to have the gameplay logic to reside on the static level placed actor then have it send an interface message to ANY actor that overlaps it. Then on the character an interface event is implemented with a HasAuthority check then whatever needs to happen can happen.

prisma snow
weak linden
quasi tide
#

Don't need the has auth check if you only have the trigger on the server or if you do the has auth check in the tirgger

weak linden
sonic python
#

Hey Does Anyone know

#

How to make in app currency?

#

If you know can you give me some.links abt tutorials..

quasi tide
#

int MyMoney = 1000;

sonic python
#

For in app purchase

weak linden
#

As in, real money?

sonic python
#

Yes

weak linden
#

That's a topic much larger than the scope of a discord message/basic tutorial LUL

graceful flame
#

Who's your payment processor?

sonic python
#

Whaaat?

quasi tide
#
  1. Make in-game currency, like you would for an RPG or any game that involves money in games.
  2. Now, make a backend (or use a 3rd party service) that updates the client's account's money after they make a purchase.
  3. Update on the client their account money
sonic python
graceful flame
#

No i mean the payment processor, like who accepts and processes the credit cards if its real money.

quasi tide
#

Maybe. Idk - I haven't looked.

graceful flame
#

Ummm

weak linden
#

Where are you publishing your game?

graceful flame
#

I don't think you have partnerships with the major credit card providers so...

weak linden
#

Steam, Playstore, Epic Store, etc?

quasi tide
#

The concept is really just adding an API call to some server that will update your in-game currency.

latent heart
#

I would have thought the playstore or whatever mac uses has some sort of api for taking your money.

graceful flame
#

Isn't that were you just buy the app?

sonic python
weak linden
sonic python
#

Yes

weak linden
#

You will need to look into it yourself, but that's the place to start

sonic python
#

Like I have a game currency set up.

#

Hmm It's my first time doing it

graceful flame
sonic python
#

Can you explain more

weak linden
#

Epic has a guide on this

sonic python
#

Yeah Done a small game with no money making thing

#

Okay

#

Now How Should I set up the value of my game currency to the real money?

quasi tide
#

100% completely up to you

sonic python
#

Oh nicee

#

Now where should I set it up?

#

The Value of my game currency

latent heart
#

In your mind.

#

FML

sonic python
#

Damn

#

Okay

latent heart
#

#define REAL_MONEY_TO_GAME_MONEY 50

sonic python
#

If I'm having like a dollar equal to a 1 unit of my game currency

prisma snow
#

How could I go about debugging the correspondence of two actors in a client/server?

I have a situation where the units in my formation are assigned to different spots in the client and the server, and seeing how it is happening would help a lot to figure out (and test) how to fix it

sonic python
#

Oh

quasi tide
prisma snow
sonic python
#

Okay

latent heart
sonic python
#

Then like for playstore

prisma snow
# latent heart UE_LOG?

With the UE_LOG I cannot "see" the units names or IDs or whatever on screen. Since I am debugging positions, a visual helper would be more useful in the long run than a console log.

latent heart
#

Just draw a debug dot at the point on the server (assume listen) and the client

prisma snow
sonic python
#

Like $10 = 1 Game currency

prisma snow
sonic python
#

They Should Buy X game currency for some amount right?

#

Then Where Should I set the real amount , for playstore?

weak linden
sonic python
#

I did

#

Like How ?

graceful flame
#

Just to rewind the convo a little bit, if you were to have something like a damage zone actor which can damage the player when they overlap it. Does that mean I should have two separate actors. One which contains the timelines for visuals and audio and another actor which contains only the box collider for overlap events to drive gameplay logic. The box collider actor would have Net Load On Client set to false?

I've been adding box collider components to level placed blueprint actors, but I guess those are running both client and server side even though I only need to check data during the overlap on the server.

sonic python
#

How ?

prisma snow
weak linden
sonic python
#

Now I Have Finished a big game u know , did everything, setted up in game currency

#

After that what's the next step for in app money

graceful flame
#

Components don't have Net Load On Client option like entire actors do.

sonic python
#

Confused

graceful flame
#

I suppose somethings could change on EventBeginPlay

weak linden
graceful flame
#

Yea I was hoping for some editor level checkbox for the component I want to skip loading on the client

weak linden
graceful flame
#

But I can settle for EventBeginPlay changes yeah

#

okay cool, thanks @weak linden

weak linden
#

Tech Jesus ๐Ÿ™

sonic python
#

Okay not confused

#

But still

#

Oh okay I kinda understood

quasi tide
#

I want to say it is something like UE_CLIENT but idk. Would have to search. Maybe UE_SERVER or something like that.

graceful flame
#

Yea I'm going to start migrating the heavy stuff first into c++ soon

quasi tide
#

Look at the character class on how they are adding the arrow component. Just do that, but with w/e the server/client macro is

sonic python
#

Now this is for the players buying - the clients , the customers

pallid mesa
chrome bay
#

Yeah probably will now I've actually made it :d

#

Honestly just lack of any kind of familiarity with Git

#

Gists look quite cool tbh

#

Easy to copy-pasta straight in. Do they end up in a repro somewhere where you can modify them etc or is it just pastebin but better?

#

oooh

pallid mesa
#

I prefer the repo tbh ๐Ÿ˜„ samples can be indexed in a master-readme easier (less hassle)

#

rather than a list of gists

#

It's a good initiative ๐Ÿ‘ Thanks James

weak linden
#

I also believe (maybe incorrect), there isn't a way to see another users gists without the link? A repo is just right there

#

Oh, it's a separate sub domain LUL

#

That's significantly less convenient than just having a "Gists" button like they do for repositories on a user profile

pallid mesa
#

are gist just single-files

#

or can they be a combo of files?

#

muuh uh i don't like it :(

weak linden
#

That works, but still a minor inconvenience LUL

distant vault
#

hello, i'm having some problems with show a widgets to the player that collides with an object and has a specific role attack to it(multiplayer). The problem is when the player collides with it, the widget get show on the other clients screen that has the role.

sinful tree
distant vault
versed ocean
#

Having some issues because obviously I'm misunderstanding something, but I made a dedicated server, I have 2 clients and a server, I made an object called a Bookshelf that is just out in the world, and it holds however many books the math calculates out it can, I was generating them on BeginPlay() procedurally and putting them on the shelf. I'm having a hard time understanding where the logic goes now I'm in multiplayer land. I had it all mastered on the client. My current goal is to have the bookshelf contain the same exact books on all clients. I tried to make the CreateBook() a UFUCTION(Server, Reliable) moved function logic to CreateBook_Implementation. Then I set the Book object to replicate. But no one owns the bookshelf its just out in the world so that method doesnt work, because the server version ticking doesnt have an owner? I'm strugglign with this. So I changed it to a UFUCTION(Multicast) just experimenting, and it does now start spawning the books on the client, but of course the order is different, etc because it appears to be taking place on the client, called from the Server ( which as I understand it is exactly what multicast does ) so I feel like I want a UFUCTION(Server) but honestly I have no idea at this point. Willing to show all the code, etc..

weak linden
#

This way, only the server will generate the books

#

Lastly, just as a note, always try and prefix your RPCs where they should be executed, I.E a Server RPC will be called ServerMySomething, likewise a client RPC will be ClientMySomething and a Multicast would be MulticastMySomething helps with readability

versed ocean
#

Always appreciated.

weak linden
#

๐Ÿ‘Œ Happy to help

#

One thing I'd like to say, if these books aren't gameplay relevant, I'd personally just have them local to each client, most players won't be too fussed if the top shelf doesn't have a large book 3rd from the right for them but their friend does ๐Ÿ˜›

#

If it's a must, but they don't do anything special, you can just drop down the Net Update Frequency to a very small number so they're not hogging your bandwidth

versed ocean
#

Part of my problem may have been I was trying what you suggest as well, but in the tick -- does the server not Tick objects?

#

i just moved it to begin play with 1 book to test as you mentioned.

weak linden
#

The server will tick objects as long as you've got it enabled on the server

#

(By default it will tick everywhere anyway so it's not something you manually need to do)

versed ocean
#

alright alright .. hmm still digging -- was shared a PDF on networking in cpp channel will read and experiment a bit here

weak linden
#

You'll get there eventually ๐Ÿ˜„

My suggestion, if you wanted these books to be "visually" correct on each client, but they serve no purpose other than decoration, you *could* have the server generate an array of books with their indexes matching the shelf, then just send that information over to clients (via an OnRep) to create locally so the books won't need to be replicated at all (which will save more bandwidth over however many shelves you intend on having)

versed ocean
#

Alright I think I understand the route you're mentioning there... I did that OnRep to sync my healthbars I will give that a try, wasnt sure you could do that with complex types *custom classes

pastel fiber
#

Is it possible to make completely TakeDamage() execute only on the server?
As you can see, the following implementation is not efficient because these two lines are still executed on the clients.

float NewCurrentHealth = CurrentHealth - DamageTaken;
return NewCurrentHealth;

Here is the complete code:

void AMyCharacter::SetCurrentHealth(float HealthValue)
{
    if (GetLocalRole() == ROLE_Authority)
    {
        CurrentHealth = FMath::Clamp(HealthValue, 0.f, MaxHealth);
        OnHealthUpdate();
    }
}

float AMyCharacter::TakeDamage(float DamageTaken, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    float NewCurrentHealth = CurrentHealth - DamageTaken;
    SetCurrentHealth(NewCurrentHealth);

    return NewCurrentHealth;
}
weak linden
# versed ocean Alright I think I understand the route you're mentioning there... I did that OnR...

You can OnRep almost anything you like, what I'd likely do for a solution for racks that have a different number of shelves is something like this.

enum EBookSize;
struct FBookShelf
{
    // Indexes for book order (0 is far left of the shelf, etc).
    TArray<EBookSize> BooksForThisShelf;
}

// Bookshelf actor class.
// Index corresponds to what shelf books belong on, 0 for bottom, 1 top, etc, etc.
UPROP(ReplicatedUsing = OnRep_Shelves)
TArray<FBookShelf> Shelves;
weak linden
pastel fiber
#
// Called when the game starts or when spawned
void AMyProjectile::BeginPlay()
{
    Super::BeginPlay();

    if (GetLocalRole() == ROLE_Authority)
    {
        SphereComponent->OnComponentHit.AddDynamic(this, &ThisClass::OnProjectileImpact);
    }
}

void AMyProjectile::Destroyed()
{
    FVector SpawnLocation = GetActorLocation();
    UGameplayStatics::SpawnEmitterAtLocation(
        this,
        ExplosionEffect,
        SpawnLocation,
        FRotator::ZeroRotator,
        true,
        EPSCPoolMethod::AutoRelease);
}

void AMyProjectile::OnProjectileImpact(
    UPrimitiveComponent* HitComponent,
    AActor* OtherActor,
    UPrimitiveComponent* OtherComp,
    FVector NormalImpulse,
    const FHitResult& Hit)
{
    if (OtherActor)
    {
        UGameplayStatics::ApplyPointDamage(
            OtherActor, 
            Damage, 
            NormalImpulse, 
            Hit, 
            GetInstigator()->Controller, 
            this, 
            DamageType);
    }

    Destroy();
}
weak linden
#

Huh, so ApplyDamage is calling TakeDamage client side too?

versed ocean
#

I was over complicating the living shit out of it.... smh.... bReplicates on the Actor ( my book and my bookshelf ) then like you said in the BeginPlay, make the books if there is authoirty ( ie: on the server )

#

done deal, works. thanks lol

#

Really appreciate the help @weak linden

weak linden
#

Nicely done! ๐Ÿ˜„ You're welcome

pastel fiber
#

Oh my ghost. TakeDamage() is executed only on the server. @weak linden ๐Ÿ™‚

dim trail
#

does fps affect server cost?

pastel fiber
weak linden
#

That being said, the server does also have a framerate, so if you have a weaker performing machine, you will have a lower server-side framerate (which would mean you'd need a more expensive one)

hushed rain
#

When I possess something new(a drone), the character(soldier) left behind is always "owned" by the server, and when I shoot it with the server it's like I shoot myself. How would I fix this?

weak linden
hexed pewter
#

I'm in APlayerState and I wanted to let know my UI that something has changed.
Is it okay to broadcast a delegate from OnRep_SomeProperty() so my UI can update whenever playerstate changes or are there some better alternatives?

weak linden
thin stratus
#

Keep in mind OnRep doesn't call on servers anyway if done via c++

weak linden
#

If you don't explicitly call it at least

#

With that in mind actually, I've always called my OnReps explicitly after changing the value, is that not needed?

quasi tide
#

On server, it is.

#

I just do a HasAuth check here and then do it. Server spawns everything, so server will always have auth

weak linden
#

๐Ÿ‘Œ

quasi tide
#

I also pretty much only work with listen servers.

weak linden
#

I always second guess things now, I've learnt a ton of stuff in the last week, stuff I thought was correct for the last 5 years ๐Ÿคฃ

silver pendant
#

Hi Chat

quasi tide
#
ACoolActor::SetTheProperty(bool NewProperty)
{
    TheProperty = NewProperty;
    if (HasAuthority())
    {
        OnRep_TheProperty();
    }
}

ACoolActor::OnRep_TheProperty()
{
    UpdateUiDelegate.Broadcast();
}

๐Ÿ‘† This is my general flow.

#

I pretty much always update my UI with a delegate. So, the listen server will update the UI correctly as well as clients. Won't matter on dedicated server, just nothing will be subscribed to the delegate.

hexed pewter
quasi tide
#

You locally predict and then do more custom logic inside of the onrep on if you accept the servers value or not

#

Most people are okay and understand why UI could take a second to update if they are lagging

hexed pewter
#

Now that you mentioned lagging I wonder how often do replicated variables skip a value or lag behind considering stable internet connection and decent ping ๐Ÿค”

green fjord
#

hello im hans from Indonesia.
i want to ask about replication pawn between client and server.
when i set actor location on pawn actor in client instance, the pawn actor on the server instance doesnt move. But when the client call custom event RPC run on server and set actor location the pawn actor move on the both instance (client instance and server instance) but in client instance the pawn move is not smooth.
how to achieve smoothness set actor location between client and server ?

#

i already try to set actor location first on client instance and every tick i call rpc (on server) to send the actor pawn location. but it still caused rollback movement because the server has a delay latency to client so the location that client send was "the past" pawn location on the server

short arrow
#

@green fjord are you making your own movement system by setting the actor location every frame?

green fjord
#

im working on multiplayer VR, because my VR character is made from pawn

short arrow
#

As far as I know... That is going to be a big challenge. Smooth replicated movement requires a lot of calculation, prediction, and algorithms. Are you unable to make your players a character? I don't really know how vr programming works

green fjord
short arrow
pastel fiber
#

Which part in UE source code makes AActor::TakeDamage() execute only on servers?

float AActor::TakeDamage(/**/)
{
    float ActualDamage = DamageAmount;

    UDamageType const *const DamageTypeCDO = DamageEvent.DamageTypeClass ? DamageEvent.DamageTypeClass->GetDefaultObject<UDamageType>() : GetDefault<UDamageType>();
    if (DamageEvent.IsOfType(FPointDamageEvent::ClassID))
    {
        FPointDamageEvent *const PointDamageEvent = (FPointDamageEvent *)&DamageEvent;
        ActualDamage = InternalTakePointDamage(/**/);

        if (ActualDamage != 0.f)
        {
            ReceivePointDamage(/**/);
            OnTakePointDamage.Broadcast(/**/);

            UPrimitiveComponent *const PrimComp = PointDamageEvent->HitInfo.Component.Get();
            if (PrimComp)
                PrimComp->ReceiveComponentDamage(/**/);
        }
    }
    else if (DamageEvent.IsOfType(FRadialDamageEvent::ClassID))
    {
        //...
    }

    if (ActualDamage != 0.f)
    {
        //...
    }
    return ActualDamage;
}
chrome bay
#

Nothing, you can run it client side if you want (but not from Blueprint)

#

The engine just expects you to call the "take damage" functions from the Server only, but it doesn't enforce it.

#

Apart from in Blueprint, where all the damage functions are tagged as "BlueprintAuthorityOnly" so won't run on network clients

#

But if you're making MP games in Blueprint you've already lost tbh

pastel fiber
#

Should Super::XYZ() be invoked when overriding?

  • Super::Tick(DeltaTime); Yes
  • Super::BeginPlay(); Yes
  • Super::TakeDamage(/**/); ????
weak linden
#

Typically, yes, unless you explicitly know why you don't want to call it

green fjord
#

in blueprint character how to check if this character is my character or other player's character that replicated on my instance?

fathom aspen
#

IsLocallyControlled

#

It's LauraControlled

winged wave
#

what are the best practices to make your game communicate with a backend? Would something like regular HTTP requests to an ASPNET Core endpoint be ok or you need more specific workflows? I'm talking mostly about data retrieval if you are building a multiplayer game

latent heart
#

Just be careful. People will reverse engineer your api and try to cheat.

#

Unless your http communication only happens from dedicated servers which are not available to the public.

twilit radish
#

Unless you don't strip out the requests / code properly lol.

#

Although really depends on how big your game is, small games tend to not have those issues. Except just random bots that crawl through the entire internet.

winged wave
#

ok thanks, for sure I will have to research on this topic

twilit radish
twilit radish
#

Oof.

latent heart
#

It has a wizard button, right?

mortal mica
#

haha, that's my fav gif of all times

meager raptor
#

Hi everyone, I have an actor component on my character pawn. Is there a way to know if it is local ?
My goal is that the actor component should act a certain way only for it's owner. I have tried "Is Actor Local" but it doesn't work on the owner (always return false)

fathom aspen
meager raptor
#

Well I'm in blueprint so I'm kinda fucked :p. But I think the issue I have is to access my pawn from the actor component so I would be able to know if I'm local. I wasn't able to use IsLocallyControlled since I need to access the control which I don't have access to (I think)

fathom aspen
#

That has nothing to with BP though. It's literally GetOwner -> Cast to Pawn -> Check if IslocallyContrrolled

meager raptor
#

ok let me check

fathom aspen
#

Though that might fail due to the pawn not being possessed yet by a PlayerController

#

Depends on what point in time you check that

meager raptor
#

in the begin play of the actor component

fathom aspen
#

Yes that smells bad

meager raptor
#

lol

#

thanks ๐Ÿ™‚

#

mmm

fathom aspen
#

BeginPlay for pawn or its comp fires before a pawn is possessed usually

meager raptor
#

so if I just create an event that I call from the pawn it might be best

#

from the pawn I can verify if my local

fathom aspen
#

The component is added before runtime, right?

meager raptor
#

I'm not sure

fathom aspen
#

Is it a replicated component that is spawned during runtime?

#

Or was it added through the simple construction script before runtime?

meager raptor
#

it is a replicated component that is added by default in the character blueprint

fathom aspen
#

So yeah it was added before

meager raptor
#

ok

fathom aspen
#

Then it should be there if you fire client RPC called from event Possessed that accesses it

#

Or you could have a replicated property that tells that your character is possessed and your component just listens to it

quasi tide
#

Is WizardCell back? ๐Ÿค”

fathom aspen
#

I don't like both approaches but that's how it is in BP

quasi tide
#

Or is this just in passing?

fathom aspen
#

In cpp it's much more neat

meager raptor
#

yeah I bet, since it's for a prototype we will try that dirty way ๐Ÿ™‚

fathom aspen
meager raptor
#

you are a smurf !

real ridge
#

Guys How I can change normal thirdperson character for plane in game? in MP bcs when I used pawn I didnt see other players seems like pawn is not replicated

#

when I use normal Character I see others but I need play as (human) I wanna replace it with plane

real ridge
#

Question is just if I should make plane from Character or try to replicate pawn which totally good fit for plane

real ridge
#

bcs now when I join session with 2 pawn I dont see each other ๐Ÿ˜„

fleet viper
#

was fiddling around with the packetlag command and set it to 200. Does this represent a ping of 200?

latent heart
#

Probably a ping of 400. Since ping is round time, not a to b.

pallid mesa
#

it depends on your requirements

real ridge
#

I dont understand

pallid mesa
#

cause pawns, unlike characters, dont bundle with a replicated movement component

#

you have to make your own

real ridge
#

they are in but they are not visible for each other

#

but when I try run as Net Mode: Play as Client and I run 2 instances

#

they are visible

real ridge
#

? its also server @pallid mesa

pseudo merlin
#

hi all, when my listen server host possesses a pawn the controller inherits the pawns rotation. when a client possesses a pawn the pawn inherits the control rotation. what might cause this difference?

#

I see the controller gets set to pawn rotation in OnPossess, but that might be server side only?

#

in general when server sets client controller rotation does that trickle down to client machines, or does that get overrwrote on server side next update from client?

pseudo merlin
#

setting control rotation to match pawn rotation on clients acknowledgepossession function seems to help

prisma snow
prisma snow
# fleet viper Isn't that the same?

Yeah but I found it quicker to iterate and also more detailed. You can setup differebt settings for client and server for example. I am sure the command does the same, but maybe it is less intuitive

fleet viper
#

I see

quasi tide
#

Just never leave the "bad" profile. Boom problem solved. Design your game around 200 ping and surely 30 ping will be fine, right?

prisma snow
quasi tide
#

Nah - 700 ping is in the realm of the player's problem, not mine ๐Ÿ˜…

prisma snow
#

I know but sometimes it helps to detect hard to catch problems

dry orchid
#

Hi I am having problems with my code I think

#

i am trying to add an impulse to my pawn's mesh but for some reason i cant make the server read the clients rotation

#
void UAction_CanicaLaunch::StopAction_Implementation(AActor* Instigator)
{
    Super::StopAction_Implementation(Instigator);

    ASCanicaPawn* Pawn = Cast<ASCanicaPawn>(Instigator);
    if (Pawn)
    {

        GetWorld()->GetTimerManager().ClearAllTimersForObject(this);
        
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, "Stoping Impulse");
        bIsPressed = false;
        if (!bIsPressed && Pawn->HasAuthority())
        {
            FVector RotationVector = Pawn->GetControlRotation().Vector();
            DrawDebugLine(GetWorld(), Pawn->GetActorLocation(), RotationVector*5000.f, FColor::Red, true);
        }

        Impulse = 0.f;
        GetOwningComponent()->OnActionStopped.Broadcast(GetOwningComponent(), this, Impulse);

        
    }
}
#

anyone knows why is this happening?

#

that action is called once by the client and once by the server but only the server can add the impulse (i havent add the code for impulse yet)

deep island
visual flint
#

Im using UE 5 with Data layers, I cannot figure out how to implement a loading screen and determining when a data layer is loaded. Im trying to add a dungeon to my game where an individual player loads the dungeon data layer while another player is roaming around the over world. I cant figure out from the docs a good solution, does anyone know of some good multiplayer data layer resources?

sonic python
#

Hey Me Again

#

When I press a button ,($10) I want to make a in app purchase

#

How to do that

#

And the product is just some integer var

prisma snow
#

On button press, send an RPC with the player controller to the server. Validate that the player has enough money, the product is available etc, then do the corresponding changes in the state (whatever they are) and replicate the state back to the player if necessary

#

@sonic python

sonic python
#

I want to know abt that Make In App Purchase, Read , Restore...

#

When I press the button

prisma snow
#

Purchase what

sonic python
#

A custom event in game instance happens

#

Which is add game currency

sonic python
latent heart
#

He wants to add a button to spend real world money to buy ingame currency for his mobile game.

prisma snow
#

Ahhh and he asks here

#

LOL

sonic python
#

Do you know where should I ask?

#

Epic - online - services?

latent heart
#

That's not related.

sonic python
#

Online subsystem?

latent heart
#

Or that.

sonic python
#

Ohkay

dry orchid
deep island
#

What are the results?

dry orchid
#

for the server

deep island
#

On the server do you have the same result?

dry orchid
#

no, in the server it changes normally

deep island
#

If you use the GetControlRotation() method do you have that value on client? Or the right one?

dry orchid
#

im gettin that one too

#

but i have an error when i compile

#

ObjectProperty FActionRepData::Instigator is not initialized properly. Module:Videojuego_Canicas File:Public/SAction.h
Display LogClass BoolProperty FActionRepData::bIsRunning is not initialized properly. Module:Videojuego_Canicas File:Public/SAction.h
Display LogClass 2 Uninitialized script struct members found including 1 object properties
Warning LogAutomationTest ObjectProperty FActionRepData::Instigator is not initialized properly. Module:Videojuego_Canicas File:Public/SAction.h

#

maybe that is what causing it?

deep island
#

Have you initialized bIsRunning correctly inside FActionRepData?

#

And Instigator too

dry orchid
#
USTRUCT()
struct FActionRepData
{
    GENERATED_BODY()

public:

    UPROPERTY()
    AActor* Instigator;

    UPROPERTY()
    bool bIsRunning;
    
};
#

thats how i wrote the struct

deep island
#

Make a default constructor

#
FActionRepData()
{
bIsRunning = false;
Instigator = nullptr;
}
#

Under bIsRunning;

#

And try to compile

dry orchid
#

ok i got rid of the error, thank you

#

also i have this one

#

Failed to load '/Game/RollingCPP/RollingOverview': Can't find file.

#

not sure what that is

#

but the rotation is not updating correctly yet

deep island
deep island
#

if GetControlRotation() is working on the client, you have something not working with GetPlayerViewPoint(), which is the function used by GetBaseAimRotation() to get the player's eyes view point

#

At the end it should use GetControlRotation() anyway on the local client, because it's calling GetViewRotation() on the pawn, which returns GetControlRotation() if the Controller is not null

dry orchid
#

that one is with GetControlRotation()

#

the blue one is de client and the green one the server

#
bool USActionComponent::StopActionByName(AActor* Instigator, FName ActionName)
{
    for (USAction* OtherAction : Actions)
    {
        if (OtherAction && OtherAction->ActionName == ActionName)
        {
            if (OtherAction->IsRunning())
            {
                if (!GetOwner()->HasAuthority())
                {
                    ServerStopAction(Instigator, ActionName);
                }
                
                OtherAction->StopAction(Instigator);
                return true;
            }
            
        }
    }
#
void USActionComponent::ServerStopAction_Implementation(AActor* Instigator, FName ActionName)
{
    StopActionByName(Instigator, ActionName);
}
#

that is how i wrote the code in the action component calling the action

#

and that is why is been call 2 time in the picture

dry orchid
#

but when the server is calling the action

fiery wadi
#

Probably a dumb question but i cant seem to find a google response, How would i use Get Ping In MS from the server ? I know its from the Session Class but im not sure how i access the server's session. ?

#

So i have it atm the player clicks Host Session and Goes tto the lobby area and I want to show the servers ping in a scroll list Player A : 12ms, Player B 35ms, Player C 100ms etc. (Player A would be the server itself in this instance)

prisma snow
fiery wadi
#

Get Player State - > Get Session -> Get Ping In MS? something like this.

prisma snow
#

Not sure how it is calculated exactly, it is not a trivial calculation

prisma snow
fiery wadi
#

Thank you

prisma snow
fiery wadi
#

Ahh thanks !

deep island
# dry orchid

Hmm, I don't know, it's not clear what it's happening

#

What's that Server: 0.0 print string?

dry orchid
#

ah thats the impulse i am adding. it has nothing to do with the rotation

deep island
#

@dry orchid ok, in the last screen the green and blue values seem correct (except for the first blue one, but I don't know where it comes from), so what is not working?

woeful ferry
#

Yo guys,

Just wanted to know I just released a nice resource for the BP multiplayer community, where BP projects can replicate UObjects without having to use c++. I don't know if I'm allowed to send marketplace links here ๐Ÿ˜…

#

oh yes ๐Ÿ˜› I'll let people go there instead.

#

Posted there now, if people wanna check it out ^^

dry orchid
#

in the last pic is the server, the server is working well

dry orchid
# dry orchid

thos one is the client. when the client runs te action it has the correct rotation but when the server calls the action trough the RPC

#

the rotation goes to 1 , 0, 0'

#

dont know why

deep island
dry orchid
#

yes

dry orchid
deep island
#

Maybe there is something else that sets a bad rotation in your code, anyway I don't know what to think, if the server is getting the right rotation, it should work, and if you have the right rotation on the client too, why when you call an RPC should the rotation be different?

#

You need to debug the code and see where the things are breaking, maybe you can even debug the engine code and see what's wrong there

#

I mean, the engine code usually works, but maybe you are passing bad things somewhere, and it's returning something wrong in those functions

plush wave
#

Ok so for vehicles

#

Is it better for them to simulate physics and replicate

#

Or better to have a custom component and fake it

dark edge
#

If you're game is meant to be a physics playground then use physics. That's what I'm doing.

#

If it's meant to be vehicles GTA style then fake it

plush wave
#

Hmm

dark edge
# plush wave Hmm

This is what I got going on if you want to take a look. It works in multiplayer but I'm NOT doing prediction as that'd be an entire can of worms. So there's ping delay between inputs and the vehicle doing the thing.

plush wave
#

Yeah, super interesting, thanks

#

so why the ping delay?

pallid mesa
#

because it doesn't have prediction

dark edge
#

prediction is bad enough when you know the limits of what the pawn can do

#

when it's people building big kerbal twisted metal style contraptions it'd be a nightmare

prisma snow
dark edge
#

no thanks lol

#

and even with great prediction you always have trouble when it comes to pawn to pawn collisions

#

I'd rather just have the delay and be done with it. It's not a racing game, it's not like tanks and artillery really need to respond THAT quickly

prisma snow
plush wave
#

Rocket league seems to do it well

quasi tide
#

They're also big ๐Ÿง 

prisma snow
#

Even without prediction physics replication is a nightmare

dark edge
plush wave
#

Right

dark edge
#

What I'm trying to make is closer to Kerbal Space Program with engines and tires and it's already a nightmare since everything is so nonlinear.

prisma snow
#

Ye. Also Frost Giant is doing prediction (via rollback) for Stormgate, but good luck assembling a team that can do lockstep, let alone lockstep and rollback in a RTS context

plush wave
#

Guessing GTA5 is similar?

dark edge
#

There's a reason why we had great flight and space sims decades before realistic driving physics. Tires are hard man.

prisma snow
undone kindle
#

What information should be on player pawn vs. player state vs. game state?

I'm making a single player game, but trying to get used to doing things the "right way" for when I do a multiplayer game in the future that will require network replication

#

Reading the docs, and network compendium, but it's still not clear to me

#

My instinct is that everything player related should go on the player state

undone kindle
#

Awesome thanks!

neon mango
#

Is there a known bug in 5.1 that shows black screens for clients?

woven basin
dark edge
#

Score is on player state. HP is on pawn

summer tide
#

Can you create multicast methods in UAnimNotifyState?

worthy knot
#

Does UE's default voice chat even work ?

#

proximity voice chat

short arrow
#

I've used it once for a small multiplayer game I made and it worked fine. However the quality was terrible, like even worse then Apex legends

#

and apex legends voice chat quality is straight booty

winged badger
prisma snow
#

Is it possible/advisable to build a net system such that bandwidth is "manually" limited?
Let me explain the context. After some tests in real conditions, I am quite sure that our current replication system for RTS is viable with relatively big unit counts. However, it is not very efficient or smart, in the sense that it basically updates all units equally no matter the context. After some research, I came again into Glenn Fidler's articles about networked physics, and the "state synchronization" approach that he describes fits our usecase really well. He describes the idea of a "priority accumulator" (an array of items with a dynamic priority, which gets sorted each time that we are doing an update).

The basic idea is that you define a max size for the update, and pick items from the array starting with the highest priority, until all items are picked or the max size is reached. In this way, important items get updated more frequently, but never exceeding a certain packet size

#

Since internet connections are quite variable, and I am not sure that it is easy to automatically detect the connection strength as to define a different max limit for each player, I was considering putting a setting that each player can pick or similar. But still, I am not sure that is a good approach

winged badger
#

that can come around to bite you

#

without a panic mechanism

#

and it is more or less what unreal does for replicating actors already

#

what are you units in gameplay framework terms, and how much data is there per unit?

prisma snow
#

Units are MassEntities, basically. There are Pawns on top of them which have some AI logic and combat stuff (GAS), but all the movement is handled manually in Mass and the position replication (which is the one I mention) too

winged badger
#

how many players?

prisma snow
#

Each unit has a 16bit ID (same for server and clients), and positions are compressed to 16bit for X and 16bit for Y

#

For player count, ideally up to 8, but to be honest reaching 4 would be already enough.

#

And unit count, max 2k, although usually it's going to be between 100-500

winged badger
#

c++ ?

#

max 2k means no character movement components or something crazy like that?

prisma snow
winged badger
#

with c++ and simplified movement components, i'd go for dedicated actor for replicating units per connection, relevant only for that connection

prisma snow
#

I need to replicate through a helper actor, that is totally necessary

winged badger
#

in it, i'd put a fastarray for each interface a unit might need to replicate stuff from, plus one for the basics, (ID, position)

#

every fast array item would have either an ID or a weakpointer to the unit pawn if you can make those net addressable

#

and i'd turn off unit replication off completely

prisma snow
prisma snow
#

currently, each unit gets updated once per second, so thats 16+16+16 * 2000 = 96kbit/s

winged badger
#

how are you replicating the data?

prisma snow
#

dunno how crazy it is honestly, a 2 player test we made with 1k units ran well

prisma snow
winged badger
#

try a fast array, i don't think it will have a problem handling that

prisma snow
#

But from testing, there are times where the update is just not necessary, and others where more frequent updates would be benefitial

#

that's why some variable approach sounded appealing

winged badger
#

fast array will only send over items you have marked dirty on server each update

prisma snow
#

I'll give it a try and make some tests

#

also I'm making some tests to see if sending full position is worse than sending deltas

winged badger
#

i don't think there will be any difference there

prisma snow
winged badger
#

my network managers are handling literally thousands of actors, and never had a single hitch

prisma snow
winged badger
#

basically

prisma snow
#

how many thousands, and how many players?

winged badger
#

8 players, can have 6-7k actors if someone dropped a nuke

#

and never had a problem with hotjoining after either

prisma snow
#

do you have dedicated servers?

winged badger
#

note that my actors don't need such frequent updates

#

no

#

but basically, whenever something above some significance threashold happens

prisma snow
winged badger
#

you update its item in the array and mark it dirty

#

there is also oodle built into UE5

#

that should help too

prisma snow
prisma snow
winged badger
#

basically, for movement

#

if the player did not change the move order

prisma snow
#

I also was considering writing a serialization system for those 16ints bcs many times I can get away with less

winged badger
#

and nothing else interfered with the unit

#

its movement is quite predictable

#

and would not need to be updated

prisma snow
# winged badger basically, for movement

what I realized in our context, is that even if units collide between them (with no combat involved) the only difference is that they arrive to location slighlty later. Not even noticeable unless playing with 2 screens and slow mo

#

So positions only get out of sync when cluster collision scenarios happen and even then it is not important unless we are fighting

prisma snow
#

There's a detail about the FFastArraySerializer that I don't find clarified, when they say it does "delta" updates, do they mean:

  1. Only the dirty structs are replicated, not the whole array
  2. Only the changed properties from the dirty structs are replicated
  3. Only the change/diff between the changed properties of the dirty structs are replicated.
#

So if I have a struct with int A = 10 and int B = 5, there is a change and now B is 6.

What will he actually be sent across the net, the two values, only value B, or the old B value minus the new one (in this case, a single 1)

thin stratus
#

I can at least say that the third option is not correct

#

That wouldn't make sense for other properties :P

prisma snow
thin stratus
#

I think it sends the element itself. But not sure if that gets cut down even smaller by only sending the inner property that changed

prisma snow
#

I'm gonna make some tests so I'll test that as well

winged badger
#

you can manually implement delta serialization on fast array item

prisma snow
quasi tide
#

@winged badger Just caught up - are you saying you are replicating like 1K+ actors that are moving around and what not through your network manager?

prisma snow
quasi tide
#

I'd imagine yours comes from a more simplified movement component though, no?

#

(I'm always lookin' for ways for maximum zombies ๐Ÿ˜ˆ)

#

Even if I don't actually need it

#

(I already knew about network managers, as an FYI)

#

Just getting them to work with movement, hadn't tried ๐Ÿ˜ข

prisma snow
distant turret
#

with EOS plugin is it possbile to create a chat system

prisma snow
#

CMC is very heavy

#

maybe the floating pawn component is more performant for zombi hordes

quasi tide
#

Ahh - nah, CMC is fine for me honestly. I only plan on having like, max, 40-ish for this zombie game I'm doing. But I always enjoy pushing things ๐Ÿ˜…

#

I already know that I'd want to do an entirely custom movement component if I wanted to go much higher.

prisma snow
#

I think CMC fell appart in mp when we had something like 100 units

#

but that was default settings

quasi tide
#

Yeah - I'm doing more Resident Evil scale ๐Ÿ˜…

prisma snow
#

maybe with a much lower update rate and appropiate settings it can do more

#

also if it is a 1st/3rd person game, only the zombies that are close are reslly relevant so you can optimize around that

quasi tide
#

Yup

winged badger
#

we can do 200-250 CMCs

#

but that took some doing

undone kindle
#

Should PlayerState be a glorified bag of properties that are public read/write accessible and let the GameMode handle validation, or should it validate its own data with custom setters so that health can't go below 0, etc.?

quasi tide
#

Do as much on the client as you can

#

PlayerState should be things that you want other people to know about the player as well as pawn agnostic things

#

You could have health in there as well mind you. You just have to reset it when you get a new pawn and handle the current pawn when it gets <= 0

latent heart
#

Unless they're (static) const.

#

(except maybe on structs :p)

undone kindle
latent heart
#

It will just cause problems later.

#

It's not necessarily about validation (though it could be), it's more about having some buffer between the code setting the variable and the variable being set, so you can add callbacks or validate or whatever.

#

It takes no time at all to add a setter/getter, but it takes ages to adjuts code when you need to add them after the fact.

undone kindle
#

Oh that makes sense, so like if I want to broadcast a change in player health. Better to just mediate through getters/setters so the interface is set up for it from the beginning

latent heart
#

Exactly!

quasi tide
undone kindle
quasi tide
#
  1. Know the rules
  2. Evaluate if you give a care about said rules ๐Ÿ˜ˆ
#

If it is my code - I do w/e I want. It's my travesty. If I'm working on a team, I do it the "correct" way.

#

For my own code - I can count on one hand how many times I've went back and was like, "Dang - I really need to do additional logic for this field"

#

(Not saying I don't use getters/setters mind you)

candid shuttle
#

Hi guys, I need some help on an issue I am having:

#

So I have a PauseMenu where a button can make a player leave the lobby or, if it's the server, destroy the session (means = kick everyone). Now when I use this button in my LobbyLevel everything works fine but when clicking while on GameplayLevel everybody gets kicked even when a Client uses the button, which certainly should not happen.
I couldn't find anything on Reddit or the ue4 forum so I attached some pics of my BPs:
(The branch I used after my MultiplayerLeaveSession Event is copied from a forum post but doesn't really do anything the DestroySession node wouldn't handle on it's own)

Thanks for any help in advance

candid shuttle
#

Without multicast it's the same. And the Multicast just fires if it's the server, which works fine, but the problem is on the client

#

And Multicast can't be fired from a client

thin stratus
#

I mean

#

You shouldn't destroy sessions like this anyway

#

If the Server crashes or similar, the Clients will be booted to the MainMenu without calling this

#

You aren't catching all edge cases with this

#

And a Client with a Session can't Join or Host anymore

candid shuttle
#

This also gets fired on EndPlay

#

Does this help?

thin stratus
#

Maybe, but best is to just Destroy it in your MainMenu GameMode and/or before calling Host/Join/Search

#

Either way, you also wouldn't need to multicast this

#

If the Server leaves, the Rest is moved to the MainMenu anyway

#
  • the Server might also leave before the RPC is even processed, and the Clients will be moved to the MainMenu naturally anyway
#

It's just not the safest/cleanest way

candid shuttle
#

The session even gets destroyed in the MainMenu just for safety reasons you mentioned. But even removing the Multicast doesn't remove the problem

thin stratus
#

Hm, strange indeed

candid shuttle
#

Ok so I should just do a OpenLevel?

thin stratus
#

I would try

#

Not sure why it would boot everyone though if just a client calls it

candid shuttle
thin stratus
#

What does your log say

candid shuttle
thin stratus
#

Opening level as Client should not disconnect anyone but that Client

candid shuttle
#

When I just open the level without a DestroySession in the MainMenu it still disconnects everyone. And this problem only appears after switching from Lobby to Gameplay Level.

thin stratus
#

But.. when you are testing multiplayer

#

In PIE

#

And you travel

#

That means you aren't using Seamless Travel

#

Which is kinda bad

#

99% of the time you should Seamless Server Travel

#

And that is not available in PIE

candid shuttle
#

I use servertravel for Lobby->Gameplay Level

#

Is this seamless travel?

thin stratus
#

Yeah, but if you can travel in PIE that means you aren't Seamless Traveling

#

No it's not by default

#

Seamless has to be enabled on the GameMode you are travling with

candid shuttle
thin stratus
#

It also changes a lot of the functions that are called

#

E.g. PostLogin in the GameMode doesn't call for this

#

And CopyProperties in the PlayerState is now available to move data over

#

Yeah

#

You can't do that in PIE though, it's disabled

#

And some Subsystems, like Steam, require this

#

Otherwise your Clients disconnect on Travel

candid shuttle
#

Yeah i see, so I need someone to test this with?

thin stratus
#

Or rather

#

Don'T reconnect

#

No, you just need to do it outside PIE

#

E.g. by starting standalone

#

or rightclicking the Uproject file and launchign the game

#

Or even packaging fwiw

#

Usually, once the traveling is "working", one only works in the current map in PIE anyway

#

So it's not too big if a hazzle

candid shuttle
#

So I need to disable steam subsystem?

#

I'll try that

thin stratus
#

No, that was just a side comment

candid shuttle
#

I did need to disable SteamSub, but the problem persists still. Do I need to call something else then OpenLevel eg servertravel

thin stratus
#

Not for Disconnecting

#

Only if you want to travel from Lobby to Gameplay, Gameplay to Gameplay or Gameplay to Lobby

#

And only on the Server then

candid shuttle
#

what do I need to call if I want to seamlessly leave the gameplay section as a client?

#

still OpenLevel?

thin stratus
#

OpenLevel

candid shuttle
#

Because that doesn't work either, kicks everyone

thin stratus
#

Can you test that in Standalone ?

candid shuttle
#

That was in standalone

thin stratus
#

Then you'll have to look at the logs of everyone

#

And see why they leave

dry pebble
#

Have an issue where server and client are in the correct custom Movement Mode (climbing) but simulated proxy knows we're in the right movement mode for one frame, then exits it to the falling logic. Even though the server knows we're still in the climbing mode. Any ideas for that?

latent heart
#

I would say find out what's changing the mode to falling.

thin stratus
#

Iirc SimulatedProxy still runs its own simulation of the movement code

latent heart
#

@undone kindle another reason setters are good ^

thin stratus
#

So it could indeed manually decide that it's falling

#

Cause it might be missing some information

#

Given most of the time you only share information between server and autonomous

#

You might just have some condition to start falling that is never false for the simulated, cause you rely on something only those two know?

#

Just a wild guess

dry pebble
#

This is what changes it to falling in PhysClimb()

        if (ShouldStopClimbing())
        {
            StopClimbing(deltaTime, Iterations);
            return;
        }

If I comment this out, the simulated proxy knows we're in climbing and never leaves it. But if I leave it on server + client say climbing and sim proxy says falling.

And this is:

bool UMMOCharacterMovementComponent::ShouldStopClimbing() const
{
    const bool bIsOnCeiling = FVector::Parallel(CurrentClimbingNormal, FVector::UpVector);
    
    return !Safe_bWantsToClimb || CurrentClimbingNormal.IsZero() || bIsOnCeiling;```

And
```cpp
void UMMOCharacterMovementComponent::StopClimbing(float deltaTime, int32 Iterations)
{
    Safe_bWantsToClimb = false;
    SetMovementMode(EMovementMode::MOVE_Falling);
    StartNewPhysics(deltaTime, Iterations);
}```
#

And Safe_bWantsToClimb is only set to true when I click "E" and face a wall. I never set it to false

#

And it's added to compresed flags etc too

latent heart
#

I'm gonna assume b_WantsToClimb is false on the simulated proxies. or the normal is zero.

dry pebble
#

But isn't PhysClimb not called on sim proxies? only server and client?

#

And only movement mode is replicated? (+ velocity, acceleration etc.)

#

And yes Safe_bWantsToClimb turns false which exits to falling state, the rest remain the same in ShouldStopClimbing() when I break point it.

latent heart
#

Then it's calling should stop climbing on the simulated proxies and causing the error. Maybe add an owner check to changing movement modes?

thin stratus
#

Pretty sure Simulated runs some code too

latent heart
#

Role != SimulatedProxy or whatever

dry pebble
#

CharacterOwner->GetLocalRole() != ROLE_SimulatedProxy)

dry pebble
#

OMG IT WORKED!

#

Adding the simulated proxy check ๐Ÿ˜„

#

Normally the red circle would say "Falling"

#

thank you so much!

#

I gotta go read up about sim proxies running physics functions now lol

latent heart
#

It doesn't make sense for simulated proxies to be changing movement modes themselves anyway, so this is probably a good general fix.

dry pebble
candid shuttle
#

because both display nothing when leaving

undone kindle
#

Since PlayerState and their Pawns are replicated to all clients, does that mean a client can see other player positions through walls using some client-side patch to the game (aka "wallhacks")?

latent heart
#

In theory, yup

candid shuttle
latent heart
#

If you're super concerned about that, you could be very strict on relevancy.

#

It will delete actors and not replicate changes when actors become non-relevant.

#

Well, maybe the delete part. Probably delete.

fathom aspen
#

If they are dynamic net actors they will get deleted

#

Which is the case with pawns

#

You can take a look at what Valo did

dry pebble
#

So I just added this to my PhysClimb functions so none of this code runs for simulated proxy and everything works. Is there a case where simulated proxies should call the custom Phys functions?

if (deltaTime < MIN_TICK_TIME && CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy)
    {
        return;
    }```
#

As I notice the while loop in PhysWalking checks if you ARE a sim prox

    while ( (remainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations) && CharacterOwner && (CharacterOwner->Controller || bRunPhysicsWithNoController || (CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy)) )
    {```
undone kindle
neon mango
#

So I have game mode updating game states array of team scores, and team scores is set to replicate but the array doesn't change from their default values?

#

Server is fine, client doesn't see the updated scores

fathom aspen
#

Probably forgot to tell GetLifetimeReplicatedProps about the array

#

I don't think UHT rants over you if you forget to do that

neon mango
#

I'm prototyping and doing this all in blueprints. Is this an issue with blueprints and I should try to do this in c++?

fathom aspen
#

Ah, nvm then

#

I boldly supposed you did it in cpp

neon mango
#

I'll end up moving in. CPP but I'm just prototyping right now and I thought this array replication works in blueprints

#

Does it matter how you set the array?

fathom aspen
#

I think you have to SET the array in BP for replication to work, prolly just adding doesn't trigger replication?

#

Cuz I at least know that happens if you use the increment operator in BP it won't

neon mango
#

I tried via the set array element and set by ref

fathom aspen
#

Sorry I'm not a BP geek, and BP is full of networking landmines so I'm just guessing

fresh cloud
# latent heart If you're super concerned about that, you could be very strict on relevancy.

not for this reason specifically, but i originally did this for the portfolio piece i'm working on. part of my design was pawns shouldn't even be spawn in when they are irrelevant to the client, and relevancy doesn't change often in my design, so when certain factors are recalculated i recheck the replicated actors and close channels on the server. this IMMEDIATELY closes them, and when they become relevant again they pop back in

#

outside of closing the channel, relevancy still has a threshold time where, after being deemed irrelevant, the channel stays open for a little for the server to be able to preserve it in case it becomes relevant in a short amount of time. this can be adjusted, but i found better reliability in just closing the channel myself

fathom aspen
#

Sad day for my MMO dev career aPES_Sob

neon mango
#

So I think it is replicating but there is a delay, of like 5 seconds?

#

IDK if its an editor testing issue in 5.1 or something else

fresh cloud
#

uh, also i remember reading somewhere that array replication is atomized in UE

#

so, for example, if an array goes from {0, 0} {0, 1} {1,1}, that exact order isn't guaranteed?

#

clients might receive the replication in unexpected order

#

i'm not saying that's the current issue, but it's something to be aware of when replicating an array

#

... i think tekkThink

neon mango
#

I switch to float and now testing with int32

#

notice the delay with iint32 replication

#

it's getting there but delayed

#

compiling now to test on individual hardware

#

Fyi not as an array

fossil spoke
#

@fresh cloud Correct, there is no guarantee that a Replicated Array will be order consistent across Clients.

#

If you need consistency of order you would need to setup support for that by some other means yourself.

neon mango
#

I can ditch the array right now

#

Good info

#

Curious about the delay

fossil spoke
#

What Actor does the Replicated property exist on?

#

A delay in replication time could mean a couple of things.

neon mango
#

A standard AActor that only server has, then that goes to the game mode to call update score and then sets replicated integers on game state

fossil spoke
#

So they are on the GameState?

#

Have you checked that the GameStates NetUpdateFrequency is relatively high? A low NetUpdateFrequency can give the appearance of delay when replicating variable values.

#

Also verify that you arent testing with simulated Latency in the Editor.

#

This would also contribute.

#

Keep in mind that a variable will only replicate (by default) if its value has changed.

neon mango
#

Enable Network Emulation is not enabled

fossil spoke
#

Can you repro the issue in a blank project?

#

What are you using to verify there is a delay?

frosty dune
#

Hello everyone. Having an issue trying to a player's steam ID with a dedicated server.

I see the message on the server after the onjoin "LogBlueprintUserMessages: [DarkRP_GameMode_C_2147482482] Steam ID: 76561198099278132 joined the game."
But when I try and access the SteamID from the player, I get a "Bad Unique Net ID" error.

fossil spoke
#

You would likely want to Replicated the SteamID variable, or access the Steam Id locally on the Client from the OSS, since the Client should have its Steam Id locally as well.

frosty dune
#

That makes a lot of sense. That's a stupid mistake on my part

fossil spoke
#

The Steam Id should be set on the Client via the PlayerState exposed through UniqueNetId

frosty dune
#

Gotcha. I'll switch that around and give it a shot. Thanks!

candid shuttle
sinful tree
fresh cloud
#

oh also very basic question, but does your host happen to be a listen server?

#

if a listen server opens a new map, they aren't just a plain client, that will kick everyone too

summer tide
winged badger
#

no, but the anim notify can call a function on something that is replicated and able to MC, like the pawn

summer tide
winged badger
#

to avoid blueprint dependencies?

#

you can call a c++ multicast, it really doesn't matter if you cast to native class

#

they are all loaded at all times

summer tide
#

To keep the integration simple. So no need to re-parent anything.

winged badger
#

sometimes casting is necessary

#

and interface seems way too much for this scenario

summer tide
#

If I can override a function from notifier in AnimBP that will work but then I have to access the notifier from animbp somehow

candid shuttle
fresh cloud
#

yeah, they count as client and server at the same time, if you want them to function as ONLY a client, the server has to be set and dedicated and hosted elsewhere ๐Ÿ˜ฆ

#

you can get verification from one of the more knowledgeable members, but to my understanding that's the case

candid shuttle
#

Can I say Bad word

thin stratus
#

Eh

candid shuttle
#

ok sry

thin stratus
#

Not related to the f word

#

A ListenServer does not provide the ability for other clients to kick

fresh cloud
#

but if the listen server abandons by loading the map, it should kick everyone else right?

thin stratus
#

This whole thing would only work if the ListenServer disconnects. That will then disconnect everyone else cause no Server available.

#

Yeah but they have the issue that a client causes everyone to leave

fresh cloud
#

oh exi i was asking that under the assumption that the "client" that was causing everyone to leave was a listen server "client"

#

which in this case would cause that to happen

candid shuttle
#

How can a client be a listen server client? A player that creates a listen server?

thin stratus
#

They are calling locally OpenLevel. I'm pretty sure there is other stuff going on that we either can't see or isn't obvious

#

I can create a new project now, let 2 clients connect to a ListenServer, and then let one Client leave and it won't break, I'm pretty sure

#

Otherwise a lot of games would have huge issues

candid shuttle
#

that's what I would think too

#

but....

#

my project doesn't wanna do that

thin stratus
#

Yeah but the chance is high that it's caused by code from you

candid shuttle
#

Thats for sure

#

Does a beginPlay node in a level BP get called from Server or Owning Client, in the MainMenu for example?

#

Because I now did this and it only prints out 'mmmmmmmmmmmmmm' one time

sinful tree
candid shuttle
#

It does print out Server, Client1 and Client 2 while I am only playing as 2 Players

thin stratus
#

BeginPlay gets called for everyone who has an Instance of the specific Actor

#

LevelBP would be called for everyone who is on that level

prisma pelican
#

why does pawn's actor get destroyed when on level reset is called, the default implementation shouldnt do this right?

candid shuttle
summer tide
#

How do you get IsLocallyControlled in AnimInstace?

candid shuttle
#

get owning player of some sort

fathom aspen
fathom aspen
summer tide
fathom aspen
#

Last I checked I found AnimInstance != Pawn so yes you can't

summer tide