#multiplayer

1 messages · Page 273 of 1

verbal ice
#

But I wouldn't switch to the GMC just for performance reasons

lost inlet
#

yes, on Steam this will represent the 64-bit Steam ID

#

which is persistent

#

and on pretty much every other platform this will represent an immutable user ID of some kind

grizzled stirrup
#

Thanks!

lyric heart
#

i fixed it with a retry system

#

basically keep retrying untill the thing is valid

honest bloom
#

I like to call that "hitting the wall many times till you realize its a wall"

lyric heart
#

what is hour-glass wait ?

#

i could limit it to a certain amount of try to stop it from looping

#

but theoretically it should be at some point valid during load

dark edge
#

Show what you're trying to actually show, but the answer is to use begin play and repnotify usually as the timing for when things are ready

dark edge
# lyric heart

Why do you have this? Player Name should just live in player state directly

lyric heart
#

it works pretty good right now

#

doesn't matter how the order of load

#

it always is correct

lyric heart
lyric heart
#

i could probably put the same code in the beginplay though

dark edge
# lyric heart

Then what is this? Or do you mean "Try set player name on some widget"

#

where does the variable that is onrepping live?

lyric heart
dark edge
#

Rename that function then, that function sounds like it's setting player name

#

which it's not doing, since it's triggered on the replication of player name lol

#

I think PlayerState defaults to a very low replication rate

#

and it shouldn't be telling UI anything, at most it should fire a dispatcher

lyric heart
#

i try to set the player name

dark edge
#

which the UI can be bound to

#

Be very clear if you mean setting the name, or updating the UI

#

they are different things

lyric heart
#

makes sense

lyric heart
dark edge
#

The widget should fetch the text

#

nothing should know or care about UI

lyric heart
#

wdym the widget should fetch the text ?

#

when ?

dark edge
#

widget should fetch the text on its initialization and also fetch it when the onrep fires through a dispatcher

#

widget cares about stuff, nothing cares about widget

lyric heart
#

oh right so set an event instead of just setting the text

#

whats the difference though ?

dark edge
#

plenty. In general your game should work whether or not UI is around, and UI is a view/control layer that talks to the game

lyric heart
#

i mean i code the way i have learned

dark edge
#

Now I don't know if PlayerState is guaranteed to be around when the widget wakes up, you need to check that. The hardest part would be handling the widget being alive, and not finding a playerstate to even bind its update event to.

lyric heart
#

i had problems with the state not loading

#

and also widget not being ready

#

so i just did this it works great

dark edge
#

widget not being ready shouldn't matter, the only thing that should do anything about updating text is the widget. set it up like this:

Widget:
Initialize -> fetch playerstate you care about -> bind UpdateText to playerstates OnNameUpdated dispatcher -> call UpdateText
UpdateText -> fetch name, update the text

PlayerState:
OnRep_Name -> call OnNameUpdated dispatcher

#

nothing should be talking to the widget. Nothing needs to have a ref to it.

lyric heart
#

well i mean theres many ways to do a thing

#

this is just what i have learned so far, i will look into dispatchers though

lyric heart
#

basically what i have is wait untill the pawns ready, wait for the widget

#

then set the text

dark edge
#

the playerstate doesn't give a shit about the widget

#

widget can retry getting the playerstate if it wants

lyric heart
#

i mean is it really that much different ? is this just because it's preferred ?

#

i don't see the big gain from doing it the way your saying

lyric heart
#

so with rep notify and the authority check

#

the client needs to be within a certain range of the server ?

#

i tried always relevant on the player and enemy still same thing

dark edge
#

the widget comes with the pawn

#

if the pawn is there, the widget is there

lyric heart
#

The hits and health are not working when I'm at a distance of server player

dark edge
#

so far we've been talking about name, this is the first mention of health

lyric heart
#

Yes I fixed name it's np

#

This problem is my hits not working

#

It works fine within range of server

dark edge
#

show the hit not working

lyric heart
#

i checked always relevant

#

i didn't up the net cull because from what i read always relevant is supposed to override that

dark edge
lyric heart
#

you can see it stops working for both

#

the player and enemy

dark edge
#

you need to show the code path

#

the enemies are spawned on server and replicated right?

lyric heart
#

yes

dark edge
#

not doing anythign crazy like spawning AI on client

#

aight

lyric heart
#

no it's on the server, i use switch on authority

#

on begin play

dark edge
#

u know what it might be

#

skeleton ticking

nova wasp
#

yeah might be the server doesn't see the bones move

lyric heart
#

?

dark edge
#

yup that's it 100%

nova wasp
#

if the server is what decides if it hits based on the server collision

dark edge
#

on the server, the sword isn't being swung

nova wasp
#

then the server has to animate those characters even if they are not visible

dark edge
#

mesh -> always tick pose

nova wasp
#

I'm not sure if refresh bones is needed for kinematic transforms

lyric heart
#

i did always tick and refresh bones

#

works !

#

thank you

nova wasp
#

one good middle ground is OnlyTickMontagesAndRefreshBonesWhenPlayingMontages because it will only update when someone is playing a montage (I assume you have a montage for attacking)

#

but ofc if the other player has to be hit on their skeleton then it must update as well I guess

lyric heart
nova wasp
#

keep in mind when it says tick montages that also applies to montage events and states

#

so if this stops ticking montages those just kind of stop

lyric heart
#

Wdym ?

#

It did work, but it could break?

nova wasp
#

this is if you use one of the options that DOESNT tick montages

#

and switch back and forth

#

from being rendered or otherwise

lyric heart
#

Oh ok ya tick on montages seems logically correct consider everything is still replicated and then my onreps work still on montage

lyric heart
#

I'll try this out and see of any bugs

valid imp
#

I'd like to yell my love for actor dormancy. I dived into it hoping to gain a few frames after some profiling, and it exceeded all my expectations.

crisp shard
valid imp
crisp shard
#

100 by default seems a bit insane anyway

valid imp
#

Yeah, I guess it only makes sense for a Doom-like where everything moves all the time except the map itself.

silent valley
#

I am working on a climbing mechanic via extending CMC. I followed a decent guide which worked for single player, now I am trying to get it working in multiplayer. I extended the SavedMove and the mode is switching correctly, the bit that is not working is when I change the capsule orientation to follow the normal of the mesh he's climbing on. The sever and client disagree and it is causing major orientation glitching.

I looked through the base UCharacterMovementComponent and it seems that they never change the orientation of the capsule away from vertical.
Is capsule rotation something I should just avoid for multiplayer?

nova wasp
#

you can change their up direction I guess

#

I don't know how you are changing the capsule orientation

#

if it works locally then in theory the server should be able to follow along most of it...

#

show debug for net corrections at the very least and try to compare the input and result on both sides

vlog would be useful here to track it over time (perhaps with the timestamp etc)

silent valley
#

Just via the usual SafeMoveUpdatedComponent call. But there's some code that lerps from current orientation to surface normal, and I suspect that's where it's going wrong. That, and, if the position is different on server+client slightly then the surface normal may be quite different.

nova wasp
#

"code that lerps from current orientation to surface normal" in what step of the movement update?

#

and is "the posision" the final transform or a seconary variable you made?

silent valley
#

PhysCustom is where the code runs.
Now I'm looking at it, I think the client and server are in agreement because there's no net corrections going on.
The problem is when one client is observing another, their orientation is flip flopping.

nova wasp
#

and yeah slightly differing positions could give big changes in results... I wonder if you could just smash the normal into the sent input

#

difficult to verify on the server but if this isn't a competitive game I doubt people will spoof it

#

the position of the normal hit on the rock in world space should be fairly consistent though unless the rock moves. even then it could be sent relative to it

nova wasp
silent valley
#

yes I agree, I was wrong in my initial evaluation. definitely an issue just for sim proxies

nova wasp
#

which is easier said than done in some cases but you might want to see if you can bake your normals (well, not bake but just... use) into the smoothing steps of the cmc update

silent valley
#

Does the sim proxy run a subset of the CMC code? Maybe it's not running the code to set the orientation?

#

or it's expecting the orientatio0n to be replicated but it's not

nova wasp
#

the cmc on sim proxies is very simple... it just gets an onrep and then moves in that way and then does some math to smooth the mesh offset from the capsule

because of this it's VERY important to see both the real capsule and the skeletal mesh at the same time to see what is actually happening with its true position which jitters a lot compared to the real mesh's final offset pos

silent valley
#

is there some debug vis I can enable?

nova wasp
#

it might receive the transform of the actor in the onrep but idk how it would rotate and resolve in the same way without knowing about it

nova wasp
#

honestly easier to just add some vlog shapes to the variuos steps

#

