#multiplayer

1 messages ยท Page 462 of 1

fleet raven
#

could work

#

the worst I've seen so far was a server with 25% packet loss

#

surprisingly, it worked mostly fine

#

but slowly

grizzled stirrup
#

It all still works it's just unpleasant to see things being corrected and also knowing you could be unlucky and fire your shot when there is a moment of loss

#

Happens in Fortnite too though

fleet raven
#

character movement can easily recover from a little loss

#

it's mostly unaffected even

rotund sapphire
#

Isnt unreal networking accounds for packet loss via the Ack packets where it repeats the transmission until it completes (or something like that) ?

fleet raven
#

for reliable rpcs yes

grizzled stirrup
#

When I play Fortnite on wifi, I get a lot of rubberbanding (chests opening late, glitching to where I wasn't, shots straight up not seeming to register)

#

But then when I plug in my ethernet it's flawless

#

I can see from the indicators I'm dropping packets on wifi

#

But yeah not a pleasant experience

fleet raven
#

๐Ÿค”

#

add a "packet loss defense" feature that sends every packet 3 times just in case

#

the server will filter out the duplicates anyway

grizzled stirrup
#

Oh no it's unavoidable, it happens in many games that I play

#

Just always is an unpleasant experience when I encounter it

fleet raven
#

ye but that might be a way to make it less of a problem

grizzled stirrup
#

I mean if it happens on Fortnite, it'll happen everywhere

#

It's a good idea though

fleet raven
#

unless the loss happens in bursts

grizzled stirrup
#

But really it's just the loss of not important packets that causes the unpleasant feeling (small skips here and there)

#

Light corrections

#

The feeling that you are shooting but you never know if you'll miss due to some loss

fleet raven
#

maybe stop using the crappy wifi ๐Ÿค”

grizzled stirrup
#

Lol I pay 100 a month for it

fleet raven
grizzled stirrup
#

It's really fast just seems to suck when not direcly next to it

rotund sapphire
#

kylekatarn you can bring up the wifi device's detail panel and play with the settings, such as allowed power for the device. Windows on a notebook might using your wifi on a reduced rate only for preserving battery. Even if you are powering your notebook from a cord.

grizzled stirrup
#

But yeah ethernet fixes it

fleet raven
#

wait why are you paying for wifi

#

you don't have your own router?

grizzled stirrup
#

Yeah that's what I mean

#

I'm paying per month for the service

#

@rotund sapphire I'm pretty sure it's just proximity, it's in the next room, and my computer has a great wifi adapter

#

It's funnily actually faster speedwise on wifi

#

But less reliable

rotund sapphire
#

A magnificent wifi adapter

grizzled stirrup
#

I use it to download things at like 20+ MB/s but on ethernet I only get 4

#

But ethernet is fully stable in games

#

I don't even know ๐Ÿ˜„

#

It is what it is

fleet raven
#

that sounds like something is configured wrongly

rotund sapphire
#

That could be a faulty of your eth cable, since there are at least two different types. duplex and not

grizzled stirrup
#

Very true I should look in to a new cable

rotund sapphire
#

I have difficulties to recall it tho

fleet raven
#

ethernet is never slower than wifi unless you broke something

grizzled stirrup
#

It's a long cable to go to the next room

#

Probably it

fleet raven
#

makes no difference

grizzled stirrup
#

I also have a plug in the wall cable that has similar performance

#

I use that recently mostly

fleet raven
#

they can be like 100m long without problems

rotund sapphire
#

I wouldnt say that Zeblote :)

fleet raven
#

*assuming non-garbage cable

rotund sapphire
#

The amount of interference the cable picks up can be severe on that distance

grizzled stirrup
#

Actually I probably have been using the wall plug ethernet adapter when I was playing Fortnite, so it's expected to not have as much speed

#

But it is fully reliable

rotund sapphire
#

Yes there are better and worse cables indeed that is true

grizzled stirrup
#

Anyway point being of all this, packet loss feels bad in games and I'm sure there are many people on far worse connections playing

rotund sapphire
#

They're probably used to it already

grizzled stirrup
#

Yeah I know I was back in the day playing on xbox

#

It was part of the experience ๐Ÿ˜„

#

medium ping peer to peer lobbies

#

Your shot MIGHT count ๐Ÿ˜„

fleet raven
#

I have one of those crappy flat ethernet cables with no shielding going through multiple rooms to reach the router and it works without problems ๐Ÿค”

grizzled stirrup
#

I think I misremembered and I had been using the shorter cable from the wall, that's most likely it

#

Had to tidy away the long one ๐Ÿ˜„

#

But yeah I'd say it's quite a luxury to have an ethernet connection for most typical gamers unless they are lucky enough to be next to the router

#

Most people probably don't even consider it

#

Especially if gaming on console etc.

fleet raven
#

using garbage wifi: ๐Ÿšซ
drilling holes through walls and ceilings for that low latency: โœ…

grizzled stirrup
#

๐Ÿ˜„

#

First thing I'll do when I get a house

fleet raven
#

well even better would be to have all the rooms wired up properly inside the walls

#

one apartment had that and it was really nice

rotund sapphire
#

It's possible to use the power outlets to transfer net in a house, but that's where i draw the line

fleet raven
#

fancy ethernet wall socket in every room

rotund sapphire
#

No i mean the actual power outlets can be used for this purpose i see it on the internet

fleet raven
#

ye but you can also hide ethernet cables in the walls much like the power cables

grizzled stirrup
#

That'd be the dream

rotund sapphire
#

That's different, and indeed a much more favored option

agile lotus
#

How would I network this appropriately

#

right now hosts saves overwrite the clients

#

even though its just loading

#

all saving happens offline and in the options menu

grizzled stirrup
#

@agile lotus I'd use IsLocallyControlled to ensure that the save is happening on the machine that is controlling the player (A client or a listen server host)

agile lotus
#

only loading happens online

#

saving happens in the main menu only

#

which is offline

grizzled stirrup
#

Well if you are loading data for each client separately then you'd load it "offline"

#

As in the client would load it

#

You could then pass that info to the server if you need to

#

Otherwise the server will load the same file for everyone

grizzled stirrup
#

Question: when a pawn dies in ShooterGame, these two lines are called: NetUpdateFrequency = GetDefault<AShooterCharacter>()->NetUpdateFrequency; GetCharacterMovement()->ForceReplicationUpdate();

#

What would be the primary purpose here? To ensure all players see the pawn in the exact position he died at?

agile lotus
#

grabbing the client controller index from server worked

twin juniper
#

What is the create session thing used for?

past rain
#

Can someone explain to me what the logic behind calling "ChoosePlayerStart" before Login and PostLogin is? Because I'm dumbfounded. I have 4 teams in my game, I assign the players their teams in Postlogin, heck I even tried in Login, and then each team has a playerstart, but since chooseplayerstart is called first, no teams have been assigned and its dumb af

#

How would one get around this?

grand kestrel
#

Find something called before choose player start. Assign teams in choose player start. Probably designed that way so it knows where you're going before logging you in.

#

You can't really think it's "dumb af" to not design something around the way you do things especially since ue4 came first

#

Don't see why you can't override the player start at post login either

fleet raven
#

that does sound dumb though

#

obvious flow would be log in > chose spawn > spawn not the other way around

grand kestrel
#

Yeah

#

I just hope or assume there's a good reason

#

Maybe it is actually just done wrong

#

Like CMC not being modular and pawn possession system ๐Ÿคญ

fleet raven
#

char movement is ultimate br_egg_angery

wet tangle
#

My multiplayer when steam is active keeps giving me the error
Invalid session info for session GameSession in GetResolvedConnectString()
when joining

past rain
#

@grand kestrel Its not really possible since the player doesnt truly exist until Login or PostLogin, so thats the earliest you can assign them a team or name or whatever

#

But for some reason chooseplayerstart is called before both of these functions

#

So I cant choose a start based on the team they are on

#

Im sure there is some workaround since games before have solved this

#

But what that workaround is... I dont know

grave kayak
#

you can probably execute your logic first before calling Super::Login @past rain , GameModeBase calls InitNewPlayer from Login and InitNewPlayer finds the player start

#

there is also a PreLogin you can use

past rain
#

So you're firstly saying Postlogin is way too late, right?

grave kayak
#

yes, postlogin has already executed the spawn logic

past rain
#

I cant figure out what to do with Login, since it returns a player controller

grave kayak
#

you can also not call super and do the logic in your login:

    ErrorMessage = GameSession->ApproveLogin(Options);
    if (!ErrorMessage.IsEmpty())
    {
        return nullptr;
    }

    APlayerController* const NewPlayerController = SpawnPlayerController(InRemoteRole, Options);
    if (NewPlayerController == nullptr)
    {
        // Handle spawn failure.
        UE_LOG(LogGameMode, Log, TEXT("Login: Couldn't spawn player controller of class %s"), PlayerControllerClass ? *PlayerControllerClass->GetName() : TEXT("NULL"));
        ErrorMessage = FString::Printf(TEXT("Failed to spawn player controller"));
        return nullptr;
    }

