#multiplayer

1 messages ยท Page 677 of 1

neon mango
#

True

#

That is wiser, think shooter game does that too if I remember correctly

winged badger
#

only reason that GetPC[0] is spreading like a plague is those damn epic community managers making tutorials

#

and generally it works well enough for the scope of that tutorial

#

it does not work well enough for production

versed ocean
#

Can you do that from blueprints Zlo? the GetFirstLocalPlayerController()?

#

I was making my game shit itself today with what you guys are talking about using this index based method.. heh

neon mango
versed ocean
#

yeah, but I was curious about this other method of GetFirstLocalPlayerController, I dont see the option from blueprints, is it cpp only?

dark edge
#

That will all depend on your prediction system or lack thereof, and your general design. Not everybody sees the same thing at all times, so you need to choose who to favor, the caster, the target, a 3rd party observer, or the server.

#

Unless you throw prediction out the window, no 2 clients will agree on the timing of everything. You need to figure out who's story to believe.

eternal canyon
#

๐Ÿ˜‚

boreal wadi
#

Working on a data driven multiplayer character selection system. Right now only testing on LAN. I have a listen server and everything works as expected. Meaning the data is loaded correctly from the asset manager, it fills my character selection screen with the necessary buttons for the characters and I can click a button and hop into the lobby. However with the client for some odd reason my buttons aren't being created and when debugging I get some weird results. IDK what the issue could be. The asset manager on the client is loading all available data and calling the delegate function (where I'm debugging) All the code runs smoothly with expected values except when creating my buttons and setting them up. Any help is appreciated. Here is the debug log . Ignore the error I accidentally set a variable to watch that doesnt exist

finite goblet
#

does COND_InitialOnly removes the object from replication computation once its replicated?

keen thorn
#

Hi, got a simple question but can't seem to figure it out. So right now I'm using "Open <ip address>" to join a server, which works fine. But there can be a situation that the server will not be up yet, is there a way to keep retrying to join the server? i.e how can I get return from "open" that it has succeeded or failed so I can retry? Thanks in advance guys

#

another question is when I use ServerTravel, clients seem to travel with parameters from server not with what it was joined with. i.e if on a client i executed "Open 127.0.0.1?playerRole=ground". This will work fine, but once the game ends and the server calls ServerTravel the client will lose "?playerRole=ground" (when I check the -log)

woeful pebble
twin juniper
woeful pebble
keen thorn
#

thanks @woeful pebble

sage isle
#

Got a question about replicating player stats, for things like hunger and thirst is it really necessary because the other players would never need access to that info. I have seen some people say its about making sure people cant change the values on their client and cheat but then how do you go about protecting against that? Is it enough to just make sure that the value is only ever being changed on the server and not on the client itself?

chrome bay
#

You can change values on the client anyway so replicating it makes no real difference to cheating

#

The reason to replicate a property is so that the client knows about the true value of stat. If only they need to know, you can mark it replicated only to them.

#

Cheating happens when servers don't verify information clients send to them

#

For example, you tell the server you are sprinting, but the server doesn't check your stamina for e.g. and just sprints anyway

sage isle
#

Ohhh yeah I made a sprint system and have it on the server but if the server isnt aware of the stamina level it could mess things up

chrome bay
#

Right

#

and if the client doesn't know what their stamina is, they might keep trying to sprint anyway

#

But since the client can send anything it wants to a server with a cheating tool, you have to treat all incoming packets the same way

#

Never do anything just because the client wants to

#

Always verify it

sage isle
#

that makes sense, a few things i found online were worried about cheating but I wasnt getting where that came from
but yeah that makes sense

chrome bay
#

clients can do whatever the heck they want to their local instance of the game, but the key is to make sure that if they try cheating, it only happens on their end, not the servers'

#

not much you can do about looking through walls etc but that's the job of anti-cheat software

peak sentinel
#

Easyโ„ข๏ธ Anti Cheat

eternal canyon
#

Lol

thin stratus
#

Riot Games released some blog post about fighting wallhacking

#

Iirc

empty axle
#

yes they did, TLDR they basically calculate the relevancy of enemy players so late that it will replicate just like 1 second before you possible can see them

#

even if you have a working wallhack you won't have the data to draw the players early enough to react

#

I mean still with a wallhack you will have a little bit more advantage but that sounds nice

crystal crag
#

Do all clients get all connected player's FUniqueReplID by default?

#

I'm just curious because I am thinking of writing my party system to use that structure as a reference to the party leader, but I wanted to make sure I wasn't doing something bad by replicating that ID to all connected clients

boreal wadi
#

Working on a data driven multiplayer character selection system. Right now only testing on LAN. I have a listen server and everything works as expected. Meaning the data is loaded correctly from the asset manager, it fills my character selection screen with the necessary buttons for the characters and I can click a button and hop into the lobby. However with the client for some odd reason my buttons aren't being created and when debugging I get some weird results. IDK what the issue could be. The asset manager on the client is loading all available data and calling the delegate function (where I'm debugging) All the code runs smoothly with expected values except when creating my buttons and setting them up. Any help is appreciated. Here is the debug log . Ignore the error I accidentally set a variable to watch that doesnt exist

meager spade
#

the FUniqueRepID for all players is stored in the session info

rancid flame
#

I want to have a timer in between respawning players, is that "safe" to have in a subclass of APlayerState? Or do I have to put it in my GameMode subclass?

lost inlet
#

a timer that the player sees?

rancid flame
meager spade
#

i personally let the GameMode handle the actual respawning and setting the timer, but then setting the respawn time on the player state for the client to see how long his respawn is

lost inlet
#

yeah, player state or controller for that

#

controller is appropriate as it's only relevant to the player the respawn timer pertains to

meager spade
#

well we show respawn times for all clients

lost inlet
#

then PS if that's the case

meager spade
#

so its either controller if only client sees, or playerstate if all sees

rancid flame
#

I shouldn't be thinking about what's "safe" or hackable as whether it's in GameMode or stuff players can see, I shoul djust be thinking about what is visible to players?

lost inlet
#

if the server is controlling the respawn what part of it is supposed to be hackable

#

if a cheat was changing the memory for the respawn timer, it wouldn't suddenly respawn them would it?

meager spade
#

(unless the cheat is on a listen server..) ๐Ÿ˜›

lost inlet
#

ah yeah but you have the keys to everything anyway

meager spade
#

yeah that is why you never make a competitive game with listen server.

rancid flame
#