or use the actor rewind debugger (if it's okay with this situation)

silent valley
#

visualizemovement does not show orientation, but I can see already that the position is glitching too.
I'll look into vlog, thanks.

#

or change the movement so it does not rely on changing the capsule orientation 🙂

nova wasp
silent valley
#

not intentionally.

#

capsule location is being moved via SafeMoveUpdatedComponent

#

ohhhh hang on, I'm also calling UpdatedComponent->MoveComponent after that to snap to the surface

#

I'll need to refactor that to go through SafeMoveUpdatedComponent

#

maybe

exotic thicket
#

All variables in GameState are replicated by default? Or do I have to set them to?

latent heart
#

Most, if not all, of them are afaik.

#

Common ones like PlayerArray etc are definitely.

#

You can check the individual vars in the source and see if they have the Replicated tag in their UPROPERTY.

dark edge
woeful ferry
#

so naturally when they replicate, they'll be added

silent valley
# nova wasp are you quantizing the location heavily?

I found the problem! the PhysClimbing function had a check for bCharacterWantsToClimb and if that was false it would switch to Falling mode.

On Simulated proxies this bool is always false, so it was constantly toggling in/out of climb mode.

I'm not quite sure why this is. On Autonomous proxy the bool is set by inputs and replicated to the server via saved move. But it seems like this saved move is not replicated/applied to simulated proxies?

#

For now I wrapped the switching to Falling mode in a if (CharacterOwner->GetLocalRole() > ROLE_SimulatedProxy) check, which seems to have fixed a bunch of issues.

nova wasp
latent heart
sage lance
#

only pain

dark edge
#

embrace the array

sage lance
#

arrays wont work

dark edge
#

What's the setup?

#

your map is of what to what

sage lance
#

i have a lot of maps but i use them to map various enums to structures or references

dark edge
#

how large are these maps, as in total number of key value pairs?

sage lance
#

the largest one i have is 150 keys

#

but i dont really need to rep that one

dark edge
#

It's probably literally faster to iterate and check (Array.Find) in the small case anyway

#

This is why you need to do multiplayer on day 1

sage lance
#

yeah ive been doing mult but i added some new systems

#

its just breaking for multiplayer saving

#

i have a save game object with a lot of maps

#

the client needs to load its save

dark edge
#

I think TMap has a function to crank out arrays of keys and values

sage lance
#

i did see someone like wrap it for replication

#

converty to array -> rep -> convert to map

dark edge
#

yeah that's what I'd do

#

or just have it be 2 arrays from the get-go, for small sizes it doesn't matter

sage lance
#

one of them is a kill log

dark edge
#

TArray<thing> Keys
TArray<thing> Values

#

why is a kill log not just an array of kills

sage lance
#

150 monster names to structs

dark edge
#

oh its counts

#

that's still not that bad

#

you're not sending it every frame right, just at GimmeTheSave time?

sage lance
#

no this is just for loading client saves

dark edge
#

yeah I'd just make arrays work

sage lance
#

i basically have made the maps just get updated in multicasts

lyric heart
sage lance
#

so you think like convert all the save data to arrays on saving and then on loading use arrays

dark edge
#

I'd just have an array of monster,kill structs and call it a day

sage lance
#

Okay but then its not indexable by the monster name enum

dark edge
#

so just find it

sage lance
#

and id have to use loops to add stuff

dark edge
#

you can look at a lot of enums in the time it takes to hash something

sage lance
#

pretty inefficient

dark edge
#

probably more efficient for small arrays

#

also since monster name is an enum

#

just cast it to int

#

and thats its index

sage lance
#

pretty hacky but its something ive thought of doing

dark edge
#

You have an array of KillRecordStructs whos size is MonsterNameEnum.Size

#

although enums for stuff that's really gameplay data is a bit icky to me

#

should be a GameplayTag IMO

sage lance
#

its there a better way to arrive at a dictionary type structure that will rep correctly ?

lyric heart
#

UEnum::GetIndexByValue

sage lance
lyric heart
#

then you would just put them in the same order as the array

#

and get by index but select the enum, get index

#

getting by index i believe is still O(1)

sage lance
#

yes

dark edge
#

getting by index is literalyl the fastest way to do this

lyric heart
#

i mean get array of values from map, make array

#

or just hard code it

sage lance
#

well id have to convert many maps to arrays but not an impossible task

dark edge
#

btw friendship ended with TArray, now TSparseArray is my best friend

#

also friendship ended with TMap, TMultiMap is my other best friend

sage lance
dark edge
#

ya dun fukt up a-aron

sage lance
#

makes no sense why you cant rep a map

dark edge
#

with the whole hashing and collision and buckets and all that jazz

sage lance
#

all it needs to do is send the map structure and it will contain that

dark edge
#

You and me could agree that the map looks like:

Tom, 34

But we might not agree on what bucket that data is in

sage lance
#

yeah but that can easily be handled locally

dark edge
#

idk, make the pull request and see if Epic bites

sage lance
thin stratus
#

Given it's still not a thing 10 years later, you can trust the fact that it's not an easy thing, or even something one should try to do. Stick to Arrays if you need replication.

lost inlet
#

I'm sure writing your own netserialize would be fun and not painful at all

thin stratus
#

Gotta be an Iris one to ensure it also stays relevant.

sage lance
thin stratus
#

On another note, I just noticed that the Iris serliazer (NetSerializer probably too) of FHitResult recalculates the Distance locally from the FVector_Quantized. Good thing I didn't quadruple check my code to find out why there is a difference between Server and Client when it was coming from the HitResult replication cutting away precision.

sage lance
exotic wasp
#

idk why TMap doesn't have replication because fast array serializer sends deltas as a map iirc

#

I can't think of a time where I've needed to replicate a map though

grand kestrel
dark edge
lament flax
grand kestrel
#

Gotta say, if they replicated it, I would not want to use it
Better to make your own struct

#

Can't imagine the pointless overhead with replicated TMap for general use

nova wasp
#

but I can kinda see why they never bothered to implement this in an official capacity as its pretty simple to work around

#

also on smaller arrays just doing AddUnique and searching by iterating will sometimes be faster than a tmap anyways

#

albeit more annoying

plush mauve
#

Is there any solution to replicating maps? I tried using a struct but that variable then just refuses to replicate?

fossil spoke
#

Usually you will create an array of a struct that has a property that is the type value and then another property that can uniquely identify it.

nova wasp
#

it is possible if you completely make a custom serializer but... don't do that if you can avoid it

#

array setup is far more simple

plush mauve
#

Whoops, sorry, I should have scrolled up. Thanks for the responses.

maiden plinth
#

Hii everyone, I'm trying to create something like a spectator feature, my client 1 is a character class and client 2 is a spectator pawn whose view target is initially set to a actor with a top down view during that time when the client 1 is moving in the view his movement is very smooth after that when the client 2 view target is changed from that top down view to the character there is suddenly a movement jitter visible in the character(client 1) can anyone explain why there is this jitter as character class comes by default with client side prediction so why when I set the view target to the client 1 it shows that jitter and how can I fix this ?

twin vessel
#

Is there any reason to not move CheckJumpInput inside PerformMovement?

I cannot see any reason against moving it there. But i might be missing something

thin stratus
thin stratus
maiden plinth
thin stratus
glacial seal
#

hmm I just noticed that after this implementation, server is able to see what happen in the client side but what happen on server is not shown xD

twin vessel
# thin stratus Doesn't the comment above it say why it's placed where it is now?

In ForcePositionUpdate it says // TODO: this is basically copied from MoveAutonmous, should consolidate. Or consider moving CheckJumpInput inside PerformMovement().

While in ControlledCharacterMove it says // We need to check the jump state before adjusting input acceleration, to minimize latency // and to make sure acceleration respects our potentially new falling state.
But in all three functions where CheckJumpInput is called, the same operations on Acceleration are performed, and PerformMovement is called right after

thin stratus
thin stratus
twin vessel
#

I want to override the jump logic if there is a wall in front of the character to implement a mantle mechanic, but if i set the movement mode to anything that is not walking or falling during the mantle, OnMovementModeChanged will reset the jump state including bPressedJump.
This is annoying because CheckJumpInput happens before bPressedJump is store in SavedMoves

The only reason against it that i can see would probably be that changing acceleration before ReplicateMoveToServer makes it so the move cannot combine, but i bPressedJump already blocks combine before the end of a move.

#

It just feels like it is wrong for it to not be there

glacial seal
# thin stratus You gotta apply the AnimLayer within an OnRep that specifies the currently equip...
    UFUNCTION(Server, Reliable)
    void Server_EquipmentLinkAnimLayer(USkeletalMeshComponent* AttachMesh, TSubclassOf<UAnimInstance> AnimationLayer);
    
    UFUNCTION(NetMulticast, Reliable)
    void Multicast_EquipmentLinkAnimLayer(USkeletalMeshComponent* AttachMesh, TSubclassOf<UAnimInstance> AnimationLayer);
        

void UEquipmentComponent::Server_EquipmentLinkAnimLayer_Implementation(USkeletalMeshComponent* AttachMesh,
    TSubclassOf<UAnimInstance> AnimationLayer)
{
    Multicast_EquipmentLinkAnimLayer(AttachMesh, AnimationLayer);
}

void UEquipmentComponent::Multicast_EquipmentLinkAnimLayer_Implementation(USkeletalMeshComponent* AttachMesh,
    TSubclassOf<UAnimInstance> AnimationLayer)
{
    if (UAnimInstance* AnimInstance = AttachMesh->GetAnimInstance())
    {
        AnimInstance->LinkAnimClassLayers(AnimationLayer);
    }
}

        On Item equip i called this (it is replicated as Item was spawn)
    //Link animation layer if not nullptr.
    if (IsValid(EquipmentFragment->GetEquipmentLayer()))
    {
        Server_EquipmentLinkAnimLayer(OwningSkeletalMesh.Get(),EquipmentFragment->GetEquipmentLayer());

    }
thin stratus
stoic rover
#

Anyone know an easy fix for spawning actors on the server, not replicating to clients

twin vessel
thin stratus
thin stratus
thin stratus
glacial seal
stoic rover
glacial seal
#

what is a better way ? learn about OnRep?

thin stratus
thin stratus
twin vessel
glacial seal
thin stratus
twin vessel
#

ReplicateMoveToServer calls PerformMovement already

thin stratus
#

It already needs the Acceleration earlier.

thin stratus
#

That should trigger the LinkLayer fwiw.

glacial seal
#

it was using server reliable and multicast xD

twin vessel
#

Well i'm stuck regardless cause not having a source build i need to copy paste the functions and i need some CVars that i cannot access

stoic rover
thin stratus
twin vessel
twin vessel
glacial seal
#

@thin stratus thanks! OnRep solve my issue ;D

lyric heart
#

How would you go about displaying health of all other players in your group ?

#

i did get it working, but i was wondering how would be good

#

i used onrep and some loops/checks

exotic wasp
lyric heart
#

s i need to loop for that

#

but also i had to use a workaround

exotic wasp
#

why do you need a loop?

#

just add a delegate to the onrep of whatever holds the player HP and have your UI bind to that delegate

#

no looping, no id needed

lyric heart
#

hmm

#

idk what your saying i think use an event ?

#

dispatcher

#

for me it's ok because i only have a couple players

exotic wasp
#

I can't entirely remember what they're called in bp but I think that's it

lyric heart
#

yes event dispatcher

#

i'm not sure here, so the widget will bind to the event

exotic wasp
#

UI should pretty much always communicate through delegates

placid cloak
#

Throwing this out there in hopes someone knows of a way. I need to run memreport -full on a headless server to find out why a crash is happening. The problem is the server doesn't have a built in console to run this from. I tried adding it through the command args in properties but that's just ignoring it or messing with the level being passed in. Any thoughts?

lyric heart
#

and also have another loop

#

i will try with event dispatcher

#

but i'm not sure how to go about this lol

exotic wasp
#

Your game logic shouldnt change regardless of if your UI exists or not

#

A delegate is the best way to do that

lyric heart
#

i just want to avoid all the loops tbh

#

it works and is ok for a small game like i'm saying for my purpose it might work

exotic wasp
#

Then your UI bind to the event dispatcher in beginplay or something

exotic wasp
#

When the onrep gets called, the event dispatcher is broadcast and the UI then updates

lyric heart
#

hmm but i need to tell each on the correct player

exotic wasp
#

Not sure I understand

#

Where is the health stored?

lyric heart
#

so when it fires off i actually want the local stuff to change

#

the health is on the player

exotic wasp
#

Actor?

lyric heart
#

yes

exotic wasp
#

You might have issues with relevancy later, but you just need to get a list of teammates when your UI first initializes

lyric heart
#

so the player state has a list of all players

#

thats what i'm using

exotic wasp
#

That works

lyric heart
#

and it works and one logs out it fires off and everything works

#

it's just that for each player onrep i'm doing all this loop

exotic wasp
#

So UI BeginPlay->loop through teammates and setup UI

#

Each player actor health has its own onrep

lyric heart
#

well i also need to setup when a player joins

#

because that would just say when you join and show the players, but when others join it wouldn't show up

#

so i set it up in the player controller

#

on acknowledge possession

#

with a few retry hacks

#

and on game mode, login/logout

#

i'm trying to think of how to fire off the proper event on whatever machine is running ?

#

i was going to use rpc, but i assumed onrep would be more performant

#

but i think with all these loops, perhaps an rpc would be better

exotic wasp
#

RPC is probably more performant but you should never use them to change state on clients or to react to changes in state

#

OnRep is ideal

exotic wasp
#

The OnRep will trigger on any client where the actor is relevant

lyric heart
#

hmm

exotic wasp
#

The only way to control what machine "receives" the OnRep is by controlling relevancy

#

You probably don't want that here

#

Relevancy will actually probably cause issues if players are far apart because the actor will despawn on clients

lyric heart
#

ya i want them to be able to spread across the whole map

#

not a huge map, but still

#

i have the enemy and players, always relevant

exotic wasp
#

You can also toggle "always relevant" which is probably fine

#

Yeah

#

Enemies maybe you don't want them always relevant

#

But for a small coop game teammates being always relevant is perfectly fine

lyric heart
#

well i want the players to be as far as part as the map allows

#

as far as if they want

exotic wasp
#

They can always do that on the server just fine

#

It just keeps the actor loaded on every client at all times

#

So you will still get health updates and such

lyric heart
#

would i have to do something on the client side to display ?

#

and then let it sync later ?

exotic wasp
#

When an actor becomes not relevant to a client, it is effectively destroyed on the client

#

When the actor becomes relevant again, it gets constructed again and goes through BeginPlay

#

Server always has everything loaded for itself because it's the server

#

If an actor is too far away and becomes not relevant, the client doesn't know it exists and will not get OnReps

#

So you either have to make the actor always relevant because that's where your health is stored, or relay the health through something that is always relevant to all like PlayerState

#

And tbh, probably makes more sense for clients to bind to a delegate on PlayerState. then in case the actor being possessed changes, the UI doesn't care because it just binds to the PlayerState

#

Sorry if that's a bit much

#

The pinned messages here have some good resources

#

@lament flax saves his notes online and has some decent replication sources

lyric heart
#

i can also put my loops in c++ might be just fine like that

#

atleast untill i can figure out what your saying, i think i get it the health shouldn't be on the player, it should be in player state

#

but i have no problem getting the health

#

or setting it normally

#

just getting every other players health and updating on my ui when other player changed

#

but events seem the best way to go, i'll look into it thanks

exotic wasp
exotic wasp
lyric heart
#

if the way i'm doing it doesn't cause a performance issue then i'm fine with it

#

for what i been trying to get working, a lot of the sync stuff is a pain

#

but now it doesn't matter how they log on, order, timing

#

everything syncs up

#

the real test will be with latency i guess over the actual web

lost inlet
coarse cave
#

Oops, yeah

glossy gate
#

heyy, right now when I try to interact with an editable text box with a client doesn't let me interact but with the server yes. I think it could be maybe a focus issue or something but I'm not sure and I don't know how can I be able to interact in the client too. if anyone can help me pls

nocturne iron
#

Does Unreal’s replication system provide a built-in way to check if an actor’s state has replicated on the client? Like some sort of counter or “change id” that increments each time replication happens, so you can confirm you’ve received the latest server state across actor channels?

halcyon ore
#

Not that I know of for like per var sorta deal
(There is a function that gets called for the entire actor)

But, from what I heard.
Vars and stuff is repliable, so it should happen, as soon as possible.'

#

What are you intending to do?
Just knowing when client has a value change, but from the server? (since server needs to send the change)

quasi tide
#

PostNetReceive can probably be used for what want perhaps.

nocturne iron
#

I have this inventory system...

// Ther user calls this function, which saves the OnResponse delegate along with a request guid. 
UKhaosInventorySystemComponent::TryMoveItem(FKhaosInventoryRequest_MoveItem Request, FKhaosInventoryResponseDelegate_MoveItem OnResponse);
// Which calls
UKhaosInventorySystemComponent::Server_MoveItem(FKhaosInventoryRequest_MoveItem Request);
// Which calls, on success, it needs to call the OnResponse delegate.. However, only if the UKhaosInventorySystemGameState (which holds state) component has also replicated the change from the request. 
UKhaosInventorySystemComponent::Client_MoveItem(FKhaosInventoryRequest_MoveItem Request);

So my solution is having something like this

// Where Revision is UKhaosInventorySystemGameState::Revision. This way I can call the Delegate if we are up to date, or wait till the UKhaosInventorySystemGameState::Revision >= Revision.
UKhaosInventorySystemComponent::Client_MoveItem(FKhaosInventoryResponse_MoveItem Request, uint32 Revision);

Hope that makes sense. Basically I am trying to ensure sync between actor channels.

nocturne iron
halcyon ore
halcyon ore
#

Or, are you trying to keep multiple moves in order?
So, if I move it from 0 -> 5, then someone else does 5 -> 3 You wanna have moved in the correct order, and such?
Cuz, that also sounds like what it is?

#

In which case, your over-complicating it.

nocturne iron
#

It's just to make sure that when the calling client receives it's acknowledgement from the server (though Client_MoveItem). It does not call the OnResponse delegate assiated with the request before the game state is also up to date.

#

Otherwise there would be bugs where the client tries to do something with a newly created item in the OnResponse callback, and the action fails client side validation because the state is not synced.

halcyon ore
#

I feel like now i'm more lost, or your describing it weird?
Client moves it, has a callback, but the callback fails, because the client didn't move the item it just moved?

nocturne iron
#

In actor channel 1 (player controller): Client sends a request to move the item. Now the server updates inventory state and acks the requesting client.
In actor channel 2 (game state): Inventory state was just changed, and is being replicated.
The issue is that i cannot assume that actor channel 2 has replicated the state on the client when the client recives the Client_MoveItem RPC, and thus I need some sort of sync key to determine it. That key is passed with the ack to Client_MoveItem, can can be checked against UKhaosInventorySystemGameState::Revision.

#

if UKhaosInventorySystemGameState::Revision => Client_MoveItem's revision we know it's safe to call the OnResponse delegate, i.e. it's safe to trust what was sent in the response struct.

halcyon ore
#

Oh, I see.
Its a miss-understanding of how I usually envision item replication.

Then, yeah.
An on rep would make the most sense here.

nocturne iron
#

How do you usually do it?

#

out of curiosity

halcyon ore
#

I replicate the items themselves, then just move them around with reliable RPC's.

Request Move
Server Move
Client Move

Since its reliable, it should keep everything in-sync.
So, when the client has its RPC move replicated, it moves the item, and done.

Should be all in-sync.

nocturne iron
#

I see, I am not really able to do that here with FastArrays.

halcyon ore
#

Ah, I see.
Yeah, I don't use any of that special stuff.

#

It makes the items that part of like unknown if sync'd but the item themselves matter far less, then client clicking on raw meat, but server thinks its a sword or something goofy.

obsidian ermine
trail cave
#

Hello! Has anyone encountered compiling a dedicated server on Linux if the project includes Wwise? The client build is purely on Windows, the Wwise license is purely on Windows, and Wise is not required in the server build.

If everything is clear with sound calls, just wrap them in a macro and that's it. But what to do with Wwise volumes and portals on the map and in the BPs, i can't wrap them in a macro))

