#multiplayer

1 messages ยท Page 24 of 1

quasi tide
#

Or apparently how friggin' easy it is to prevent the end game collapse from happening ๐Ÿ˜…

thin stratus
#

Well with the new changes, cheaters can end the games a lot faster hehe

quasi tide
#

Of all games, DBD is one game where it should be quite easy to not have so much client auth stuff.

thin stratus
#

They had a lot of changes in the past years. The game was Listen Server driven oriignally iirc

#

And is only recently a DediServer game

quasi tide
#

Yeah, it was. Dedicated Server only came before I started playing though. So pre-2020-ish at least.

thin stratus
#

Killers are still in favor for most of the game I think

#

High Ping Killers are a pita

#

Cause they hit you when you are long through the window

quasi tide
#

The hitboxes...omg the hitboxes.

thin stratus
#

It's so bad that higher skilled players actually purposely check if the killer has a high ping xD

#

Cause it changes the whole play style

quasi tide
#

I'm still baffled at how seemingly, the end game collapse isn't tied to the GameMode directly. Like, how else can the clients prevent it from happening

twilit radish
#

What is the end game collapse?

thin stratus
#

It's a timer fwiw

#

If the timer hits 0, all Survivors die

twilit radish
#

How on earth should a client ever be allowed to change that.

thin stratus
#

I think the issue is that cheaters managed to just call the event for it directly

#

Skipping the timer

#

But how that exactly works, no idea

#

People can do quite a lot in DbD. Heal themselves. Take themselves off of Hooks. Stand up. Teleport, etc.

twilit radish
#

Rip.

#

With so many people you would expect them to be able to afford it to fix stuff like this. At least things like teleporting, healing etc.

#

But then again, who am I to say that lol.

kindred widget
#

Money does not buy good programming. Money just buys more people to stare at the problem scratching their head.

quasi tide
#

I feel the same dude. I'm all about co-op games over pvp games.

thin stratus
#

pvp is fine, competitive is not

twilit radish
#

Money should absolutely be able to effort a programmer who can fix stuff like healing, teleporting hacks though. I get not everything is an easy fix but that just sounds really terrible.

thin stratus
#

Basically if I can fight with some friends against each other, all is fine. If it's against randoms for some made up currency and rank, then it's not

quasi tide
#

idk if that hack is still a thing though

thin stratus
#

I remember the time where I had to change my location to Turkey to even find games

quasi tide
twilit radish
#

Honestly managing / checking state on all calls from a client is not a good time.

#

There are probably a million combinations in most games of when things are allowed and not ๐Ÿ˜…

quasi tide
#

In DBD's case, it'd be quite simple for this case. Literally just check if the number of gens completed == 5 ๐Ÿคฃ

twilit radish
#

Sure. But just in general it's not a fun time ๐Ÿ˜›

thin stratus
#

What I always wonder is how that even reaches the Server

#

But that might be me thinking the RPCs are the only way

twilit radish
#

Is it an Unreal game?

thin stratus
#

Yes

#

In theory, none of this code would ever be on the client

kindred widget
#

If you don't want to manage whether a client can do something then suck it up and eat the lag of not allowing client prediction and only ever send basic requests to the server.

thin stratus
#

Maybe some replicated timer for the UI

#

And that's about it

#

So I do wonder how a Client can even get the Server to execute an Event that theoretically doesn't exist on the Client, and even if it does it wouldn't affect the server state

#

It must literally run on the Server

twilit radish
#

Maybe something that interacts with the timer on the server can be triggered from the client? Never played the game so idk.

quasi tide
#

It's an incredibly simple game, gameplay loop wise.

#

Max of 5 people in a match. So it's not like they're hurtin' for performance.

#

No real AI in the game either (other than one killer's zombies, which gets like 2 of 'em)

#

The only client-auth thing I can think of, that would make sense imo, is the QTE's in the game. And that's just for simplicity sake. @thin stratus

#

Probably a PITA to make that server-auth

unborn nimbus
#

I have two actors in the same area that are not relevant to each other using rep graph but they can still collide, certainly this should not be the case right?

thin stratus
#

I mean, relevancy should not stop the actor from existing on the server

#

Which is the one that handles the collision

unborn nimbus
#

ah yea that makes sense

latent heart
#

Relevancy is more about clients and servers, not the authoritative server itself.

manic trellis
#

hi there,
I am doing RepNotify, but it giving the error.
I am attaching the picture of code that causing error and also the error.
thanks in advance.

latent heart
#
  1. Close the errors list and use the output log.
fathom aspen
latent heart
#
  1. Don't screenshot errors, copy + paste.
#
  1. That's a missing function you need to provide an implementation of in your class. SEe that link ^
manic trellis
#

thanks for the information this helps me a lot to resolve the issue.

halcyon totem
#

does post login work for dedicated servers? My code isnt working on my dedicated server for my post login

echo geode
#

How to properly setup a timer in Multiplayer game? I want to show the remaning timer as widget for the clients.

twin juniper
#

Alright I successfully made it and can say that it does sends you an invite directly to Steam hence you don't need to handle it ingame.

echo geode
dapper obsidian
#

For anyone having trouble with building the Gamelift server SDK using VS22:

  • use GrepWin to replace vc141 with vc143 and 2017 with 2022 in all the files;
  • if it complains about a missing OpenSSL header, manually copy the openssl folder over from your UE5's ThirdParty\OpenSSL\1.1.1k\include\Win64\VS2015\ folder;
  • if it complains about the SIO Client include dir and library file not being set, put the paths in the CMakeLists.txt directly (taking care to replace \ with /).
dusty mural
#

Hi All, I am wondering if it is possible to write a UE5 multiplayer server using Golang to serve levels and chunks to the players? If so, does anyone know of any examples that might be available some were. Thanks in advance.

thin stratus
#

I assume you can do whatever you want, but I doubt there is an example on this.

#

Most users who would share this info are using UE servers

dusty mural
#

@thin stratus Yea, you are probably right and I am investigating the UE servers as well. Just wanted to see what might be out there and available. Thanks

gilded vapor
#

I'm not sure on the specific downsides aside from increasing the amount of data the server/listen-server will need to consume.

I also just posted a fix for RootMotion on the reddit post if that's relevant for your game

gleaming kite
fathom aspen
#

From this channel pins

devout dagger
#

Hello, I have a another question, I have varaible inside my pawn and I want it to change when I press a button and that the server and all the clients know about the change , as I understand I can not change the variable from the client, what is the best way to do it then? .

harsh ice
#

I am spawning project title

#

It's only working on cliet or server.

#

Not working for both at same time.

fathom aspen
harsh ice
#

What is RPC ?

fathom aspen
#

Remote Procedure Call

harsh ice
#

Ahh do you know anything about my problem?.

fathom aspen
#

A function that can be executed in a remote callspace

fathom aspen
harsh ice
#

I have this currently.

fathom aspen
#

There is a tool (a button really) called print screen

fathom aspen
# harsh ice

You have a client RPC that calls a server RPC. That smells bad

#

If you're already on server then do your thing

harsh ice
#

Project title is spawning but only on server or client at once

fathom aspen
#

Why the ping pong

#

So you want it replicated

#

If I'm intuiting you right

harsh ice
#

Yeah and i made 2 custom events. Run on owing client and server

fathom aspen
#

Yeah I can already see that and it hurts me

harsh ice
#

Is it bad ?

fathom aspen
#

Spawn it server-side and make sure it's replicated

#

That's pretty much the workflow of replicating dynamic actors at a very basic level

#

I've seen somewhere that if you put them in struct and replicate the struct then they do

#

Yeah pretty sure they don't

#

GAS doc says they do which made me lose my mind a while ago lol

harsh ice
#

How do I know i am using tmap ?

fathom aspen
#

Yeah literally nothing related if that's what's worrying you

harsh ice
#

It will work on a normal map ?

#

I was just testing

harsh ice
#

Because rpc to server is not working

fathom aspen
#

Have you read the networking compendium?

harsh ice
#

Yeah that's why i am asking here

#

I test only client or server works at a time

#

Both are not working together. I don't understand this.

fathom aspen
#

At this point what I intuited is that he wants to spawn this projectile to all connections, i.e. replicate it

#

But there seems to be a language barrier here

harsh ice
#

I did

devout dagger
harsh ice
#

is this not correct ?

#

In both client

#

Replicated actor

#

I want all clients to see this projectile

fathom aspen
fathom aspen
#

Server RPC that changes the replicated property in question

fathom aspen
# harsh ice

Then on SVR_spawn call the SpawnActor function

#

No need for the client RPC at all

#

And this ^

harsh ice
#

Ahh i understand

oak prawn
#

While the server owner gets on the vehicle, the customer cannot get on the vehicle. How can I solve it?

fathom aspen
#

Yes because u are using GetPlayerController(0)

dark edge
#

Input is local only. input won't happen serverside for your pawn

#

You'll want to do

Input -> Run on Server Event -> Do the Thing

#

In your case
Input -> ServerPossessCar -> Server handles the possession call

devout dagger
dark edge
#

Self if this is in the PlayerController, Self.Controller if it's in a pawn

fathom aspen
#

Found in this channel pins

halcyon totem
#

is using a switch has autortiry node in the game mode blue print bad practice

#

I am having an issue where things spawn correct if I host a game but not if its a dedicated server