/// Assign team here for example

    // Customize incoming player based on URL options
    ErrorMessage = InitNewPlayer(NewPlayerController, UniqueId, Options, Portal);
    if (!ErrorMessage.IsEmpty())
    {
        NewPlayerController->Destroy();
        return nullptr;
    }

    return NewPlayerController;```
past rain
#

So copy paste the contents of the super, into my own

#

and just do my logic above it?

grave kayak
#

well... if you need the player controller for the team assignment for example

past rain
#

I do, I assign it in playerstate

#

which needs the playercontroller to get to

#

So I'd use NewPlayerController as the controller

grave kayak
#

yep

past rain
#

okay let me try

grave kayak
#

you can also let your custom PlayerController assign its own team in PostInitializeComponents

winged badger
#

you won't have a PS then

#

not unless you override half the GameMode

grave kayak
#

PlayerState is spawned in PostInitializeComponents, right?

winged badger
#

its created from PostLogin

#

indirectly

grave kayak
#
void APlayerController::PostInitializeComponents()
{
    Super::PostInitializeComponents();

    if ( !IsPendingKill() && (GetNetMode() != NM_Client) )
    {
        // create a new player replication info
        InitPlayerState();
    }```
winged badger
#

ah, so it is, unless its seamless travel

#

then it gets recreated later

grave kayak
#

yeah, seamless travel is with state migration and such

#

and you only have the playerstate guaranteed on the server after PostInitializeComponents, otherwise you need to wait for the replication event

winged badger
#

but to spawn a player on a startspot of your choosing, taking information not available at construction into consideration

#

i think you just need to override a single GM function

grave kayak
#

would be weird to override ChoosePlayerStart and do team assignment there though

winged badger
#
    /** Return true of FindPlayerStart should use the StartSpot stored on Player instead of calling ChoosePlayerStart */
    virtual bool ShouldSpawnAtStartSpot(AController* Player);
#

that one

#

just needs to return false

#

by the time you normally spawn pawns when the game starts that information is ready

#

problem is PC does FindPlayerStart before anything is ready and caches it

grave kayak
#

won't it spawn at 0, 0, 0 then though?

winged badger
#

no, ChoosePlayerStart will exec