I understand that wrapper classes can be created, but they would be inconvenient to configure, as Wwise classes have many parameters, and transferring all of them to a wrapper class for each one seems like a hack.

But maybe there's a better solution?

fossil spoke
#

Therefore, all you need to do is to compile out any calls to their SDK.

#

A Blueprint callable function is not covered by their licence, the call to their SDK that the Blueprint callable function calls is what you want to remove.

#

So the Blueprint function becomes an empty stub basically.

lament flax
#

And next to the server rpc call in the widget i would also update the slots like the change already happened to have some fancy item prediction

halcyon ore
#

Update the item like it already happened?
That seems wasteful?
2 reps to move an item?

#

Nvm
Brain fart. 😛

lament flax
#

1 local "update slot display" for local client prediction

#

the server will rep the state back anyways

cursive mirage
#

When making an indie multiplayer game, is there a difference in frame performance (game heaviness) between Unity and Unreal Engine?

#

Please consider the game design as Lethal Company.

thin stratus
cursive mirage
#

Sorry for asking something so trivial.

thin stratus
#

Yeah, you can make all kinds of games with UE. And maybe UE is initially a bit overloaded, but especially for an Indie Multiplayer Game, UE offers a lot more stuff out of the box. I'm pretty sure you can make an equally unoptimized mess with Unity if you aren't making sure your code and assets are fine.