fathom aspen
fathom aspen
dark edge
#

gamemode always has authority so that switch is doing nothing

halcyon totem
#

I made a video

plucky prawn
fathom aspen
#

I will make sure to like and subscribe

dark edge
halcyon totem
#

for some reason its not spawning it on the platform

#

on a dedicated server

#

what would cause it?

dark edge
#

how do you live like this lol

fathom aspen
#

๐Ÿ kek

halcyon totem
#

thats what everyone says to me...

dark edge
#

If you don't know, all the function paramters exist as variables in scope

#

you can just use get FUNCTIONPARAMTER and it's a little variable node

#

no need to spaghet all over

fathom aspen
#

So 100% not if it was somebody else's

dark edge
#

use the parameter variables and make it nice and neat

halcyon totem
#

but what could cause it to not work on the dedicated server?

dark edge
#

We can't tell wtf is going on, maybe you'll find a pin you didnt connect when you clean this up

fathom aspen
#

Pretty sure there's that node

dark edge
#

Make it look nice and clean like this

fathom aspen
#

Adriel I'm giving you a ๐Ÿช

dark edge
#

Also IDK if you're aware or not but there's functions in GameMode you can override like ChoosePawnClass and ChooseStartLocation etc

#

idk if i got the names right but there's a bunch

#

you're basically recreating them

fathom aspen
sonic flame
#

oh yeah

#

sorry ab that

harsh ice
#

It's working now. But Static mesh is not showing

plucky prawn
#

Adriel going off is the highlight of my day so far

solar swallow
#

Hi, what would be the proper approach for sending player inputs to the server? For example, when the player presses a button, the shoot function gets called. In the shoot function, it checks if theres any actor in the way, and if there is, damage is done to that actor. What do I need to add to the shoot function so the actual shoot logic runs server side and the results get sent back to the player?

fathom aspen
#
  1. RPC to server (server RPC) - That's pretty much the only way to pass data from client to server
#
  1. Now from server to client you have either:
    a) client RPC
    b) property replication
#

To know which to use read this:

#

From this channel pins which I highly suggest

solar swallow
#

ok thank you, I'll check it out

thin stratus
#

If I simulate Ping in the Editor, with Outgoing MinMax = 5000 (totally overdoing it on purpose), my Net Clock shows a RTT of roughly 5000ms and a Latency of 2500ms.
That's fair. Now if I send an RPC to the Server to Start a Cooldown, and I also start the Cooldown locally at the same time, when the Cooldown of the Server comes to the Client (let's assume I replicate it somehow), shouldn't it be RTT off?
So if I reduce the Cooldown on the Server by RTT, shouldn't it, when replicating to the Client, match the Client's predicted cooldown more or less exactly? (Given the Ping is totally fixed and not going higher or lower)

twin juniper
#

How can i detect in an OnRep if the replication comes from the actor being relevant/created (for late joiner) ? I actually want to handle my onrep logic only in those case

#

I'm thinking about "COND_InitialOnly" but i don't know if the late joiner gets the initial bunch when creating the actor instance on their own

chrome bay
#

GetWorld()->TimeSince(CreationTime) == 0.f

#

May not work for map-placed actors though

twin juniper
#

Oh i know why lol

chrome bay
#

That doesn't look like an initial only property?

twin juniper
#

forgot to mark the property dirty

twin juniper
chrome bay
#

Properties should always be flagged as dirty on their first channel open

twin juniper
#

do you know if late joiner simulated proxies gets the initial bunch ?

#

even if the owner has the actor created since a few mins ?

chrome bay
#

yeah they would

#

But in the state it's currently in

twin juniper
#

so COND_InitialOnly and checking if OwnerRole is simulated in OnRep ?

chrome bay
#

Could do but that has to assume that OwnerRole has been applied by the time that OnRep is called, which hopefully it would be

twin juniper
#

cause i have some race condition where owner has not yet replicated and bIsEquipped has

chrome bay
#

yeah figures

twin juniper
#

Does commenting this line do it ?

chrome bay
#

Comment it out in [/Script/OnlineSubsystemUtils.IpNetDriver]

#

yeah

twin juniper
#

Alright got the confirmation that Repgraph is breaking my weapons ๐Ÿ˜„

thin stratus
#

Hm, when calculating RTT via ServerRPC -> ClientRPC, does it make sense to send the latest RTT with the ServerRPC to also have the number on the Server?

#

Cause I can't really get the number, or does UE have the RTT or RTT/2 somewhere accessible for me?

thin stratus
#

Round Trip Time

eternal lake
thin stratus
#

Yeah

#

I send it now to the Server when syncing so that's fine I guess

livid sluice
#

I'm having this weird Issue. When jumping the camera seems to sort of snap to the jump location. It works fine however inside the editor and when running the build locally. When I add it to a dedicated server however I get this issue. Presumably because of ping. But other items such as eating are played without delay.
Points to note: Standard unreal jumping mechanic and animation
Replicate movement is turned on.
If anyone can point me in the right direction it would be really helpful.

eternal lake
# thin stratus Yeah

If you have a straightforward back and forth over the server I'd just calculate the difference in world/instance time on the server

#

I would imagine you might be able to find the client's ping somewhere if that's of any use

eternal lake
livid sluice
#

No when played standalone its perfectly fine as well.

eternal lake
livid sluice
#

The area in red is just to detect vaulting.

livid sluice
eternal lake
livid sluice
#

yea can try. Will need to re-build to replicate the issue however.

livid sluice
#

When deployed locally the issue is non existent either.

#

Which leads me to believe that the issue is latency related. But everything else works quite fine.

eternal lake
#

What is moving around like in the deployed client?

livid sluice
#

Perfectly smooth.

#

Jumping seems to be the only thing affected.

#

my jumping I mean camera movement

#

because, while looking at the person jumping through another character, the jumping seemed perfectly fine.

#

Since jumping is the only action which causes a jerk reaction my assumption was the sudden movement causes the camera to lag behind and snap into place when it catches up.

#

however I have no idea on how to test this theory or how to fix it.
I am currently trying your suggestion though. it's building as we speak.

elder rivet
#

Hi everyone

Iโ€™m having problems with migrating a large level map with many items into my current Lyra project.

What do you think is the best solution?

Or is there any better ways?

Iโ€™m a little bit of a beginner with stuff so any help or advice would go a long way ๐Ÿ™‚

fathom aspen
#

This has nothing to do with multiplayer. You might want to check #ue5-general

fathom aspen
elder rivet
fathom aspen
#

Lyra == multiplayer ?

#

I must have missed the news

twilit radish
#

Lyra is fully multiplayer compatible lol. You can even setup your own EOS integration if you want.

fathom aspen
#

I know that ofc. But their question has nothing to do with multiplayer

#

And they insist that it does because it has the word Lyra in it

twilit radish
#

Ah alright.

#

Vori's net clock doesn't work in standalone mode I just realised. The betrayal D:

#

Oh wait nevermind it does.

fathom aspen
#

But I wanted him to appear before court ๐Ÿ˜”

twilit radish
#

Lol.

#

Wtf? A SetTimer method doesn't have to be a UFUNCTION?

#

My life is a lie.

#

I was looking at his clock and was like "Why is the request internal not a UFUNCTION?" ๐Ÿ˜†

latent heart
#

Things only have to be ufunctions when exposing to bp or using with dynamic delegates.

fathom aspen
#

Yeah it doesn't ๐Ÿ™‚

latent heart
#

Or other random UPROPERTY stuff like the hide condition stuff

twilit radish
#

I'll be busy removing UFUNCTIONS the next days ๐Ÿคฃ

fathom aspen
#

IIRC also the input binding functions don't have to be either, but I could be wrong

twilit radish
#

๐Ÿ˜ฆ

fathom aspen
#

Disprove me

twilit radish
#

That's effort.

#

I really hate this scenario, I have a timestamp for a countdown. But I don't want to put it in a RPC because people need to get that variable if they decide to join mid way through. But it's so ugly to put it in a DOREPLIFETIME :/

fathom aspen
#

Better be ugly than it breaking bigger_brain

#

Still it won't be synced that easy if it was replicated right? It has been ages since I read that vori post

twilit radish
#

Hm?

fathom aspen
#

Yeah he's pretty much firing RPCs

#

Ping-ponging

twilit radish
#

What won't be synced?

fathom aspen
#

I'm saying if you go the for the built-in network clock and just depend on a replicated timestamp you won't get accurate results on different clients

#

Even in editor I couldn't get them to be accurate

twilit radish
#

Oh no, I'm using Vori's clock and a timestamp that then adjusts based on that.

fathom aspen
#

Ah ok lol

#

But you don't need your timestamp to be replicated, right?

#

I mean it's updated by a client RPC

#

At least that's how I see it

#

I'm wondering though does he fire RPCs on intervals? Because then that doesn't make sense to me

#

Yeah he does so every second

twilit radish
#

Vori's clock fires RPC every so often to get a dynamic average, my timestamp is replicated so that if you join midway through it's still there.

fathom aspen
#

I mean seems like an expensive task ehh

twilit radish
#

A RPC every 1-5 seconds or whatever really is nothing though.

#

And for the benefit of not having a dumb network clock totally worth the small amount of bandwidth imo.

twilit radish
#

I'm aware. But it's the best I can do.

#

Waiting for Unreal to replicate it's weird timestamp is just as bad lol.