(Sorry I'm still trying to get my head around multiplayer)

lost inlet
#

a client messing with their memory via cheating isn't going to make that value change on the server

#

replicated values are one way, server to client

magic helm
#

Hello, I'm having trouble with some data asset syncing across the network. Wonder if anybody has had experience with that?

I have pre-runtime created assets that are made by designers and edited by them but also have to make runtime ones(for holding data that is set at runtime and its only modified when created as such...). Wanted to see about any suggestions for syncing those runtime created data assets so they point to the correct one(network wise).

Ive so far been using NewObject<UMyDataAssetType>(this); locally and this is an actor component. But didn't know if there's a different way I should be spawning them to sync up properly or not...

#

Also thinking of just adding replication to the data asset that I'm spawning at runtime and replicate it directly but I want that as the last resort...

proven plover
#

Having issues spawning actors from gamemode in multiplayer. I understand the gamemode runs on server, but I still expected for the actors to show up on the client. Seems liek the answer is obvious I just dont know it

bitter oriole
sinful tree
magic helm
bitter oriole
#

Data assets are completely unrelated to multiplayer, they're fixed baked content

#

They cannot replicate

magic helm
#

I mean... it is possible to make a UObject replicate... just don't wanna do that haha

fossil veldt
#

Is there a way to refer to an actor that is serialized into a UWorld without replicating it?

#

Like does it get assigned a GUID that would be valid unless said default actor in UWorld gets deleted?

bitter oriole
bitter oriole
#

Just use a struct in an actor

magic helm
# bitter oriole Just use a struct in an actor

We're building a game where its essentially pulling all of our configurations and such from data assets, and then be able to pull the configurations from the dedicated server at runtime(incase we need to tune stuff) instead of cooking and re-packaging the game and pushing a client side update. But thats more high level than what I was asking, it was regarding after those configuration payloads are pulled in, wanted to see if I could create them at runtime and if there was any techniques where I could map them to the same spots networking wise so I don't have to force them to replicate(which btw you can totally do, I have done it before with other UObjects but its a bit involved with actor channels and such)

#

But honestly moving to structs is best route, just means alot of rewriting lol

fossil veldt
#

Just to be clear, Data Assets are Assets if they exist in your game, they'd typically exist on the client side and the server side because they are litterally assets containing data that are a part of your game pak

#

sounds like what you want is just a format like json honestly

bitter oriole
#

Json page fetched by the server from a central authoritative server/db, deserialized into a replicated struct

#

Maybe 20 lines of code

fossil veldt
#

๐Ÿ‘

magic helm
#

So I understand what your saying on all of this, but for our game we cant use JSON because these payload configurations also include things like textures, models, materials, etc

fossil veldt
#

You can use JSON for that

#

Use TSoftObjectPtr

magic helm
#

But for our game the assets will not be on the hard disk until its been pulled from the server

fossil veldt
#

Are you going to be patching it in via DLC?

magic helm
#

Nope

fossil veldt
#

How do you plan on inserting the content

magic helm
#

So I'm trying not to say too much because of NDA, but its basically using the UGC pipeline of loading assets at runtime but before it does that, we send the packages from the server to the device(we also handle placing it in the correct directories and such) and then tell our asset manager to load it at runtime. But thats relating to more hard disk, client side loading vs making the data assets at runtime for those configured assets(so afterwards its basically tuning those new client side loaded files)

#

I would prefer to not continue talking about it if thats ok? I did get the answer I'm looking regarding just using a struct for it to construct runtime related information and objects

#

Just requires rewriting some stuff(which I wanted to avoid)

meager spade
#

@fossil veldt all our actors we save are based on an aactor subclass

#

which we hold GUID's ourselves

#

so we can link things back together, etc

#

its also how we link things when the map randomizes

rancid flame
#

I'm trying to make a quick-and-rough way to restart matches once the round is over. It seems that AGameMode does this with GetWorld()->ServerTravel("?Restart",GetTravelType());

My question is what should I be doing about UI widgets, should I be destroying and recreating them? It seems that their owner is old or something?

#

I've tried destroying them and recreating them but I'm kind of blinding testing overriding random functions within APlayerController to see what would work (EndPlay, RestartLevel, BeginPlay, ClientRestart_Implementation etc.)

bronze arch
dark edge
#

You won't see pawns as they come around the corner.

bronze arch
#

adjust some offset

dark edge
#

If you have a way to detect that they're close to being visible that'd work. We are doing 2d Line of Sight so could fairly easily do some expansion of the visible field to use for replication purposes.

dark edge
bronze arch
#

never tried that but brainstorming is allowed ofc

dark edge
#

I've brainstormed it a few times and it's hard in 2d and fuqqin gnarly in 3d pretty sure.

#

Might be easier to precompute some sightlines functions or just use volumes.

#

Say you're in a room, only replicate those on rooms you could possibly see into.

bronze arch
#

that also option

#

i drawed some example like that
player aim is pointing actual line trace and the linetrace hits wallhackcheck collision(depends how bigger u wanna offset with that)
if hits server allows send data for that players and creates actor or visible back
if not hits, then nothing to do.

#

wouldnt this work?

#

green: linetrace
red: extra collision like wallhackcheck with offsets scale
black: is just player head Worry

boreal wadi
#

After some further digging I think this error = parent failed to evaluate: extracting data from value failed is the reason Im running into this issue on the client. Has anyone ever seen this error? I've googled it and not much pops up. as you can see here all the data is being filled but somehow my call UCharacterButtonWidget* CharacterButton = CreateWidget<UCharacterButtonWidget>(this, CharacterButtonWidgetClass); is returning a null widget ONLY on the client even though clients are supposed to create the widgets.

dark edge
#

Now if you knew where every corner was and could aim just inside that and check for colliders that might be a thing but then it just gets silly

#

And that's only for 2d. For 3d, forget it.

boreal wadi
#

I'm Running into an issue that I'm willing to pay to get help figuring it out. 100$ bucks if someone can help me get the answer. I will share code and willing to hop in a discord call before you agree to the task to walk you through whats going wrong and what I've done so far to try and fix it so you waste no time. Tag me or send a PM if you're interested. Its a pretty advanced topic and will require some indepth knowledge but as I said I'll walk you through the problem before hand so you can find out if you can handle it.

sinful tree
boreal wadi
spark owl
#

is there anyway to detect if a physics object is desynced for clients on the server side?

stray gull
#

im trying to replicate this MovementStatus variable but the second "Server" print is not changing which is causing issues with what im doing next, why is this happening. - The function to determine this is replicated correctly and the variable is also set to replicate

silent valley
#

Fun fact, I wrote a PVS occlusion culler for a demo which got me my first job in games back in 2003.

thin stratus
#

You are seeing a very simple issue, but it's not actually

#

If you check the link from noggs above, you will notice that a wall isn't actually that easy to trace

#

What do you trace of the character? every single bone? polygon? What if something that isn't actively traceable is visible due to a hole in the wall?
There is tons of edge cases that come up and the blog post from riot explores those quite well

#

They sadly don't go into detail for their system that cuts the map into sections and how exactly that is helping iirc

#

But it's a good idea

bronze arch
thin stratus
#

Hm no idea, don't have the time to check it. You'll have to look at it and see if they do it properly

#

It's totally fine to start with something naive, aka "Yeah that's gonna solve the whole problem." and then look at all the issues that weren't considered and reiterate (which is exactly what the poor soul at riot did).

#

So maybe you want to try it out yourself first

orchid yoke
#

hello, does the server only replicate an actor to the client if a property changes?

kindred widget
#

Yes. And only after the end of the frame. So changing a property 500 times in a single frame, it'll only replicate once.

dull tinsel
#

Hey anyone know why my 3D widgets don't accept input anymore if I play in anything other than standalone mode?

azure hollow
#

hey guys I'm working on an async multiplayer and I'm using PlayFab as backend.
Basically I need to send a struct of my ghost race (with location and rotation) to the server and store the file. So far so good. The fact is, I would like to compress in someway the struct so that I can add more keys when recording my race. Since I need to send a JSON to PlayFab, is there anything that I can do to compress my Struct before sending the data? Something that I can 'pack' and 'unpack' It's my first time with these kind of things, thankssssss

sinful tree
azure hollow
#

yes is it possible?

#

mmm because I don't properly know how it works. I just know that what PlayFab wants it's a JSON so I was trying to understand more

#

Ye since I have no experience I don't really know how much is too much, the limits for data are 300K if I'm not wrong and I'm within the range waaay down...just reducing size can be good to speed up loading and stuff that's all

sinful tree
# azure hollow yes is it possible?

Best you can really do is round floating point values to as minimal amount of decimals as possible, and if you have control of the field names, try to keep them as small as possible while still having somewhat clear names. Pass whatever data you can as numbers rather than strings (ie. if you have a field named "Class" don't store "Medic" or "Soldier", instead store 0 or 1).

orchid yoke
#

what exactly tells the server that a property has changed though?

kindred widget
orchid yoke
#

c++

kindred widget
#

It's a little more complicated but the simple version is... When you register in GetLifetimeReplicatedProps, you're telling the replication system that this actor has a property it wants to replicate. So on tick, replication system does some checks. Basically does some checks about last replication time, relevancy, net priority, etc. And then checks values if they're changed. If they were, replicate them.

orchid yoke
#

alright, thank you!

dark edge
silent valley
prisma snow
#

Hi! I am doing some networked movement tests. I am trying to have an CustomAIController that I spawn manually on the client and has the capability to move units independently on the server.
I have succesfully spawned the controller, which owns the pawn, and then I call my "ClientSideMoveTo(location)" function. Although the debugger is showing me that the function is called (I made a HasAuthority() check to be sure my breakpoint is only running on client), then this function is not executing in the client - instead, it runs on the server only.

#

Is there maybe something that stops AIControllers or Controllers in general from issuing commands on client side?

#

Some example code as reference:

kindred widget
#

Why do you need a client side AI controller exactly?

#

I understand that client needs ability to move the AI, I'm just not sure why the need for the client side controller?

prisma snow
#
MyPlayerController::ExecuteMoveOrder(AUnit unit, FVector location)
{
    AClientSideController* controller = unit->GetClientSideController();
    if(controller && !HasAuthority())
    {
        controller->ExecuteMoveOrder(location); // this is executed client side
    } 
}

//In controller class
AClientSideController::ExecuteMoveOrder(FVector location)
{
    if(!HasAuthority)
    {
        //do stuff. Here, code is not being called anymore
    }
}
prisma snow
# kindred widget Why do you need a client side AI controller exactly?

I am doing some tests for an RTS and I wanted to move units client-side in an independent way from the server, so that I don't have to replicate movement. It might not be the best approach, but it was a quick one to test and rule out (or not). Basically, the move orders are sent via RPC and each controller moves the unit independently. I use an AIController because it has already pathfinding features setup

#

Also, is there any way (besides breakpoints + HasAuthority() checks) to know in the debugger if I am seeing the stack call from server or client? Sometimes is evident but not always

lusty badger
#

I'm trying to make a light switch, each time a player activate it, it turns on the light
But I'm having problems with Server RPC not being called from clients.
I'm guessing is because the switch actor has not net owner, how could I set an owner to it? The switch is on the level since the beginning, it's not spawned later

sinful tree
# lusty badger I'm trying to make a light switch, each time a player activate it, it turns on t...

You cannot call RPCs from actors that are not owned by the client. What you should do is have an RPC from say your player controller that passes along the referencing actor you're wanting to interact with. The server can then use the interface to perform what is needed on the actor - of course, you should also have your server verify if the player is within range to actually interact first before performing the action.

kindred widget
sinful tree
#

So something like:
(On Client): Presses Interact Key > Does sphere trace in front to find actor > If Hit Actor > RPC to Server with Actor
(On Server): Is Passed in Actor within X distance of Player's Character > Interact Interface > Object implementing interface performs action

lusty badger
kindred widget
#

UKismetSystemLibrary::PrintString(this, "StringHere");

prisma snow
lusty badger
prisma snow
kindred widget
#

But you said you spawned the controllers on the client?

prisma snow
#

Just understood

kindred widget
#

Authority != Server/Client

prisma snow
#

The Client has authority

#

because he spawned the controller

prisma snow
kindred widget
#

If you want a check for server, use GetNetMode() < NM_Client

prisma snow
#

perfect, thanks! ๐Ÿ˜„

crystal crag
#

@meager spaderight but do all clients have all other simulated proxy client's unique repl IDs?

#

So if I'm player 1, can I see player 2's unique repl ID on my game client (both are connected in a dedicated server / client setup)

kindred widget
#

Pretty sure those are all replicated from the PlayerState?

crystal crag
#

Ok cool

#

I was thinking that they were replicated, but I wanted to make sure I wasn't going to be doing anything bad.

spark owl
#

does the "Is Server?" node return true if it's a listen server host or dedicated server?

spark owl
#

thanks

boreal wadi
#

Has anyone ever seen this error before? Not sure what caused it. I changed one function from a regular function to a UFUNCTION(Client, Reliable) and that started popping up in my logs.

meager spade
#

that seems right

#

you are simulating lag

#

so your moves can timeout

grand kestrel
#

Should really just use clumsy anyway, no need to setup anything, really convenient

#

But yes, what Kaos said

#

Simulating a ton of latency

hoary lark
#

Isn't that going to be equivalent to a ping of 1000?

#

Eh, I mean you don't have to set anything up to use the built in console vars either...

bitter oriole
#

Those settings will give you about 1.1s max ping which is quite unreasonable

#

100ms of packet lag will give you about 250ms which is a more reasonable worst case

grand kestrel
fierce oriole
#

Hello! Anyone I can bounce this idea off of?
Im conceptualizing a "Multiplayer Wind System". Inside a closed spline bp in the Level the area inside the Spline will generate a Replicated 3d heighmap of some sort, so that a Windier Area will be the same for all Players. Could I use a Material? Some kind of field? Im kind of stumped how to do this with multiplayer

winged badger
#

something like heightmap is usually best left not replicated

#

if i had to replicate anything there, it would be spline points

#

and generate the same heightmap client side

raven tangle
#

hey guys, how do I run a blueprint flow just on the character actor which run in the owning client?

#

I want to run stuff on Event Tick only in the client that controls the character, not on proxies (if that's the right term) of that character in other players' clients

meager spade
#

check IsLocallyControlled

#

@raven tangle ^

raven tangle
sage isle
#

I am still working on understanding multiplayer stuff and I know you have to properly do variables on the server to keep people from being able to cheat (easily anyways) but I am struggling with this. I tried to have it so the hunger variable is only being changed on the server but then it updates the UI I made for the client, is this the right way or am I at least on the right track?

sinful tree
sage isle
#

Got it, I figured this wasn't ready yet, but couldn't a use a function to update the UI rather than a rep notify, I thought the repnotify was a lot more costly than a regular replicated variable

sinful tree
#

RepNotify variables are the appropriate way to advise of state changes from the server and I don't think they're any more heavy than standard replicated variables. You have a choice, you can constantly poll what the value is (say on event tick or by "binding" your UI to the value, or even having a timer set up to do it) and then just use a standard replicated variable, or, you can use a repnotify that fires the generated function which you can then use to control anything that needs to change when the variable changes. Constantly polling for a value is heavier than just using an event-based approach where something triggers things that need to change.

The OnRep function can still call your event dispatcher which I imagine your UI is bound to.

vocal quail
#

Hello there. Needing some help. Having some issues with creating a Multiplayer LAN lobby. Everything works fine upto creating the joining players own widget. Host and client needs to have different UI. Client joins fine and the host widget is updating with the new player, but when I spawn the client Widget it takes over the host widget. I am spawning widget from Lobby Player controller wich is called from Lobby GameMode. Any pointers on this?

#

I am using the event onPostLogin on GameMode. Checking if it is the host or client that has joined (host is always first one) in a PlayerArray. If not host, branch to client spawning UI with the playercontroller fed from the onPostLogin

winged badger
#

PostLogin is server only function

#

you can't create client UI from there

#

as UI can only be created locally

vocal quail
#

I am calling a spawn UI function in the client playerController from PostLogin

winged badger
#

what you're doing is having a client PC log in, then you spawn UI for that client, on server

#

with predictable results

#

manage your UI from HUD

#

that way you can't crosswire it, only 1 instance of HUD exists where PC is also local controller

vocal quail
#

So create a HUD BP, and move the logic from PlayerController over there? Isnt playerController parent of HUDclass?

winged badger
#

your use of parent there is ambiguous

#

GameMode sends RPC to PlayerControllers under the hood to initialize a HUD, providing them with the HUD class to use

#

this happens shortly after PostLogin, often in same Tick

near swift
#

how do i make it lag in 4.26 netemulation.paklag isnt working

bitter oriole
#

Packet lag works fine, how did you set it up ?

near swift
#

im following the tutorial on gamedev.tv im just using it in the ` in game and using the command

bitter oriole
#

Put this in DefaultEngine.ini

[PacketSimulationSettings]
PktLag=100
PktLagVariance=10
PktLoss=5
PktOrder=1
PktDup=0

near swift
#

ok thanks

winged badger
#

4.25 and later

#

have it under play options too

#

you don't need to enter commands by hand

near swift
#

i put it up to 1000 nothing happened

#

same result

winged badger
#

default engine change requires editor restart

near swift
#

same thing

bitter oriole
#

So how do you know nothing happened ?

#

These do work, btw

near swift
#

im trying it with and without it but nothings changing

#

theres no difference

marsh quest
#

hi, how are properties tracked during replication?

#

as in, how does the engine know that PropertyA was once 1 but has had its value changed to 2 for replication

near swift
#

i figured it out the = sign is redundant

dark edge
frail silo
#

So I started with the first person template. How would I make it so that the other player aren't just a pair of arms?

kindred widget
#

@frail silo Add a second skeletal mesh. If you don't have a mesh already then add the ThirdPersonTemplate to your project, set second mesh as the mannequin. Set OwnerOnlySee true on the arms, set OwnerNoSee true on the third person mesh.

frail silo
#

Thanks that worked. How do I get animation to play? I have the third person animation blueprint set as the Anim Class but it is stuck in a static pose. Does Multiplayer require anything special settings checked?

kindred widget
#

It should not. You should be able to use it same as singleplayer.

viscid monolith
#

Hi, how would i make character actor to be different for your character and other players. I mean, i need to make so if you possesed into character your actor won't have body and more things, but you will have hand and a weapon attached to it. But you will still see other players as normal.

hollow eagle
#

make a separate skeletal mesh for full body vs first person perspective. Set the full body to owner no see, set the first person version to only owner see.

viscid monolith
#

How would i check if this client is owning a character actor?

hollow eagle
#

I'm not sure why that's relevant.

#

these are options on the skeletal mesh, you don't do anything but set them and forget about it.

viscid monolith
#

I didn't know about these options. Than it's a way easier than i thought. Thanks!

limber gyro
#

hey guys, im in a bit of a pickle trying to connect to a remote hosted server

#

my logs are stuck at SendChallengeResponse

#

does any 1 have any idea?

spark owl
#

do you guys have any reccomendations for setting lots of variables on server when a player joins a server? I'm getting lag spikes on some servers. Should I just have a delay on everything it sets so it's not doing it all at once?

#

also could a player controller casting to his player state, and the game state cause lag spikes?

spring vortex
#

Anyone know where is the best place to store some data for when the client loads in after the sever has started a session? For example, I need to get an int array from the server and pass it to the client when the client loads in

#

I've tried writing to an actor in the level but that is useless as the client get's their own version of it

#

Basically I just want to make sure a client doesnโ€™t have a copy of a destroyed instance foliage actor when they load in.

sinful tree
# spark owl do you guys have any reccomendations for setting lots of variables on server whe...

Some of it may be that you're not putting the replicated variables in a good class (ie. does it need to be on playerstate vs. on player controller), or they're not scoped very well and are replicating to everyone when they shouldn't (ie. should maybe the variable only be replicated to the owner rather than to all players if it's something on playerstate).

Casting shouldn't cause lag spikes as far as I'm aware, unless you're casting to hundreds of different classes or are casting repeatedly on tick or something similar.

sinful tree
spring vortex
#

Originally it was stored on the player and passed through to the game mode on save, then on load it took the array and removes the instances. This works fine in SP obviously.

#

I've tried a few different things, like writing to the game mode directly, but when the client loads in that array is empty since the client doesn't have a game mode

sinful tree
#

Gamestate would probably be best. Just make that array set to replicate with a RepNotify and use the OnRep function to perform whatever it's supposed to do when the array changes. If the array is ever changed later, then all clients, even those that join later, will perform whatever is in the OnRep function.

spring vortex
#

thanks, man. I will give it a whirl

spring vortex
sinful tree
spring vortex
#

Something just came to me, not the most ideal method but just need to see if it works

prisma snow
#

Hi! I am debugging client side movement, I have a setup where I have a server AIController, and a mirror client-only AIController, both perform the same orders with same settings (via RPC) but the movement itself is not replicated (this is a test/POC to reduce bandwidth). What is happening, is that the server can move the units normally, but the client cannot - the units are "stuck" (the order is recieved). I can only think this is a collision-navigation issue that is not setup correctly for multiplayer settings. I checked that "Allow client side navigation" is enabled, but I am clueless about what else could be causing the issue. How can I debug navmeshes client-side?

verbal tendon
#

Hi! I'm writing a network action framework that hooks into a number of things that we need for the game I'm working on.

This requires custom serialization. From what I have gathered from the documentation and looking at the engine source code is that Network GUIDs are globally unique - what worries me is the distinct guid cache that each network connection has. I'm wondering if somebody knows if it's safe to use the first of the multiple connections' packagemap to serialize with.

{
    // Server
    auto* NetDriver = Actor.GetNetDriver();
    if ( NetDriver->ClientConnections.Num() >= 1 )
    {
        return NetDriver->ClientConnections[ 0 ].Get()->PackageMap.Get();
    }

    auto* Conn = UGameplayStatics::GetPlayerController( &Actor, 0 )->GetNetConnection();
    if ( Conn )
    {
        return Conn->PackageMap.Get();
    }

    // This will happen in singleplayer
    return nullptr;
}```

Or if I'm missing something here. I have tested this in PIE with multiple connections and that works, but there might be caveats that I haven't seen at this stage.
marble gazelle
#

where do you call the getter / what are you trying to do? (no idea if this is save, but depending on where you call this it's possible you don't need it)

verbal tendon
#

It's called for serializing whe being sent for client to server, or from server to clients for network usage through RPC and when being received, through the usage of FBitNetReader/Writer

marble gazelle
#

thse have a ptr to the package map

#

or do you create the instance of these?

verbal tendon
#

Those are created by the engine, not doing anything revolutionary and building on top of the existing multiplayer functionality

jolly siren
#

Anyone use wwise voice chat? Wondering how it compares to vivox

verbal tendon
#

Just wondering if @chrome bay has a clue, since I see that you've written about PackageMap in here before ๐Ÿ™

marble gazelle
#

well if you use the one from the engine, then these already have the ptr to the correct map

#

FNetBitReader::PackageMap or FNetBitWriter::PackageMap

verbal tendon
#

Those classes need the pointer passed to them, because they use the packagemap for serialization purposes, namely matching UObject* to GUID, that's partially what the question is about

marble gazelle
#

that's why I asked if you instantiate them or the engine does it, as I would have expected if the engine gives you such a writer it would init it for you

verbal tendon
#

It's why I'm asking, the packages are done on the Connection/NetDriver, and each connection has their own package map, but the docs do state GUID to be globally unique. So I'm wondering if someone knows if it's safe to do what i'm doing or if there's something that won't be serialized properly even if UObject* work.

I'm planning out the systems for future work, and if somebody has done this before that's great information to have to put my mind at ease ๐Ÿ™‚ If there was a single packagemap for all connections I wouldn't be worried one bit, but since there isn't. I have concerns ๐Ÿ˜„

#

It's probably fine, I haven't looked at that part of the engine code before and my time is limited, if nobody knows I'll just end up looking at the engine source code more ^_^

marble gazelle
#

I'm just not sure if the package map for each client has the same IDs, they will be unique, but do all clients replicate the same objects^^ so maybe some objects are missing in the map?

chrome bay
#

And Net GUID's are unique per-connection

#

You can't guarantee they will all ack in the same deterministic method, especially when you consider packet loss and latency

#

But I'm not sure why you need it exactly? As with USTRUCT()'s you can create a NetSerialize() method which passes in the relevant UPackageMap

verbal tendon
#

That's what I was fearing ....

chrome bay
#

Yeah Net GUID is completely unique per connection. No guarantee at all they will resolve to the same object instance between different connections, it's probably a fluke that it works at all currently

#

But if it's for an RPC, just send a USTRUCT() with a custom NetSerialize method

#

The UPackageMapClient passed into that will be the one relevant for the serializing connection

verbal tendon
#

By that logic though I'd need to write more custom code that serializes the data for each connection instead of just hooking into unreal's existing functionality for distributing it to all clients via a multicast RPC from the server. That's what I didn't want to be doing

chrome bay
#

That's what the multicast already does

#

Any data containing a UObject or FName reference is serialized once for every connection

#

That's the same process for any property or RPC

#

The only time a property is serialized once for all connections is if it has a NetSerialize and has WithNetSharedSerializer = true

#

That goes down a special Shared Serialization path

#

But you can only do that with POD, you can't do that for anything containing a UObject or an FName

verbal tendon
#

The multicast doesnt know that it contains that data

chrome bay
#

Reflection does know

verbal tendon
#

No it only gets a bitstream

chrome bay
#

But it knows what that bitstream represents

#

Data is (almost always) uniquely serialized for every connection

#

No idea never done it

verbal tendon
#

I've got a whole range of actions, that all take different parameters, but need to call the same functionality. So they all piggyback on top of a single RPC void ExecuteOnServer_Struct( ACharacter& Character, ERPC RPC, const TArray<uint8>& Payload, int64 BitCount )

It gets serialized on the calling client, forwarded to the server through the RPC above, where it then takes that data and multicasts it to all clients.
The problem here is that doesn't work with existing functionality if it's just being called from the server

chrome bay
#

Yeah so my advice is avoid all of those RPC params. Create a USTRUCT that you pass that has a custom NetSerialize method

#

Then do the serialization there

#

That's exactly what it's there for

#

Well that and other things

marble gazelle
#

no, just for that

chrome bay
#

You can use it for a lot, custom compression, forcing atomic state etc.,

#

But you can support a degree of polymorphism too

marble gazelle
#

just joking

#

yeah I use a lot of custom serialization when I reach the end of unreals default support^^ like for templated types

verbal tendon
#

So the custom NetSerialize is then used by the engine and it uses a shared packagemap?

#

So that implementation of NetSerialize could contain an FBitReader/Writer that would then work without issues?

chrome bay
#

No, net serialize will be called for every connection

#

And each time it is, the UPackageMap is the connection it's being serialized for

#

unless you can use shared serialization, in which case the UPackageMap will be null

#

Behold the params of NetSerialize:
bool FST_PolyStruct::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)

#

The Ar is either an FBitReader/Writer depending on whether it's saving or loading

#

Map is the UPackageMapClient

#

And that will be called anytime that struct is sent over the network

#

Whether for RPC's or property replication

#

And you need to define the template type too:

struct TStructOpsTypeTraits<FST_PolyStruct> : public TStructOpsTypeTraitsBase2<FST_PolyStruct>
{
    enum
    {
        WithNetSerializer = true,                // Use NetSerialize
        WithNetSharedSerialization = false,        // Unsafe if we may contain UObject/FName properties internally (calls NetSerialize with no package map)
    };
};```
verbal tendon
#

Hm interesting. Something to explore, thank you that's info I didn't have before

#

I gotta see if that fits the bill

chrome bay
#

If you found an old thread of mine on UE4 forums where I was sending TArray<uint8> ignore it, it's from a less-wise version of me ๐Ÿ˜„

#

Actually link me too so I can wipe it out ๐Ÿ˜„

verbal tendon
#

Link you too? ๐Ÿ˜„

chrome bay
#

yeah

#

If that's where you got that idea from anyway

verbal tendon
#

Yeah I saw a thread somewhere that gave me ideas ๐Ÿ˜„

chrome bay
#

yeah if I was the one writing in it (TheJamsh) - wipe it from your memory

verbal tendon
#

I didnt take the same approach ๐Ÿ˜„ but it was a fire spark

#

Which is how I ran into the issue with packagemap

chrome bay
#

Yeah, I would have ran into it sooner or later with that method. I should have just used NetSerialize

#

But at the time, I was dumb dumb

verbal tendon
#

The reason why I'm doing it is to save hundreds of lines of code, because we have a lot of networking functionality that needs to be done. I can create fully working RPC functionality this way in < 10 lines for each new thing ( excluding the data USTRUCT that the function wants if it wants one )

chrome bay
#

yeah you can use NetSerialize to do things like send polymorphic data etc.

verbal tendon
#
chrome bay
#

yeah.. christ I'm deleting that thread

#

This topic currently has over 5000 views and may be a popular search destination.

#

RIP Google search

verbal tendon
#

hahaha ๐Ÿคฃ

#

That's the thing right. A lot of people take what they find and then use it as a bible and say "this is how it has to be done". I found your stuff, it gave me an idea - I tried it, then looked at the engine source code and was like ... wait a minute โฐ ๐Ÿ˜‚

chrome bay
#

yeah I was more active on the forums when I was dumber ๐Ÿ˜„

chrome bay
#

UObjects and (to some extent) FNames are acked per-connection

#

The PackageMapClient keeps the ack'd GUID's and is what allows you to serialize UObject ptr's over the network

#

But they are unique per-connection

#

Client A might use "24", Client B might use "351414" for the same object

#

So data has to be serialized multiple times, for each connection it's sent to. Unless you just have "plain old data" like a vector or float, it can be serialized once and the same bitstream sent to each connection.

#

FVector for e.g. is always three floats and always sent atomically, so it can use shared serialization

#

If you don't know then don't use it

#

The above should explain it pretty clearly

#

Tl;DR, UObjects and FNames can't be shared, other stuff usually can be

#

"too long, didn't read"

chrome bay
#

What I'm saying is that it can't be shared

#

yeah

verbal tendon
#

Think of it like a map: GUID -> Instance. Each client has different instances of these things and different IDs
Vectors, like integers are just data that you send ( copy over ),

But if you send a pointer UObject* from one PC to another, they need to know what you're refering to, that's done via the GUIDs

#

Because you cannot send pointers to memory over the network and have them point to the same thing ๐Ÿ™‚ The IDs are used to facilitate that, because you can send integers over the network, that's simply copied data that will be the same on both PCs

placid pendant
#

hey y'all, I have a replication question. Right now I have door set to open on server and replicate its movement to client. When the server walks through the doorway when its open he cleanly passes through, but client lags a little bit as they pass through the open doorway. Anyone else run into this?

acoustic thunder
#

does any one here have this issue with the advanced sessions plugin
where the joined player appears to be possessing the pawn but cant do anything at all?

kindred widget
acoustic thunder
kindred widget
#

Sessions are just the initial connection info. If a client connects, you should be past the session issue and into replication. I'd start by making some prints in your input. See if it even runs on the pawn the client is trying to move. If nothing your possession code might be off somehow.

acoustic thunder
#

welp
now not even the host can control the pawn

verbal tendon
#

Look at your controller, start printing things on screen to help you debug

#

Something as simple as printing when your controller of choice has possessed the pawn can be helpful to make sure the right controller is still doing the possessing, or possessing at all

#

and then you work your way down of things you should work and check if they do or dont until you find the culprit

glossy veldt
#

Hey guys, I have the following problem:
When a character in my game is killed he turns into a ragdoll. This is done with an OnRep Function.
This is the code:

void ASPCharacterBase::OnRep_IsRagdoll()
{
    if(bIsRagdoll && !IsPendingKill() && GetMesh() && GetMesh()->GetPhysicsAsset())
    {
        if (GetMesh())
        {
            GetMesh()->SetCollisionProfileName(SP_COLLISION_PROFILE_RAGDOLL);
        }
        SetActorEnableCollision(true);
        GetCapsuleComponent()->SetCollisionProfileName(FName("NoCollision"));
        GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
        GetCapsuleComponent()->SetCollisionResponseToAllChannels(ECR_Ignore);
        
        GetMesh()->SetSimulatePhysics(true);
        GetMesh()->WakeAllRigidBodies();
        GetMesh()->bBlendPhysics = true;

        GetCharacterMovement()->StopMovementImmediately();
        GetCharacterMovement()->DisableMovement();
        GetCharacterMovement()->SetComponentTickEnabled(false);
    }
}

On the client the Ragdoll has the collision responses it should have (not fall through the floor but otherwise not be affected), but the collision Capsule still has collision enabled.
On the Server everything works as expected.
Any help appreciated!

acoustic thunder
#

@verbal tendon @kindred widget
thanks for the suggestions
I got it working and it was the easiest solution
I just had to set input mode to game
๐Ÿคฆ

verbal tendon
#

Easy is good! That's why you check for culprits. Glad you got it sorted!

acoustic thunder
#

next time Im gonna make sure to always use the node
even when it might not be necessary ๐Ÿ˜†

hexed thunder
#

is there a detailed tutorial documentation on seamless travel flow and what happens to server actors throughout entire process from original map to transition map to new map, and then back from new map to original map when travelling back

#

im having an issue where I am able to server travel from a starting map to another map fine but when i try to return from the other map to starting map server crashes, both times using servertravel command and seamless travel enabled for both

verbal tendon
unkempt tiger
#

What does it mean if my editor-launched standalone session was filled with laggy, jerky networking, and after restarting my computer everything began to work normally again?

#

anyone maybe run into similar scenarios? I'm just trying to wonder if it means I messed up bad somewhere, or if its just the engine doing its occasional derpyness

#

(I'm not saving anything locally, the game is completely 'reset' every time I start a session)

hexed thunder
#

essentially packaged build will crash but running in UE it works ok

verbal tendon
#

Right then your next steps are figuring out what exactly is crashing it

#

Is it easily deducable from the stacktrace that you get on the crash? I'd start with that you can post a screenshot of that

hexed thunder
#

sure let me do that, it didnt seem helpful i have verbose logging on

verbal tendon
#

Then based on the nature of the crash ( whether it's your content or engine based ) - if you can easily make a fresh project and just do a few things and get it to crash reproducible you might be looking at an engine bug ( or just some config that's not right )

hexed thunder
#

I attached a message log if that helps ive been pretty stuck on this one

verbal tendon
#

Do you not have a stacktrace on crash?

hexed thunder
#

sorry is that in log folder as well?

#

i mean thats the end lol

verbal tendon
#

sorry I got carried away with something else, yes not having debug symbols on the stack trace isnt great

#

because otherwise it would show you where it crashed

hexed thunder
#

is that just packaging as debug instead of development?

lost inlet
#

you should be able to get PDB files regardless of what the build type is

sterile plaza
#

Good evening. I have a bit of a weird actor replication situation going on. I have an actor that when possessed by the server, replicates its location to clients properly. But if possessed by the client, the server moves it properly, but the owning client sees it never move. I'm RPC'ing the inputs to the server and having the server move the actor. I thought maybe having the client possess that pawn is messing with it, but if I don't actually possess it, it still happens. I know it's a weird case, but I'm struggling to think of reasons why this would be happening.

marsh quest
#

hi, why am i getting this error?

#
LogRep: Error: InitWithObject: Object == NULL
LogRep: Error: StartReplicating: Object == nullptr
peak sentinel
#

How do you guys handle this boolean when you are dashing or have very high velocity?

#

This should never be enabled most of the time but when you have very high amount of velocity you must disable it, I'm wondering how do you guys calculate when to disable it again

dull tinsel
#

Does anyone know what needs to be done to get 3d widgets to work in multiplayer? I can see the buttons highlight when I hover my cursor over the buttons, and they respond visually to clicks but don't fire the on click events for client or server.
Works fine in stand alone

eternal canyon
#

Also if u want client auth movement u also have to enable server take client position or whatever

peak sentinel
#

Because afaik there isnt any other way to allow high velocities on client without that boolean

eternal canyon
#

I would rather just have them be predicted and be corrected then use client auth

#

But idk u do u

naive dome
molten matrix
#

I keep having issues with property replication. Could someone help me figure out what I'm missing? I created my own custom C++ class that inherits from AActor to represent a team state and I added this as a replicated property of my custom player state, but changes on the server side don't get replicated to the clients.

Here are things that I've checked:

  • The player state is marked as replicating and does get replicated properly. It even has another property in it (sub-class of APawn) that replicates just fine.
  • Property is annotated with "UPROPERTY(Replicated)".
  • Property is set as "DOREPLIFETIME(AMyPlayerState, TeamState);" in GetLifetimeReplicatedProps.
  • I tried changing the property on the server side every time there's an input from the player. I see it change repeatedly on the server but never on the client.
  • The client never changes this property.
  • The team state is marked as bReplicates = true and bAlwaysRelevant = true;

The creation and assignment of the team state property effectively looks something like this:

    AMyTeamState* Team = NewObject<AMyTeamState>();
    Team->Number = 1;
    Cast<AMyPlayerState>(GetController()->PlayerState)->TeamState = Team;

Any idea what I'm missing?

odd iron
#

Hi Guys ..
How can i replicate this function for Server/Client .
I've tried to call it on multicast from server but it wont work since its from player controller

kindred widget
#

Also semi confused why you're spawning the team state from what looks like the pawn? TeamState sounds like something that should be created in your GameMode or GameState classes.

molten matrix
kindred widget
#

I would definitely start with switching the creation calls. If it's an actor, always create it with SpawnActor.

molten matrix
#

That was it! ๐Ÿ™‚ Thank you!

#

You probably saved me a couple of hours of digging into NetDriver.cpp ๐Ÿ˜‰

kindred widget
#

Yeah. Ran into that one myself a few months after starting with the engine. ๐Ÿ˜„ In general, NewObject is only for runtime creation non actors. The SpawnActor code does a bit of specific world registering with it's world, bunch of other stuff too.

shrewd kernel
#

Hey guys I need a little bit of help.
I created a bp weapon class then attached it to my character but everytime I try and rotate the weapon on the server it also rotates on the client and vice versa, any idea how to get it to only rotate on the server and the client can see it rotating without theirs rotating and vice versa

verbal tendon
kindred widget
#

I'm not actually sure if you can disable that. If you wanted a work around, you might be able to put a scene component into the weapon itself, attach the mesh to that, and rotate the mesh instead of the actor. That should not autoreplicate without replicates movement on.

verbal tendon
#

This part is what confuses me the client can see it rotating without theirs rotating and vice versa It sounds like you have two instances of your WeaponBP on two characters, and the server rotating one of them changes the rotation of the other as well. Atleast that's what I get from the description, which is why I think clarification is in order ๐Ÿ˜„

shrewd kernel
shrewd kernel
verbal tendon
#

Can you share some code or screenshots of what you're doing for us to help you further?

shrewd kernel
molten matrix
#

@shrewd kernel I'm not really proficient with blueprints and I'm not sure I know exactly what the issue you're running into is, but if it rotates on both the client and the server, could it be because both the client and server are hitting the code path to rotate the thing? So it's not that the rotation is replicated from the server, it's just that the client is moving it all on its own?

In your screen shots, it seems to call "Rotate With Camera" on event tick. Would that run on both the server and client?

shrewd kernel
shrewd kernel
# shrewd kernel

But the problem is both weapon bp on both client and server are facing the same direction

verbal tendon
#

So this is easy

#

Thanks for providing the screenshots

#

you have two instances of WeaponBP

#

both are set to change the rotation of their weapon on the server ( to the server's camera )

dark edge
#

@shrewd kernel Go over your code and be super specific about what happens and what data it is using. For example, if your control rotation drives the camera and camera drives the weapon rotation, they'll both move.

verbal tendon
#

therefore changing the camera on the serve causes a change in rotation on both

#

That is not the way you would do this, as a first rule of thumb you dont want to cram everything into Tick() and handle things that way

#

For weapons, if you're just starting out you can attach the weapon to the camera. Later on in the project you'll want to change that. You can have the weapon attached to a particular socket either on your mesh or on a drawview representation, based on what setup you'll have later, what animation assets you'll have to work with

hexed thunder
#

Hey so I was trying to get a debug build of my game but the debug build is failing for clients getting kicked on joining when i seamless travel from a lobby to a game map, BUT on the other builds like dev/shipping it doesnt crash client

shrewd kernel
verbal tendon
#

One thing to keep in mind with all of this, if you want to make a MP game that is P2P, is that one of your players will be the host. Therefore if you have actors that you want to be "local" only. Whilst spawning them on any clients except for the host will work fine, if you spawn them on the host, make sure they're not set to replicate, or you'll be in for a little surprise ๐Ÿ™‚

#

That's for when/if you venture into drawview weapon territory, or other local-only actors

dark edge
#

@shrewd kernel for a hint, a handy variable to use for your aim rotation is from Get Base Aim Rotation. If you use ControlRotation, that'll only work for the owner of the pawn and the server. It won't be valid for a 3rd party.

shrewd kernel
#

Also tried a component but when I try to write a code to match the pitch, it also moves with it

verbal tendon
#

If you are intent on doing it this way, you need to spawn 1 actor per client ( make sure it doenst replicate ), so that you have a local weapon to work with, and then you can do whatever you want to it in Blueprint

#

however keep in mind you should only do that for visual actors, as they are local actors, that means no networking things will work on them, as they are not shared between clients

shrewd kernel
verbal tendon
#

It depends entirely on what you're trying to achieve, if you're just playing around and learning things, the answer is whatever works or whatever is the most fun or whatever you're learning the most from

hexed thunder
#

Can you debug a packaged game with blueprint debugging if its blueprint code ur trying to debug?

shrewd kernel
surreal plaza
#

I have a function in c++ that goes from a first person view to an over the should view and moves control to a pawn. This function isn't a ufunction and it is crashing when called on the client. Is there anything inherently wrong with that? I wasn't considering making this switch server side as it is fine from a cheating perspective and only the things done while in a particular view will the authorized.

#
    GetController()->Possess(Launcher->Cursor);
    APlayerController* Player = UGameplayStatics::GetPlayerController(this, 0);
    Player->SetViewTarget(this->Launcher->Projectile); ```

Like that.
glossy veldt
#

Hey guys, I still have the following problem:
When a character in my game is killed he turns into a ragdoll. This is done with an OnRep Function.
This is the code:

void ASPCharacterBase::OnRep_IsRagdoll()
{
    if(bIsRagdoll && !IsPendingKill() && GetMesh() && GetMesh()->GetPhysicsAsset())
    {
        if (GetMesh())
        {
            GetMesh()->SetCollisionProfileName(SP_COLLISION_PROFILE_RAGDOLL);
        }
        SetActorEnableCollision(true);
        GetCapsuleComponent()->SetCollisionProfileName(FName("NoCollision"));
        GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
        GetCapsuleComponent()->SetCollisionResponseToAllChannels(ECR_Ignore);
        
        GetMesh()->SetSimulatePhysics(true);
        GetMesh()->WakeAllRigidBodies();
        GetMesh()->bBlendPhysics = true;

        GetCharacterMovement()->StopMovementImmediately();
        GetCharacterMovement()->DisableMovement();
        GetCharacterMovement()->SetComponentTickEnabled(false);
    }
}

On the client the Ragdoll has the collision responses it should have (not fall through the floor but otherwise not be affected), but the collision Capsule still has collision enabled.
On the Server everything works as expected.
Any help appreciated!

kindred widget
hexed thunder
#

is there like a great in depth explanation of how pawn/controller works when a client is joining a server?

kindred widget
#

If you read C++ well enough, your best bet is probably just to start from the login function and go through it.

glossy veldt
# hexed thunder is there like a great in depth explanation of how pawn/controller works when a c...

https://youtu.be/IaU2Hue-ApI

Maybe this one and the engine source

What happens when you start up your Unreal Engine game? This video is a guided tour of the Engine's initialization process: along the way, we'll glimpse the high-level structure of the Engine (modules, game instances, local players, and viewports) and we'll see how all the different parts of the Game Framework (game modes, game states, player co...

โ–ถ Play video
dark edge
#

Do you guys do items as UObjects or UStructs for a multiplayer item/inventory system?

peak sentinel
peak sentinel
meager spade
#

i use a mix of both ๐Ÿ˜›

#

struct for replicating, UObject gets created/destroyed locally

crystal crag
#

When a player state becomes non-relevant, does that just mean that the object stops being replicated, or does it actually get deleted temporarily? I am thinking it would just stop replicating, but it would still exist in the client's memory.

#

Is that correct?

fossil spoke
#

PlayerStates are Always Relevant

crystal crag
#

Oh ok. Well I guess I picked the wrong class as an example

#

swap out player state with any other actor class that isn't always relevant

fossil spoke
#

Pawns would be a better example.

crystal crag
#

ok then, let's say Pawns. Is what I am thinking correct - it would still exist in memory?

fossil spoke
#

The Actor when it is no longer relevant will be destroyed on the Client (Server it will always exist, because Server doesnt cull as its Authority).

#

When the Actor comes into relevancy again, it will be spawned again.

crystal crag
#

Ok cool. Thanks for the clarification.

#

I was trying to think of where to store player party data that would be replicated. I was debating on sticking it in the game state, but that might get awkward. I was thinking that maybe it would make more sense to stick it in the player state.

#

And by party data, I don't mean using the online subsystem party classes at all. I am using my own custom party system

#

I also do the same thing that @meager spade is doing (at a high level at least) and it seems to work well.

#

Regarding the inventory system I mean, I do the same thing at a high level

peak sentinel
kindred widget
#

Dunno why Kaos prefers it, but structs tend to replicate more gracefully than UObject arrays. FastArrays for one example and Swapping array locations is another if my initial testing was correct. Swapping array locations for a UObject on server seemed like it led to the object being destroyed and recreated on client. At least creating object locally allows you to handle that however you like.

crystal crag
#

In a game atm, but performance is one thing for me. I use the fast array for replication of structs

peak sentinel
#

That's a very reasonable thing to use structs instead

kindred widget
# peak sentinel Why do you need a mix of both?

Also on this. It's probably worth noting that largely there's only really one major difference between UObjects and Structs as far as data objects goes. UObjects allow easier access from blueprint via BlueprintPure/BlueprintCallable directly on the object as well as delegates for data changing, structs require static blueprint functions in libraries usually to get complex data from them or to handle their data better like validity functions or "ShouldShowThisWay" functions and they don't have access to delegates in blueprints.

winged badger
#

it generally doesn't matter much, the BP accessibility here

#

this is usually deep in c++ territory

dark edge
#

When an item is instantiated into the world (dropping a gun for example), what do you guys do then? I'm guessing the typical approach is just to have the abstract representation of the item be a field on the actor or are there other options?

crystal depot
#

yo kid

#

1v1 kid

#

KID
KID

#

Omg kii

#

kii

#

kiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiid

kindred widget
#

I think someone's off their meds? O.o

clever urchin
#

Hello guys, I have a health bar on a player in a multiplayer game. Is there a way to hide the health bar for the controlling pawn but show it to the other players in the network?

peak sentinel
#

Either the first one or UT's projectile prediction method

dark edge
peak sentinel
#

They store the locally controlled projectiles on PC and when server spawns an actual replicated projectile, on one of the replication functions of AActor (PostReplication or something) client loop over its local projectiles and replace it with server's replicated projectile

#

So generally yeah, as you said

dark edge
#

@steep abyss we just spawn them locally everywhere but our projectiles are super predictable with no gravity or drag so it works out pretty well.

#

There's no prediction built in besides that in GAS, but you can look at the Unreal Tournament source code.

#

Also the CMC

#

Honestly the easiest approach is to favor the shooter and do some sanity checks on server. Won't be MLG ready but it'll work.

#

Anything involving rollbacks and prediction keys will get gnarly fast.

peak sentinel
#

Burst Counter + spawning projectiles on OnRep locally goes brrr

#

real brrrr

#

hell yes

#

It's only lossy on simulated proxies

#

And if you are not higher than 200 ping, its not really happening a lot

#

Of course packet drop is the issue not the ping at all but

#

Still works awesome

#

Of course

#

Though HLL does this way too, it's only required if you are making a competitive shooter like Valorant or Siege

#

I even heard CoD does not even do server-side checks btw ๐Ÿคญ

#

Hell Let Loose

dark edge
#

What approach would you guys say is best for a shooter with all slow visible projectiles?

peak sentinel
#

I think I would still go for burst counter + local spawning on OnRep way. I have slow projectiles too but they are not that slow

peak sentinel
#

Study CMC, study UT, study GAS and check all of the headers of networking related files on UE source

#

Also there are nice GDC's on youtube for networking

#

Unreal Tournament

peak sentinel
#

FRepMovement, PreReplication, PreNetReceiveLocationAndRotation etc.

#

I just read their repo, if you want you can download it and compile but you need VS2015

#

since its old

#

Check UTProjectile.h first, then UTCharacter and UTWeapon

#

Those three should give you a general idea of their way of shooter networking

#

game developer conference

#

Just google it

#

Not all maybe but you should understand the theory of everything you need

sinful marlin
#

I got a variable thats off by 1 between server and client. The client is always one lower.

// header
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated)
uint8 AttackChainCounter{0};

virtual void PrimaryAttack();
UFUNCTION(Server, Unreliable, WithValidation)
virtual void Server_PrimaryAttack();

// cpp
void AMYPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
  //...
    PlayerInputComponent->BindAction("PrimaryAbility", IE_Pressed, this, &AMYPlayerCharacter::PrimaryAttack);
  //...
}