pliant cypress
#
if (SoldierCharacter->IsLocallyControlled())
{
    if (bWeaponEquipped && EquippedWeapon && EquippedWeapon->GetWeaponMesh() && SoldierCharacter->GetFPSMesh())
    {
        LeftHandTransform = EquippedWeapon->GetWeaponMesh()->GetSocketTransform(FName("FP_LeftHandSocket"), ERelativeTransformSpace::RTS_World);
        FVector OutPosition;
        FRotator OutRotation;
        SoldierCharacter->GetFPSMesh()->TransformToBoneSpace(FName("hand_r"), LeftHandTransform.GetLocation(), FRotator::ZeroRotator, OutPosition, OutRotation);
        LeftHandTransform.SetLocation(OutPosition);
        LeftHandTransform.SetRotation(FQuat(OutRotation));

        FTransform RightHandTransform = SoldierCharacter->GetFPSMesh()->GetSocketTransform(FName("hand_r"), ERelativeTransformSpace::RTS_World);
        FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(RightHandTransform.GetLocation(), RightHandTransform.GetLocation() + (RightHandTransform.GetLocation() - SoldierCharacter->GetHitTarget()));
        RightHandRotation = FMath::RInterpTo(RightHandRotation, LookAtRotation, DeltaTime, 30.f);
    }
}
#

hand is rotating, but weapon rotation is getting wierd

exotic wasp
#

It won't keep state synchronized if a player late joins or relevancy changes

nocturne iron
#

Cant figure out why UKhaosInventorySystemComponent::OnRep_Backend (replicated subobject) is being called with nullptr on owning client. What am I missing?

// AMysticPlayerController
class AMysticPlayerController : public APlayerController
{
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Inventory")
    TObjectPtr<UKhaosInventorySystemComponent> InventorySystemComponent;
};

AMysticPlayerController::AMysticPlayerController()
{
    bReplicates = true;
    InventorySystemComponent = CreateDefaultSubobject<UKhaosInventorySystemComponent>(TEXT("InventorySystemComponent"));
}
// UKhaosInventorySystemComponent
class UKhaosInventorySystemComponent : public UActorComponent
{
    virtual void BeginPlay() override;
    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

    UFUNCTION()
    void OnRep_Backend();

    UPROPERTY(ReplicatedUsing = OnRep_Backend)
    TObjectPtr<UKhaosInventorySystemBackend_GameServer> Backend;
}

UKhaosInventorySystemComponent::UKhaosInventorySystemComponent()
{
    PrimaryComponentTick.bCanEverTick = true;
    bReplicateUsingRegisteredSubObjectList = true;
    SetIsReplicatedByDefault(true);
}

void UKhaosInventorySystemComponent::BeginPlay()
{
    if (ensure(GetOwner()) && GetOwner()->HasAuthority() && ensure(!Backend) && ensure(BackendClass))
    {
        Backend = NewObject<UKhaosInventorySystemBackend_GameServer>(this, TEXT("InventoryBackend"));
        check(Backend->IsSupportedForNetworking() && Backend->IsNameStableForNetworking())
        AddReplicatedSubObject(Backend);
    }
}
#
// UKhaosInventorySystemBackend_GameServer
class UKhaosInventorySystemBackend_GameServer : public UKhaosInventorySystemBackend
{
    UKhaosInventorySystemBackend_GameServer();

    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

    // Replication plumbing
    virtual bool IsSupportedForNetworking() const override { return true; }
    virtual bool IsNameStableForNetworking() const override { return true; }
    virtual int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;
    virtual bool CallRemoteFunction(UFunction* Function, void* Params, FOutParmRec* OutParms, FFrame* Stack) override;
}
exotic wasp
#

Use the replicated subobject list later in that resource

#

And is the actor you have this on replicated?

nocturne iron
nocturne iron
#

I set bReplicates=true and bReplicateUsingRegisteredSubObjectList = true in constructor.

exotic wasp
#

I think you might also want to create the New object only on the server and have it replicate down

#

Also not sure the name is stable since you're using NewObject

nocturne iron
# exotic wasp I think you might also want to create the New object only on the server and have...

Yeah, this is what i am doing here

    void UKhaosInventorySystemComponent::BeginPlay()
{
    if (ensure(GetOwner()) && GetOwner()->HasAuthority() && ensure(!Backend) && ensure(BackendClass))
    {
        Backend = NewObject<UKhaosInventorySystemBackend_GameServer>(this, TEXT("InventoryBackend"));
        check(Backend->IsSupportedForNetworking() && Backend->IsNameStableForNetworking())
        AddReplicatedSubObject(Backend);
    }
}
nocturne iron
#

Though I just needed to name them the same in NewObject.

nocturne iron
exotic wasp
#

Stable name would be for something you can uniquely create on both client and server and have them match

#

Or assets

nocturne iron
#

I see. That does make sense.

tame sapphire
#

Hi all, looking for a bit of direction on this one. Just not sure how to plan it out. Basically I have server AIUnits that a player passes 'Actions/commands' to and the server executes this command at a certain point within the turn. However I want to start the game with players being able to choose a spawn tile. I got the logic for selecting the tile but I'm just mentally blocked on how how to show/hide the tiles dependant on if the server unit is alive or dead.... didnt see a game logic kind of channel so asking here as it is multiplayer

#

in my head im setting on the player controller if the unit is alive or dead and updating the hud and showing/hiding the tiles then but fdor some reason it just doesnt make sense and im after input on a direction to go if it doesnt

tame sapphire
#

Im assuming on the destroy of the event i hide all spawn tiles and on event destroy i show show them and update the HUD at the same time? or should the unit begin and destroy events call the 'Command controller' attached to the unit and update from there

gray blade
#

can anyone answer, im trying to make a system where when you transition levels in a session data like inventory and health travel. im aware the game instance is usually the go to but since the GI is persistent the whole engine runtime and i dont want the data in ouside the origin lobby is it a good idea to save it inside the playerstate?

#

(ugh just came to the revelation seamless travel doesnt work in editor)

torn hull
#

Hey, I’ve got a progress bar for something like health. It doesn’t need to be updated every tick, only on certain events. The “health” variable is replicated on my health component, but when testing with lag, I noticed the widget bar that uses the replicated variable gets out of sync on client.

I made a workaround by creating the same variable on my character (not replicated) just to update the widget. The downside is I now have to update two variables: the one on the component and the local one.

Is this a good idea, or is there a better way to handle updating replicated variables on widgets?

gray blade
plush mauve
#

If I have a very large replicated struct array on GameState with maybe 10k-30k entries, is there any reliable way to know when that array has finished replicating for the first time on client login?

#

If I make it repnotify, when does the notify fire.... only once when it has completely finished replicating? Or does it replicate large data in stages and fire multiple times?

verbal ice
#