grave kayak
#
AActor* AGameModeBase::FindPlayerStart_Implementation(AController* Player, const FString& IncomingName)
{
    UWorld* World = GetWorld();

    // If incoming start is specified, then just use it
    if (!IncomingName.IsEmpty())
    {
        const FName IncomingPlayerStartTag = FName(*IncomingName);
        for (TActorIterator<APlayerStart> It(World); It; ++It)
        {
            APlayerStart* Start = *It;
            if (Start && Start->PlayerStartTag == IncomingPlayerStartTag)
            {
                return Start;
            }
        }
    }

    // Always pick StartSpot at start of match
    if (ShouldSpawnAtStartSpot(Player))
    {
        if (AActor* PlayerStartSpot = Player->StartSpot.Get())
        {
            return PlayerStartSpot;
        }
        else
        {
            UE_LOG(LogGameMode, Error, TEXT("FindPlayerStart: ShouldSpawnAtStartSpot returned true but the Player StartSpot was null."));
        }
    }

    AActor* BestStart = ChoosePlayerStart(Player);
    if (BestStart == nullptr)
    {
        // No player start found
        UE_LOG(LogGameMode, Log, TEXT("FindPlayerStart: PATHS NOT DEFINED or NO PLAYERSTART with positive rating"));

        // This is a bit odd, but there was a complex chunk of code that in the end always resulted in this, so we may as well just 
        // short cut it down to this.  Basically we are saying spawn at 0,0,0 if we didn't find a proper player start
        BestStart = World->GetWorldSettings();
    }

    return BestStart;
}```

๐Ÿค”
winged badger
#

need to take some care with ChoosePlayerStart so you don't break the PlayFromHere in editor

#

basically needs to return default implementation if its PIE

past rain
#

@grave kayak

grave kayak
#

but judging from that code he'll need to do team assignment in ChoosePlayerStart, which is a weird

past rain
#

That got it working

#

Thank you

grave kayak
#

no problem ๐Ÿ˜ƒ

past rain
#

Just out of curioisty

#

is there a reason behind this madness of design?

#

You'd think logically you'd choose a player start after the player exists

grave kayak
#

you can also do team assignment in the PostInitializeComponents of PlayerState

past rain
#

Is postInitialize called before choose player start?

grave kayak
#

think that's the cleaner design, since then you can encapsulate the team logic in PlayerState

#

yes

past rain
#

am I suppose to override that function in playerstart or in game mode?

grave kayak
#

PlayerState

#

and only assign the team on the server and let it replicate to the clients

past rain
#

hmm

#

Im currently assigning players their team based on NumPlayers, which I increment at Login/PostLogin

#

Im gonna have to find another system then I assume?

#

Or just create a NumPlayers variable in playerstate

#

and increment it in postinit?

#

no that wont make sense

grave kayak
#

NumPlayers is exposed in game mode, you can get the game mode from the world

past rain
#

ah right

#

getauthgame mode

grave kayak
#

yup

past rain
#

Yeah that definitely seems like a clean design, Lets see if I can do it

winged badger
#

GM tracks number of players on its own

grave kayak
#

you probably want to change it based on amount of team members if you want to have fair teams, but i'll leave that to you

past rain
#

each team consists of 1 player

#

its a free for all

#

makes things easier :p

grave kayak
#

right, in that case use the already existing NumPlayerse of GameMode, it's based on the amount of non-spectating playercontrollers

past rain
#

Yup, I made the post init function, removed login

#

now im just using postlogin

#

gonna compile and see if this bad boy runs

#

Hmm

#

auto GM = Cast<ACS_GameMode>(GetWorld()->GetAuthGameMode());

#

It returns null in the post init component

#

Is it possible the game mode doesnt exist yet?

winged badger
#

no

#

but its possible PC doesn't know about its own world

past rain
#

Let me check

#

eh

#

it was just a dumb bug

#

had to restart editor

#

and it works now!!

#

Much cleaner design

grave kayak
#

make sure you put that within a HasAuthority block, game mode only exists on server, would return null on clients

winged badger
#

in PostInitializeComponents?

#

Authority check won't work there, no Roles are set yet

#

has to do a NetMode check

past rain
#

I've tested it on dedicated servers and Im not getting any errors

#

so it seems like the client isnt trying to get the auth game mode

#

or something like that

#

Anyways thank you for both the help, and Im sure I'll be seeing you again soon ๐Ÿ˜„

grave kayak
#

no problem

grizzled stirrup
#

In general do people use HUD classes as a nice way to store all client UI widgets and have logic to add / remove them from the screen, or do many just do that in the PlayerController?

#

I imagine it's preference to some degree at this point

#

It does seem nice that the HUD is client only so you can never accidently try to add a widget to the viewport on the server

#

But then again it saves a cast every time you want to call a HUD function if you just want to do it on the PC instead

#

Or else you could have intermediate PC functions that just call HUD functions, but I'm sure that's bad practice

winged badger
#

HUD can subscribe to delegates, you know

#

and its more then just a preference, managing UI from PC/Pawn is clutter

#

violates the single responsibility principle

grizzled stirrup
#

That principle being things shouldn't be multipurpose if possible and hold their own specific purpose instead?

#

I only bring it up seeing stuff like this in shootergame:

AShooterPlayerController* MyPC = Cast<AShooterPlayerController>(Controller);
    AShooterHUD* MyHUD = MyPC ? Cast<AShooterHUD>(MyPC->GetHUD()) : NULL;
    if (MyHUD)
    {
        MyHUD->NotifyWeaponHit(DamageTaken, DamageEvent, PawnInstigator);
    }
winged badger
#

makes them unmaintainable

grizzled stirrup
#

That double cast could be saved if it's on the PC but yeah I agree

winged badger
#

if you mix stuff up

grizzled stirrup
#

It'd be nice to have ALL client UI stuff in the HUD class

#

Frees up the PC for being a PC!

winged badger
#

once you start managing UI from different objects you'll find yourself spending an hour looking for an object that manages some piece of UI before long

grizzled stirrup
#

Well I have all client UI in the PC so I know it'll always be there

#

But I like the idea of it being in a HUD class too

winged badger
#

in tiny/hobby/leaning project that is not much of a problem

#

but when you have over 1k custom classes in the project, ouch

grizzled stirrup
#

I def won't have that many custom classes, but in my eyes it's either get controller and cast to hud and then call the function or get controller and call it directly

#

It's just a bit easier to get ahold of

#

But also easier to call it in the wrong place like on the server

winged badger
#

HUD can also hook into delegates, as an alternative

grizzled stirrup
#

Would you recommend I for example make the HUD subscribe to a delegate that gets broadcast when a client calls an OnRep_TakeDamage event?

#

That'd then pass in the damage taken for example

#

That'd skip the need to cast etc.

winged badger
#

i prefer using delegates for frequent updates

grizzled stirrup
#

I thought a big point of using them would be to avoid things like binding on tick for infrequent things like updating health or ammo?

winged badger
#

UMG is exceptionally bad at... performance

#

function bindings are just year 2000 terrible

#

direct variable bindings are better, but just

#

just an average RPG game UI, nothing elaborate, will take 5-6ms on gamethread just to keep itself up to date when you use UMG function bindings

grizzled stirrup
#

Yeah binding on tick seems to be the worst idea ever

#

Do you mean function bindings as in on begin play the widget casts to the owning pawn and binds a custom event to OnHealthUpdated for example?

#

That'd pass in a single float only when health is updated and set the text, once

#

Is that still awful?

#

I thought that was the way to go to prevent tons of needless updating

winged badger
#

thats fine

#

you don't want to make a function for binding an umg variable

grizzled stirrup
#

Ah yeah I'll stay way from that

#

I always use SetText()

#

So it only sets it once, usually from a delegate broadcast

#

Another slight negative on using the HUD- if you only need say one or two extra widgets for different game modes, you'd either have to pack all possible widgets into a single master HUD class, or else have lots of extra HUD classes per mode that makes it a bit harder to navigate your project

#

Whereas there'll usually be a unique PC for each mode in my case, and in the master PC I have a create / add widget function so it's a very small bit of extra code to add

#

But as you said, harder to keep track and it's not fully separate

#

Though if the mode is TeamDeathmatch for example, I'll know any team deathmatch specific UI will be in TeamDeathmatch_PlayerController for example

winged badger
#

you can have a HUD base with most of the stuff, then just extend when you need a change

grizzled stirrup
#

Yeah I guess it really depends on the complexity of the project

#

If you need 10s or 100s of widgets, then HUD is the way to go to keep it separate

#

If you only need like 2 - 6 widgets on screen during gameplay like in my case, it's probably fine to just have a UI section on the PC

#

Since most modes only need a single specific widget, it wouldn't warrent creating a new HUD class for each one

#

There's no actual technical downside to not using the HUD class right?

#

Just purely a workflow decision

winged badger
#

it tends to get out of hand

grizzled stirrup
#

If I do see that happening I'll migrate to HUDs

#

I just hate jumping through hoops when possible

#

It's one less step, one less cast and one less class to worry about for the time being which makes life a bit simpler when dealing with UI

#

But then I can definitely see what you mean- with a large project it could get horrible

#

Will monitor and switch if needed

#

Looking through my PC, it's almost all UI anyway, quite a sparse class for what I need at the moment

past rain
#

@grizzled stirrup Was the issue from a few days ago where the client was stuttering locally only on listen-server, while it was fine on a dedicated server ever solved?

#

Something about having to build from source and change something in the CPC?

grizzled stirrup
#

@past rain I tried many things, some worked but all had downsides

#

The thing that worked the best to stop the stuttering and have frame perfect movement from the perspective of the listen server is p.NetEnableMoveCombining 0

#

However keep in mind this appears to send a client RPC on tick to the server

#

So it uses significantly more bandwidth and isn't really a great option

#

There are other tricks to smooth only the animation since that also only gets updated on each net update and not interpolated but it messes with the timing of animations and also doesn't look that much smoother since the location / rotation updates are the most jarring

#

I'm honestly not sure why it doesn't work out of the box because the server should in theory be easily able to interpolate between client updates, maybe it's something Epic didn't quite finish up as listen servers weren't their priority

past rain
#

I know plenty of games made in unreal that uses client server model

#

take dead by daylight for example

#

No clue how they get around this

grizzled stirrup
#

Keep in mind other clients see each other and the server completely smoothly

#

This only affects the listen server's view of clients

#

But yeah I'd love an interp solution that worked like it does on dedicated

past rain
#

Reading what you just said, we might be talking about different issues

grizzled stirrup
#

I'm sure it's not actually that difficult to vinterp if needed

#

Yeah possibly

past rain
#

Let me quickly describe what Im talking about - Client-server mode only - Server sees all clients smoothly, All clients see other clients + server smoothly

#

the only issue is that the client sees ITSELF as stuttering

#

and only itself

#

So only your own player is stuttering, and only from your own point of view

grizzled stirrup
#

Ah yeah I remember your post- that is definitely something to do with you setting values on the client but the server disagreeing and moving them back

#

It shouldn't happen for example on the default third person template right?

#

You had some rotation logic happening on tick right?

past rain
#

The way I have it is that, GameState holds the player speed value

#

Because every 30 seconds, all palyers in the game change speed

#

So at the begin play of the character, I get the speed from the gamestate, and set it to my player

#

This is how Im currently doing it, but I guess something Im doing here is wrong

#

SetSpeed is called by the server

grizzled stirrup
#

Have you logged both the client and server speed values to verify this is working?

past rain
#

I have multiple times, but I will do it agian now to check

thin stratus
#

Something like Speed should be done via an OnRep

#

I mean 1. you need everyone to update it 2. if you have late joiners or people getting relevant suddenly, they won't get the RPC anymore

past rain
#

No late joiners

#

Im doing it in beginplay and have the gamestate keep the player speedso I can set it accordingly

#

if they die and respawn

thin stratus
#

And they are all in relevancy range?

#

Just making sure you don't build something that will break

#

Either way you'd need to multicast the change then though

past rain
#

Im setting the speed on the server, then having an RPC on the client

thin stratus
#

Also is that SetSpeed called on BeginPlay?

past rain
#

isnt that enough?

#

and yes it is

thin stratus
#

No it's not enough

#

What's with the other players?

#

They should walk with the wrong speed?

past rain
#

oh

#

in gamestate, I get all the players

thin stratus
#
  • BeginPlay is too early
past rain
#

and call set speed

#

So every 30 seconds, this function is called in game state

thin stratus
#

Then it's okay I guess

#

Cause BeginPlay of the Pawn itself is too early

#

It's not possessed at that point

#
  • you still need the Multicast
past rain
#

So once setspeed is called from the server, it should call a multicast function that does the same thing?

thin stratus
#

Well yeah, you need to update the MaxWalkSpeed on all players

past rain
#

Isnt that what I already do? The function ClientSetSpeed_Implementation will be called on the owning client or am I wrong?

thin stratus
#

And the other players?

#

Or do you only have two?

rotund sapphire
#

You could just replicate this value and create an onrep call on it

thin stratus
#

Already suggested that

grave kayak
#

honestly, it's easier to just use a replicated var for this ๐Ÿ˜›

#

as robert mentioned

past rain
#

The logic is this - the game state called setSpeed 4 times because there are 4 players, and at the end of the setspeed function I call an RPC on the local owning client, so it should update for all clients too

#

I do have that sparkie, but in the end I still need to update max walk speed, since im using the cpc

thin stratus
#

If you only call it these 4 times on the server + 4 times the ClientRPC, you basically always leave out the other 2-3 players

#

And if you use an OnRep, as suggested, it would properly call on all Clients for all Pawns

#

Which is kinda like a Multicast anyway

#

Point is the same

past rain
#

Let me ask this then, does any of this explain why on a dedicated server it works fine

#

but on a listen server it doesnt

grave kayak
#

can you show where you're executing movement?

thin stratus
#

I wouldn't directly explain that. But it's still not enough to only update on the owning Client

#

The versions of the pawn on the other clients won't get the update

grave kayak
#

^

thin stratus
#

I can repeat this another 20 times if you want :D

past rain
#

Are you saying Im not updating on all the owning clients, but instead just 1 of them?

thin stratus
#

No

#

You are not understanding how a replicated Actor works apparently

#

If you have 4 Clients. 1 ListenServer and 3 Clients connected.

#

And you spawn ONE Pawn for one of the Clients.

#

Then this Pawn exists 1x on the Server

#

And 1x on EACH Client

#

WIth the SetSpeed function you affect the Server one

#

WIth the Owning Client one you affect the owner

#

And the other 2 are left out

past rain
#

I thought the CPC max walk speed was replicated behind the scenes

thin stratus
#

No, then you wouldn't need the ClientRPC in the first place

#

It's not replicated

#

You need to update MaxWalkSpeed by hand everywhere

#

That's why we suggest an OnRep float "CurrentSpeed"

#

That just updates the MaxWalkSpeed

wanton pebble
#

i've got a question. I'm trying to replicate a speed multiplier

{
    AddMovementInput(GetActorForwardVector() * Value / SpeedMultiplier);
}

void ASCharacter::MoveRight(float Value)
{
    AddMovementInput(GetActorRightVector() * Value / SpeedMultiplier);
}```