void AMYPlayerCharacter::PrimaryAttack()
{
    UKismetSystemLibrary::PrintString(this, FString::Printf(TEXT("PrimaryAttack: %i"), AttackChainCounter));
    Server_PrimaryAttack();
}

void AMYPlayerCharacter::Server_PrimaryAttack_Implementation()
{
    UKismetSystemLibrary::PrintString(this, FString::Printf(TEXT("Server_PrimaryAttack: %i"), AttackChainCounter));
    ActivateAbilityByHandle(PrimaryAbilityHandle);
    if(++AttackChainCounter>2) AttackChainCounter = 0;
}

I'm printing the value of AttackChainCounter from inside the GameplayAbility activated through ActivateAbilityByHandle().

#

Those two prints are printing the same value, but my print in side the ability is showing a one difference. Which the difference is there because it's used to select the animation and client and server are playing different animations.

#

It just seems like the server is starting 1 ahead of the client? Because it never changes from being one off.

#

Testing on Listen server, the Client sees the correct animation (due to the correct value of AttackChainCounter) and the Server sees the value being one ahead. Testing on dedicated, each clients animation on their own screen is correct, the animations on the other clients are one ahead ritsu_think

willow adder
#

does anyone know why DemoNetDriver Console Comand demoplay test give me a Black screen no lights .... i set everything to replicated