You might hit the size limit per bunch

#

i would make your own system to chunk it and reassemble it on the other side

#

which would solve your problem of knowing when it's fully ready on the client

nova wasp
#

may as well send size of the array

torn hull
#

Hey, by default components exist on all instances of the character. Is it possible to make a character component only on the server? I want to create a detection radius for a certain character, but if it exists locally someone could just hack its radius, right? Also, there’s no need to create this on all clients since only the server will fire the overlap event. Should I just destroy it on locally controled characters? It seems to work fine

nova wasp
thin stratus
# torn hull Hey, by default components exist on all instances of the character. Is it possib...

In C++ you have more control over it. In blueprints you would need to remove it the way you currently do. You still pay the price for creating and destroying it but at least it won't be part of the updated component transforms.

In terms of cheating, there is nothing the client can do unless you allow them. If the component doesn't have an ServerRPC, or is altered by one from the outside, that modifies the radius on the server, then nothing can happen anyway

nocturne iron
#

Is there a good way of doing per-connection filtering of fast array entries? I basically need a relevancy check per entry.

nova wasp
#

maybe if they point to a specific sub object, those can be filtered

nocturne iron
#

Well shit.

nova wasp
#

the easy thing is to just make multiple fast arrays

nova wasp
#

making replicated sub objects and filtering them with groups etc

#

iirc you should be able to just not replicate them to some clients but

#

I don't know what the data actually is

#

or why it filters per client

#

making a whole new object for replication is not free of course

nocturne iron
#

Hmm. Okay. I am looking to add some sort of relevancy to items, such that they are replicated based on their proxy actors position, what inventory they are in etc. All items UObject subobjects of the game state. Not sure what the best pattern is here.

nova wasp
#

having a network manager is a great idea for some things but idk if this should be a global list of spatial things

nocturne iron
# nova wasp having a network manager is a great idea for some things but idk if this should ...

Yeah, i have a InventoryStateComponent on the game state which holds a list of inventories and items. Just the data, then the proxy actor refers to it by handle. So the items, and their data in themselfs are not spacial. I have a lot of data on the items in a component like system, where each item trait has their own data. They are called item fragments. So I thought it made a lot of sense to keep a state component with that owns the data.

nova wasp
#

having fragments tends to be in a definition at least in Lyra

#

which is just a class path networking wise

nocturne iron
#

I have two types of fragments. Static and instanced. Instanced fragments has per instance data, which is individually serialized to the database. Static fragments are just gotten from the item definition primary asset.

#

The spacial relevancy of the actor proxies is easy. But in the current implementation, the non-relevant item data is also replicated to all clients, which inefficient due to replicaing too much data and insecure since a client would be able to just read the memory and see what items are in the game.
That is really the part I am looking to change. How do I make relevancy per subobject, and how do I connection-specific view for lookup.

nova wasp
#

I still don't see any part of this that needs the global manager on the gamestate

nocturne iron
#

How should it be then? Who owns the subobjects?

nova wasp
#

the actor instance that they represent, no?

nocturne iron
#

And then change ownership when the item is picked up?

nova wasp
#

I guess idk why the handle here to the gamestate matters unless you want to have them sort of exist even when not nearby to serve as a global lookup

nova wasp
nocturne iron
#

Hmm

nova wasp
nocturne iron
#

No problem.

nova wasp
#

is there a notion of "teams" or alliances in this game? could there be a bucket per-team?

#

or are there more than a handful of potential sets of items you want to send

nocturne iron
#

So, the inventory system is designed for a survival extraction shooter somewhat like Tarkov, or Dayz. We have ~1-2k items per map. I am still a little conflicted on the who owns the items question. I guess you could have a point that the actor/object representing them should also own them..

nova wasp
#

if the items are on the floor then they should just replicate by distance, no? I'm confused

#

you could probably do something fancy and pack them down into a network manager for each rough area or grid cell like Mass replication does (they have a manager actor for groups of entities called bubbles but idk exactly how they transition between them)

nocturne iron
#

It just seems like a lot of sync barriers, and not sure what effect is has on rollback. The current implementation is highly transactional, so it's easy to have a list of "predicted transactions", there is also that the user API has an OnResponse delegate for each requested action. That means that the per-client system component needs to wait for all side-effects of the request to be fully replicated before sending a response, which is somewhat easy with a central manager- and likely also doable if the items are owned by actors. I guess that would just be OnRep if they are reconstructed

nova wasp
#

yeah the single holy list does help avoid dupes I assume

#

also

#

the idea of this transaction does not have to be replication, the replication could just be representing where the item is

#

the transaction could be a series of reliables

#

where other clients just see the results as the represented areas

#

the representations could just be a potential request into the global manager, but the representations are spatial etc

nocturne iron
#

This kinda boils down to the philosophical question of is an item actor the item, or just an interface for item. The interface for an item model works very well for UI, because the UI is totally decoupled from the actual item, so server build can just disable the game feature providing inventory UI and work anyway. But for world actors it more nuanced.

nova wasp
#

which is kinda what you do now but what I mean is to not have the instance data in the global manager replicated, but maybe sent alongside the sort of spatial thing where they are results from the holy database

#

indices sent that you arne't close to or can't really own are ignored etc

nocturne iron
#

Hmm. yeah.

nocturne iron
nova wasp
#

so the holy gamestate list could serve as an authority only thing

#

where it is sort of the goalkeeper of the item and serves to represent the path it took to get to where it is

#

but the players see an actor with stuff on it etc

#

they don't need to know about the gamestate, they just need to see an item on the floor and press E on it

nocturne iron
#

That might not be too bad

nova wasp
#

but I honestly have never had to make something like that from scratch so don't take my word for it, there might be some nice examples around of people making similar pvp/extraction etc survival games where item transactions are an issue

nocturne iron
#

I am wondering what not having that list on the client would mean. The only think I can think of is prediction of actions, like showing green text if i can pick up the item based on some fragment condition, and red if not. If the client only knows the actor, that would have to be a server RPC to get that information. Also other types of "can I move an item here" checks, that are currently done based on the clients version of the "holy gamestate data".

#

It's a pretty smooth solution for solving the relevancy issue tho.

#

And likely the simplest and fastest as well. Due to replication graph / iris.

glossy venture
#

Hello everyone, currently bashing my head against the wall known as "Steam Advanced Sessions Setup" in UE 5.6. I've been through every tutorial and fix and just can't get it to work. I have what is nearly a default thirdpersongame going on but with a main menu screen to create/join sessions.

Every single time the Join Session node fails where it has the "failed to join session2" print string. I've got no idea what I'm doing wrong or what I could even troubleshoot at this point. Got some experience in single plalyer games, this stuff throws me for a loop. Would greatly greatly appreciate any help or insight getting this rudimentary multiplayer system working.

Also note this isnt a packaged project, all testing has been done in the editor with 2 windows for testing 2 players.