but if i try do DOREPLIFETIME the SpeedMultiplier, i hit a breakpoint in UnrealType.h
thin stratus
#

Let me tell you that directly: This is the wrong way to do that.

wanton pebble
#

.___.

thin stratus
#

Everything that affects the CMC

wanton pebble
#

you up to explain how do it properly?

thin stratus
#

Needs to be strictly build into it

#

It's a chunk more complex

#

I can link you a Wiki post

#

You need to make your own child of the CMC

wanton pebble
#

i couldn't find SetMaxSpeed in C++

thin stratus
#

And add the speed multiplier stuff properly

#

otherwise it desyncs

thin stratus
#

This literally has a SpeedMultiplier example

#

So you should be good with that

#

Tbh even Sendans changing of the Speed is wrong

#

But well

grizzled stirrup
#

What is the cheapest way to replicate a took damage UI notification event from the serverside character after taking damage to the cilent character which can then call the necessary UI functions locally? A ClientRPC or an incrementing uint8 RepNotify property set to COND_OwnerOnly?

#

Thinking the RPC is easiest since no one else has to see it right?

winged badger
#

you're already replicating health

#

just broadcast a delegate when health changes and hook into it

past rain
#

@thin stratus How would you change the speed correctly from scratch?

grizzled stirrup
#

It can be increased though, I guess I can store the old local health before changing it? Would I have to change my CurrentHealth property to be an OnRep property or is there a way to broadcast the delegate another way?

#

I have already a delegate for OnHealthUpdated that the server calls when taking damage

#

But that's a manual specific one

thin stratus
#

@past rain Same thing that I posted for Lukas

#

You need to do that inside the CMC

winged badger
#

so, broadcast it from OnRep_Health

grizzled stirrup
#

so I should change my CurrentHealth property from Replicated to ReplicatedUsing = OnRep_Health ?

winged badger
#

it is a simple approach, and one that doesn't add any extra network overhead

grizzled stirrup
#

Even doing so, how can I know if I took damage or gained health from a pickup?

winged badger
#

its c++, right?

grizzled stirrup
#

Yeah, I guess I could look into the way Jamsh showed a few days ago

#

Passing in the old health also

winged badger
#

UFUNCTION() void OnRep_Health(float OldValue);

grizzled stirrup
#

Damn that's all that needs to be done? ๐Ÿ˜„

#

That's pretty sweet

winged badger
#

yes

past rain
#

@thin stratus This is pretty much the first time I dabble with multiplayer, and my game will be very simplistic and minimm multiplayer stuff, I dont really want to dabble yet in things like that

grizzled stirrup
#

Last thing- how does the OldValue get passed in?

#

Since the server will set CurrentHealth

#

Which will then trigger the on rep event

winged badger
#

the DataChannel checks how many parameters the OnRep function has when DispatchingRepNotifies

#

and adjusts accordingly

grizzled stirrup
#

Oh so it'll literally match and automatically pass in the old CurrentHealth before it got updated?

winged badger
#

yes

grizzled stirrup
#

That's incredible

#

Wow

#

Thank you so much

#

That's a much more elegant way to do it

past rain
#

So I think Ive made changes

#

I have no clue if its correct though

winged badger
#

its why the OnRep_Something has to be a UFUNCTION @grizzled stirrup

grizzled stirrup
#

Makes sense!

#

It's working great

#

Only slight downside is having to create local OldCurrentHealth floats before setting CurrentHealth on the listen server so he can pass it in when calling his own OnRep_CurrentHealth manually

#

But it's by far the best solution

#

Thank you very much!

wanton pebble
#

does anyone know why changing the max walk speed of the client makes it super stuttery?

#

like at max walk speed 600 it's fine, but as soon as i set it to 200 (crouch) or 800 (sprint)

#

it's stutter city

#

nvm, solved it

#

if anyone's looking, it's because the speed variables had to be set on both the server and the client

wanton pebble
#

another replication question ๐Ÿ˜…

#

my ADS is compromised solely of an animation

#

which i set using a variable, IsAiming

#

however, i can't get both the server and the client to show the animation themselves and see the other show it when the other is ADSing

#
    if (WantsToAim == true && CanAim == true)
    {
        if (Role < ROLE_Authority)
        {
            ServerSetAimingTrue();
        }
        else
        {
            IsAiming = true;
        }
    }
    else
    {
        if (Role < ROLE_Authority)
        {
            ServerSetAimingFalse();
        }
        else
        {
            IsAiming = false;
        }
    }
    //```
#

this is what i'm trying for now, with my implementations being just IsAiming = false/true;

#

alongside that i'm replicating the IsAiming variable using DOREPLIFETIME

#

DOREPLIFETIME(ASCharacter, IsAiming);

#

any idea why my server can't see my client executing the animation?

grizzled stirrup
#

@wanton pebble Server probably doesn't know about WantsToAim so it won't get set (if you are running this same function via the server)

wanton pebble
#

oh that'd make sense

#

yep that was it @grizzled stirrup , thanks a bunch!

grizzled stirrup
#

No probs ๐Ÿ˜ƒ

wanton pebble
#

one final replication question before i get banned from this channel xD

#

i'm trying to do a dual mesh system

#

i've got it all set up with one exception

#

but while the server sees the client executing this, the client can't see the server lean

#

but if i run just a singleplayer game and go into an external camera, the TPS mesh moves as it should

#

any idea what the issue could be?

#

this happens whether Aim Rotation is replicated or not

thin stratus
#

That replicated rotation is in what actor?

#

@wanton pebble

wanton pebble
#

It's just in the animbp for the tps mesh

thin stratus
#

AnimBPs aren't replicated

#

You need to replicate stuff in the Character and then pull it into the AnimBP

wanton pebble
#

So I'll need to do my function within the animbp in the character?

thin stratus
#

Anim Blueprint and Character BP are two different things

#

The AnimBP is not replicated.

#

You need to do all replication in the Character.

#

And then grab the Variable from the Character inside of the AnimBP

wanton pebble
#

Ok, thanks

#

I'll try that out tomorrow

unreal pine
#

Hello friends - Anyone know if I can override a PostNetReceiveVelocity event on a projectile in Blueprint? I'm having some projectile location jitter on clients

twin sable
#

does anyone know why when I get the resolved connection string I get the steam id but not the map url despite having loaded one on the hosting server?

I've read its supposed to look like "steam.123456789:7777//Game/Maps/MainMenu_Entry" instead

#

NVM its because you should have seamless travel turned off

fossil spoke
#

For initial connection it should be a hard travel yes.

twin sable
#

yeah, realised in the end

#

thanks though

#

you wouldnt happen to know why using OnlineSubsystemSteam makes the clients lag around but without its buttery smooth

#

they rubberband back constantly

fossil spoke
#

๐Ÿคท that could be anything

twin sable
#

agh ๐Ÿ˜›

fossil spoke
#

Whats their ping?

twin sable
#

it happens when testing in the editor

#

and through steam alike

twin sable
#

looking at a fresh project I've noticed on my project the in rate never goes above 300. I'm not sure what could be causing this

manic pine
#

your outrate is 10kbs?

#

did you increase the default bandwidth limit

twin sable
#

I dont think so. havent messed with the networking settings

#

but the in rate is super low which might be whats causing it

manic pine
#

try something like this for testing

[/Script/OnlineSubsystemUtils.IpNetDriver]
MaxClientRate=100000
MaxInternetClientRate=100000
[/Script/Engine.Player]
ConfiguredInternetSpeed=100000
ConfiguredLanSpeed=100000
#

DefaultEngine.ini

#

yeah im more concerned about your out rate being 9.998KB/s, which is suspiciously close to the 10kb/s limit

twin sable
#

thats with the new settings

manic pine
#

so its using 40% more than the 10k cap

#

hows the stuttering now

twin sable
#

that actually fixed it

#

thanks

#

so much!

#

is the initial limit just low or am I doing somethign wrong do you think?

manic pine
#

great!

#

hmm i think the initial limit is legacy maybe... its very easy to go past it

#

i believe e.g. fortnite uses 40KB/s

#

once the client goes past it, he starts dropping packages

#

instead of sending them to the server

#

since the movement component is the one using the most bandwidth, its affected the most

twin sable
#

makes sense

#

bloody awesome though. now i can work on actual gameplay again

silent sigil
#

I have a question about seamless level transitions and voip. I'm running into a weird edge case

#

In order to debug the issue I broke down the problem into a simple sandbox project. I have a simple multiplayer game with voiptalkers on the player pawns