pearl moon
#

question, if anyone can point me in the right direction:
Is there a function in UE4 to start up a client or another "dedicated server" from an existing/running gamemode? i'd like to "spin up/down" servers as they are needed for different maps in the game as players enter and leave them. To simplify, I want to, in c++, initiate and shutdown game instances, kind of like how a player (client) loads and exits their game

#

or is the above mentioned method even necessary? can I instead run multiple "levels" or "maps" on the same authoritative game server?

silent valley
pearl moon
chrome bay
#

That's usually not done in-engine, it's done by some third-party software running on the box.

#

Which instance becomes the "primary" one otherwise

pearl moon
#

ok gotcha, yeah was trying to avoid anything 3rd party, seems it can't be helped if I want to get an instancing system in place

chrome bay
#

Whatever provider you choose to use for dedicated servers will sometimes have something of their own. Amazon GameLift for e.g. has it

#

But ultimately the point is that it's something managed by the server host, not the UE server instances themselves.

pearl moon
#

makes sense

verbal shoal
#

why on the not replicated actor overlap events inside this actor firing on the server and all client copies?

Is it right, that if the server creates this actor then all events will be auto "replicated" without replicated=true in this actor?

chrome bay
#

Nothing about overlaps is replicated

#

The overlaps will fire locally

unkempt tiger
#