Thx for any info/assistance in advanced 🙂 👍
(there are many videos but this is the written guide I'm trying to follow: https://unreal-chronicle.hanayou.dev/docs/miscellaneous/advanced-sessions-setup
I'm stuck on Testing Multiplayuer in the Editor, since I can not get Join Session to work)

An adventurer’s handbook to Unreal Engine

lyric heart
lyric heart
#

but if you package your game

#

when you run it

#

while steam is running

mystic estuary
#

Hello, I have a fast serialized array with structs that contain object ptrs. Everything gets replicated as it should, but when I started testing it, client-side it seems to GC the uobject eventually. Server-side it's always valid, but client gets rid of it for some reason. The outer of the object is an actor component which the client has, I double checked and MyUObject->GetOuter() inside PostReplicatedChange() is correct... The server never GCs it unless it doesn't want to have the object anymore.

What could the reasons for it to be GC'd in case the outer is valid? Is there any way to hook to something that would tell me what object got GC'd?
nvm I was changing the outer server-side after AddReplicatedSubObject, so clients had it set to the old outer which got destroyed

lyric heart
lyric heart
shy gust
#

hey all , I dont think this issue is unique to Steam networking but, with steam implemented in my racing game, im noticing I need Seamless travel enabled on all my gamemodes .
However , enabling this makes restarting the scene kind of impossible? as in the Restart Game Node, no longer works , im not sure if there is a work around, I use the restart game node mainly for restarting the races in all my various modes in my game, its pretty important.
but if anyone has any ideas id really appreciate any and all insight, thx

TLDR how do you handle restarting in seamless travel scenarios?

nocturne iron
grave lynx
#

hey, I have a actor, inside, I use SetOwner(MyPawn) if the player interact with it. I override OnRep_Owner(), I added a log inside but this funtion seems not triggered, any idea?

shy gust
nocturne iron
nocturne iron
#

That is

UFUNCTION()
virtual void OnRep_Owner() override;
grave lynx
#

compile error

#

Override of UFUNCTION 'OnRep_Owner' in parent 'AActor' cannot have a UFUNCTION() declaration above it; it will use the same parameters as the original declaration.

nocturne iron
#

Ah, my bad. Though that was required.

#

Are you calling SetOwner from server?
bReplicates = true?
Is the actor relevant to the client?

#

I also assume you expect the OnRep to be called on the client, not on the server?

nocturne iron
grave lynx
nocturne iron
exotic wasp
fallow mango
#

does anyone know why an animation would affect player position on server, but not when playing as client?
some setting within the player bp

#

it's going through an RPC and works with a different character, just cant seem to find why

glossy venture
# lyric heart so when you hit host does it travel to the listen map ?

Thanks for the reply! I have been testing with Play As Listen Server set for the Net Mode. Was just trying to test everything out in editor before properly connecting it to Steam to test the packaged product. Got plenty more game to build before packaging, just need to make sure players can interact in real time before I can develop much further.

When you hit host it doest travel to the listen map, even for both players without a problem! Only issue is no matter the order the Join Session button has never worked, and always returns the "Failed to join session2". So all I have right now is both players who are able to host their own games, both of which use the same listen map.

mystic estuary
#

Hello, does anyone deal with moving uobjects between different outers? I want to give a different outer for a replicated uobject, but it seems not to replicate that change. I had to change it client-side, as well as move the sub object from actor channel to the new outer for it not to be marked as garbage when the original outer gets destroyed. It seems to work, but the approach seems wrong, I feel like it can break easily. Did anyone else try to do something like this?

verbal ice
#

what you're doing is pretty much what I've had to do as well so that sounds right

#

Make sure you remove the object from the previous outer's replication list, and add it to the new one

mystic estuary
#

Yes, that's what I do, but I still have to manually unregister the sub object from actor channel client-side

#

Otherwise it gets marked as garbage when the old outer gets destroyed

verbal ice
#

yep

mystic estuary
#

Did you have any other problem with that?

verbal ice
#

an interface that may help you is IActorSubobject_Interface

#

i think thats what it's called

mystic estuary
#

I'll look into that once I'm at the computer

verbal ice
#

you can slap it on the UObject and it has functions the engine will call when it's created/destroyed from replication

#

but that's about it

#

keep in mind the object will be recreated on the client

#

i wouldn't attempt to move it there

#

you'll end up with dupes

#

or worse probably

mystic estuary
#

So it'd be better to recreate it server-side, and don't change the outer altogether?

verbal ice
#

You can change the outer on the server

#

Just know that the client will recreate it

mystic estuary
#

Are you sure though? The only reason I had to deal with it is that the object got GC'd. I move it from one fast serializer array to another, which reside in different actors, yet the object got GC'd as if it's the same one

lyric heart
#

I'm trying to access the HUD from the player controller, but it keeps failing ?

#

I'm looping through the player array

#

And using the controller of the current in the loop

#

To call an event in the hud

#

Hmm, I'm trying to update player cards when postlogin

#

I generate the cards on possession np, but when others join after I'm having an issue rebuilding the cards

trail cave
trail cave
lyric heart
lyric heart
trail cave
trail cave
#

When you looping server controllers - call this event(Run On Owning client)

lyric heart
#

i have tried this

#

it doesn't work

#

maybe i was doing it wrong

#

in the controller i have an event

#

that sets runs an event on the hud

#

this works fine when ran from the controller

#

but when in game mode, on postlogin it's not working as expected

trail cave
lyric heart
#

this is on postlogin

#

it keeps saying FAILED

trail cave
#

HUD dont't exist on server

#

You call Get HUD in server

#

You need put get HUD in controller event

lyric heart
#

not the hud

#

i'm not understanding lol

dark parcel
#

HUD is local to each player

#

listen server has one

#

clients have one each.

#

they are local, not networked nor reachable by other player other than the owner.

trail cave
dark parcel
#

Maybe what you want to do is,
As server -> Tell every client to do X?

In that case,
As server -> Loop every controller -> Execute functions in that controller via client RPC.

#

RPC is for event based though, the cards should always be updated via OnRep imo.

#

Updating variables with RPC is recipe for disaster.

trail cave
# lyric heart i'm not understanding lol

betteer solution to read documentation about networking, to unerstand how all it works. As said ColdSummer - if u fix that function and it will work - it's doesn't matter, because the current method for updating cards is incorrect in itself.

lyric heart
dark parcel
#

z1kot shows how server can tell clients to run function.

But for what you want to do, you shouldn't even talk to anyone's HUD.

lyric heart
#

ya the docs

dark parcel
#

server don't even need to know anyone's widget or any player widget for that matter.

#

what you want the server to do is to propagate STATEs

#

So in this case, think of card as Inventory and items. They are normally represented as actor component.

Server -> Get Player -> Get CardComponent -> Set Card values or w/e.

#

the card can be a replicated variable. Clients will eventually get the server value on the next Net Update.
In which they client can do OnRep (Card)-> Broadcast.CardUpdated.

#

and here, the Widget listen to the broadcast

lyric heart
#

i'm creating them dynamically

dark parcel
#

so whenever the card is updated on client side, it updates the widget.

#

Yes, and the answer remain the same

lyric heart
#

its not the update thats a problem

#

it's creating them

dark parcel
#

Having server telling clients, hey update your widget

#

is noob mistake, sorry for the language.

#

just my honest opinion

#

and yeah im noob too

#

but I believed Im over that stage

lyric heart
#

ya i'm really new to networking

#

multiplayer is really difficult imo

dark parcel
#

yeah but once you understand replication it's actually the easy part.

lyric heart
#

i guess i can use onrep

trail cave
dark parcel
#

the next part is hell

#

Physics and real time combat

lyric heart
#

idgaf about all that

#

i just want these damn cards to work lol

#

i been stressing for hours over this crap

dark parcel
#

give your self weeks

#

I dunnoe about others, but I went through countless errors.

#

until one day, it click.

lyric heart
dark parcel
#

show code

trail cave
#

@lyric heart Check again my message))))

lyric heart
dark parcel
#

Player States != player controller

#

show code?

trail cave
#

Multiplayer or singleplayer - it's doesn't matter. Widgets always just listening, also in singleplayer you must not call directly update widget)

#

But singleplayer forgives many problems and it works) But not in multiplayer)

dark parcel
#

so when widget doesn't exist, game break.

haughty ingot
trail cave
lyric heart
#

and it's succeeding

trail cave
#

@lyric heart

dark parcel
#

Show code X_X

lyric heart
trail cave
haughty ingot
#

PostLogin is generally too early to do anything with the player state IIRC.

Depending on if you’re doing seamless or not, HandleStartingNewPlayer is the function you would want IIRC.

dark parcel
#

RPCs are for event. so Like welcome message, or good bye message.

For your cards, just make your card a replicated variable.

#

what ever the server set the client will eventually update.

thin stratus
#

Wild suggestion: If one needs to react to a player joining locally and needs access to the PlayerState of said player, one could use the BeginPlay method of the PlayerState.

nova wasp
#

assuming an object is present in multiplayer that is a distinct property or object is always a bad idea

#

replication-wise at least

thin stratus
#

Iris seemingly makes this worse, as even the few order rules we had for RPCs and Properties went out of the window.

nova wasp
#

one simple thing is if you have 2 things that can show up at random times is to just have both do the same "are we both here yet?" call that can only trigger once and puts them into an initialized state and does the actualy "do stuff" code for whichever one is second

haughty ingot
#

I love how whenever someone is asking for specific help on a topic they don’t understand, it devolves into everyone talking more in depth into something the person clearly doesn’t understand big_brain

nova wasp
thin stratus
trail cave
thin stratus
#

Seems like the original issue was mainly accessing the HUD on the server and expecting it to be valid.
But yeah, I do see a lot of tutorials and such use PostLogin to notify players about a new player.
And that's not necessarily wrong, but if it requires certain other actors to exist locally, then it quickly breaks.

thin stratus
#

Or maybe my suggestion, but I can't say I posted that to actually answer the question of the poster.

haughty ingot
lyric heart
#

...

#

now it's broken lol

trail cave
#

@lyric heart Fast solution for your problem.

#

But i recommend to read docs, there're many useful info and good examples

nova wasp
# lyric heart now it's broken lol

it's kinda difficult for us to follow along with what changed here without seeing what the code is and what the result pressing play is

trail cave
lyric heart
thin stratus
#

I mean, engage is here for like 2+ years or so. And I'm pretty sure they worked on multiplayer stuff before. Confuses me sometimes when I see peeps still struggle that hard and then also fail to actually post proper information instead of "now it's broken lol".

lyric heart
#

brb

nova wasp
#

no shame in multiplayer stuff being confusing I guess

thin stratus
#

Yeah I guess. Just somewhat expected some of the basics to be there by now.

lyric heart
#

this is my first time doing multiplayer

trail cave
haughty ingot
#

I’ve seen that phenomena a lot and I just attribute it to wanting to make a game more than learn how to make a game and improve. (Not to say that’s exactly what’s happening in this situation, but in general).

That’s why it’s often more you’ll see people wanting to just have their code fixed instead of explained. (Again, not saying this scenario, Engage).

thin stratus
lyric heart
#

now all of a sudden the player isn't spawning ?

#

i have a backup but i'm hoping not to lose a days work lol

thin stratus
#

HandleStartingNewPlayer is a native event.

#

You gotta call the Parent function, otherwise you are overriding the C++ code.

trail cave
thin stratus
haughty ingot
thin stratus
#

It fully replaced this:

void AGameMode::HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer)
{
    // If players should start as spectators, leave them in the spectator state
    if (!bStartPlayersAsSpectators && !MustSpectate(NewPlayer))
    {
        // If match is in progress, start the player
        if (IsMatchInProgress() && PlayerCanRestart(NewPlayer))
        {
            RestartPlayer(NewPlayer);
        }
        // Check to see if we should start right away, avoids a one frame lag in single player games
        else if (GetMatchState() == MatchState::WaitingToStart)
        {
            // Check to see if we should start the match
            if (ReadyToStartMatch())
            {
                StartMatch();
            }
        }
    }
}
lyric heart
#

thank you

thin stratus
trail cave
nova wasp
#

calling the parent is super unintuitive in bp in general for me and I wish it was kinda more clear "hey, there COULD be a parent here but there isn't" which of course is sometimes the point but should at least be clear

thin stratus
#

E.g.

void ASomeActor::BeginPlay()
{
  // Doing something that is required inside a child BP's BeginPlay would work here, but now the Actor as a whole "hasn't begun play yet".

  Super::BeginPlay(); // This sh*t is calling the child BP's BeginPlay.

  // Doing something that is required inside a child BP's BeginPlay is too late here.
}
haughty ingot
trail cave
haughty ingot
#

@lyric heart can you take a clear screenshot of the entire extent of everything you’ve connected to the HandleStartingNewPlayer event?

lyric heart
#

atleast i don't know how to use it

haughty ingot
thin stratus
lyric heart
#

this doesn't work

thin stratus
#

@lyric heart Please start explaining what doesn't work. You will drive people away from helping you like this.

haughty ingot
#

I understand it’s frustrating, but you need to put in effort as the person asking for help, to expect others to give their time

lyric heart
#

it's not updating the huds in each player

thin stratus
#

What does TryTryAgain do anyway?

lyric heart
#

you would assume it would try try again on each one ?

haughty ingot
lyric heart
haughty ingot
#

Can you post a screenshot of it, please?

lyric heart
thin stratus
# lyric heart it works, it creates the widgets

The code in the image you shared can't be at fault. If you put a print string into TryTryAgain and it calls properly for each new player on all connected players and the new one, then it's not at fault.
Which means TryTryAgain or anything after that is at fault.

haughty ingot
#

Ok let’s, start over

thin stratus
# lyric heart

That's not enough info to help with. Which of these events are all calling and which aren't? You have a PrintString node there. Put more into it. Check if everything calls the way you want it.

trail cave
haughty ingot
#

wait no, that’s not what I meant

thin stratus
lyric heart
#

ffs all i want is cards for the players lol

#

the try try again works for when possessed

#

it shows the ones that already logged in

#

i run it on acknowledge possession

haughty ingot
#

All you want is to have everyone update their hud when a new player joins, right?

lyric heart
#

i want to remove all created cards, and create cards based on the player array

#

which trytryagain does

#

set all widgets is on the hud

dark parcel
#

That's easy. As server -> Get all player -> Get each card variable, set to null. Done

#

what ever you want to set the value, just do it in the server as replication goes from server to client.

thin stratus
#

@lyric heart The big thing here is that you have all the options to debug this instead of showing these images to us hoping we spot the issue.
You have Breakpoints and PrintStrings. If something somewhere doesn't work, then a PrintString and a Breakpoint would both indicate that.
You clearly don't know where and why it fails, so please do yourself the favor and figure that out first.
Put PrintStrings along the whole execution chain, from PostLogin or whatever you use up to where the Cards are created.
And print meaningful information with that, not just a random string. Print the Object DisplayNames, the PlayerNames, etc.
Once you have that it should show you where it stops working.

#

Because right now all you do is show us parts of your code, saying "code works" but "it's broken".
Who the hell should know how to fix that with that info?

#

My light doesn't go on. But the bulb works (haven't tested), the breaker is in (haven't checked) and the light button is functional (haven't pressed it).
Please tell me why the light doesn't work.

#

I'm gonna die in Hollow Knight a few times now. That'll be more enjoyable I guess.

lyric heart
#

they are not created yet

lyric heart
#

it's failing on the cast to hud

trail cave
thin stratus
#

Good, that's a first clue. Are you sure the HUD class is set to your BP_HUD Blueprint?

#

@lyric heart ^

lyric heart
#

-.-

thin stratus
#

If you are unsure, please print the DisplayName of the TargetHUD variable when the Cast fails.

#

It will either say the wrong name or none. None being invalid then.

lyric heart
#

its empty

trail cave
lyric heart
#

running as owning client fixes the cast fail

#

but for some reason it's still not working

thin stratus
thin stratus
lyric heart
#

if i knew the problem i'd solve it lol

#

i can't figure where its failing, it seems to run just fine

#

like it's not stopping

thin stratus
trail cave
#

and just in hud get game state and make your logic

lyric heart
thin stratus
#

You are still at the stage of figuring out the problem.

it seems to run just fine
It certainly isn't, otherwise you'd see your expected result.

lyric heart
#

-.-

trail cave
haughty ingot
#

Cedric’s just angry because he’s on his 10th death in 5 minutes hollow knight lenny_think

lyric heart
#

i've tried so much stuff lol i'm really frustrated tbh

trail cave
thin stratus
lyric heart
#

the try try works

#

the code i sent doesn't work

#

when i mean doesn't work

#

it just doesn't do what its supposed to do

#

if i knew why i wouldn't be here

#

i'd fix it myself

thin stratus
#

@lyric heart Sure, you still won't get around putting PrintStrings in and showing us the result of all of this.
"Doesn't work." "Doesn't do what it's supposed to do." is all not gonna help us helping you.

#

Cause, as you said, if it was working and doing what it's supposed to do, you wouldn't be here. (:

haughty ingot
dark parcel
#

making it almost impossible to even know what's on your end.

dark parcel
# lyric heart

This make no sense btw, why is the server passing a HUD?
Remember HUD are local to each client, server doesn't have the client's HUD, so I don't even know what you are passing there.
In any case TargetHUD will be null.

lyric heart
#

i'm wanting to update all huds when a user logs

#

when they come into the game, update all lists of widgets

#

for every player

#

i've tried several ways and it's not working

#

there is not a fixed amount widgets

#

i'm destroying and recreating based on player array

#

but it's not working

#

and yes i said (not working) becausei have no clue why

#

i have not tried onrep but i don't want this as a state i just want it to fire off when people join

#

and what would i even do ?

#

on rep what ?

dark parcel
#

Anything that needs to be sync = don't RPC it.

lyric heart
#

hmm

dark parcel
#
  1. Player enter the game -> HUD is created -> Hud gets the Card component -> Hud bind to all the delegates (e.g CardUpdated).
#

following soo far?

#

above is all local logic.

#

nothing networked.

#

you just have to make sure that the card component exist. If it live inside a player character then you need to ensure that the client already possess a character.

lyric heart
#

i mean it works fine when player enters the game

#

it loads accordingly

#

np

dark parcel
#

you are approaching the problem incorrectly

lyric heart
#

but when people login, i need it to update on all machines

dark parcel
#

the sooner you accept it the sooner you will be able to move on.

#

People update stateful things with RPC all the time

#

and say, look it work.

#

untill it doesn't.

lyric heart
#

i wonder it's the way i retry ?

#

so in a loop i do if fail, delay and retry

#

but the retry is inside the loop body

#

do you think this is fkd ?

#

i'm new to latency as well

#

something i never really had to deal with

dark parcel
#

not about latency but you are adding more complication.

#

Code can be clean with proper event triggered.

lyric heart
#

why this doesn't work is all i'm asking

#

and is this a failure ?

#

will it goto next loop value ?

dark parcel
#

OnNewPlayerJoin -> Tell the clients that a new player join.

Client receive the RPC -> It execute function to create a widget for that new player and reflect it's state.

#

Why tell client, destory and re-create everything.

lyric heart
#

even if it's wrong

dark parcel
#

What you want is just to push a new widget for every single player that join.

lyric heart
#

i just want to know why it's not working

dark parcel
#

I don't know what's not working.

lyric heart
#

and i think this loop thing is an issue

#

hmm

dark parcel
#

but I can see you are doing it incorrectly.

lyric heart
#

thanks i will try with event eventually

#

dispatcher or whatever

dark parcel
#

Yeah but that's not even networking related

lyric heart
#

it will pull the wrong value ?

#

if you delay and call an event inside the loop

#

i think i fkd that up

dark parcel
#

not sure what delay even do here.

#

Delay inside loop doesn't do anything afaik.

#

cuz the default bp macro loop runs in a single frame.

lyric heart
#

do you not understand what i'm saying ?

#

if i have a loop

#

and i have an event inside the loop

#

if i call the event inside the loop on a fail

#

to "retry"

dark parcel
#

on a fail?

lyric heart
#

of like a cast fail or something

#

a different path

#

and then i run the event again

#

to try again

dark parcel
#

I have no idea what you are saying

lyric heart
#

ok nvm

dark parcel
#

also delay does nothing here

lyric heart
#

i'm pretty sure i'm correct

dark parcel
#

no logic that you need requires delay whatsoever

#

New Player Join -> Tell clients, a new player has join, go push a widget to your HUD for this new player.

#

The new widget is but a view model that show the Cards of that player.
So that specific PlayerState-> Get the character of that player -> Get the card component -> Get the cards and display it.

#

Player Left the game -> Tell clients, hey that player have left the game, go destroy the widget that belong to that player.

tardy fossil
#

could even possibly have the playerstate just do its thing on begin play and not deal with RPCs on player join/leave

lyric heart
#

my biggest issue is reorganizing the widgets

#

but i'm working on this approach to just add a widget when logged in

lyric heart
#

I can't create a widget in the controller ?

#

Only local player controllers can be assigned to widgets

dark parcel
#

1.) PlayerState BeginPlay