#

but when I transition between levels, if I'm talking on the mic it causes a stacktrace, that is sometimes fatal but sometimes recovered from

#

it usually recovers on the server and goes to the next level but the voice buffer is perpetually full

#

and so the voice stops working

#

the error is

#
[2019.05.13-09.42.06:750][548]LogOutputDevice: Error: Component Name: AudioComponent /Engine/Transient.VoipListenerSynthComponent_0:AudioComponent_0 World Name: World None.None Component Asset: /Engine/Transient.VoipListenerSynthComponent_0:Synth```
silent sigil
#

it looks like it has something to do with registering the voip talker to the player and the component it is being attached to being destroyed during teardown of the level

thin stratus
#

Do bots and their PlayerState survive SeamlessTravel?

#

I kinda doubt. In CopyProperties I'm moving my TeamState over to the next PlayerState

#

And that works for Clients, but bots seem to be resetted

jolly siren
#

I wouldn't think that bots would persist

thin stratus
#

Their PlayerStates are added to the List of persisting actors

#

:/

jolly siren
#

hmm yeah it adds the entire PlayerArray

thin stratus
#

I assume AIControllers are not kept, so the PlayerState isn't either

#

Yeah so "HandleSeamlessTravelPlayer" passes an AController

#

But handles only a PlayerController

#

It skips the CopyProperties stuff for everything else

#

Maybe it does indeed keep the AIs, but doesn't handle it properly to reinit them

#

Hm nvm, it does

#

Wtf

jolly siren
#

Does what?

thin stratus
#

WEll in the GameMode class in HandleSeamlessTravelPlayer, it filters between PC and non PC

#

Now I'm not sure if that is called for AIControllers

#

Okay it is. The TeamState is just null

#

Weird that it works for the Client

distant trellis
#

I have an issue where when you select number of players 2 and the server is interacting with one client my stuff seems to replicate fine but when i try dedicated server client's can't damage each other.. anyone have any ideas?

scenic raven
#

Hello everyone!

#

when I run mygame.exe -server

#

it listens on the wrong ip (a vnet I have set up)

#

is there a way to bind it to the right ip address?

worthy perch
#

I've never used this yet, but there's this: PORT: Tells the engine to use a specific port number.

manic pine
#

thats an OS problem

#

you can change priority for the windows network adapters ye

distant trellis
#

about to ditch this ability system and go back to C++ replication lol

scenic raven
#

thx

thick shale
#

In the CMC, if I wanted to override any rotation that a RootMotion montage applied, with the Player's input rotation, is there a simple way to do that?

hushed garnet
#

hey all, im having a bit of a moment here. enabled the built in steam plugin and put in the defaultengine.ini the correct variables to define my own appid, but doesnt matter what i do or set, when launched either via a built development build or standalone in the editor it always launches as the spacewar app. I have been trying various things now for a few hours

tribal shell
#

hey, I have an error everytime i Package the Project

ERROR: Unable to compile source files.

ERROR: UnrealBuildTool failed. See log for more details. (C:\Users

twilit swift
#

Hey all, does anyone know if using a RepNotify is more efficient than a Multicast? Same?

#

I've got a heavy multicast that's eating up network bandwidth. Looking for alternatives.

manic pine
#

its certainly not less efficient

#

and it allows you to specify how often to do the update(net update frequency) etc.

#

but if youve a multicast thats that heavy then you might have a design problem to begin with

twilit swift
#

Could be. It syncs prop transforms across all clients. Lots of props in my map and they get moved and shifted around a lot during gameplay. I'm not sure how else to sync things.

manic pine
#

whats the current RPC argument

twilit swift
#

It's a rotation and a vector_NetQuantize_10.

manic pine
#

per object right, so its in a tarray?

twilit swift
#

Yes well, there's one that syncs everything when a new client joins (that one uses an array). The one I'm currently trying to fix is called on the actual prop class and only passes with its own location/rotation.

manic pine
#

why didnt you just replicate the location and rotation directly?

#

or is it non replicated classes

twilit swift
#

It's a non-replicated class.

manic pine
#

mmm what you could do is looking into delta serialization

#

its a tarray version that only replicates changed indices

twilit swift
#

hmm... ok that sounds interesting. Thanks! ๐Ÿ˜ƒ

manic pine
#

still the same information that needs to be sent obviously, but you wont have all the overhead related to actual rpc calls

twilit swift
#

Nice! thank you!

tribal shell
#

i have problems with the "advandes steam sessions"
I cant package project after I turn the plugin on

versed socket
#

Networking question: I remember hearing in a training livestream a few months ago that the best practice for multiplayer is not to rely on multicasted events or on replicated events in general, but rather to rely on OnRep variables and replicated variables of as small a size as you can go (e.g. Bytes, Chars, and Booleans) and then simply reacting to changes in those variables.

If that's the best practice, then doesn't that imply, then, that all of our framework classes are gonna be a mess of variables like bWantsToFaceDirection or Behavior_State? I just want to make sure that that's a correct interpretation of what they're saying.

thin stratus
#

I assume it means that if both ways are possible, that OnRep is the one to take.

#

If it makes 0 sense to use an OnRep variable, then don't do that.
Neither use an RPC if it makes no sense.

#

Technically it's no magic to find out what to use.

thick shale
#

Is it just a bad design decision to try to override Root Motion Montage rotation from the CMC?

versed socket
#

Stupid follow-up question: how do I know if it makes 0 sense to use an OnRep variable?

fleet raven
#

when you're doing a one time thing that leaves no lasting changes

#

and it won't matter if clients miss it

grizzled stirrup
#

Any clever ways to work out shotgun damage without sending a gigantic amount of info per shot?

#

Assuming we want say 20 pellets in the shotgun with each individual trace capable of damaging a different actor

#

No matter what way I think about it, there's going to be 20 RPCs going up at once unless I can pack them into a single RPC?

jolly siren
#

Definitely pack them

grizzled stirrup
#

Just trying to imagine how to sort them so that the server knows how much damge to deal each actor in the array of hit actors that's sent

#

Assuming it's fine for my client to work out how much each actor should be damaged (in my case that is fine)

#

My client can run a for loop of traces, populate an array of hit results, check each one if hit a damageable actor, then populate an array of actors damaged

#

If I also populate an array of damage floats as I'm populating the array of actors damaged, maybe they'll stay in order and I can do a for loop on the server and damage HitActor[0] by DamageAmount[0] ?

#

It's still potentially quite heavy sending an array of actors and an array of floats in one RPC I'd imagine

fleet raven
#

sending 10 actors (netguid) and 10 damages (float?) is 60 bytes

#

that's nothing

#

client side hit detection is very sketchy tho

grizzled stirrup
#

@fleet raven can you elaborate on netguid?

#

I have an array of AActor* atm

#

And yep float damages

#

Also client hit detection is fine in this case (co op game not PvP)

#

Against server AI

#

I'm having clients do as much as possible locally but this is one case where they will have to send a bunch of data per shot

#

I guess a realistic shotgun scenario would only be say 3 actors hit with 8 pellets each or something, so it's not as bad as it seems, just unsure of how to "link" which actors get which damage when sending to the server

fleet raven
#

a replicated actor will have a netguid which is sent as 2 or 3 bytes

grizzled stirrup
#

Oh that is super cheap!

#

Much less scary than I imagined

#

So even in the worst case scenario it'll be fine

fleet raven
#

even if it was sending 1KB per shot it wouldn't matter

#

unless you got some magical minigun-shotgun combo

grizzled stirrup
#

Haha nope this'll be by far the most expensive operation

#

Well maybe rapidly firing rifles will be just as expensive since they send many separate RPCs in a short timeframe

#

But I also think I'm underestimating the speed of networks and overestimating how large the data is

#

Any ideas on how the server can know how much damage to deal to each sent actor? Just hit me that some actors will be hit multiple times so the order of the array won't match, maybe this is where TMaps come in?

gleaming vector
#

well

#

replicating an actor is only cheap if that actor has already been replicated

fleet raven
#

well why not just sum up the damage to each actor and send that

gleaming vector
#

also

grizzled stirrup
#

@gleaming vector well in this case they are AI enemies that are already replicated from the server to the client, so should be cheap right?

gleaming vector
#

when doing shooting

#

yeah

#

what I mean is the first replication of the actor is the whole actor

#

after that point, it's done by guid

#

anyway

#

I've implemented shotguns

#

and other shooter mechanics

#

I never replicate the bullets

#

I replicate the shots

#

the server sends down information about the projectiles to the client so that it can simulate it

#

you can start predicting a projectile if you want, and then correct that predicted projectile when you get the authority in

grizzled stirrup
#

@fleet raven I'm not sure how to "link" them, imagine pellet 1 hits Actor A, pellet 2 hits Actor B and pellet 3 hits Actor A again, not sure how to tell it to add it to his existing damage float and also correctly tell the server- deal X damage to Actor A, B etc.

#

@gleaming vector Oh you are miles more complex- I'm just using simple clientside traces in my case ๐Ÿ˜ƒ

fleet raven
#

make a temp map on the client side to sort it out

grizzled stirrup
#

And the client can make the call on damage too as it's not PvP

fleet raven
#

not replicating the projectiles is interesting

gleaming vector
#

oh

grizzled stirrup
#

Ok will look into maps, thanks!!

gleaming vector
#

then replicate from client to server impacts

#

i kinda sorta did this on squad when I worked on that game

fleet raven
#

you mean like instead of using replicated actors, you send a multicast rpc to spawn a projectile somewhere?

gleaming vector
#

the shot was replicated to the server (with a shotid), and then the impact was replicated up (with the corrisponding shot id)

grizzled stirrup
#

I'm not even going that far, this is purely the damage amount on server- there will only be one normalized impact replicated

#

I just want to have each pellet count in terms of damage

gleaming vector
#

sure

grizzled stirrup
#

The cosmetic fx will be cheap and simple

gleaming vector
#

then batch your impacts

#

or, well, you really can't in some cases

#

there is some code I've seen in the engine (i forget where) that counts outgoing RPCs and if it's over a certain number, it batches a bunch of events into a single RPC

grizzled stirrup
#

Cheaper / simpler just to send one FVector_NetQuantize for the impact loc and have the clients simulate the impact normal + do a big impact FX in the center average of where the pellets hit- not as nice visually but nice and simple

#

But of course for more realism you'd have to send more

gleaming vector
#

oh, i see what you are trying to do

#

but what happens if you shoot at a corner

#

and half the bullets go past the corner and the other half impact it?

grizzled stirrup
#

The client will see a big ugly impact fx in the cornder

#

And not past it

gleaming vector
#

the bullets that keep going may impact another person a few frames later

grizzled stirrup
#

Corner*

#

But only remote clients

gleaming vector
#

oh

grizzled stirrup
#

The client who shoots can spawn more detailed FX if he wants

gleaming vector
#

just replicate the shot event for remotes

#

and then spawn projectiles that don't care about impacts

grizzled stirrup
#

Oh yeah that too, at the moment I have everyone doing the simple blocky FX

gleaming vector
#

just for effects

grizzled stirrup
#

I'll probably spawn a decal for each impact

#

But only one centralized particle system

gleaming vector
#

i use "spawn projectiles" here but I mean however you carry that damage event over distance (can be a line trace)

grizzled stirrup
#

From what I've tested at least, it's not usually worth spawning 20+ separate impact fx in each impact location in terms of what you get in performance

#

The decals are worth it

gleaming vector
#

sure

grizzled stirrup
#

But in many cases a big centralized single FX works great

gleaming vector
#

you can get away with a number of particle effects

#

since particle effects are actually much cheaper than decals

grizzled stirrup
#

It's a shame that decals are quite costly but they give the most visual impact imo for shotguns to see the spread like that

#

20+ particle systems can work great too but if they want to look decent usually it involves a separate mesh emitter for each impact hole as well as sparks/ lingering heat spot

#

I'd be curious on the performance differences between them, either way shotguns are just creating a lot of stuff in one frame ๐Ÿ˜„

gleaming vector
#

yeah

#

well

#

do it and profile it

#

then turn it off and do it another way and profile it ๐Ÿ˜›

#

that is, honestly, the best path forward in this situation

grizzled stirrup
#

Yep!! Will likely go cheap and cheerful (no decals, one centralized impact fx)

#

But first, gotta figure out sending the actual separate damage amounts / actors to the server

#

Thanks for the help though, got some good ideas to test for FX when I come to it later

neon violet
#

Is epics cross platform sdk3a master server/online subsystem?

#

And is it a better idea to not implement steamworks and wait for them to release it?

gleaming vector
#

no

#

and if you stick to the online subsystem abstraction, switching will probably be nothing more than an ini change

silent sigil
#

@thin stratus @jolly siren thanks for looking at it. it seems like the bug has something to do specifically with server travel while someone is talking on the mic

#

i'm trying to repro without seamless travel

#

i also can't figure out why when i have a voiptalker component on the pawn i dont need to manually call the register with player state function

#

it just works without

#

when i do call that function it crashes, but even without calling that function it still doesn't work when someone is talking

weak fog
#

hey, if anyone here happens to have a solid understanding of this diagram, pls feel free to PM me if you wouldn't mind answering a few questions

fleet raven
#

just put your question here

weak fog
#

iight so basically 2 things:

1.) What do the diamonds represent in this graph?
2.) is there a generally agreed upon "best practices" for passing data around in this system?

example for #2:
let's say I have some GameState data like the score, and some PlayerState data like health. Both of these need to be fed into the UI, preferably via event dispatchers. Should I just have dispatchers anywhere that I need to send data from, and then pull it wherever I need it, or is it better to go through some kind of hierarchy?

additionally, I could go through some kind of general event manager service, but there will presumably be a ton of different events per gamemode, and as far as I can tell, I can't put the binding of events behind an interface (I can do the calling, though)

silent sigil
#

Do I need my eyes to be checked? I don't see a single diamond

#

I see circles which seem to represent server/client. and i see rounded rectangles

weak fog
#

oh wow, it's transparent lol. hold up lemme find a better one

#

there ya go

fleet raven
#

it's probably explained near where you found this diagram

#

ownership/"created by" would make sense

weak fog
#

that's what I'm thinking as well, but is there no ownership of pawn ?

fleet raven
#

not really, since they can be arbitrarily spawned and you can then possess/unpossess them

#

can have pawns in the world that aren't related to any player

weak fog
#

i see. admittedly pawn is probably what I'm the most hazy about in terms of what type of information goes where

#

ahh that's a good point. a player may have a pawn or may not

#

in that case yeah, i think ownership is the relation

silent sigil
#

oo wow those were hard to see

weak fog
#

honestly they were driving me so crazy that when you said that, i thought maybe i imagined them

fossil spoke
#

You can think of Pawn as the visual representation of the player.

weak fog
#

right, separate from things like input control etc

fossil spoke
#

They can still implement input controls though.

#

Depending on your needs

weak fog
#

so an example of useful info from the pawn would be like, if you were making a minimap--relative location on the map

fossil spoke
#

Health is probably a better example.

weak fog
#

hmmm...my initial instinct was that that would go in PlayerState

fossil spoke
#

Since the Player can still exist as a Spectator when they die, you want the Pawn to have Health that then allows it to be "Killed"

#

PlayerState is better for information that is specific to a Player that all Clients would want to know.

#

Health is specific to a Pawn, not a Player, since a Player can control arbitrary Pawns with different abstractions of what Health might be.

#

Score is a better example of something to store on the PlayerState

#

Since other Clients might want to know other Players scores to display that cosmetically.

weak fog
#

okay. so i had some misconceptions but i'm understanding better now

#

it seems in this case like i may want to be able to call/receive events from any one of these framework classes tbh

fossil spoke
#

There is no single point of contact thats going to supply you with everything you need. All these classes work together to create the framework.

#

Its more about figuring out the best place for information and then how to provide it to external systems as seamlessly as possible.

weak fog
#

right. the latter part of that is somewhat eluding me

silent sigil
#

is there anyone i can have an in depth conversation about voiptalkers with?

fossil spoke
#

Its good to ask yourself what the information is doing, who might want to access it and why. This will help you decide where it should reside.

weak fog
#

basically I tried to make an event service, but as far as I can tell, you can't return a delegate (at least in blueprints). perhaps with C++ i could finagle it

#

but now that you're saying this, i wonder if a better way wouldn't be to use the event system to reinforce the framework

#

PAWN_EVENT_*, GAME_STATE_EVENT_*, etc.

#

and listeners accordingly

fossil spoke
#

Yes Event Driven Design is a good approach

weak fog
#

hmm. done TDD but never EDD. i like it

fossil spoke
#

It means that systems are querying data when they need them, instead of external systems strongly coupling themselves to other systems by forcefully providing that information.

weak fog
#

oh yeah, that's exactly my goal right now

#

you've already got the wheels turning. if i only have event types relative to the framework classes, then I can just set up my eventing based on those classes

fossil spoke
#

If your not familiar with the SOLID design principles i recommend doing a little research and at least being familiar with it.

weak fog
#

yep, i know SOLID. that's kinda how I came to these questions, through my desire to adhere to it so badly

fossil spoke
#

Your not going to write everything perfect the first time.

#

Iteration is your friend.

#

Also make sure you understand the networking context of each of the framework classes like the back of your hand.

weak fog
#

yeah. the trickiest one was PlayerController imo. still gotta make sure i'm super comfortable with them all tho

fossil spoke
#

Which are the columns of your image you posted

#

Yes it being unique as it is.

weak fog
#

yeah, i spent a while just console logging everything and seeing if it printed client or server, or both, and what could replicate and on which policy

#

you've really helped a lot. this discord is so nice

#

luv u all

silent sigil
#

I'm just gonna dump some stuff here

#

so, voiptalkers

#

I have a fps character. i have a voiptalker attached

fleet raven
#

theres one pretty important gotcha with this gameplay framework: replication sux and a client can have a pawn before he has a player or game state

silent sigil
#

yeah, i have a wait macro

#

to fix that very thing

#

it just hangs till the player state is valid

winged badger
#

one can force its hand by changing around some NetPriorities on those actors @fleet raven

winged badger
#

Pawn is default 3, actor 1

silent sigil
#

so i have two blueprints there

winged badger
#

and GS/PS don't have the defaults altered

silent sigil
#

one registers the voiptalker to the player state

#

the other does not

fleet raven
#

that's not 100% reliable though, if packets get dropped they can still replicate in different orders

#

I would like a feature that simply guarantees, 100%, for certain things to replicate before others

silent sigil
#

what exactly is register with player state doing?

#

i copied the bp wrong so it doesn't show the voip talker as connected to that block as the target but it is

#

i poured through the code last night

#

and i see the map of talkers linked to player ids

#

what confuses me is that the talker works fine without this mapping

#

i wasn't sure if there was some magic happening with the component setup

winged badger
#

that is a tall order Zeblote

silent sigil
#

but i couldnt find any in the engine source

fleet raven
#

is it really tho

#

I wouldn't have a problem if it results in delaying a join by a few times latency by simply pausing the replicating until the client has confirmed receiving the game state

#

wait - can I not already do this by using the replication graph? br_animated_thinking

plush wave
#

How does one limit voice chat to certain players and not all players?

#

Or is that something that would require Vivox, for example?

silent sigil
#

what do you mean by limit?

#

like limit who hears who

thin stratus
#

@weak fog As stated in the Document, this is taken from an outside source (recreated).
The Compendium is meant as a collection of information that is spread around the internet, so while a lot of text and images in there are mine, I found these diagramms to be so good that I used them (see Source 2).

silent sigil
#

So I did solve my problem

#

I still don't understand the register with player state, since not using that seems to solve the problem.

#

but it was 2 problems

#

1 was, i had to not use that, and 2 was i was calling start networked voice in "begin play", which doesn't get called after map travel. so that's an embarrassing mistake but all working now.

thin stratus
#

When using Seamless Travel, is the GameMode the exact same one in the next level (if same class) or does it also pass over data from old to new?

#

Cause I'm kinda confused as to how UT manages their TeamInfo class.
They just copy it over from Old PlayerState to new PlayerState and never add it to the ActorList that should survive.
Now if I understand that correctly, it should survive anyway because it's referenced in the PlayerState?

#

Is there an easy check to see if an Actor is from a previous level?

#

Other thing is, that they don't even check if the TeamStates array is empty or not and always recreate it.

#

What is the OnCopyProperties call for then >.>

#

I'm currently checking if the array is empty or not and post seamless travel it seems to be.
So either my GetSeamlessTravelActorList doesn't work (which technicallly it should do already cause the states are referenced in PlayerState, GameState and GameMode) or this is a new GameMode.

#

Gnah, it should be possible to make the TeamStates survive a travel so that everyone just keeps their Team.

silent sigil
#

@thin stratus being referenced by player state doesn't necessarily guarantee it survives afaik

thin stratus
#

I'm adding it to the list of actors that should survive anyway

silent sigil
#

is teaminfo an actor?

#

i tried searching for it

#

and couldnt find it

#

online

thin stratus
#

Yeah

#

But not part of UE4 of course

#

It's custom

silent sigil
#

oh if it is a custom actor

#

it must be added to the seamless travel actor list

thin stratus
#

Literally what I wrote not even a minute ago :D

silent sigil
#

lol yup

#

im confirming that, the reason is the reference gets saved but not the actor being referenced.

thin stratus
#

I think the way I set everything up is already wrong. I need a proper way of creating the Teams and then reusing them later.
And that has to work for Players and Bots.

silent sigil
#

hmm

#

and you want the bots to persist too i assume

thin stratus
#

Currently bots only join a team if they are created, sadly they also survive (which is technically okay) the travel, which never adds them to a team again.

silent sigil
#

oh i see

thin stratus
#

Which technically is also okay, if the freaking TeamStates would survive properly

silent sigil
#

why don't you have the team state be an enum var on the various controllers

thin stratus
#

Cause it does a lot more than just keeping score.

silent sigil
#

i see

#

i mean

#

it sounds like you want to have a score state, that is for the game as a whole

thin stratus
#

Keeps track of leaders, top scorer, party members etc.

silent sigil
#

that is one piece of information

#

and the individual team information for the players

#

team state sounds like it is doing too much

thin stratus
#

Na, it's the same thing that Unreal Tournament does

silent sigil
#

oh ok

thin stratus
#

It's a solid system if it would survive the travel

silent sigil
#

gotcha

thin stratus
#

I'm just again a bit too lost with all the gotchas of travelin seamless

silent sigil
#

i def was dealing with that

#

are you in c++

thin stratus
#

Yeah

silent sigil
#

hrm, yeah i exposed the actor list in the game mode to blueprints to debug what i was working on

#

was a dead end but i did get the pawns surviving the travel

#

as a thought

#

there are some functions for when an actor finishes travelling

#

add some debugs there to the team stats class

thin stratus
#

Right now it works like this:

  1. GameMode::InitGame creates a TeamState per needed Team.
  2. GameMode::InitGameState passes the TeamState Array to the GameState so everyone can access it.
  3. When the Player leaves the Spectator State (In PlayerController) it asks for a Team to join.
  4. TeamState array is added to list of surviving actors.
  5. PlayerState is passing TeamState over in CopyProperties.
silent sigil
#

and see if maybe the actors are surviving but the references need to be reset on the players

thin stratus
#

Yeah that would be helpful

#

Have to check AActor api to see what exists for that

#

Just for debugging

silent sigil
#

let me pull up my project, i am doing a much simpler thing, but i know the game mode had a function you could override

thin stratus
#

Seems like actors have a "bActorSeamlessTraveled" boolean

silent sigil
#

i wasnt sure if it was just for controllers though

#

well that'll work for you

thin stratus
#

At least for debugging yeah, but still not sure about the whole process of when to create the states and when not, what function is best for that etc.

silent sigil
#

i suggest putting something debug logic wise in the actor that it'll self fire.

#

are you sure game mode init game wont be called post seamless travel?

thin stratus
#

e.g. InitGame calls even after the travel

#

Yeah it does, which is one of the points why I think UT doesn't really persist the Teams anyway

#

Even though they pass the TeamState via PlayerState

#

ยฏ_(ใƒ„)_/ยฏ

silent sigil
#

i see

#

but you are checking if a new one is needed

#

and not generating a new one if not

#

i assume

thin stratus
#

Yeah i check if the Array is already setup

#

Which it isn't

#

Which makes me believe the TeamStates array isn't surviving or at least not as I want it to

silent sigil
#

for the game mode there is some copy logic

#

you might want to override

thin stratus
#

Idk if the GameMode has a function to move over stuff

silent sigil
#

to make the old array copy into the new one

#

it does

#

i believe

thin stratus
#

I only know about the PC and PS stuff

#

So "bActorSeamlessTraveled" is false for GameModes post SeamlessTravel

#

.>

silent sigil
#

yeah

thin stratus
#

Only thing I found

silent sigil
#

yeah im looking through the github code for gamemodebase

#

it looks like maybe you can use the game state class

#

but im not seeing how tbh

thin stratus
#

Can't see any function here either though

silent sigil
#

SeamlessTravelTransitionCheckpoint was my best guess

#

but by the time you hit the transition map

#

the game mode will have changed

thin stratus
#

There is also no way to access old and new GS or GM

silent sigil
#

it's weird cause the docs def say the game mode actor should persist

#

on the server anyway

#

are you only looking at the server

#

or the client gamemode as well

thin stratus
#

Client has no gameMode

silent sigil
#

sorry, yeah, i was confused

#

i thought it was reped for some reason

#

try setting a bool in the game mode on begin play, seemless travel and see if the bool is still set

#

im just grasping

thin stratus
#

I wonder if I can grab the CurrentWorld in the new GameMode

#

But that also sounds so hacky

#
    /** the world we are travelling from */
    UWorld* CurrentWorld;
    /** set to the loaded world object inside that package. This is added to the root set (so that if a GC gets in between it won't break loading) */
    UWorld* LoadedWorld;
#

LoadedWorld is the new one that the new GM is in

#

if I can grab the CurrentWorld (and it's still valid) and get the GM of it, I could access it

#

But that sounds wrong too

#

I feel more like I need to ge the same path PlayerState is going somehow

#

So instead of keeping the TeamState, I need to copy over the data at some point

#

But where the fuck is the entry point for something like that

silent sigil
#

I feel like you should be able to keep the team state via GetSeamlessTravelActorList, and then just find all actors of team state post seamless travel

#

and rebuild your array

thin stratus
#

Let me try to use PostSeamlessTravel to just print the amount of TeamStates in the World

silent sigil
#

sounds like a good start

thin stratus
#

Cause technically, it should be 4 instead of 2

silent sigil
#

gl man, i gotta get some sleep. hope you figure it out

thin stratus
#

Yeah sure, thanks for your time!

#

Have a good night!

silent sigil
#

np!

thin stratus
#

Welp, it's indeed 4 teamstates

silent sigil
#

cool, so def being added to the list

#

i was just thinking you maybe added them wrong

thin stratus
#

Welp, now I have to find out how to properly get a grab on them.
It's easy to just find and reinit them, but I have to stop the other 2 from spawning again.
This freaking boolean should be true for a seamless travel gamemode >.>

silent sigil
#

no arguments here

thin stratus
#

Wait what

#
// scope because after GC the kept pointers will be bad
AGameModeBase* KeptGameMode = nullptr;
AGameStateBase* KeptGameState = nullptr;

// Second pass to rename and move actors that need to transition into the new world
// This is done after cleaning up actors that aren't transitioning in case those actors depend on these
// actors being in the same world.
for (AActor* const TheActor : ActuallyKeptActors)
{
    KeepAnnotation.Clear(TheActor);
    TheActor->Rename(nullptr, LoadedWorld->PersistentLevel);
    // if it's a Controller or a Pawn, add it to the appropriate list in the new world's WorldSettings
    if (TheActor->IsA<AController>())
    {
        LoadedWorld->AddController(static_cast<AController*>(TheActor));
    }
    else if (TheActor->IsA<APawn>())
    {
        LoadedWorld->AddPawn(static_cast<APawn*>(TheActor));
    }
    else if (TheActor->IsA<AGameModeBase>())
    {
        KeptGameMode = static_cast<AGameModeBase*>(TheActor);
    }
    else if (TheActor->IsA<AGameStateBase>())
    {
        KeptGameState = static_cast<AGameStateBase*>(TheActor);
    }

    TheActor->bActorSeamlessTraveled = true;
}```
#