What type should I be looking for if I want to net serialize a stream of bits (perhaps with changing length) inside my struct? Or actually just RPC a stream of bits

verbal shoal
# chrome bay Nothing about overlaps is replicated

for example:

I run ContentExamples project, open map "Network_Features", setup listen with 3 players;
disable on this Button "Replicated" properties http://joxi.ru/52a1L7RsEjzQY2

why in this case - all clients see "hello" http://joxi.ru/L21LZPRfRdMNMm , if some client overlapped this button?
if it should be overlapped locally, then only one client should see this, which overlaps this trigger.
but this event fires on all machines (server and clients).

I also tried to set in the Multiplayer Options "Launch Separate Server" to true and "Run under one process" to false.

Joxi โ€“ ัƒะดะพะฑะฝะฐั ะฟั€ะพะณั€ะฐะผะผะฐ ะดะปั ัะบั€ะธะฝัˆะพั‚ะพะฒ ะธ ะพะฑะผะตะฝะฐ ั„ะฐะนะปะฐะผะธ ะฟะพ ัะตั‚ะธ

ัะดะตะปะฐะฝ ะฟั€ะธ ะฟะพะผะพั‰ะธ Joxi.net

Joxi โ€“ ัƒะดะพะฑะฝะฐั ะฟั€ะพะณั€ะฐะผะผะฐ ะดะปั ัะบั€ะธะฝัˆะพั‚ะพะฒ ะธ ะพะฑะผะตะฝะฐ ั„ะฐะนะปะฐะผะธ ะฟะพ ัะตั‚ะธ

ัะดะตะปะฐะฝ ะฟั€ะธ ะฟะพะผะพั‰ะธ Joxi.net

chrome bay
verbal shoal
chrome bay
#

Because every instance has it's own copy of each actor. If that actor moves on every instance then it will overlap.

rotund spruce
#

Hey so im new to game development and ill be honest, im pretty confused when it comes to multiplayer. Im working on a multiplayer game and was expecting id have to build a server to run it. Could you guide me in the right direction on the hardware side. Thanks

kindred widget
#

You don't necessarily need a server. It depends on your game type.

rotund spruce
#

Its a fall guys style parkour game with different levels. Im not expecting to many people to be playing at once so it wouldnt have to be the highest spec

kindred widget
#

@rotund spruce There's a chance you can probably just use Listenservers. Dedicated servers are mostly required for two reasons, cheating prevention or performance. Listenservers are basically just a version of the server within the host's application that other players can connect to. Dedicated is a whole other process just for the server. For instance if you've played older FPS shooters, most of them are listenservers. They upload stuff to actual servers at times, but their gameplay is done in listenserver style where one player is also the host. Dedicated are more like a traditional MMO. No player is the host.

rotund spruce
#

I see, and what service would you suggest for providing a listenserver

verbal shoal
chrome bay
#

But Player 1's pawn exists on Player 2's instance.

#

And if they are using the character pawn, then movement is being replicated

#

There is no replication of the event happening.

kindred widget
#

Technically you can code them to run on all three at the same time. Players running the game on Steam wouldn't be able to connect to players running on EOS, but the game's coding would be pretty much the same.

#

On the other hand, if you need a persistent, always online world for whatever reason, then you need dedicated. I don't know what that runs personally.

verbal shoal
chrome bay
#