#

And in the end it's the server that calls possess on the pawn, so eh.. Whatever ๐Ÿ˜„

fathom aspen
#

There was a PR, but you know how it ended

buoyant oasis
#

I'm making a scoreboard and need it to regenerate it when a player joins or leaves but I'm struggling where exactly I should call a delegate to trigger that. At first I had placed it in AddPlayerState of the GS, but it would be called before the player states were replicated to all the clients. Just wondering where I should call that delegate from.

quasi tide
#

There's an event that happens when a player joins/leaves. Seems like a good candidate

#

Inside the GameMode

buoyant oasis
#

There is OnPostLogin but that shares the same issue with the player states not being replicated yet

chrome bay
#

AddPlayerState and RemovePlayerState is where I do it from

#

AddPlayerState and RemovePlayerState are called client-side from the newly replicated (or destroyed) PS actor, so it has to be there.

buoyant oasis
#

Okay, I'll have to look into it a bit more, good to know that I was at least on the right track.

chrome bay
#
{
    Super::AddPlayerState(PlayerState);

    if (UHT_WorldEventManager* WEM = UHT_WorldEventManager::Get(this))
    {
        WEM->NotifyPlayerArrayUpdated(this);
    }
}

void AHT_GameState::RemovePlayerState(APlayerState* PlayerState)
{
    Super::RemovePlayerState(PlayerState);

    if (UHT_WorldEventManager* WEM = UHT_WorldEventManager::Get(this))
    {
        WEM->NotifyPlayerArrayUpdated(this);
    }
}