So the old gameMode is marked as Traveled

#

Are you shitting me

#

Weirdly enough, the GameMode is copied over to the new world usually

#
if (KeptGameMode)
{
    LoadedWorld->CopyGameState(KeptGameMode, KeptGameState);
    bCreateNewGameMode = false;
}
silent sigil
#

so whats yours doing?

thin stratus
#

We will soon find out :P just breakpointing it

silent sigil
#

gotcha

thin stratus
#

Just in case someone is/was interested in what shit is being moved over

#

So it does indeed completely survive the travel

#

Not even recreated, it's the same actor

#

Now the question is ,why is the obvious bActorSeamlessTraveld false in InitGame post travel

#

Man I need a new coffee

#

I hope all of you just reading this are actually learning something

silent sigil
#

half awake but excited to learn how it ends

thin stratus
#

So, before I go further through the breakpoints: Yes it is keeping it and the TeamStates are still in the array at that point.
Now the question is: Why is the Number of TeamStates etcl not work anymore post seamlesstravel

#

Cause I'm doing this in the InitGame function: if (TeamStates.Num() < NumTeams && !bActorSeamlessTraveled)

#

And right now, if I open the inspector, TeamStates is of num 2 and NumTeams is 2

#

Even bActorSeamlessTraveled is true

#
// Init the game mode.
if (AuthorityGameMode && !AuthorityGameMode->IsActorInitialized())
{
    AuthorityGameMode->InitGame( FPaths::GetBaseFilename(InURL.Map), Options, Error );
}
#