yeah exactly

kindred widget
#

Are there any good engine delegates that run on all machines pre server travel?

#

GameInstance's OnNotifyPreClientTravel doesn't seem to work, at least on host.

chrome bay
#

FCoreUObjectDelegates::PreLoadMap?

#

Likely fires post-travel starting though

kindred widget
#

That one isn't working at all except for hard loads.

#

Trying to tie in loading screen hooks. It's working perfectly on the hard loaded maps, but nothing seems to hook correctly on host for servertravel. O.o

chrome bay
#

Isn't the point of seamless travel to not have loading screens though :D?

#

That said I used, and it worked without any issues

FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &UST_GameInstance::EndLoadingScreen);```
kindred widget
#

There's a bunch of automated setup that needs to happen before player sees anything. So needs hidden.

#

Yeah, currently using those two exactly. But it doesn't seem to work for an actual server travel call.

chrome bay
#

Failing that you can always create a specific loading screen module and set it's load time to "PreLoadingScreen"

#

AKA the ShooterGame approach

#

Pre/Post load worked ok for me in the past though

kindred widget
#

Will mess around with it a little more. Thanks. ๐Ÿ˜„

chrome bay
#

You testing outside of editor btw?

winged badger
#

it is fairly easy to rig one

#

controllers will get PreClientTravel called on them

#

and the ServerTravel functions are/can be wrapped to broadcast it on host

surreal plaza
#

I have a general authorization code organization question. For the case of some general client side action that needs to be processed through the server.... like ....

      Server_DoMyThing()
} else {
   // What happens here in a generic case?
}

Server_DoMyThing_Implmentation()
{
     // Do all the things
}

For the case of the listen server, where I am assuming Role is Role_Authority, does the server and the _implementation method just share a function that actually does the effect of the method? The server can't just call the server method directly.

#

Do people usually have a separate function that houses the core logic and is called by both the local authority and the implementation, like this....

if (GetLocalRole < Role_Authority) {
      Server_DoMyThing()
} else {
    DoTheThing()
}

Server_DoMyThing_Implmentation()
{
     DoTheThing()
}

DoTheThing() 
{
   // Do all the things
}
#

That seems off to me.

kindred widget
#

@surreal plaza Semi confused by the question. But in general your code should never call the implementation. This is true for server functions or BlueprintNativeEvents. Your code should always only call the default Server_DoyMyThing(). As far as RPCs go. some people do split them up. I think it's pointless. Running a Server Function on the server(listenserver or dedicated, or even standalone) will result in a non networked function that just runs locally. So both server code and client code can call Server_DoMyThing().

surreal plaza
#

So in the case where there isn't a client side difference (like local motion smoothing until I get server update), I don't even need the authority check? I just call the server method?

if (buttonPress) {
    Server_DoMyThing();
} 

And I don't care if it was called on a client or server?

#
float ANetworkingTutCharacter::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);

    //Decrease the character's hp 
    
    Health -= Damage;
    if (Health <= 0) InitHealth();

    UpdateCharText();

    return Health;
}

void ANetworkingTutCharacter::ServerTakeDamage_Implementation(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
}

bool ANetworkingTutCharacter::ServerTakeDamage_Validate(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    //Assume that everything is ok without any further checks and return true
    return true;
}

void ANetworkingTutCharacter::AttempToSpawnBomb()
{
    if (HasBombs())
    {
        //If we don't have authority, meaning that we're not the server
        //tell the server to spawn the bomb.
        //If we're the server, just spawn the bomb - we trust ourselves.
        if (Role < ROLE_Authority)
        {
            ServerSpawnBomb();
        }
        else SpawnBomb();

        //todo: this code will be removed in the next part
        FDamageEvent DmgEvent;

        if (Role < ROLE_Authority)
        {    
            ServerTakeDamage(25.f, DmgEvent, GetController(), this);
        }
        else TakeDamage(25.f, DmgEvent, GetController(), this);
    }
}

void ANetworkingTutCharacter::SpawnBomb()
{
    //Decrease the bomb count and update the text in the local client
    //OnRep_BombCount will be called in every other client
    BombCount--;
    UpdateCharText();

    //todo: spawn the actual bomb in the next part of the tutorial
}

void ANetworkingTutCharacter::ServerSpawnBomb_Implementation()
{
    SpawnBomb();
}

bool ANetworkingTutCharacter::ServerSpawnBomb_Validate()
{
    return true;
}
surreal plaza
kindred widget
verbal tendon
surreal plaza
#

I also see this for general gatekeeping in functions, to guard logic sensitive content.....

SomeCriticalSupportingFunction() {

   if (Role < Role_Auth) { return }

   // Do the critical stuff

}```
verbal tendon
#

I think different minds will have different opnions on this. I prefer to have a clean codebase where those authority checks aren't put in. But that's a broader discussion topic, sometimes you'll need them. When starting out though that's not what you want to be worrying about

#

The engine absoluely will let you program without doing any authority checks, and part of learning all of this is to pace yourself and not take too much on at once. Part of that would be limiting networking code complexity until you become more familiar with things

#

You'll find enough hurdles along your way to keep you occupied ๐Ÿ˜„

meager spade
#

you can't avoid using HasAuthority tho

#

what if you need to do stuff on BeginPlay authority only?

kindred widget
#

Personally, I don't even like local role that much in most netcode. It's only truly useful in some actors, and largely with prediction stuff. I much more prefer an explicit server/client check of GetNetMode < NM_Client.

meager spade
#

but GetNetMode can also cause issues

verbal tendon
meager spade
#

if used incorrectly

#

especially on listen servers

#

Replicated Actors is always fine to check LocalRole though

kindred widget
#

Haven't run into that yet. I just prefer the definite machine check rather than actor check. Authority can be true for a client spawned actor. GetNetMode() < NM_Client cannot.

meager spade
#

yes ofc

#

Authority means "Who has authority over this Actor"

#

not if its server/client

#

which causes confusion to some people

#

but replicated actor will always have server as Authority

verbal tendon
#

And that's why those things are best avoided when starting out, until other aspects of the language are mastered and one has time and space to deal with them

#

getting overwhelmed with UE when just starting out is real

#

The networking part of Unreal is not the most beginner friendly. Especially when compared to something like Materials

#

It's easy to get into and you can learn more as you work along, but with Networking you either get it right or you don't. And it either works or it doesn't ๐Ÿ˜„

kindred widget
#

The amusing part of that though, is that knowing why the engine is structured the way it is for multiplayer also allows for much cleaner singleplayer design.

#

Also potential multiplayer upgrade much easier if you choose to at a later point.

surreal plaza
#

If you develop everything multiplayer, how do all of these (if any) change between dedicated and listening servers?

surreal plaza
#

(I am absolutely multiplayer out of the gate, so I trying to keep track of it early on)

verbal tendon
#

Quite a bit actually

#

Here's the problem. Listen Server and Dedicated server work differently, and that's something you need to be aware of when making multiplayer

#

Because dedicated servers are just a server, but listenserver are client+server - one strong example of this is if you are spawning local-only actors on clients. If you do that on a listen server, and that class is set to replicate by default, instead of being local-only it now shows up on all clients, because you spawned it on the server ( ListenServer )

#

on a dedicated server that wont happen, because the only clients you are spawning those on are not servers themselves

shadow aurora
#

Ok so I have a question that's sort of about Game Instances...

Say I have an object (a manager for rewards in my case) that is stored on the game instance in a multiplayer game, and a delegate is broadcast on that object from the gamemode (which exists on the server). If a client has bound to that delegate in the object, does that event get triggered for them? Or will only server-side objects that have bound to the delegate receive the notification that that event is happening?

verbal tendon
#

But I would say this is a concept for later once you've grasped the basics on how RPCs work how to structure your codebase with networking in mind and develop in the engine

#

And how you're gonna do your replication as you build the game, there's a bunch to learn and experience

verbal tendon
kindred widget
#

Personally, I don't think there's really much difference between a dedicated and listenserver for most network coding. The only major difference is to avoid clogging the dedicated server with visual calls. Most engine code already does this. In the end the Dedicated server is nothing more than the server with the local player removed from it.

shadow aurora
verbal tendon
dark edge
shadow aurora
#

Yeah I might need to read up some more on game instance vs game state. Thanks guys!

verbal tendon
verbal tendon
kindred widget
#

There are only two ways that networking happens. You directly call an RPC, or you replicate data through replicated properties on the server. If you're not sending an RPC, or running on OnRep from replication but you run a function(including binding broadcasts) this will always run locally on that machine.

nova wasp
#

in an ideal world the sim is deterministic and has the same results on server and client

#

your initial location will be fine but the way things pan out after are not deterministic

#

but I honestly am leaning towards doing that method

#

I honestly would like to know if there are any major pitfalls with this besides the obvious trusting the client

peak sentinel
#

How do you guys handle 'player joined the match' notification?

#

I'm thinking to use GameState and call a multicast in PlayerController's OnPossess function and notify HUD about the text

#

But I'm not sure about if I should use reliable multicast or not

winged badger
#

why?

#

PlayerStates replicate, they register with GameState when they do

#

and the Add/RemovePlayer functions are virtual

#

you need PS anyhow to display any player information

#

so why would you multicast anything, everything is already networked

#

and its not just doubling up the network traffic for this

#

what happens when your multicast arrives before the player's PlayerState Actor replicates? what are you going to display then?

#

forcing what is essentially the same data take 2 different network paths is the most common cause of replication races

#

@peak sentinel @grizzled stirrup

peak sentinel
winged badger
#

if you are limited to BP only you can just have PlayerStates contact a local HUD directly from BeginPlay

#

as you require c++ to override Add/Removeplayer

peak sentinel
#

I'll do that way

dark edge
#

@grizzled stirrup if your projectiles are slow enough then doing them server authoritative is probably best, with some sort of catch-up or predict + replace mechanic on the client doing the shooting.

#

Hell even New World doesn't use predicted projectiles. Not that it's the gold standard of design but it's a data point.

#

@grizzled stirrup the approach we will probably end up using is just replicating velocity changes and events.

#

But we use a custom projectile component that uses line traces so it's a little bit less chaotic than something that uses a shape

#

The meat of the problem is that all the machines are going to disagree on what the exact state of the world is if you have any sort of prediction. So you have to pick and choose which client to prioritize in certain situations

#

The OverWatch guys have a great talk about this

verbal tendon
#

@grizzled stirrup I've done this before in a game and it's totally viable. As long as you carefully craft the relationships between actors involved

#

Local projectiles can only affect the local player. Players report when they are hit, other players dont care about anything but themselves

#

that way even when the gamestates are technicalyl not deterministic at every frame, they are deterministic in the end as gamestates sync up when the individual players report events that affect everyone ( Like player X reporting that they are hit/died )

#

Obviously caveat is that your game design cannot have the actions of one player affect that of another / or the projectiles

#

There are restrictions making a game this way that you need to be very conscious about

#

It's not just about PvP

#

Assume one of the game designers decides they want to give players ability to make a "bubble" in which projectiles are slowed

#

now you have the actions of one player potentially affecting the projectiles of another, and it's a quick slippery slope of "oh shit"

#

Yes it would still work, but it wont be quite as expected

#

because projectiles are localized, if you have someone playing with latency

#

you now potentially doubled the time it takes for the effects of one player to affect the gamestate of the other

#

instead of it being half while actions are server authorative with client predictions

#

I'd be cautious when making such a choice, you do lock yourself into a certain direction. It is possible, but it's certainly not there for most games

#

Yup. And also if there is killing involved, who gets the kill on an enemy doenst matter, two separate players can see doing the final blow on an enemy ( if you go down such a route, there are lots of choices to be made here ), but ofc the server will know the enemy was already dead when the 2nd fatal hit is reported

#

that's something else to be aware of, you're going to need those extra checks on your incoming data

#

Is this for your 9-5 or for a project on the side?

#

Sorry I gotta take a call, i'll be back in a bit later

#

This isnt a call to be made easily

#

Sure as I said all of this is possible, you just gotta know the pros and cons of the different implementations and make the best call for your game

#

The next thing you want to do is create utility functionality for those specific RPC calls. Since you're gonna need 2 RPC calls for each action (1) owning-client-actor to server (2) server-multicast . Then on reception not run it for the original actor, and ofc run the code instead instantly when it does (1) and that can be the foundation for this particular networking model for your various actions that you want to run that way

#

No you need to filter on the receiving end, but that's trivial to do

#

Yeah ๐Ÿ™‚