void UHT_WorldEventManager::NotifyPlayerArrayUpdated(AGameStateBase* InGS)
{
    check(IsValid(InGS));
    checkSlow(InGS->GetWorld() == GetWorld());

    ConditionalBroadcastNetworkReady();
    OnPlayerArrayUpdate.Broadcast(InGS, InGS->PlayerArray);
}```

That's my code for it anyway.
pallid mesa
#

late joiners will sync their clock in postnetinit @twilit radish

#

their value will become more accurate over-time

#

๐Ÿ˜„

distant turret
#

Is Playfab of microsoft same as AWS?

twilit radish
#

No, they are different companies and don't offer the exact same functionality or pricing.

twilit radish
pallid mesa
#

the timestamp on where ur countdown started u say

#

ah yes ๐Ÿ˜„

pseudo gull
#

can someone help me on the following issue? iยดm replicating my avatars on my project on the pawn begin play, using two custom events one for the server (run on server /reliable) and another for the clients (multicast). But when a player joins late, it doesnยดt see the correct avatar from the rest of the players. The rest of the players see the correct avatar on the incoming player

fathom aspen
#

Also check this channel pins for other cool stuff

pseudo gull
#

will do! thanks!

ocean vessel
#

Hi! Am I able to become a listen server at any point or only when I'm opening a level (with ?Listen argument)?

pseudo gull
dark edge
#

Just start as listen server

halcyon totem
#

does a switch has autority node inside of a rep notify varible make any sense, is it ok to do this or does the rep notify take care of all that

dark edge
#

wait

#

you might still need the switch for your mechanic. Repnotify fires EVERYWHERE (in bp), when the variable updates

#

if you wanna know if you're on server or not you'll want the switch

latent heart
#

It isn't fired, by default, in c++.

#

So if you're not calling it manually on the server in c++, it makes no sense to use it.

#

If you're using BP, ignore my words.

dark edge
latent heart
#

Tbh, I think it kinda makes sense.

#

It's bad, but it makes sense.

ocean vessel
# dark edge Just start as listen server

So If I want to Let people join only at some point(not from the start), I open a level as a listen server and when I want others to join I create a session or what?

latent heart
#

If the listen server is running, people can join whenever. Whether it's discoverable is another question.

dark edge
#

Game is a listen server on startup

clear island
#

how can I make a chaos vehicle client authoritative? is there any setting similar to CMC's "bServerAcceptClientAuthoritativePosition" ?

solar swallow
#

I've got a server RPC set up for whenever the player presses the enter key. The issue is when I go to do a line trace to check for an object, the camera's up/down rotation is not checked on server side. How would I replicate this?

#

this is the line trace from the server's point of view. On client side, it was looking up and down

#

Setting the camera component to replicate doesn't seem to do anything

#

And the UsePawnControlRotation option is ticked on the camera

ember dagger
#

I had an issue before with camera rotation and replication with my aim offsets. Not sure how you're handling the line traces, but you could calculate the camera rotation locally and send that information to a server rpc and set a variable on the server. Don't set the variable as replicated. If you're adding controller yaw and pitch locally for your camera, the server won't know that. But you can use the get control rotation to get camera rotation. That replicates only client to server if I remember

#

Control rotation won't replicate client to client however so if you need that you'll need to set a variable locally -> server rpc -> multicast -> set variable for clients.

solar swallow
ember dagger
#

Hmmm I havent spent time with c++ so I can't honestly say from looking at it. At least with blueprints I mean passing variable to server rpc -> set variable on server rpc. The reason I said don't set to replicate for the variable is because i believe that's more expensive. But I honestly don't know for sure. I'm also starting out with it.

halcyon totem
#

if a client joins a dedicated server is it locally controlled?

latent heart
#

What?

pallid mesa
#

who, the client? yes

latent heart
#

The server still, generally, has authority over it, but the client will control its own input.

digital blaze
#

Hey I tried making a multiplayer game about 1 year ago, and streamed 50 hours, I thought about putting a guide together, has there been any new development in multiplayer (i haven't touched ue5)

#

i went along the steam network approach

echo geode
#

Correct me if can do better with widget creation for all players in multiplayer game:

First that I use GameState has array of Player States which we have a reference for each player in the world. So I take a reference via player state object and from the player controller. And thus creating the widget from the RPC which is "Runs only client(Client Only)" to reflect it is own HUD(which is locally controlled) from player state

fathom aspen
#

Yes that's a good approach.

fathom aspen
digital blaze
#

did ue5 change much for mutliplayer, i see the docs have been totally updated

#

they still look very unintuitive however ~

#

actually i'm getting ptsd reading the official docs

fathom aspen
#

If you mean the multiplayer related ones then I might be dreaming

#

Going to ask someone to pinch me, brb

#

Banter aside, they didn't even update their docs. They even have a popup warning that says that at the footer of the page.

#

Unless you are talking about EOS stuff then that's something totally different. And they are two channels next

solar swallow
#

When the server possesses an actor, the actor's movement gets replicated normally for all clients. But when a client possesses the same actor, it doesn't get replicated to other clients or the server. I'm running the possession on a server RPC. GetController()->Possess(Actor); What could I do to get the actor to replicate to everyone. The actor already has replication and replicate movement enabled

digital blaze
short arrow
#

does "net load on client" not load the actor for late joining clients?

dim trail
#

has anyone here built an activation queue for multiplayer abilities/cooldowns?

gleaming kite
#

Do rep notifies run on the server in BP?

short arrow
gleaming kite
#

thank you

faint eagle
#

how do I prevent some actors, placed in editor and visible in world outliner, from spawning on clients? to be specific I'm talking about ARecastNavMesh. AFAIK there's this bNetLoadOnClient property on AActor, but this one is inaccessible on ARecastNavMesh in editor for some reason ๐Ÿค”
inb4 recast navmeshes are autodestroyed on clients anyway - yeah I'm aware of that, but we have a strange bug where sometimes recast actor's NavRenderingComponent holds a reference to the world in its Outer property and doesn't let the GC to finalize something which causes client crashes

thin stratus
#

The netloadonclient thing would probably only work if the actor is replicated or?

#

And the only thing it prevents is that it doesn't load from disc. It would then be replicated down with the newest info

#

Not sure if the boolean has an affect without replication

dim trail
#

would the timer ever end on the server before the client though?

elder sable
#

Hi, any ideas why the beacons are not working in the editor ?

CreateNamedNetDriver failed to create driver from definition BeaconNetDriver
It's working in standalone

bitter oriole
elder sable
#

Mhh it's weird, the game net driver is working, will keep searching

queen pine
#

Would anyone know any causes of clients disconnecting while using any RPC's?
This only happens in standalone (not in the editor). I've tested this in steam advanced sessions, both online and steam LAN, as well as local LAN without steam. All tests have the same result
Basically, I've noticed that when the client sprints, crouches, or interacts with anything using an RPC, they disconnect and rejoin the default map.
I'm using blueprints and I've looked around quite a bit without much success as to what can cause my specific issue.

#

-I'm also interested in any debugging strategies i can use that can help. Also, I find it very tedious to wait for someone to help me test multiplayer with steam. I feel like i could be using a virtual machine to do this, however, my CPU doesn't support this fully, so it'd have to be a remote vm.

chrome bay
#

First port of call would be to look at the logs and see why they're being disconnected. Sounds like the Server is kicking them to me

queen pine
#

Would you know of any better way to test multiplayer without using 2 pcs?

chrome bay
#

Check you aren't overflowing the reliable RPC buffer somehow

#

There is no other way if you're using Steam

elder sable
#

A VM

queen pine
elder sable
#

Yep

queen pine
#

Virtual box?

elder sable
#

You just need 2 accounts

#

i'm using vmware workstation player

elder sable
#
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

I added this in DefaultEngine.ini, but it seems to be ignored

#

Ok i found

void nest
#

Hello. I'm trying to replicate a massive amount of instances (static meshes) over the network. Now I can't really let the server do all the spawning / instance creating. I also really can't replicate the transforms because there are just too many. I've tried with only 3000 and already it takes ages for the client to get that data. So sending the actual data is not an option for my usecase sadly. So I'm trying to find a way to use random seeds. The thing is I don't need the instances to be replicated. I just need them to appear on the same location on all clients, that's it. So a random seed would seem perfect for this. Problem is, I can't get it to work. The seed produces always the same result on the server. But on the client it's always different. How can I get the same results on the client as on the server?

worn wagon
void nest
#

Well currently I'm just using seed 0

#

on both client and server, but that doesn't work

#

shouldn't that work?

worn wagon
#

What function do you put the seed into, it should produce the same results on both independently

void nest
#

The seed is fed into a function which does a huge loop to generate transforms

#

The function fires on client and server

worn wagon
#

And when you say it's always different on the client, is it always the same different result on the client for the same seed or it's always a different result?

void nest
#

Lemme double check that

#

Results on the client seem to be always different

#

while results on server are always the same

worn wagon
#

Well that's what you should be exploring first, I can't tell without seeing your code but you want to get it to be deterministic.

mortal kernel
#

does a bool array set to repnotify replicate if a boolstate inside of his array changes?

void nest
#

I wonder, does load priority of things influence the results of randomisation with seeds? Like could it be that because of replication not being always in a similar order be the problem?

solar swallow
dapper obsidian
#

During testing, does it matter what GameLift region you upload your builds to? My default region is eu-west-3 but aws gamelift upload-build aborts with
Could not connect to the endpoint URL: "https://gamelift.eu-west-3.amazonaws.com/"
and I'm wondering if it's okay to try to upload it to another region.

void nest
worn wagon
#

Yeah stream uses SRand

#

Can you show how you initialise the stream?

void nest
#

I kinda don't atm. It's just a hardcoded number for now. Is that an issue?

#

It was set to 0, changed it to 100, but still the same issue

worn wagon
void nest
#

Hmm I never set or change the stream. It's always just a hardcoded number. o_O

worn wagon
#

I don't have much to go on ๐Ÿ˜„

void nest
#

This is the function that generates the transforms and in goes the stream

#

which is just a public variable with a default value set to 100

worn wagon
#

You might be calling the frotator/float from stream function more times on the client or something, everytime you calls those it mutates the seed

#

you'll only get the same results if you call it the same number of times

#

when you init the seed you get the same sequence of values everytime

#

but if you called it more times on the client it will get out of sync

void nest
#

There are multiple planets that all call this function. Could that be the cause? Like that on client it's never the same planet replication sequence or something?

worn wagon
#

Could be, like I said it's hard to tell when I only get a tiny window into your code

#

But that's something you could check

void nest
#

ill try removing all other planets and see if it works with just one

worn wagon
#

Make sure the stream isn't being replicated too, that would cause the issues you described

void nest
#

Yup, that was it. it's fixed now

#

Ok so yeah it's most likely the planet replication order

worn wagon
#

Ah good ๐Ÿ˜„

void nest
#

Thanks for thinking along ๐Ÿ™‚

worn wagon
#

np glad you fixed it

void nest
#

Would setting a custom seed for each planet solve this issue you think?

#

Because I wonder, does the seed mutate only when the initial value is the same? Or does it also mutate when other seeds are used?

#

I could centralize this code in a singular actor though and just wait for all planets to load on the client and then fire the instance generation code once

#

Yeah I'll do that

worn wagon
#

Yeah try it

#

The seed mutates every time you're calling those functions to generate floats/rotators, this is the cpp code and what's actually going on

void nest
#

Ah yeah makes sense, so basically each time the seed is used it mutates

worn wagon
void nest
#

Centralizing it will then be the best way to solve this I think as I can than guarantee that the seeds are only used once in a very particularly defined order

worn wagon
#

That means it's important to call the frotators/floats in the same order too, since the frotator function will mutated the seed 3 times as opposed to the float doing it once

#

If you're running the same code it shouldn't be an issue though

#

Actually maybe it doesn't matter xD

#

You found the problem anyway

void nest
#

Yeah, problem is though that there isn't really a way to define the order in which planets are replicated from the server to the client. And because each planet does it's own generation (each calls this function internally) I therefor have no control over which planet calls the function first and in what order they are called from the other planets.

#

Unless there is, but I'm not aware of xD

worn wagon
#

You need to eliminate the replication order issue

#

Actually you want a different seed I imagine

void nest
#

Yup, I'll just make a planet object spawner that waits clientside and server side until all planets are loaded to then spawn all objects in one go on all planets

worn wagon
#

otherwise they'll all spawn in the same spot

void nest
#

Alright I know what to do ๐Ÿ˜„

#

Thanks again!

worn wagon
#

Np! gl

fathom aspen
fathom aspen
split siren
#

I have a float Points on server and I want to replicate it to client as if it was int32, meaning if the value changes from 0.1 to 0.8, it would still remain floored to 0. But if it changes from 0.8 to 1.1, it should replicate 1.1f to client.
I know it's a bit weird, but the value will be changing a lot by small increments, and those are not necessary to replicate.

short arrow
fathom aspen
#

You will have to make your own pretty sure

#

But it's pretty much to copy what they do for FVectors as they are basically 3 floats

clear island
#

just wondering if there's already some setting I'm missing or if its something that has to be custom made

split siren
worn wagon
# clear island anyone knows anything about this? ^

Never used chaos vehicles, only thing I know of with normal physics simulations is the bReplicatePhysicsToAutonomousProxy field which determins whether a physics simulation is server/client authoritative for primitive components.

oak prawn
#

When he dies he has to switch to the other player but stays on his own camera.

clear island
desert oar
#

Hello guys hope someone can help me with this, it seems so simple yet i cant figure out why this does not work. This is on my gamemode bp and i call it from a widget and it does not work for the client. Im sure im missing something, i have tried replicating the event on server but still not working (maybe because i need to compile?)

oak prawn
fathom aspen
#

At this point your mission is to find the networking compendium in this channel pins and read it a few times

daring gorge
#

hey guys, quick question
im trynna make is like a 1v1 2d game, i want the player to face the cursor, i was able to do this by getting cursor position using controller and finding the look at rotation for it and setting players z as the result z, although i am unable to replicate it t the clients, and when a client joins it doesnt really follow the cursor as it should?

#

any idea why this is happening? or how i should make it work

twin juniper
#

Why do delegate declarations still giving me unknown specifier error even tho I included "Interfaces/OnlineSessionInterface.h"?

latent heart
#

Copy+paste code and exacty errors.

twin juniper
#
error C3646: 'FOnReadFriendsListCompleteDelegate': unknown override specifier
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
#

FOnReadFriendsListComplete FOnReadFriendsListCompleteDelegate;

latent heart
#

Hopefully that is enlightening!

twin juniper
#

Yes it's a type that is already included in #include "Interfaces/OnlineFriendsInterface.h"

#

oh shit

#

I do have #include "Interfaces/OnlineSessionInterface.h" only

#

thank you xd

latent heart
#

Np

elder sable
#

Is it possible to use create session and find session in PIE with the null subsystem ?

zinc acorn
#

so not entirely a multiplayer question but kindof a multiplayer question but is there a way to load into a level with a different gamemode than what is assigned in the world settings?

zinc acorn
#

nvm i think i have found it by googling some more

elder sable
# worn wagon Yes

Anything special to do ? I'm launching 2 clients as standalone from the PIE, i create a session, the the 2nd client can't find it

worn wagon
#

SessionSettings.bIsLANMatch = true;

elder sable
#

I'm in LAN aswell

worn wagon
#

Same things for finding
SessionSearch->bIsLanQuery = true;

elder sable
#

Yep, got the same

worn wagon
#
DefaultPlatformService=NULL```
elder sable
#

It's working only if i start the session from a standalone game (not in PIE)

worn wagon
#

Got that in DefaultEngine.ini?

#

oh

elder sable
#

I have steam, but it fallback to the null subsystem

worn wagon
#

Oh PIE doesn't technically work, since the other instances automatically travel with the host by default

#

So I was wrong about that

elder sable
#

Ok so i have to start a session from a standalone game ?

worn wagon
#

Yeah

elder sable
#

Ok thanks !

worn wagon
#

You can make it easy with a .bat file "Path_to_epicgames\Epic Games\UE_5.0\Engine\Binaries\Win64\UnrealEditor.exe" "path_to_.uproject" -game -ResX=800 -ResY=800 -log

twin juniper
#

When BeginPlay is fired, all replicated properties are sure to be replicated at this time ?

silent valley
twin juniper
silent valley
#

As far as I've seen, yes.

twin juniper
#

bIsEquipped should be on true for simulated at this time

elder sable
#

Mh i have a beacon server and client in PIE, i got no errors but the OnConnected is not called on the client, any ideas ?

silent valley
twin juniper
silent valley
#

Ok i don't know anything about that code you sent ๐Ÿ˜†

twin juniper
#

I tried a few things since, using an OnRep_IsEquipped, but in some case owner has not yet replicated so i can't attach the weapon to the owner

#

Also tried OnRep_Owner BUT in some case bIsEquipped has not yet replicated and i can't check that the weapon is currently equipped