This should never call as the Actor is initialized at this point

#

And it indeed doesn't go in there. Now I'm confused. How am I able to break point that function if it's skipped

#

Magic?

pallid mesa
#

wait, hold on, weren't controllers and ULocalPlayers the only ones meant to survive to seamless travels o_O

thin stratus
#

By the looks of it, the LocalPlayer isn't even teared down

#

So it doesn't have to persist ?

#

PlayerState def persist

pallid mesa
#

that... should be new, I don't recall this behaviour lol

thin stratus
#

Well I only add the TeamStates by hand

#

The list above from Visual Studio is otherwise untouched

pallid mesa
#

lmc

thin stratus
#

Oha now it makes more sense

#

This SeamlessTravel stuff calls twice

#

Once from A to Transition and then from Transition to B

#

And A to Transition the GameMode survives, Transition to B it doesn't.

#

Now is that my bad for not setting something up properly is the question

silent sigil
#

do both game modes exist in the transition map?

thin stratus
#

Both?

silent sigil
#

the game mode for the end map

thin stratus
#

I never touched the Transistion map

silent sigil
#

when does the final game mode come online

thin stratus
#

Thought that just uses the same GameMode and that's it

silent sigil
#

during transition

#

or on final map load

#

if it is during transition you can copy everything over

#