rancid flame
#

I'm encountering an issue where nullptrs are appearing in a replicated TArray<T> of UDataAsset subclass instances. It's an inventory and on picking up something I'm using NewObject<UInventoryItem>(this, ItemClass) and adding it to the array.
Is there a way that objects could be cleaned up or the array replicated with nullptrs?

kindred widget
#

@rancid flame Little lost. Why are you replicating the DataAsset pointers?

harsh lintel
#

what is an acceptable Net-Culling distance for player characters in a 30 player game?

rancid flame
kindred widget
#

I mean more where is the DataAsset coming in?

rancid flame
kindred widget
#

So UBYGInventoryItem is a DataAsset subclass?

rancid flame
kindred widget
#

I would reconsider that a little. DataAssets are not used in networking like that really. DataAssets are pretty much Datatables, with functions. They're mostly for static game data. It's likely your inventory items should just be a simple UObject.

#

For instance. you might have a DataAsset or DataTable with a GameplayTag key in it. Make a UObject with two replicated values, Tag and Count. These replicate, and you could use the tag to look up that object's static data in the datatable or DataAsset like It's name, max counts, icons, meshes, etc. Then count is of course changing so it needs to be sent from server as well.

rancid flame
kindred widget
#

That might be fine. Though if UInventoryItem is a DataAsset still, it needs to be a pointer to the asset, not the class. DataAssets are like Textures or Meshes in that regard.

rancid flame
#

It's worked so far with TSubclassOf heh

lost inlet
#

lotsa hard refs

rancid flame
kindred widget
#

Me personally, I don't like passing classes around a lot. I prefer just looking up basic data from a basic key. So my system is set up off of GameplayTags. Two serious reasons for this. One is that the class method requires a bunch of small classes for the items themselves. Each item needs it's own class. 2,000 game items later.. and that's one hell of a content browser. Also it's just unweildly for design. You have hundreds of items, you have to remember hundreds of classes and their data setups. This is much easier to handle in tables than it is opening multiple classes to edit things.

rancid flame
kindred widget
#

Tags also allow you to switch gameplay logic without even looking anything up. Consider use items for instance. GameItems.Consumables.Apple versus GameItems.Throwable.Grenade You use this item. Logic branches on the tag. It's a consumable, so you look up the consumables table, get the data you need and execute that logic. Or if it's a throwable, so you set up the gameplay logic to change controls so that the throwing indicator shows. Not to mention because the tags are tiered, it allows quick lookup for the tables.

rancid flame
kindred widget
#

But yeah. For DataAssets, you'll want straight pointers. Either SoftRef or a usual Hard pointer.

#

Class pointers would work if you had UObject subclasses instead of data assets. Then you could replicate the class pointer and look up CDO data.

rancid flame
#

It still doesn't really explain why my pointers to instances of UDataAsset subclasses would be null in my array tho

kindred widget
#

They are, but you don't really instance them. Not normally anyhow.

#

And that's fair.

#

To be honest. I've never tried replicating a TSubclassOf of an asset type before. O.o

#

The count replicates fine?

rancid flame
#

It's just if I pick up and drop items very quickly as a client, suddenly one of the entries in the TArray is nullptr

kindred widget
#

Do they replicate normally otherwise?

rancid flame
grizzled stirrup
#

Is the first player controller in the world ALWAYS going to be the local player, regardless of it being a client or a listen server host?

kindred widget
grizzled stirrup
#

I'm using C++, which library func is this?

#

GetWorld()->GetFirstPlayerController ?

kindred widget
grizzled stirrup
#

Ah very nice! Getting it from the GI will guarantee it's the local one

#

Thanks for the example

kindred widget
#

I have a simple static template. Same function name for a blueprint non templated function.

#
template <class T>
T* UTarrionObjectLibrary::GetLocalPlayerController(const UObject* WorldContextObject)
{
    static_assert(TPointerIsConvertibleFromTo<T, const APlayerController>::Value, "");
    
    UWorld* World = WorldContextObject ? WorldContextObject->GetWorld() : nullptr;
    UGameInstance* GameInstance = World ? World->GetGameInstance() : nullptr;

    return GameInstance ? Cast<T>(GameInstance->GetFirstLocalPlayerController()) : nullptr;
}```
#
APlayerController* UTarrionObjectLibrary::GetLocalPlayerController(const UObject* WorldContextObject)
{
    return GetLocalPlayerController<APlayerController>(WorldContextObject);
}```
random verge
#

I'm just curious if anyone knows if Fortnite already uses the push model for replication or not?

small onyx
#

does anyone have a guide to multiplayer possession for clients in a listen server?

winged badger
#

you just call possess server side?

#

not quite sure what would a guide talk about there

#

it also doesn't matter much if its listen or dedi

small onyx
#

so currently i have the character controller unpossess it's current pawn then multicast a spawn event and then have that controller possess it

winged badger
#

you're doing a multicast from client

small onyx
#

i believe so

winged badger
#

yeah, thats not good

#

spawn actor and possess should be only ever executed on server

small onyx
#

okay i'll make some changes and see if that works if it doesn't i'll be back here in a bit.

small onyx
#

would you unpossess client side?

lost inlet
#

no

ornate surge
#

completed this 24hour course ๐Ÿฅต

#

is there any good tutorial for setting up dedicated servers?
can you only make dedicated servers from the github source code instead of the launcher version of ue4?

rapid bronze
#

Yes

violet sentinel
fierce grove
#

Hello can I start listening to a pixel streaming streamer at runtime?

meager fable
#

Looking at FOnlineSessionSteam there's

uint32 FOnlineSessionSteam::FindInternetSession(const TSharedRef<FOnlineSessionSearch>& SearchSettings)
{
    bool PresenceSearch = false;
    if (SearchSettings->QuerySettings.Get(SEARCH_PRESENCE, PresenceSearch) && PresenceSearch)
    {
        FOnlineAsyncTaskSteamFindLobbies* NewTask = new FOnlineAsyncTaskSteamFindLobbies(SteamSubsystem, SearchSettings);
        SteamSubsystem->QueueAsyncTask(NewTask);
    }
    else
    {
        FOnlineAsyncTaskSteamFindServers* NewTask = new FOnlineAsyncTaskSteamFindServers(SteamSubsystem, SearchSettings, OnFindSessionsCompleteDelegates);
        SteamSubsystem->QueueAsyncTask(NewTask);
    }

    return ONLINE_IO_PENDING;
}

What's the difference between FindLobbies and FindServers Tasks?

grizzled stirrup
#

I believe lobbies are listen servers and servers are dedi servers

thin stratus
#

Yop

meager fable
#

thanks

thin stratus
#

That's what the presence stuff is for basically

grizzled stirrup
#

But remember SEARCH_PRESENCE is now SEARCH_LOBBIES in 4.27

meager fable
#