#

Hud Logic

#

and the widget

#

Card container is just a widget that has a horizontal box, where whenever a new player join, a new widget (player card) get pushed in.

#

@lyric heart

#

gonna sleep, gl.

lyric heart
#

i think i figured most of it out, if i'll look at what you posted if it's not working

#

i created the widget in the player state

#

and used a multicast

dark parcel
#

I just notice there's a bug on my end

#

client have some extra values but oh well, i can't look into it now.

dark parcel
#

but I can't stop you

#

if you insist

#

you are just shooting your own foot

lyric heart
#

once i learn the dispatcher method then i'll be better of

#

but it's not a bunch of players

#

it's just a few players

dark parcel
#

doesn't matter really, you are complicating it.

lyric heart
#

i'm not worried about complication, i'm worried about performance

dark parcel
#

You are still trying to let server telling clients what to do.

#

when it's client job to create it's own widget and view the state of it's world.

#

All server need to do is set the card values, no more no less.

#

Client can handle displaying it on their own end.

dark parcel
dark parcel
#

setting the card should only be a server action

lyric heart
#

why the ++ isn't working ?

#

if i set a random y i can see it fires off multiple times

#

and i can set the value initially as well

limber gyro
lyric heart
#

i tried with + 1 it didn't work

sage lance
humble idol
# lyric heart

It's quite unorthodox to change the value of a replicated variable from a net multicast...

torn hull
#

Hey, I’m wondering what your recommendation is, since I don’t really have the experience to know what problems I’ll stumble upon later. I’ve got two different pawns for two different teams, where team members are selected at the beginning of the round. Those two characters have slightly different UI, but still share some stuff in common.

I’m in the early prototype phase, so the difference isn’t huge yet, but I’m wondering where I should create widgets in the long run. Right now I’m creating them on pawns, and I’ve got two different HUD widgets for each team member. At first I was creating them on Begin Play, but when testing with lag, clients didn’t get it without adding a delay node, and that felt kinda sketchy. So I moved it to On Possessed. Since you’re only possessed when the team is selected (not on level start or travel)

I was also thinking about creating them on the player controller, but then I’d need to switch every time based on a variable that defines what team member you are, and that feels like it could turn into spaghetti real quick.

Second idea is to create some widgets on the common parent that these team members are derived from, and only create unique widgets on the children. But then I couldn’t have one HUD widget where all the other widgets are, right? I would have to create individual widgets, or using widget switchers?

What’s your take on this when you’ve got two teams with different characters and different UI (but not completely different)?

torn hull
#

I quickly changed this creation from screen above to a parent, (like in the second idea I described), and I feel like it might be the best option. The plan is to create HUD child widgets as generic as possible, then just tweak some variables on them, like the name in this screen above, for example. I won’t completely avoid using widget switchers, but for now this still seems like the easiest idea.

thin stratus
#

OnPossessed is server-only.

#

OnControllerChanged calls for both, so there you can filter for IsLocallyControlled.

#

Pawn-specific UI you can create in the Pawn. Game-specific UI in the GameState.
Team-specific UI in, for example, a custom TeamState.

mystic estuary
#

It should be called ReceiveControllerChanged for pawns*

thin stratus
#

Yeah, can never remember the damn BP name

mystic estuary
#

Yeah, I hate the inconsistency

thin stratus
#

I would have to create individual widgets, or using widget switchers?
Not sure about the switcher, but it's probably a good idea to have one core Widget that acts as a base layer manager and then add the different widgets runtime into predefined slots and what not.

#

Depends on your game what you need.

torn hull
#

Okey, thanks. Is this a big differnece than calling on possesed from server and tnec custom event on owning client liek in my example, is this more performance friendly?

thin stratus
#

It's redundant would be one argument.

mystic estuary
#

It's just more correct, there's no reason to fire an extra RPC for something you already have

thin stratus
#

Your UI should pull the data from the other objects.

#

You don't really want to set the name on the UI like that.

mystic estuary
#

For your goal I would try to use UIExtension from Lyra. You can define extension points that can receive other widgets from anywhere in the code. It's a small encapsulated utility plugin to extend your UI in a modular way. You can pretty much copy it from sample project, and paste it directly in your game

torn hull
mystic estuary
torn hull
#

Cuz different team doesn’t have stamina but a stealth bar. I wanted to create it as generic custom progress bar in my HUD class with a canvas panel, and then just change the name for the eacch team

mystic estuary
#

How do you update the progress bar though?

torn hull
#

Im using set percent function Im calling fromm pawns where this widget is created. I made simmple function inside this widget. Screen on the left is from pawn, and on the right is function inside widget

mystic estuary
#

You rarely want your gameplay code to deal with UI. The UI should be self-contained, and pull all the data from your character, components, controllers and whatnot.

So, you would have your progress bar reading the stamina or stealth value depending on what it is. Most likely that would be two separate progress bar widgets. They might share a parent for common stuff, but they would be two different blueprints for ease for extension. One would read stamina, the other stealth value. You eventually might also want to add different visual properties to them depending on what they are, and it'll be very easy to do since they'll be already separated.

In case of UI Extension plugin, you would define an extension point where the progress bar should be, and then add the one you need depending on the team

torn hull
#

But what if it’s changed only on events? I don’t want to read this value every tick, only when needed. Then I should use an interface to trigger this event with some value as input? I don’t want to cast to my pawns on every widget to read its variable.

mystic estuary
# torn hull But what if it’s changed only on events? I don’t want to read this value every t...

Reading that on tick would be considered bad practice. You usually shouldn't cast to your pawns to read the value, because these values shouldn't be on pawns directly. Usually people create separate components to handle things modularly, even if you use it only in that pawn, it still makes sense to isolate your stamina and stealth in components to make it easier on you. This way, you would need to GetComponentByClass out of GetOwningPlayerPawn instead, and then use event dispatchers to read the values when they are changes

torn hull
#

Ok, thanks for tip, I'll try to do it. Im using components for stealth/stamina, but I didnt know about GetComponentByClass

mystic estuary
#

That should be enough to make it encapsulated. However, note that this is #umg territory 😄

torn hull
#

Yeah, that was unexpected turn xd

thin stratus
shy gust
#

Hey all, Im trying to figure out when the player controllers are reloaded in a server travel restart (as in server traveling to the level were already in to restart the scene)

If im understanding correctly, the player controllers are not unloaded in this scenario, but the Game Mode is. So if I check for all existing player controllers when the game mode loads back in after the restart, all of the playercontrollers should already be loaded by that point correct?

tame sapphire
#

If I have an Actor on the Server and the actor has a static mesh. I can currently Hide/Show that mesh for all connected players, how would I go about showing/hiding for each player individually? e.g. looping through the connected players array and showing/hiding based on a var in the player state?

#

the server owns the tile so dont think owner no see workss even more so as any player could need to 'see' the tile if dead etc. Think this is the direction i need for it to work or even achieve what i want (its a spanw tile that you should only see if your dead/dont have a valid character)

coarse cave
#

I think that's typically done w/ either RPCs or and override of IsNetRelevantFor

#

But depending on your use case, you might just do it all on the client. If the client knows which conditions a tile should be visible/hidden, you could hook those events on the client (e.g. an event when they're dead, or don't have a valid pawn) and control visibility there.

tame sapphire
#

i updated the function to a multicast but i dont think im in the right ball park currently (I also changed the valid get to is not valid) will look into IsNetRelevantFor

#

@coarse cave thank you, I think the later part works for me in this use case

#

as in the following works for each player individually so i should be able to use this

lyric heart
#

geez i figured it out mostly, just got a few more tests but i think i got it working, not the best approach but one that works.

thin stratus
shy gust
thin stratus
#

Not sure this is exposed to Blueprints.

#

Multiplayer without C++ is wishful thinking.

#

You can use that method you posted but it will call for post login too

#

There should be one for seamless travel

#

But if it's not exposed then not sure.

#

C++ 😅

shy gust
#

I mean its gotten me pretty far already but ahh, brutal. thanks for the insight tho , I appreciate it. ill experiment catThumbsUp

thin stratus
#

I know. But sooner or later you hit the wall.

shy gust
#

I dont doubt it , ive already had to jump through alot of hoops i didnt expect and make work arounds for my racing game.

lyric heart
#

Got it, thanks for the help

errant charm
#

whats the best way to replicate a timer?
need the time remaing to be read by clients as well

halcyon ore
#

replicate either the end time, or the start time, and know the length of time.

Like, if all matches last 60 minutes, you can replicate the start time.
Or, you can just replicate the end time.

Both have some end result.

shy gust
#

I have a similar question about timers,

does anyone know if there's any method to create fps independent timers?
ive read alot of mixed information and settled on using really long Timeline nodes, but ive noticed that they are inaccurate if the framerate drops.

coarse cave
#

That's why you use a start time or an end time as suggested above. You'll only run into framerate related issues if you're trying to accumulate DeltaTime

halcyon ore
#

Same reason why a timeline still has issues.
Cuz, the same thing that drivers timers, drives timelines, and everything

fossil spoke