#

So i need a place where everything is replicated, BeginPlay should do it

silent valley
#

Oh I see well in this case you probably need to try the setup in OnRep for Equipped and Owner

twin juniper
#

Nah it's not fixing anything as i said above

#

there is still a few cases where one of both has replicated in the "wrong" order

silent valley
#

You can put them in a struct then, the structure will be replicated as a whole

twin juniper
#

My BeginPlay is only called one time, when weapon is added to inventory (when removed from inventory it spawns an APickup, so a different actor)

twin juniper
#

I can't put the Owner pointer in a struct it's literally smth build in the engine

silent valley
#

Oh wait you also need the owner actor to be replicated. This kind of dependency is hard to handle.

twin juniper
#

Well if you want to attach your weapon you generally need the owner yeah ๐Ÿคทโ€โ™‚๏ธ

#

that was kind of obvious tbh ๐Ÿ˜„

silent valley
#

Trying to remember how I setup our weapons...

twin juniper
#

I've been struggling with weapons race replication for over a year now

#

i'm just so tired of that ๐Ÿ˜ซ

silent valley
#

Ideally the simulated proxy should not need to access the owner

twin juniper
#

Then again how you want them to attach the weapon to the owner ?

#

I'm sure there's a place where everything has replicated so i can't play with all these things without issues.

silent valley
#

I don't think you can ever guarantee that, due to relevancy etc either actor may disappear at any point

solar swallow
#

Hey guys, over the last few days I've been trying to get a strong understanding of multiplayer. Would I be correct with the following procedure for handling a client shooting a weapon? In the parentheses, I've included stuff I'm not sure about.

  1. Shoot key is pressed
  2. Using a server RPC, the server does a line trace to check for other players
  3. If there is a player in the line trace, you call a take damage function on that player. (The take damage function does not need to be an rpc)
  4. The take damage function gets called on the hit actor. This function will just decrease the health variable (What is the difference between setting the health variable to replicated vs RepNotify)
  5. In the original server RPC, after calling the damage function, the ammo count variable is decreased. The variable is set to replicated so the client version knows how much ammo it has
  6. The result is the client only tells the server it pressed the shoot key. The server handles all the shooting logic and updates the replicated variables to the clients. This way, it is not possible to cheat
plucky prawn
#

As for cheating, it wouldnt go so far to say it's not possible. It's pretty much always possible but you are removing the authority from the player to tell the server "trust me bro, I can do damage to this actor"

hexed nest
#

same thing happens if If I play with a server and 1 client

#

I see the logs on both screens

#

My guess is this happens because I'm testing all this locally on one PC? So all the clients are sharing the same Unreal engine instance, and so they all see the logs?

latent heart
#

In the options there a checkbox for doing all multiplayer clients under 1 process.

#

Turn it off.

hexed nest
#

thank you that fixed it! I actually did try toggling that on previously, but was super confused when the Unreal engine loading screen showed up loll and just closed the whole thing

pale obsidian
latent heart
#

I would recommend never running under a single process because it isn't a good simulation of a real client/server environment.

#

I imagine it's slower and uses more resources, though.

pale obsidian
#

Definitely, but I'd rather make sure the client-server interactions are working

latent heart
#

Indeed!

tacit bough
#

My general logic might be flawed. Here's my problem:
I'm working with PlayerController::GetInputKeyTimeDown() to check how long a button has been held down by a player. This works fine on the server, but since the player controller doesn't exist on clients, the call fails there.

Is there another way to keep track of how long a button has been held down on a client via e.g., the PlayerState?

#

I've gotten around this issue like so:

but it really smells I think hah...

#

NVM! got it all working now, although I had to do this...

sinful tree
# tacit bough NVM! got it all working now, although I had to do this...

Your logic shouldn't be working in such a way that clients would need to know about the input of another player. The client performing this action would need to RPC to server and then the server replicates what happens to the clients.
"Get Input Key Time Down" is likely only client-side too, so it wouldn't be something that the server itself would know about for each client.

The solution to this would be to have a server RPC triggered when the desired input key is pressed and save the time on the server, and when they key is released you send another RPC and calculate on the server based on the saved time how long the input was held.

Also, it's really bad to check those options in the CMC - they effectively allow your client to tell the server where they are located - in other words, those with know-how will be able to teleport anywhere in the game.

#

They're good for short bursts of movement where you may want to avoid the server correcting, but shouldn't ever be just left on.

ancient moth
#

Hi ! I have made a little level to test my cat character, and I made the mistake to put a "simple" ball replicated to player with it, with physic simulation... Now I'm at 4 hours of conferences and "hey I did it, but I won't show you how" videos about client prediction... What I did...

Anyway... Even in editor, without any lag, the ball is shaking a little, in particular when the client push the ball in continue. Someone have an idea about way it looks so awful ? I disabled physics sim on client, removed gravity, disabled all collisions... So I don't really understand what could cause this thing. At least a confirmation that this is due to client updates from the server and not a wrong setting on the client ?

https://www.youtube.com/watch?v=fMDT-XbZE04

thin stratus
#

I feel like I'm either encountering something "normal" that never occurred to me or a bug:

I have a Replicated Array of <FSomeStruct>. That Struct has 2 Properties that are actively marked as NotReplicated.
The Local Client can add to the Array (and in specific cases also remove from the Array), but the Server is the one (usually) to remove from the Array.
That has to do with predicting something locally and that works fine.

The problem comes up when the Server removes an Entry from the Array. In the OnRep it seems like the properties are sort of mixing up.
If I have an entry with 50 for one of the NotReplicated properties and another with 60, and the one with 50 is removed, then the OnRep suddenly has the replicated properties of the 60 entry (correctly) mixed with the NotReplicated ones from the 50 entry.

Or in other words, the 60 becomes a 50 for no reason.

[0] Some.Replicated.Tag.A | 50
[1] Some.Replicated.Tag.B | 60

When [0] is removed, the Server has:

[0] Some.Replicated.Tag.B | 60

as expected, but the Client has:

[0] Some.Replicated.Tag.B | 50

Like how does that mix up? Is it because the Array, when receiving the updates and running NetSerialize, only overrides the properties of Index [0] that are replicated and the NotReplicated ones are just kept?

I mean, that would make sense, but also really annoying :D

marble gazelle
#

as the default replication doesn't know you removed / moved an element, and thus it will just replace the data from the server at Index N with the replicated values, but won't move anything (pure assumption, but it would make sens)

thin stratus
marble gazelle
thin stratus
#

Yeah, minus the NotReplicated ones

#

Which is the issue I guess

#

But I can't mark the replicated cause the Data is different (on purpose)

marble gazelle
#

eh no

#

it doesn't do move operations, so the values are likely to just be overwritten with the new data, and only the replicated data I think

thin stratus
#
UPROPERTY(Transient, BlueprintReadOnly, ReplicatedUsing="OnRep_AbilityCooldowns")
TArray<FAbilityCooldown> AbilityCooldowns;

USTRUCT(BlueprintType)
struct FAbilityCooldown
{
    GENERATED_BODY()

    virtual bool operator==(const FAbilityCooldown& Other) const
    {
        return this->CooldownTag == Other.CooldownTag;
    }

    friend uint32 GetTypeHash(const FAbilityCooldown& In)
    {
        return GetTypeHash(In.CooldownTag);
    }

    float GetTimeRemaining(float CurrentTime) const
    {
        return FMath::Max(Timestamp + Duration - CurrentTime, 0.f);
    }
    
    UPROPERTY(BlueprintReadOnly, Transient)
    FGameplayTag CooldownTag;

    UPROPERTY(BlueprintReadOnly, Transient)
    bool bServerApproved;

    UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
    float Timestamp;

    UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
    float Duration;
};
#

Timestamp and Duration are the issue

marble gazelle
#

yeah, I got that.
As said, I think the issue is, that the array replication das 1:1 "copies" of the replicated data, but doesn't clean already allocated entries

thin stratus
#

I can fix this in the OnRep I guess, because I have the old state

#

Yeah

#

It basically inserts part of the struct

marble gazelle
#

well it copies what get's replicated and ignores the rest, as it doesn't have any data

thin stratus
#

It removes the [1]for the Client and inserts the changed data into [0], minus the 2 nonreplicated ones

chrome bay
#

Hmm if it's not replicated, client shouldn't be touching those values when it receives from server, very odd.

#

"NotReplicated" should effectively be invisible to net stuff

#

I can see it being a problem if you defined a NetSerialize tho

thin stratus
#

I did not

chrome bay
#

Is the issue actually caused by reordering elements on the client?

thin stratus
#

Sort of. It happens only if it shrinks

#

I think

chrome bay
#

Yeah that sounds right then - it doesn't strictly care about element order, it just says "this is the data for element 2"

#

whatever is there will get that info

#

fast array addresses elements via a fixed ID so it's sort of impervious to that

thin stratus
#

[0] Cooldown.Ability.A | Timestamp: 500 | Duration: 3
[1] Cooldown.Ability.B | Timestamp: 700 | Duration: 8

Becomes

[0] Cooldown.Ability.B | Timestamp: 500 | Duration: 3

in the client when the Server removes Entry [0]

chrome bay
#

yeah, that makes sense to me

marble gazelle
#

yep. as we described

thin stratus
#

Yeah it does to me too, but I need that to not happen haha