if both actors exist in that map

#

i dont know if they would

thin stratus
#

As far as I understand, it should keep the GameMode from T to B too

silent sigil
#

i agree

thin stratus
#

Cause from A to T it's one and the same GameMode

silent sigil
#

maybe the transition map doesnt have a game mode assigned

pallid mesa
#

and T to B GameModeBase?

silent sigil
#

is it an empty map?

thin stratus
#

Well I sadly skipped the loop

#

Gotta have to run a travel again to see what actors survive from T to B

#

I tell you, develop a Splitscreen, LAN, Online, heavily UT inspired game nearly alone

#

And you will sooner or later know the freaking engine

pallid mesa
#

you got splitscreen? nice

thin stratus
#

Yeah....

#

Would rather not have it, cause UI is a mess with this

#

And they want Online Splitscreen at some point

#

I will die

pallid mesa
#

welp it looks pretty nice

#

but yeah, I feel you

thin stratus
#

List from T to B

#

Missing GameMode, GameState and GameSession

#

Super not cool

pallid mesa
#

Okay, I'm going to debug a side project to see if I get 1:1

#

I don't do gamemode discovery in this one, but not sure if because my url option impl I got the right behav

#

or just because the engine handles it for me

thin stratus
#

All I do in this one is ServerTravel with the ?game=TDM url iirc

#

So it keeps the GameMode

pallid mesa
#

yeah, that seems right, iirc

#

try to read the built in options string

#

to see if it has your settings, while this thing boot up

thin stratus
#

Yeah also checking the point where they try to keep all actors

pallid mesa
#

single process, right?

thin stratus
#

Launch Game via uproject file

pallid mesa
#

k, dc?

#

or just listen?

thin stratus
#

Actually just offline splitscreen atm

#

Doesn't really matter if you listen to something or not

pallid mesa
#

well yeah, there are a couple shenanigans implied on empty servers and dc that can give you headaches, but gona try purely SP

thin stratus
#

I already found the problem

#
void AGameModeBase::GetSeamlessTravelActorList(bool bToTransition, TArray<AActor*>& ActorList)
{
    // Get allocations for the elements we're going to add handled in one go
    const int32 ActorsToAddCount = GameState->PlayerArray.Num() + (bToTransition ? 3 : 0);
    ActorList.Reserve(ActorsToAddCount);

    // Always keep PlayerStates, so that after we restart we can keep players on the same team, etc
    ActorList.Append(GameState->PlayerArray);

    if (bToTransition)
    {
        // Keep ourselves until we transition to the final destination
        ActorList.Add(this);
        // Keep general game state until we transition to the final destination
        ActorList.Add(GameState);
        // Keep the game session state until we transition to the final destination
        ActorList.Add(GameSession);

        // If adding in this section best to increase the literal above for the ActorsToAddCount
    }
}
#

It doesn't keep itself when traveling from transition

#

Only if toTransition

#

Now please someone tell me why

#

I can easily keep these three in my own gamemode with !bTransition or just overriding everything

pallid mesa
#

๐Ÿค”

thin stratus
#

But not sure if that's a good idea

#

Do I want to keep the GameMode?
It's most likely in a late MatchState

#

Doubt they reset it already

pallid mesa
#

If anything, debug T->B and look for the initialization code

thin stratus
#

Well you can clearly see that they don't keep the GameMode from T to B

pallid mesa
#

yeah no they don't but the URL I guess stands for something