also what does the EOnlineComparisonOp mean when setting QuerySettings

        m_pSessionSearch = MakeShared<FOnlineSessionSearch>(FOnlineSessionSearch());
    m_pSessionSearch->QuerySettings.Set<bool>(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
thin stratus
#

When creating a session

#

You can provide settings

#

Like GAMEMODE

#

or MAP

#

Or whatever makes sense for your game

#

When searching, you can specify basically a filter

#

Let's say you have a game like... idk... Dark Souls. Where you always have a Session running to get invaded.
Now you would have some setting called CanBeInvaded, which the player's game might update depending on specifics in the gameplay.

When searching for Sessions as an invader, you can then have a QuerySettings check for CanBeInvaded needing to be "true"

#

So ``true, EOnlineComparisonOp::Equals

#

Or maybe you want to filter password protected servers

#

Where you pass in a boolean for "This server is pw protected" and you can filter them already in the query

#

Of course some filtering can be done on the client side

#

By just not showing the results, but that's not always a solution

meager fable
#

that makes sense

#

but why is it also provided when setting a variable

thin stratus
#

There are also DoesNotEqual or so as options

meager fable
#

does that actually matter then?

thin stratus
#

Because you are filling in the settings for querying that you then give to the backend

#

The line you posted says

#

"Search for Sessions with PRESENCE being TRUE"

meager fable
#

ohh

#

I get it now

#

thanks for explaining

thin stratus
#

m_pSessionSearch->QuerySettings.Set<int32>(NUM_PLAYERS, 0, EOnlineComparisonOp::Greater);

#

That's pseudo code, but that's a line that could search for sessions with the NUM_PLAYERS (whatever that is) setting having to be greater than 0

#

Not sure if Greater is an option on that enum, or NUM_PLAYERS already being defined

#

OnlineSessionSettings.h has a few defines

#

You can make your own of course

#

Or just hardcode the FName

meager fable
#

yeah seems like it provides all common comparison operators

enum Type
    {
        Equals,
        NotEquals,
        GreaterThan,
        GreaterThanEquals,
        LessThan,
        LessThanEquals,
        Near,
        In,
        NotIn
    };
#

looking at it I wonder how near works

thin stratus
#

m_pSessionSearch->QuerySettings.Set<int32>(SETTING_NUMBOTS, 0, EOnlineComparisonOp::GreaterThan)
m_pSessionSearch->QuerySettings.Set<FString>(SETTING_GAMEMODE, DesiredGameMode, EOnlineComparisonOp::Equals)

#

Some examples

meager fable
#

like when a value is near another value

thin stratus
#
if (SessionKeyToSteamKey(Key, SearchParam.Data, KeyStr))
{
    if (SearchParam.ComparisonOp == EOnlineComparisonOp::Near)
    {
    //Near filters don't actually filter out values, they just influence how the results are sorted. You can specify multiple near filters, with the first near filter influencing the most, and the last near filter influencing the least.
    switch(SearchParam.Data.GetType())
    {
    case EOnlineKeyValuePairDataType::Int32:
        {
            int32 Value;
            SearchParam.Data.GetValue(Value);
            SteamMatchmakingPtr->AddRequestLobbyListNearValueFilter(TCHAR_TO_UTF8(*KeyStr), Value);
            break;
        }
    default:
        UE_LOG_ONLINE_SESSION(Warning, TEXT("Unable to set search parameter %s"), *SearchParam.ToString());
        break;
    }    
}
else
#

Guess Steam just uses it to sort the results

#

So the closer a session setting is to the specified value, the higher in the list it will be

meager fable
#

makes sense now

#

thanks for the explanation again

thin stratus
#

No worries

grizzled stirrup
#

Anyone notice a much much longer time loading when testing multiplayer standalone in 4.27? It used to take a few seconds longer than a packaged build, but now it takes about 20-30 seconds to load the main menu and 20-30 more seconds to load a session map. This makes testing 3 player multiplayer instances extremely painful as iterations have to be made frequently and there's now loads of extra waiting around per instance

peak sentinel
#

Man, when I'm gonna hear a good thing about 4.27 lol

grizzled stirrup
#

Oodle = great but so far I'm noticing longer editor load times and much much longer standalone loading times

#

This issue doesn't happen when packaged, it's fast as usual

peak sentinel
#

Well yeah things introduced with 4.27 is good but its shipped broken

grizzled stirrup
#

Only clue I can see in the logs is UNetDriver::TickDispatch: Very long time between ticks. DeltaTime: 17.16, Realtime: 0.05. IpNetDriver_1

#

But that's just letting us know that it's taking forever

grizzled stirrup
meager spade
#

i got quicker editor loading time

#

with 4.27 compared to 4.25..

grizzled stirrup
#

Can you verify opening a standalone instance of the game doesn't take an ungodly amount of time?

#

Like 20-30 more seconds than usual?

#

If so then it thankfully must be on my end

meager spade
#

i don't open standalone in editor

#

always test outside

grizzled stirrup
#

No from the uproject

meager spade
#

yeah i dont use that

#

๐Ÿคท

grizzled stirrup
#

You make a packaged build for each iteration?

meager spade
#

every test iteration yes

grizzled stirrup
#

I'm debugging code here that requires a unique GI per instance and that'd take all day doing that

grizzled stirrup
#

What has broken with Niagara?

peak sentinel
#

But I'm not using 4.27

#

People were complaning about it a lot

#

a lot

meager spade
#

Niagara is broken in all version

grizzled stirrup
#

In the discord channel?

#

I'll have to check

#

Heavily using it

kindred widget
#

Standalone loads at the same rate in 4.27 that it did in 4.25. If your standalone is taking a long time to open, you're loading too many assets at once.

grizzled stirrup
#

Ok good to know, I'll test with a blank proj

kindred widget
#

Can definitely confirm that editor opens a ton faster in 4.27 though. Work project went from 1 min 26 seconds to about 48 seconds.

grizzled stirrup
#

Previously with the same assets it loaded in like 2-3 seconds on 4.26

#

So maybe the way the engine is loading them has changed or something in 4.27

#

Shouldn't be taking close to 30 seconds

kindred widget
#

My Standalone take forever to open on work project, but that's just because we use a singleton that has a lot of data and stuff connected to it. On personal projects it's barely slower than opening PIE.

grizzled stirrup
grizzled stirrup
#

I'll try on a different machine and with test projects, thanks!

#

If not it's time to get into weak object pointers I think

meager spade
#

soft object pointers ๐Ÿ˜›

kindred widget
#

^

grizzled stirrup
#

soft yes ๐Ÿ˜„

#

But I suspect it's to do with something else in my project as it loaded so fast before

#

Haven't touched anything but just upgraded

kindred widget
#

One weird thing about testing in 4.25 vs 4.27. 4.25 had a weird severe lag when replicating a few hundred UObjects in an array in PIE. Doesn't even hitch on 4.27

grizzled stirrup
#

Engine upgrades are a curious minefield eh? ๐Ÿ˜„

kindred widget
#

I remember finding some mention that it might have been due to some logging or something. Could never find anything about it. ๐Ÿคทโ€โ™‚๏ธ Absolutely glad it's gone though.

meager fable
#

is there some kind of delegate that happens on the clients during servertravel? I want everyone to fade to black on level travel

meager spade
#

there are many things

#

but delegate likely not

#

but the controller has somethings that get caleld

#

void APlayerController::PreClientTravel( const FString& PendingURL, ETravelType TravelType, bool bIsSeamlessTravel )

#

ah

#
{
    OnNotifyPreClientTravel().Broadcast(PendingURL, TravelType, bIsSeamlessTravel);
}``` this also gets called
#
    FOnPreClientTravel& OnNotifyPreClientTravel() { return NotifyPreClientTravelDelegates; }```
crystal crag
#

Why is discord search so terrible? I search for my username and it says it can't find any messages, yet I was just writing messages out a few days ago in this channel.

sinful tree
#

Are you including from:?

crystal crag
#

yeo

#

*yep

#

I'm just trying to find an older conversation I had with someone. I can't remember if there is another method that gets called by the engine on the server when a player disconnects other than in the AGameSession class.

#

Also google is not helping me find the answer either ><

#

GameMode has PostLogin but I don't see anything in the source such as PreLogout / etc.

#

Oh nevermind. I am just blind apparently.

#

There is a Logout method

sage isle
#

I was trying to create an object that the players can interact with, when they approach a widget was supposed to be displayed and then they could interact with it. However, when any player gets near the object the widget displays on all their screens and everyone can interact with it no matter how far away they are, I am struggling with trying to fix this.

kindred widget
sage isle
#

Yup, that did the trick!

small onyx
#

So i've spawned a pawn and controller on the server

#

however how would i enable the HMD Enable (for vr) for the client

#

i create a event to run enable HMD on running client but it just freeze the application

dull tinsel
#

I'm still looking for how to make 3d widgets receive player input when playing in multi-player
Works fine in stand alone.
Anyone have any ideas?

grizzled stirrup
#

When logging out the name of a replicated actor on the client, is it normal that it can have a name like BP_Character_C_1 but a different actor on the server could also be named BP_Character_C_1?

#

Are the names generated clientside right based on the order they were added into the world on each local machine?

#

I noticed this after a seamless travel

grizzled stirrup
kindred widget
#

I don't know the exact conditions it happens, but there are cases surrounding servertravel where on a listenserver GetPlayerController0 can actually return a client's controller. This will never happen on a client itself.

#

But with the GameInstance call, that won't happen. Cause that only returns local controllers. Only way you're getting a wrong one with that is if you're running multiple players on a local coop.

grizzled stirrup
#

Ok great thanks!

#

In that case do you know if it's possible for two different actors to have the same name (one on the server, one on the client?)

#

When doing SomeActor->GetName()

#

In my case after seamless travel, the local pawn changed from BP_Character_C_0 to BP_Character_C_1 but the server pawn stayed at BP_Character_C_1

#

Am I correct in saying that these names are generated for each machine even if it's a replicated actor so it's fine if they are not matching with the server?

kindred widget
#

Possible I assume. At least as far as I know, there only two ways in which things tend to have stable names. One is loaded with level, I think those are name stable, and there is supposedly a way to name stable spawn actors on client and server at the same time, but with the same name, which allows predictive spawning of replicated actors on clients. Never bothered with it personally, but I know traditionally spawned actors aren't name stable.

grizzled stirrup
#

Ah excellent thanks!

#

Glad it's not a hard rule that they'd always match

#

In this case I assume the servers pawn replicates down first on the client after the seamless travel, therefore making the local pawn second in his local world and needing the _1 suffix

rocky kestrel
#

I'm trying to make plane rotation in multiplayer correct. What I'm doing wrong? Problem: rotation of controlled plane doesn't match. player sees own plane rotating about 2x slower than it should.

#

This works kind of but very bad way to fix I think

kindred widget
rocky kestrel
#

@kindred widgetIn event tick I'm updating spring arm's world rotation to point middle of planet Earth. but yeh.

kindred widget
#

I admit. For the sake of beginning, I would make this client authoritive.

#

It's quite a bit simpler than server authoritive, client predictive movement.

#

The basic idea of client authoritive is that you simply do the rotations on the client, and then you server RPC the yaw float to server and let that replicate, set the replication condition to skip owner.

#

So.. MoveRight would be CanMove->FigureAndSetRotation->ServerRPCNewYawValue

#

Then you set the yaw value on server, set it's replication condition to skip owner. Then in your tick function, you branch at IsLocallyControlled, if not locally controlled, interp the rotation to whatever server is sending. That'll keep it looking mostly smooth even if you get irregular updates.

rocky kestrel
#

Thanks! But umm I'm so beginner at replication that I don't understand what should I do.

#

set Rotation variable to skip owner and set it in server function?

kindred widget
#

One sec. This is inside of a Pawn blueprint, or?

rocky kestrel
#

yup!

#

I mean character is parent class

kindred widget
#

Hmm. Part of the issue is that you don't have an easy way to reconstruct the float into something meaningful.

#

I have some math functions that would help, but they're all in C++. :/

woeful lichen
#

I'm having a bit of an issue that might be a bug, but I'm not sure: The initialization for my level involves spawning two actors, and then setting one actor (call it Actor1) as the parent to the other (Actor2). Note that the second actor will eventually be detached and live independently, so I don't believe I can use a child actor component. Unfortunately, both of the actors cannot be part of the level itself, and instead are created on the server, and then replicated to the clients. On the server, it works correctly, but when it replicates to the clients, it seems to set the relative location of Actor2 to be the world-space location. Thus, Actor1 will be at the correct location on the client, and Actor2 will be parented to Actor1, but be at Actor1's location times 2! If I add a delay after spawning the two actors (say, of 3 seconds or so), the parenting works correctly (Actor2's relative location is 0, since it's parented to Actor1). Is this just a weird networking race condition?

rocky kestrel
#

:/ This is full Bp project And I don't have experience of c++ "only one university basic course" ๐Ÿ˜„

kindred widget
#

@rocky kestrel This may or may not help you. But I translated some of those functions to BP, at least the relevant ones. This is the pawn blueprint. Really simple. The only thing missing here is the vectors for your planet's up vector and location. I had planet actors I got that from via simply GetActorLocation, GetActorUpVector.

#

The rest of these functions are in a BP library. Hence the need for the world context pin in some of them. Some of them use the others.

rocky kestrel
#

@kindred widget thank you!!!

#

You did a lot

dark edge
#

@rocky kestrelIf you need stuff to stay in sync, don't replicate the additions etc, replicate the results.

Simplest replicated movement I can think of goes like this.

Tick -> Is Locally Controlled? -> Get Axis Value -> Send to server
Server recieves axis value -> updates rotation

rotation is replicated by checking "Replicate Movement"

#

This will have a ping delay but will match everywhere. Later you can transition to locally setting rotation, sending that to server, letting it replicate out as a variable, and then onrep, setting it.

pastel tangle
#

How do you posses a character

#

in multiplaye r

#

as a client

#

?

kindred widget
#

@pastel tangle RPC to server from client's controller, and have the server version of it call possession on the pawn you want.

pastel tangle
#

sorry how do i do that

#

can you explain in private chat?

#

@kindred widget

kindred widget
#

Not really sure how to explain that more. It's a single RPC with an actor or pawn parameter.

pastel tangle
#

i mean how do i do it in code

#

i didnt quite understnad

#

whats an rpc

kindred widget
pastel tangle
#

im spawning players through widget

#

what do i cast to for "has authority"

#

and is this even how the code is supposed to look for spawning and possesing in multiplayer?

#

halp pliz

#

ok so i came up with this

#

the client doesnt posses the character on button clicked for some reason

still arrow
#

Does anybody know if/how Unreal natively handles WiFi Direct compared to regular WiFi? I'm currently working on an android mobile game, the networking of which already properly works, but since the game concept doesn't go beyond local coop, I'd like to add options for players without router access, eg. on the train

meager fable
#

what is the cost of sending an actor through RPC? Is it just a 4bit pointer or something massive?

kindred widget
#

@meager fable 8 bytes if memory serves. Basically enough data to resolve the pointer on the other side. Nothing major.

surreal plaza
#

I am trying to posses a pawn that the character is carrying around through server authorization. Will I need to pass the server method a reference to the given playercontroller or does getcontroller automatically return the relevant player on the server?

meager fable
#

wonderful, thanks

kindred widget
#

IE, shouldn't need to pass the controller through. Server set the values client has anyhow, so it should have the data for it.

surreal plaza
kindred widget
#

Er. Not sure what I was thinking. I don't even think you need to cast that to a player controller.

fluid flower
#

Hey all, what do you all use for server deployment/orchestration and monitoring? I'm looking to either implement something myself but before I do, perhaps there's some good solutions out there already.

near swift
#

are there any tutorials about client side prediction besides the one on game dev .tv

twin juniper
#

Why "Auto Posses Player" Player1 not works for the client?

#

I thought I can use this as a quick way to assign characters to clients in order

#

For server Auto Posses Player 0 works well

#

But as the client joins he will get the default pawn instead of the wanted one

exotic spindle
#

is there any preprocessor directive for dedicated server? Like #if PLATFORM_WINDOWS

lost inlet
#

UE_SERVER

exotic spindle
#

that was quick. Thanks.

twin juniper
#

Why there are literally zero documentation on how to make the engine connect to a server, or host one on the official site?

keen surge
twin juniper
keen surge
#

there is a full tutorial series by unreal engine about hosting/joining sessions using listen server (and even connecting it through steam)

exotic spindle
#

@lost inlet any chance the same also exists for the .build.cs?

#

nm, found it ๐Ÿ˜…

keen surge
#

yeah that one is fairly limited...

twin juniper
#

Only Starting a Server console command is being mentioned

keen surge
#

there's also a lot of useful resources in pinned messages

#

In this video we take a look at the finished project and step through each of the features that will be covered in this series. We show our functional Main Menu and its options, a lobby where players can chat with one another and select their characters for the game, some server options such as changing the map or match time as well as the abili...

โ–ถ Play video
#

this is the tutorial series, altho a bit outdated

twin juniper
#

I just found that one ye

keen surge
#

for C++ there's sadly even less documentation etc

#

but most of it is very similar

twin juniper
#

I have a really good c++ tutorial series by Tom Looman from Udemy, I almost learnt there everything I know

#

but he used commands to connect clients not via Blueprint/c++ function

#

that is what I am interested in how should that be done

#

Idk if I could use "Execute Console Command" BP

#

cause I will have no console enabled

rose prawn
#

I have a question. Would you prefer using replicated variables for late connection or calling functions manually as player joins to the session? If I use Replicated Using variables, I don't really have to manually trigger anything since the variable will trigger function in any changes. But it will be replicated all the time so it might become costly, but manually triggering functions without replicating variable seems too much work. (but less costly)

keen surge
#

I've also found a tutorial later to create and join sessions through C++ if you would like

#

which also includes steam

twin juniper
#

@keen surge Maybe do you know how to execute smth on the server when a client connects? In Blueprint

keen surge
#

No clue, I don't work with blueprints for MP

silk pilot
#

Does this work as a switch to allow certain "threads?" through?

kindred widget
#

It does. But it's some weird assumptions.