chrome bay
#

client resizes the array, then dumps data into element 0

thin stratus
#

Preferably without having to split this into more than one array

#

I have the old array in the OnRep, I guess I can check the values for the remaining entry and override

marble gazelle
#

I think fast array would fix that, or write a simple custom replication, that replicates "remove element0" and not "copy into 0"

thin stratus
#

Not really nice though

chrome bay
#

yeah "fast" array would probably fix that, since elements are identified by ID instead

thin stratus
#

Is FastArrayReplication slower for small Arrays? (similar to TMap vs TArray)

short arrow
#

If you guys were going to make an MMO type party system, (something like WoW where you can see your party members health bar and stamina next to your screen) where would you put the server sided logic?

chrome bay
#

Seems to depend, it has a constant overhead by writing the size,num deleted + num changed with every send

#

Plus the element ID itself is int32

short arrow
#

Playerstate, Gamestate, Or Controller? ๐Ÿค”

short arrow
marble gazelle
thin stratus
#

In other words, I usually make new State actors for this

chrome bay
#

but each element in this case is going to have at least 1 index property (int32), two property headers (2x uint16) - so it might not be that measurable in practice

thin stratus
#

They can be listed in the GameState if you need it

#

And they have a list of Players via PlayerStates

#

And some additional data such as who is the leader etc.

short arrow
#

I was thinking both yeah

thin stratus
#

You can override the IsNetRelevantFor to handle replicating it only to the Party Members too

short arrow
#

you make an actor to keep track of the party?

thin stratus
#

Yop

chrome bay
#

maybe you could save some more by writing a netserialize, compressing the "duration" to a float 16 ๐Ÿ˜„

thin stratus
#

I do that usually for Teams

marble gazelle
thin stratus
#

When you say Custom Replication, what does that even entail

#

Just NetSerialize stuff?

short arrow
#

interesting, v interesting

marble gazelle
chrome bay
#

yeah I'd go fast array, turn off the per-element delta serialize, and use NetSerialize and squeeze it down to a 32-bit float for timestamp and 16-bit float for duration. Each element is then 32 for ID, + 48 for data.

thin stratus
#

But I mean the Timestamp and Duration shouldn't replicate at all

#

Maybe Duration in the future I guess

#

But for now they are only meant to be part of the Struct for organization reasons

chrome bay
#

Oh it's a tag and cool - oh hell yeah, could make it utterly tiny then

#

tag index + a bit for bool

thin stratus
#

Yeah, right now I'm mostly wanting to fix the bug itself, before I optimize stuff

#

I will start with turning it into FastArray. Haven't done that yet, so yeaha for doing something new

chrome bay
#

yeah I think FA kills two birds with one stone. Problem is you have no way to identify the elements uniquely

#

Delta serialization on arrays... what would possibly go wrong ๐Ÿ˜„

thin stratus
#

I mean I do have the Previous Array in the OnRep

#

Which I can always check for the two values if needed

#

It's just not pretty

chrome bay
#

Also, would be interesting to see if this is impevious to packet loss and/or replication arriving out-of-order (which always happens for arrays)

thin stratus
#

FA gives me a per Entry callback or?

#

Google it is

marble gazelle
#

you get a post replicate general callback and a per element one

chrome bay
#

yeah

marble gazelle
#

you can just look at the source code, has a nice example for setting it up

thin stratus
#

Is the PerElement one also for Adding/Removing

#

Or only for changes?

marble gazelle
#

3

#

it has 3 cbs

chrome bay
#

There is at least one issue with the per-entry callbacks, in that they don't fire when UObject properties get mapped (but the array callback does). Not an issue in this case tho

#

Just a "fun" gotcha

#

Which messed with my inventory system for ages -.-

marble gazelle
thin stratus
#

Asking mainly due to currently having to figure out what the F actually changed so I don't notify everything about every entry every time

chrome bay
#

yeah callbacks are add/change/remove

#

per element

thin stratus
#

Cool

marble gazelle
#

just be aware, that order on server and client can be different, if you change smth on the client. the elements will be mapped properly, but the order may be different

chrome bay
#

yeah that too

#

Doesn't seem like that would be a huge issue here?

#

Also you do have the timestamp already, could probably sort elements by timestamp maybe to keep order consistent?

#

Or even by element ID

thin stratus
#

I don't need sorting

#

The system is basically a partially predicted cooldown with server auth

#

Client can add to locally instantly put the Ability on cooldown for x seconds with timestamp y.

#

CooldownCondition on the client is "Is that Tag in the Cooldown Array?"

#

Server then later also applies the cooldown, which only replicates the Tag back, so nothing should change. (the boolean is a different story, but not so important here).

#

The Server then checks on tick if the CD (on its end) ran out and removes the element.

#

I do modify the actual CooldownDuration on the Server by RTT so it lines up with what the Client expects.

#

The bug with the data not being "kept", basically causes, visually, to have the remaining of the two cooldowns (if two are active) to just show "0.0", cause it takes over the Duration and Timestamp of the one that ran out

#

It doesn't affect gameplay, but shows the predicted time wrong, as the Tag gets "Mapped" to the wrong Duration adn Timestamp if the array shrinks

#

So no, I don't care about order at all

#

Most important is:

  • The Tag is in the Array
  • The Duration and Timestamp remaining untouched for the Client, as the Values differ for Server and Client
#

I will, in the future, change how Duration works, because we could have abilities that have their cooldown lowered, and not sure if that is always predictable.

#

And the Server has a different Duration value than the client so I have to split that in the future.

#

But one step after another

chrome bay
#

In a sense the fast array method of identifying items with a "key" is basically how GAS prediction works anyway

#

And is what allows clients to predictively do things and tell server "i did a thing", and get the result back

thin stratus
#

Yeah it sounds like a better approach

#

I didn't use it cause I thought it's the same logic as when to use Map vs Array

#

There will never be more than maybe 5 entries in that array

#
USTRUCT(BlueprintType)
struct FAbilityCooldownEntry : public FFastArraySerializerItem
{
    GENERATED_BODY()

    UPROPERTY(BlueprintReadOnly, Transient)
    FGameplayTag CooldownTag;

    UPROPERTY(BlueprintReadOnly, Transient)
    bool bServerApproved;

    UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
    float Timestamp;

    UPROPERTY(BlueprintReadOnly, Transient, NotReplicated)
    float Duration;
};

USTRUCT()
struct FAbilityCooldownArray : public FFastArraySerializer
{
    GENERATED_BODY()

    UPROPERTY()
    TArray<FAbilityCooldownEntry> Items;

    bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParams)
    {
        return FastArrayDeltaSerialize<FAbilityCooldownEntry>(Items, DeltaParams, *this);
    }
};

template<>
struct TStructOpsTypeTraits<FAbilityCooldownArray> : public TStructOpsTypeTraitsBase2<FAbilityCooldownArray>
{
    enum
    {
        WithNetDeltaSerializer = true;
    };
};
#

Does that look correct for the start?

#

Website tutorial I found seems to be a bit dated

chrome bay
#

yeah that's about the size of it ๐Ÿ˜„ - just a case of doing stuff like marking the FAbilityCooldownArray as dirty etc. when adding/removing elements

thin stratus
#

Yeah I read about it

chrome bay
#

I usually just have the array be private and add accessors to avoid forgetting about it

thin stratus
#

The callbacks are part of the Item, right?

chrome bay
#

you can do both

#

Surprisingly the fast array serializer header documents it pretty well

#

worth a look

thin stratus
#

Ah, I'm not used to documentation from epic

chrome bay
#

IKR ๐Ÿ˜„

#

are you in 5.0 or 4?

#

in 5.0 they moved it into it's own header I think, and also made some fixes

thin stratus
#

5

chrome bay
#

cool

thin stratus
#

4 is for noobs

#

Na jokes aside, yeah found it

#

I assume the "Order of Lists not being identical" is just a matter of handling it via some order int fwiw

#

If I ever need that

#

Or some context driven order

#

Like timestamp as you said

chrome bay
#

yeah basically elements are identified by ID, it doesn't care about the order when replicating

#

Server + Clients maintain their own ID->Index map

thin stratus
#

Ah the website I found basically just had an outdated copy paste of the header comments

chrome bay
#

haha

thin stratus
#

:D:D

#

How to get clicks

#

/** Step 6 and beyond:

  •    -Declare a UPROPERTY of your FExampleArray (step 2) type.
    
  •    -You MUST call MarkItemDirty on the FExampleArray when you change an item in the array. You pass in a reference to the item you dirtied. 
    
  •        See FFastArraySerializer::MarkItemDirty.
    
  •    -You MUST call MarkArrayDirty on the FExampleArray if you remove something from the array.
    
  •    -In your classes GetLifetimeReplicatedProps, use DOREPLIFETIME(YourClass, YourArrayStructPropertyName);
    
  •    You can provide the following functions in your structure (step 1) to get notifies before add/deletes/removes:
    
  •        -void PreReplicatedRemove(const FFastArraySerializer& Serializer)
    
  •        -void PostReplicatedAdd(const FFastArraySerializer& Serializer)
    
  •        -void PostReplicatedChange(const FFastArraySerializer& Serializer)
    
  •        -void PostReplicatedReceive(const FFastArraySerializer::FPostReplicatedReceiveParameters& Parameters)
    
  •    Thats it!
    

*/

#

So

#

-You MUST call MarkArrayDirty on the FExampleArray if you remove something from the array.
I assume I also have to pass in the removed entry into that?

chrome bay
#

negative - just remove it, then call MarkArrayDirty()

#

It goes through and rebuilds the ID->Element info and figures out what has been removed next time it replicates

thin stratus
#

You can provide the following functions in your structure (step 1) to get notifies before add/deletes/removes:
Only one of them has Pre in the name, yet the comment says "before add/deletes/removes"

#

(also remove and delete is the same or not hehe)

chrome bay
#

Ah no, you get "Pre" remove, and "Post" add/change

thin stratus
#

What is "Receive"?

#

As in, what is the usecase of it

chrome bay
#

Ah that's called on any change IIRC

#

Sort of like an internal/extra OnRep

thin stratus
#

Right and the FFastArraySerializer has some sort of way to get a hold of the class instance that the struct lives in?

chrome bay
#

But it also fires when GUID's are mapped too, I think the params tell you whether it was a genuine "received from server" or just GUID's being mapped

thin stratus
#

So I can actually make use of the callbacks

chrome bay
#

It doesn't - but it can only be a member property (can't be embedded in other structs etc) - so it can be common to just store the owner inside

#

GAS does that a lot

thin stratus
#

So my item just needs the owner

#

Ah I see, it would have it if we use PUSH MODEL

#
FFastArraySerializer()
        : IDCounter(0)
        , ArrayReplicationKey(0)
#if WITH_PUSH_MODEL
        , OwningObject(nullptr)
        , RepIndex(INDEX_NONE)
#endif // WITH_PUSH_MODEL
        , CachedNumItems(INDEX_NONE)
        , CachedNumItemsToConsiderForWriting(INDEX_NONE)
        , DeltaFlags(EFastArraySerializerDeltaFlags::None)
    {
        SetDeltaSerializationEnabled(true);
#

OwningObject hmmmm

chrome bay
#

Hah, interesting. Yeah I've never used that, I just make my own property

thin stratus
#

Probably better yeah

#

Random programmer "Let's turn off PushModel"

#

Thanks!

chrome bay
#

It's pretty cool tbh, gives a lot of control

#

Becomes one of those things you start using way too often ๐Ÿ˜„

thin stratus
#

Yeah I just always put it away under "Whenever I have to do an Inventory in Multipalyer."

#

Which I never got to

#

Clients always want funky movement features from me. Send help

chrome bay
#

boi do I have the plugin 4 u

#

Not that anyone will buy it when I launch it because inventory is one of the more fun parts of dev

thin stratus
#

Why is it, that the more hardcore Multiplayer programmers consider shit like this fun?

#

Like, why do we love touching Inventories and Movement

chrome bay
#

literally no idea

#

sucks ass when it doesn't work

#

But super satisfying when it does

thin stratus
#

Can I just do whacky BP shit please, for gods sake. Whoever reads this: Never become good a Multiplayer and C++ and offer your skills to others. Run!

#

So you are making a plugin for Inventory stuff?

#

I always feel like the Marketplace would probably mostly provide โ‚ฌ$ for Editor shit

#

Based on the amount of Editor Mods I had to write for people

chrome bay
#

Yeah, it started out for the hover tank game then realised I could quite easily adapt it to handle a lot of different styles pretty efficiently. The actual inventory portion is ready, just I have to make some example projects now and I really cbaaaaa

thin stratus
#

I usually run into situations with stuff like this where it becomes increasingly difficult to allow users to just plug and play things if they could be reaaally different for every project

chrome bay
#

Yeah I 'm hoping I struck a good balance with this one

#

definitely never going to have the "be all and end all" system

thin stratus
#

Yeah

#

I already notice that with the simple BP shit I made couple of years ago

harsh ice
#

I am working on a fpp multiplayer game.

#

I spawn weapons and attach them to fps arms. But it's visible

#

And i have to show weapons in third person

twin juniper
#

I have the same setup as ShooterGame for the weapons equip functions and attaching

chrome bay
#

Todd Howard Voice - It just worksTM

twin juniper
#

I tried like 10000 ways to avoid race replication issues for late joiners

#

but yeah i can't figure out how to do it properly

chrome bay
#

We're doing nothing different to what ShooterGame provides AFAIK

twin juniper
chrome bay
#

It does

twin juniper
#

i know that HLL yes since i played it recently

#

but yeah i'm kinda lost now ๐Ÿ˜„

thin stratus
#

Isn't it enough to have a State in the Weapon that OnReps?

#

That's usually how I handle that

chrome bay
#
{
    SetCurrentWeapon(CurrentWeapon, LastWeapon);
}

void AShooterCharacter::SetCurrentWeapon(AShooterWeapon* NewWeapon, AShooterWeapon* LastWeapon)
{
    AShooterWeapon* LocalLastWeapon = nullptr;
    if (LastWeapon != nullptr)
    {
        LocalLastWeapon = LastWeapon;
    }
    else if (NewWeapon != CurrentWeapon)
    {
        LocalLastWeapon = CurrentWeapon;
    }

    if (LocalLastWeapon)
    {
        LocalLastWeapon->OnUnEquip();

    if( NewWeapon )
    {
            NewWeapon->SetOwningPawn(this);
        NewWeapon->OnEquip(LastWeapon);
    }
}```
twin juniper
#

i don't have states in my weapon

thin stratus
#

Then in the Character fwiw

twin juniper
#

at least not like ShooterGame

#

i have bIsEquipping, bIsEquipped, bIsReloading as states tho

#

but not like shooter game

chrome bay
#

Actual HLL code above, minus some stuff

#

Works totes fine

twin juniper
#

I tried a few things since, using an OnRep_IsEquipped, but in some case owner has not yet replicated so i can't attach the weapon to the owner
Also tried OnRep_Owner BUT in some case bIsEquipped has not yet replicated and i can't check that the weapon is currently equipped

chrome bay
#

We don't predict weapon equips - because fuck that headache

thin stratus
#

The Owner is the thing you need to OnRep

thin stratus
#

either directly or via a Struct that has some more info

twin juniper
chrome bay
#

There's a key part here btw:

// Make sure weapon's MyPawn is pointing back to us. During replication, we can't guarantee APawn::CurrentWeapon will rep after AWeapon::MyPawn!
NewWeapon->SetOwningPawn(this);
thin stratus
#

RaceCondition between Properties -> STRUCT

chrome bay
#

Yeah that's not identical - see above

twin juniper
thin stratus
#

Why not

twin juniper
#

GivenTo does the same

chrome bay
#

You're not doing it in the OnRep

twin juniper
#

But yeah it does not avoid what i said above

chrome bay
#

You also have no garauntee what order properties vs RPC's will arrive in

thin stratus
#
struct FWeaponEquipState
{
  APawn* OwningPawn;
  bool bIsEquipped:
}

void AWeapon::OnRep_WeaponEquipState()
{
  if (WeaponEquipState.bIsEquipped && IsValid(WeaponEquipState.OwningPawn))
  {
    // Attach
  }
}
twin juniper
#

I need the two to be replicated when i do my stuff

thin stratus
#

+- USTRUCT/UPROPERTY etc.

chrome bay
#

We don't replicate the equipped state independently

#

The problem you have is two independant actors deciding whether something is or isn't equipped

chrome bay
#

You need to determine it from one actor/source only

thin stratus
#

Yeah, again I usually have an Struct with the required data in my Weapon

chrome bay
#

In our case the pawn is what decides - since only one weapon can be equipped at once and it avoids race issues between weapons

thin stratus
#

When I equip the Actor, I tell it who it is equipped to and that it is indeed equipped

#

If the Pawn doesn't exist yet but the boolean is true, you get a non resolvable netID the first time the OnRep calls

twin juniper
#

also

thin stratus
#

Once the Actor exists it will call the OnRep again usually

twin juniper
#

since CurrentWeapon does have an OnRep and then call Equip inside

chrome bay
#

If you look at ShootertGame btw - you'll notice "IsEquipped" is not replicated by the weapon

thin stratus
#

With the pointer being valid

twin juniper
#

late joiners should also have it

#

but Owner is also not yet replicated when they get that

chrome bay
#

That's why we call SetOwner() manually

twin juniper
#

I may need to convert my GivenTo to simulated proxies

#

actually i imported it from UT4 to avoid race replication but for owning client

#

i also searched to see how UT4 was avoiding race replication

chrome bay
#

So you've got UT4, Lyra and ShooterGame all mixed in :D?

twin juniper
#

and yeah it's kinda crap

chrome bay
#

That's a fresh sort of hell

twin juniper
thin stratus
#

idk, this seems rather straight forward to solve if you simply handle the state yourself?

#

And even if you use two different OnReps, you can still call a TryEquip function

#

Which checks both values

chrome bay
#

You essentially have redundancy atm - too many properties being used to replicate the same state info.

twin juniper
chrome bay
#

Weapon is replicating it's equipped state, clients are being told via RPC to "equip", and the pawn replicates it's current weapon too

twin juniper
#

i replicated bIsEquipped to see if it would fix the race replication with owner

chrome bay
#

That can all be boiled down to one prop which defines all state

twin juniper
#

but it's worse tbh

chrome bay
#

IMO - what is and isn't "equipped" is a pawn-level property, as in it determines what is/isn't equipped.

#

It also avoids weapons fighting with each other over whether they are/aren't equipped or not

thin stratus
#

Yeah if you can only have one at a time, then the Character makes more sense

#

Which would also make it even easier with a simple OnRep_Weapon

chrome bay
#

If you don't want to set the owner client-side the way we do, you can follow the same path Cedric said and call a "TryEquip" both when the owner is received, and when the currentweapon is received. Then you check both properties

#

yeah

twin juniper
#

i just need to ditch bIsEquipped tbh

chrome bay
#

yeah, it shouldn't be replicated at least

#

The fewer points of contention you have between properties the better

chrome bay
#

It's creating an extra race condition

twin juniper
#

ClientGivenTo set the owner on it's end

chrome bay
#

Yah but that's also not going to work

timid moat
#

Hi!

chrome bay
#

You don't even need that RPC, the Owner is already a replicated property

#

And the RPC is also going to be fighting with the various states

timid moat
#

Do you know if there is a simple of example of a local multiplayer game done with Unreal 5 and C++?

#

Thanks!

chrome bay
#

And if that RPC is changing persistent state, it's a bad RPC

twin juniper
chrome bay
#

ClientGivenTo is setting the owner - it's bad straight away

#

Owner is a replicated property, there's no need to RPC it

#

And the RPC will have it's own inherent race condition

twin juniper
#

ah you meant for GivenTo

chrome bay
#

ye - get rid of that

twin juniper
chrome bay
#

Client can already figure out what it's been "given to" when it receives OnRep_Owner()

twin juniper
#

like when spawning and giving weapons

chrome bay
#

Any RPC that changes state = bad

#

Especially if that RPC is also changing an already replicated property

#

It's just another race condition waiting to happen 1/99 times

twin juniper
#

So i should just ditch GivenTo and use OnRep_Owner to make my given to logic ?

chrome bay
#

definitely

twin juniper
#

but it will just fuck all of my weapon logic ๐Ÿ˜„

chrome bay
#

This is also how shootergame handles it btw

#
{
    if (MyPawn)
    {
        OnEnterInventory(MyPawn);
    }
    else
    {
        OnLeaveInventory();
    }
}```
twin juniper
#

ClientGivenTo also handle the "if it's your first weapon tells the quickbar to active it and equip it"

#

If i do that in OnRep_Owner it will do that for everyyyyyyy clients, every weapons

chrome bay
#

You have another race condition right there btw

twin juniper
chrome bay
#

"IsLocallyControlled"

twin juniper
#

not the owner itself

twin juniper
chrome bay
#

No garauntee the pawn will be able to determine if it's locally controlled when it receives that RPC

#

What if pawn/controller relationship hasn't replicated yet?

twin juniper
#

Yeah true i might already have this issue ๐Ÿ˜„

chrome bay
#

basically, and i mean this nicely - this is all wrong ๐Ÿ˜„

twin juniper
chrome bay
#

You need 2 properties to do all of this - and one of them already exists (owner)

#

Also Lyra's inventory can suck a fart IMO

twin juniper
#

yeah i'll try the shooter game way then

twin juniper
#

also not lyra quickbar ๐Ÿ˜„

chrome bay
#

This is all very confusing ๐Ÿ˜„

twin juniper
#

That's stuffs from my old project, i merged to lyra to benefits Experiences (gamemodes mainly that's the only thing i had not)

twin juniper
#

But yeah it might be confusing, i might replace "Lyra" next time i share code to not confuse people

chrome bay
#
{
    CheckEquip()
}

void Character::OnRep_CurrWeapon()
{
    for (AllWeapons)
    {
        Weapon->CheckEquip();
    }
}

void Weapon::CheckEquip()
{
    bool bShouldEquip = GetOwner() && GetOwner()->Weapon == this;
    if (bShouldEquip != bIsEquipped)
    {
        // Blah
    }
}```
#

There's a simple psuedo-code setup

#

Using the simplest logic I can think of

twin juniper
#

yeah but Equip also needs to happen on Server

#

That's why the current way i do it (like shooter game) is good

chrome bay
#

It will - the server sets the CurrentWeapon property and thus calls the CheckEquip() also if required

twin juniper
#

but with like 4-5 RPC ๐Ÿ˜น

#

but i might try your way, it seems already more reliable than UT4

chrome bay
#

Probably because UT4 also does predicted weapon equipping which is a fresh hell in itself

#

HLL/ShooterGame etc. has latency when changing weapons - but I'd rather that tbh

bitter oriole
#

What the actual f

twin juniper
#

but it's the cost

#

Fortnite also has latency for weapon switching on high ping

chrome bay
#

I'm 99.9% sure UT does what it does anyway - but UT does some mad stuff for that 120Hz..

#

Yeah honestly predicting weapon switch is utter chaos

#

Would rather suffer the lag and tell people to download more RAM

bitter oriole
#

"Tech support hello, yes, did you try moving to a country with fiber"

twin juniper
#

But UT4 is old af, i'm wondering how it would looks like in 2022.. with GAS ๐Ÿ™„

chrome bay
#

Well UT4 is also unlike most other stuff Epic releases, in that's it's very tuned to make a specific game.

#

I mean even the bots aren't using any of the engines AI tooling really, it's all custom and likely copy-pasta from past UT games

twin juniper
#

Yeah but seeing the code they could simplified like 60% of the game with GAS ๐Ÿคทโ€โ™‚๏ธ

chrome bay
#

Yeah GAS wasn't really around then though, or at least was very unproven

#

UT4 predates Paragon IIRC

#

Which is when GAS got it's first trial by fire

bitter oriole
#

UT4 is very old stuff by now, yes

twin juniper
chrome bay
#

Also, since it was the fourth game - they probably didn't need an ability system ๐Ÿ˜„ Safer to just copy-paste from the previous 3 games

twin juniper
#

and they switched over Fortnite later

bitter oriole
#

I'd play UT with abilities tbh

chrome bay
#

that would be cool

twin juniper
#

Splitgate ?

chrome bay
#

Also obligatory "bring back paragon" TM

bitter oriole
#

I would still not play Paragon though

chrome bay
#

Aww I liked it ๐Ÿ˜„

twin juniper
#

was it a mess with marketing ?

#

or with the game as a whole

chrome bay
#

No direction + fortnite raking in cash

twin juniper
chrome bay
#

Paragon wasn't that financially successful IIRC

bitter oriole
#
  • competing against mf DotA
twin juniper
#

or you mean development cost

chrome bay
#

Yeah and also competing with so many well-established games

twin juniper
#

yeah i remember that it was the BR hype back in this time

#

PUBG, H1Z1 etc

chrome bay
#

Just never took-off the way Epic expected I think, and they kept changing really fundamental things that made it hard to keep up

#

Sort of lost focus towards the end

bitter oriole
#

I think the formula simply wasn't attractive enough in the face of entrenched, well supported competitors that run on potatoes

chrome bay
#

yeah

#

Blew me away visually though first time I played

bitter oriole
#

The visuals were seriously dope, yeah

chrome bay
#

Was like the good old days of playing a new Gears game on X360

#

they did whaaaaat?

#

anway.. back to work ๐Ÿ˜„

thin stratus
#

@chrome bay Do local changes trigger the callbacks?

#

Or do I just call them locally by hand?

chrome bay
#

yah no callbacks for local change

short arrow
#

so I tried digging into the cpp myself but couldn't figure it out with my limited knowledge. PlayerID is a replicated property that can be found in the playerstate.

It randomly assigns a value to players that is always unique. I'm wondering if anyone knows the limit to this PlayerID ? I would like party members in my game to know who's in their party based on an array of playerid's but I want that array to be a byte and not an int.

thin stratus
#

tbh, I would not use that ID

#

I would use the UniqueNetId

#

Which is provided by whatever Subsystem you use

#

Which should be truly unique per Player Account

short arrow
#

this party won't be persisting, once you log dc you're out. And we will be using steams but I'm pretty sure it's like 20 chars long

#

my goal is to keep the replication cost as low as I can get it

thin stratus
#

As far as I can tell from the code, PlayerId is limited to int32 - 256 as it only starts at 256 @short arrow

#
int32 AGameSession::GetNextPlayerID()
{
    // Start at 256, because 255 is special (means all team for some UT Emote stuff)
    static int32 NextPlayerID = 256;
    return NextPlayerID++;
}
#

Lovely to have UT stuff in UE...

short arrow
#

so I should be able to pass the value as a byte with no issues then?

thin stratus
#

A byte is not int32

#

And since it starts at 256, I would say no

short arrow
#

right but I can convert it, int32 - 256 means 0 - 256?

#

oh

#

that's weird

#

my player ID's are usually between 100 - 200

thin stratus
#

You lose the initial 0-255

#

hmm

short arrow
#

oh wait a second

#

mayb not kek

#

that's super lame

#

thanks for confirming it for me!

thin stratus
#

No worries

split siren
upbeat basin
thin stratus
#

Join Server and Joining Session are two different things

#

You can join either without joining the other

#

But usually, one joins the Session and then the Server

#

That does mean that one needs to leave the Server and leave the Session

#

So in fact, destroying the Session is somewhat needed. Now I don't know if Epic does this in Lyra somewhere outside the Leave Game Flow (e.g. in the MainMenu GameMode or so)

#

Now I think the Server registers players with the session

#

And also unregisters them