#multiplayer
1 messages ยท Page 677 of 1
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
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
Index based method being what I proposed earlier or something else?
yeah, but I was curious about this other method of GetFirstLocalPlayerController, I dont see the option from blueprints, is it cpp only?
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.
on a 500bpm metronome
๐
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
does COND_InitialOnly removes the object from replication computation once its replicated?
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)
Well...if it doesn't open the ip then it'll keep on trying again and again until that server exists and once it does it'll join it instantly!
Well u can't predict when a person will cast a spell
is there no timeout?
i don't believe there is, you'd get more functionality like that with the native nodes or with advanced sessions
thanks @woeful pebble
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?
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
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
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
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
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
Easyโข๏ธ Anti Cheat
Lol
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
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
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
the FUniqueRepID for all players is stored in the session info
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?
a timer that the player sees?
Yes
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
yeah, player state or controller for that
controller is appropriate as it's only relevant to the player the respawn timer pertains to
well we show respawn times for all clients
then PS if that's the case
so its either controller if only client sees, or playerstate if all sees
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?
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?
(unless the cheat is on a listen server..) ๐
ah yeah but you have the keys to everything anyway
yeah that is why you never make a competitive game with listen server.
I guess the respawn timer inside PlayerState is a replicated variable, but even then the server has authority?
(Sorry I'm still trying to get my head around multiplayer)
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
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...
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
Data assets are content, so they don't replicate any more than a texture. Use a struct instead for procedural content.
Make sure your actors are marked to replicate.
Yeah thats what I was kind of worried about haha. Yeah I guess I have to move all of the data asset's base stuff into a struct and then throw the struct into the data asset...
Data assets are completely unrelated to multiplayer, they're fixed baked content
They cannot replicate
I mean... it is possible to make a UObject replicate... just don't wanna do that haha
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?
By design data assets cannot replicate, it would make zero sense, they're assets - game content in a pak file
I know
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
That sounds like you don't actually want Data Assets
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
Json page fetched by the server from a central authoritative server/db, deserialized into a replicated struct
Maybe 20 lines of code
๐
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
But for our game the assets will not be on the hard disk until its been pulled from the server
Are you going to be patching it in via DLC?
Nope
How do you plan on inserting the content
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)
@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
Oh interesting, ty!
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.)
what if;
checking walls in the server and player each other(lets call line trace in easy)
if there is wall, remove the character from server on that player, so wont get any data (move location, character actor etc) for that
then wallhack player wont see any players when behind in the wall. 
That works slick except at literal edge cases.
You won't see pawns as they come around the corner.
adjust some offset
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.
Way easier said than done.
never tried that but brainstorming is allowed ofc
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.
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 
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.
Yes but where do you aim on that bigger collider? The center and edges are obvious but if it gets bigger then even that don't work. Then you're firing like 36 rays at a big collider per pairing. It gets weird fast. The edge cases are aiming thru small gaps etc. It'd be very easy to miss the opportunity to hit the big collider.
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.
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.
Do you have it set up so that the widget is being created on the Character?
No its being created on the player controller.
is there anyway to detect if a physics object is desynced for clients on the server side?
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
@bronze arch @dark edge this was the Valorant approach, great article
https://technology.riotgames.com/news/demolishing-wallhacks-valorants-fog-war
Fun fact, I wrote a PVS occlusion culler for a demo which got me my first job in games back in 2003.
The problem is how to check the wall
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
@silent valley @thin stratus thank you for such a good informations!
i wasnt deep in to this because my game doesnt need for that at that moment.
while researching i found something i guess. might this helps ?
https://github.com/87andrewh/CornerCulling
seem project is up to date
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
hello, does the server only replicate an actor to the client if a property changes?
Yes. And only after the end of the frame. So changing a property 500 times in a single frame, it'll only replicate once.
Hey anyone know why my 3D widgets don't accept input anymore if I play in anything other than standalone mode?
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
You're hoping to reduce the JSON output size?
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
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).
thanks
what exactly tells the server that a property has changed though?
Are you using Blueprint or C++?
c++
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.
alright, thank you!
Ahaaaa. So i was somewhat on the right track. You open for freelance? Might have a couple things for you.
Sorry I have my hands full at the moment! I also have some roles open in the job channel if anyone wants to come work with me on an online survival game ๐
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:
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?
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
}
}
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
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
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.
They're not as popular, but personally I like Kismet PrintString. It literally tells you what machine it's printing from. ๐
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
Thaaaanks! I'm gonna give it a try
Does it also work in C++?
UKismetSystemLibrary::PrintString(this, "StringHere");
Thanks a lot!!! ๐
That was it! Thank you so much
Nice. So this is confusing, the code is being called with HasAuthority() returning true, but according to Kismet, the code is being called by the Client and not the Server
But you said you spawned the controllers on the client?
Just understood
Authority != Server/Client
Exactly!! Thanks
If you want a check for server, use GetNetMode() < NM_Client
perfect, thanks! ๐
@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)
Pretty sure those are all replicated from the PlayerState?
Ok cool
I was thinking that they were replicated, but I wanted to make sure I wasn't going to be doing anything bad.
does the "Is Server?" node return true if it's a listen server host or dedicated server?
Yes
thanks
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.
Should really just use clumsy anyway, no need to setup anything, really convenient
But yes, what Kaos said
Simulating a ton of latency
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...
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
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
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
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
Got it, good stuff, thanks!
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?
Authority != Server/Client.
Your replicated variables should be set to RepNotify. When the server value changes, the generated OnRep function will be fired and this is where you can update your UI from. Also in that current set up your timer code would be started on clients as well, but that's not really necessary since it's really only necessary to run on the server.
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
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.
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
PostLogin is server only function
you can't create client UI from there
as UI can only be created locally
I am calling a spawn UI function in the client playerController from PostLogin
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
So create a HUD BP, and move the logic from PlayerController over there? Isnt playerController parent of HUDclass?
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
how do i make it lag in 4.26 netemulation.paklag isnt working
Packet lag works fine, how did you set it up ?
im following the tutorial on gamedev.tv im just using it in the ` in game and using the command
Put this in DefaultEngine.ini
[PacketSimulationSettings]
PktLag=100
PktLagVariance=10
PktLoss=5
PktOrder=1
PktDup=0
ok thanks
4.25 and later
have it under play options too
you don't need to enter commands by hand
default engine change requires editor restart
same thing
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
i figured it out the = sign is redundant
I would do it field based with influencers. Much how you don't replicate lighting, but replicate point and directional lights.
I would start with a directional wind, and some vortex and scaling actors.
WindVector = GlobalWind + LocalWind + slight noise
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?
@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.
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?
It should not. You should be able to use it same as singleplayer.
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.
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.
How would i check if this client is owning a character actor?
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.
I didn't know about these options. Than it's a way easier than i thought. Thanks!
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?
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?
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.
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.
Where is this int array stored in the first place?
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
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.
thanks, man. I will give it a whirl
I'll need to think on this since I actually need two pieces of information and not one for the rep notify
Can always put it in a replicated structure if that's the case.
Something just came to me, not the most ideal method but just need to see if it works
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?
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.
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)
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
Those are created by the engine, not doing anything revolutionary and building on top of the existing multiplayer functionality
Anyone use wwise voice chat? Wondering how it compares to vivox
Just wondering if @chrome bay has a clue, since I see that you've written about PackageMap in here before ๐
well if you use the one from the engine, then these already have the ptr to the correct map
FNetBitReader::PackageMap or FNetBitWriter::PackageMap
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
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
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 ^_^
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?
It's not possible to share the GUID no - each Package map is for each client connection
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
That's what I was fearing ....
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
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
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
The multicast doesnt know that it contains that data
Reflection does know
No it only gets a bitstream
But it knows what that bitstream represents
Data is (almost always) uniquely serialized for every connection
No idea never done it
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
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
no, just for that
You can use it for a lot, custom compression, forcing atomic state etc.,
But you can support a degree of polymorphism too
just joking
yeah I use a lot of custom serialization when I reach the end of unreals default support^^ like for templated types
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?
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)
};
};```
Hm interesting. Something to explore, thank you that's info I didn't have before
I gotta see if that fits the bill
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 ๐
Link you too? ๐
Yeah I saw a thread somewhere that gave me ideas ๐
yeah if I was the one writing in it (TheJamsh) - wipe it from your memory
I didnt take the same approach ๐ but it was a fire spark
Which is how I ran into the issue with packagemap
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
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 )
yeah you can use NetSerialize to do things like send polymorphic data etc.
Iโm trying to use UCLASS() objects instead of USTRUCTS() in my custom networked movement component. The idea is, I want to build a master component that handles all the primary replication - and then child classes can add custom properties. For example, hereโs a struct thatโs used so send client input. The issue is, I want to be able to send ch...
yeah.. christ I'm deleting that thread
This topic currently has over 5000 views and may be a popular search destination.
RIP Google search
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 โฐ ๐
yeah I was more active on the forums when I was dumber ๐
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"
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
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?
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?
This shouldn't have anything to do with Sessions.
I thought it was because in the engine running
1 as a listen server and the other as a client works completely fine
but when I launch the project as a game to test it out
I get this issue
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.
welp
now not even the host can control the pawn
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
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!
@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
๐คฆ
Easy is good! That's why you check for culprits. Glad you got it sorted!
next time Im gonna make sure to always use the node
even when it might not be necessary ๐
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
Is that while using a packaged build or in PIE?
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)
packagedf build, PIE works or in standalone
essentially packaged build will crash but running in UE it works ok
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
sure let me do that, it didnt seem helpful i have verbose logging on
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 )
Do you not have a stacktrace on crash?
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
is that just packaging as debug instead of development?
you should be able to get PDB files regardless of what the build type is
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.
hi, why am i getting this error?
LogRep: Error: InitWithObject: Object == NULL
LogRep: Error: StartReplicating: Object == nullptr
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
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
I would not use that if u are looking to avoid cheating generally as you are given the client authority over its movement during that time
Also if u want client auth movement u also have to enable server take client position or whatever
It's fine to enable it for a small amount of time on my case, I'm just wondering how can I know the time to disable it back
Because afaik there isnt any other way to allow high velocities on client without that boolean
I would rather just have them be predicted and be corrected then use client auth
But idk u do u
Anyone having issues with creating a session in 4.27? Returns failed for me all the time.
Got the correct setup going, and all works fine in 4.26. I'm using Steam Online Subsystem.
Seemed to find the same issue here:
https://answers.unrealengine.com/questions/1049704/view.html
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?
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
I'm not sure what you're missing, but one thing I will point out is that it's not generally a good idea to NewObject actors. NewObject is usually reserved for components or below except for components in constructors which is CreateDefaultSubobject. World's SpawnActor should be used for Actors or their inheritors.
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.
Sorry, yeah I can see how that looks confusing. I'm normally creating it from the game mode but I added the same code in the pawn as part of the input, just to make sure I didn't accidentally write it too early or that it got re-initialized to null later on. So when the pawn sees input, I create a new team state and write it. This is very temporary and was just to try and figure out the issue.
I would definitely start with switching the creation calls. If it's an actor, always create it with SpawnActor.
That was it! ๐ Thank you!
You probably saved me a couple of hours of digging into NetDriver.cpp ๐
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.
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
You're going to have to be a little more specific with your description. If you rotate an actor ( with everything set to replicate ) on the server, the client should and will see the changes
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.
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 ๐
Even when the weapon is not replicated, it still moves on both the server and client
Yep, pretty much with replication turned off
Can you share some code or screenshots of what you're doing for us to help you further?
Note though that theres a function that updates it pitch of the weapon with the camera's
Airt
@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?
Not sure
But the problem is both weapon bp on both client and server are facing the same direction
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 )
@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.
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
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
Does that make sense?
Will try that now
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
@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.
Got it, thanks
Apologies, I tried using the camera like u suggested and it sorta works but the weapon is going out place and its only the pitch I intend to match with the camera movement
Also tried a component but when I try to write a code to match the pitch, it also moves with it
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
What's the best way u would recommend
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
Can you debug a packaged game with blueprint debugging if its blueprint code ur trying to debug?
Alright, how do I use the camera method correctly, cause it keeps going outta place
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.
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!
You can't possess client side first of all. And second, you're accessing a few pointers without checking them. The second would be my guess about the crash without seeing any crash reasons.
Great! Thanks.
is there like a great in depth explanation of how pawn/controller works when a client is joining a server?
If you read C++ well enough, your best bet is probably just to start from the login function and go through it.
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...
Try at 14:10
Do you guys do items as UObjects or UStructs for a multiplayer item/inventory system?
How do you make client predict that? It corrects you instantly when you reach a specific value on client
I have a more simple (and weird) inventory system but I'd use UObjects for a generic approach: https://jambax.co.uk/replicating-uobjects/ (Jambax also explains inventory system with UObjects there, dont mind the title)
i use a mix of both ๐
struct for replicating, UObject gets created/destroyed locally
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?
PlayerStates are Always Relevant
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
Pawns would be a better example.
ok then, let's say Pawns. Is what I am thinking correct - it would still exist in memory?
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.
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
Why do you need a mix of both?
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.
In a game atm, but performance is one thing for me. I use the fast array for replication of structs
Swapping array locations for a UObject on server seemed like it led to the object being destroyed and recreated on client
Ooof
That's a very reasonable thing to use structs instead
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.
it generally doesn't matter much, the BP accessibility here
this is usually deep in c++ territory
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?
yo kid
1v1 kid
KID
KID
Omg kii
kii
kiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiid
I think someone's off their meds? O.o
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?
Either the first one or UT's projectile prediction method
What's the general approach to UTs method, spawning locally then interping and replacing with replicated when it arrives?
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
@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.
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
What approach would you guys say is best for a shooter with all slow visible projectiles?
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
I only use actual projectile prediction of UT with grenades on my game
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
Also study AActor's replication methods and functions
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
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 
does anyone know why DemoNetDriver Console Comand demoplay test give me a Black screen no lights .... i set everything to replicated
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?
hmm, this kind of answered my question, short answer seems to be no, one map per server: https://forums.unrealengine.com/t/can-i-run-multiple-server-instances-in-the-same-dedicate-server/51819
Each server can only manage one map. The common approach is to run multiple unreal server processes on the same machine.
You can start/stop these however you like.
ok perfect, thanks for confirming...i'll set up some kind of "server manager" UObject then to manage the starting and stopping of the servers
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
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
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.
makes sense
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?
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
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.net
ัะดะตะปะฐะฝ ะฟัะธ ะฟะพะผะพัะธ Joxi.net
Because the same actor exists on all instances and is overlapping in each instance
but how the copy of the actor on the other instance knows that it's overlapped by another player?
Because every instance has it's own copy of each actor. If that actor moves on every instance then it will overlap.
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
You don't necessarily need a server. It depends on your game type.
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
@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.
I see, and what service would you suggest for providing a listenserver
player 1 has own copy of button, player 2 has own copy of button.
player 1 overlaps this button.
and for me, if there is only a copy of the button, then this copy only should fire the overlap events.
I guess that all events in copy actors are "replicated automatically" if the server created this actor and replicated variable relative only for rpc and actor properties.
Am I wrong?
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.
Not fully sure I follow the question? Listenservers are for players themselves to host so there is no provider. How they connect is based on what platform you release on. For instance you can code your game to run on Steam/EOS/Connect by IP, etc. That won't really matter much.
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.
fuuuh, now I totally understand this!
Thank you!
player2 see that replicated copy of player1 overlaps player2 local copy of the button )
yeah exactly
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.
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
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);```
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.
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
Will mess around with it a little more. Thanks. ๐
You testing outside of editor btw?
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
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.
@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().
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;
}
This example for Orfeas Eleftheriou is highlighting what I mean. The ServerSpawnBomb is a wrapper around SpawnBomb that the server calls directly.
This is correct. So in this case, your button press could call ServerSpawnBomb. It won't matter if you call this function on the listenserver or a client version of the actor, either way it'll either end up called on the server version of the actor.
Think of it like this. WIth your button calling ServerSpawnBomb() if it is on the client (owning actor), it'll go over the network and be executed on the server. If it's called on the server it will just execute. The authority checks in your code aren't necessary and just amke the logic harder to follow. The engine takes care of this for you
That makes sense. So the role authority checks still serve the purpose of deciding whether or not to do local effects, right?
I also see this for general gatekeeping in functions, to guard logic sensitive content.....
SomeCriticalSupportingFunction() {
if (Role < Role_Auth) { return }
// Do the critical stuff
}```
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 ๐
you can't avoid using HasAuthority tho
what if you need to do stuff on BeginPlay authority only?
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.
but GetNetMode can also cause issues
Yes, as I said you cant completely avoid it, but you dont want to do like what has been posted above for writing gameplay functionality
if used incorrectly
especially on listen servers
Replicated Actors is always fine to check LocalRole though
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.
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
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 ๐
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.
If you develop everything multiplayer, how do all of these (if any) change between dedicated and listening servers?
Well ... ๐
(I am absolutely multiplayer out of the gate, so I trying to keep track of it early on)
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
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?
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
No, because the broadcast exceution only happens on the server, as the gamemode only exists on the server, therefore that never happens on non-server clients
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.
Ahhh okay gotcha... I think I am just a bit confused on how the game instance actually works. Because the few things I've seen about it have suggested that it exists both on the client and the server.
Delegates are not networked. And you are executing the logic from the gamemode ( server-only ), therefore any code execution will only be where the broadcast happens
Game instance has the lifetime of the application on your computer. You might be thinking of GameState
Yeah I might need to read up some more on game instance vs game state. Thanks guys!
What you really need to do is when this happens on the server, is do a multicast so that all clients can then have the logic execute locally ( like for showing that they have received X reward )
Reading up on stuff is always a good idea! ๐
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.
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
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
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
How did I miss PlayerState ๐คฆโโ๏ธ You're right
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
Yeah, thanks for the info
I'll do that way
@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
@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 ๐
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?
@rancid flame Little lost. Why are you replicating the DataAsset pointers?
what is an acceptable Net-Culling distance for player characters in a 30 player game?
Yeah it's a bit weird. So I have UInventoryItem that has a per-instance count on it. (e.g. you have 30 bullets in you inventory is 1 instance of UAmmoItem : public UInventoryItem with its Count variable set to 30.
I guess I could change it to storing an array of FInventoryEntry that has a TSubclassOf and replicated count...
I mean more where is the DataAsset coming in?
When the player runs over an AItem in the world, I see if there's already one in inventory that I can increase the count of, but if it's not then:
100cm, Daredevil Simulator(tm)
So UBYGInventoryItem is a DataAsset subclass?
Yes, they're assets that I define BP subclasses of for like the name, gameplaytags, icon etc.
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.
hmmm I'd really rather avoid large singular DataTables, what about something like this?
USTRUCT()
struct FInventoryEntry
{
GENERATED_BODY()
UPROPERTY()
TSubclassOf<UInventoryItem> ItemClass
UPROPERTY()
int32 Count;
}
UCLASS()
class UInventoryComponent : public UActorComponent
{
GENERATED_BODY()
UPROPERTY(Replicated)
TArray<FInventoryEntry> Inventory;
}
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.
Really? It's pointing to a blueprint subclass of the DataAsset so I thought TSubclassOf<T> was correct
It's worked so far with TSubclassOf heh
lotsa hard refs
This is for a prototype but yeah I guess it should be some kind of soft ref instead?
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.
You're right for that case yeah. In our prototype we're gonna have < 30 items
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.
I'm also using tags like that ๐ So I don't need to look up the actual items
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.
I thought that DataAssets were just (*EDIT) UObject subclasses that you could create BP subclasses of
It still doesn't really explain why my pointers to instances of UDataAsset subclasses would be null in my array tho
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?
yup
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
Do they replicate normally otherwise?
Yup as far as I can tell
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?
If by first, you mean GetPlayerController0, then usually yes. Though there are Servertravel cases where that is not true. If you're working with C++, a library function to get the first local controller is safer. Not to mention it's actually performantly faster. ๐
I'm using C++, which library func is this?
GetWorld()->GetFirstPlayerController ?
Ah very nice! Getting it from the GI will guarantee it's the local one
Thanks for the example
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);
}```
I'm just curious if anyone knows if Fortnite already uses the push model for replication or not?
does anyone have a guide to multiplayer possession for clients in a listen server?
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
so currently i have the character controller unpossess it's current pawn then multicast a spawn event and then have that controller possess it
you're doing a multicast from client
i believe so
yeah, thats not good
spawn actor and possess should be only ever executed on server
okay i'll make some changes and see if that works if it doesn't i'll be back here in a bit.
would you unpossess client side?
no
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?
Yes
data asset allow creation of new data asset types, which has two different UI actions: make new class, make new asset
DA* would be specific asset object (99% use case)
subclass<DA> would be a asset class (very rare use case)
also prefer using primary data asset.
so replicated entry struct would be DA* and int count field
Hello can I start listening to a pixel streaming streamer at runtime?
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?
I believe lobbies are listen servers and servers are dedi servers
Yop
thanks
That's what the presence stuff is for basically
But remember SEARCH_PRESENCE is now SEARCH_LOBBIES in 4.27
also what does the EOnlineComparisonOp mean when setting QuerySettings
m_pSessionSearch = MakeShared<FOnlineSessionSearch>(FOnlineSessionSearch());
m_pSessionSearch->QuerySettings.Set<bool>(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
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
There are also DoesNotEqual or so as options
does that actually matter then?
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"
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
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
m_pSessionSearch->QuerySettings.Set<int32>(SETTING_NUMBOTS, 0, EOnlineComparisonOp::GreaterThan)
m_pSessionSearch->QuerySettings.Set<FString>(SETTING_GAMEMODE, DesiredGameMode, EOnlineComparisonOp::Equals)
Some examples
like when a value is near another value
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
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
Man, when I'm gonna hear a good thing about 4.27 lol
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
Well yeah things introduced with 4.27 is good but its shipped broken
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
Are there any other noticeable things I should be looking for that have broken in 4.27? So far other than this it seems fine
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
No from the uproject
You make a packaged build for each iteration?
every test iteration yes
I'm debugging code here that requires a unique GI per instance and that'd take all day doing that
Niagara
What has broken with Niagara?
Niagara is broken in all version
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.
Ok good to know, I'll test with a blank proj
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.
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
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.
So far it actually fixed bugs that were causing crashes for me with Niagara in 4.26 and no more level streaming log spam for each hidden sublevel. And 50% smaller package size. So far 4.27 seems like a win
Yeah barely slower than opening PIE is what I'm used to in all prior versions
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
soft object pointers ๐
^
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
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
Engine upgrades are a curious minefield eh? ๐
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.
is there some kind of delegate that happens on the clients during servertravel? I want everyone to fade to black on level travel
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; }```
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.
Are you including from:?
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
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.
You should cast the other actor to a Pawn class, and ask IsLocallyControlled. If not, don't do anything.
Yup, that did the trick!
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
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?
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
Maybe I'm running into this ServerTravel edge case if not? I'm calling GI->GetFirstLocalPlayerController(World) and getting the pawn from there to get the local player pawn, but is there a chance that after seamless travel it could return someone else's pawn?
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.
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?
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.
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
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
Are these absolutely the only rotations you're doing?
@kindred widgetIn event tick I'm updating spring arm's world rotation to point middle of planet Earth. but yeh.
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.
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?
One sec. This is inside of a Pawn blueprint, or?
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++. :/
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?
:/ This is full Bp project And I don't have experience of c++ "only one university basic course" ๐
@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 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 RPC to server from client's controller, and have the server version of it call possession on the pawn you want.
Not really sure how to explain that more. It's a single RPC with an actor or pawn parameter.
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
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
what is the cost of sending an actor through RPC? Is it just a 4bit pointer or something massive?
@meager fable 8 bytes if memory serves. Basically enough data to resolve the pointer on the other side. Nothing major.
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?
wonderful, thanks
Cast<APlayerController>(GetController()) or in blueprint GetController->CastToPlayerController should work fine if you're calling this on the server version of the currently possessed pawn.
IE, shouldn't need to pass the controller through. Server set the values client has anyhow, so it should have the data for it.
Great. I am going to give it a shot now.
Er. Not sure what I was thinking. I don't even think you need to cast that to a player controller.
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.
are there any tutorials about client side prediction besides the one on game dev .tv
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
is there any preprocessor directive for dedicated server? Like #if PLATFORM_WINDOWS
UE_SERVER
that was quick. Thanks.
Why there are literally zero documentation on how to make the engine connect to a server, or host one on the official site?
the client is always going to be player 0, the indices are used for local co-op
So my theory was correct then, thank you!
there is a full tutorial series by unreal engine about hosting/joining sessions using listen server (and even connecting it through steam)
Well I tried to look here https://docs.unrealengine.com/4.27/en-US/InteractiveExperiences/Networking/
yeah that one is fairly limited...
Only Starting a Server console command is being mentioned
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...
this is the tutorial series, altho a bit outdated
I just found that one ye
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
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)
I've bought the same course just to kickstart me on the multiplayer syntax in C++
I've also found a tutorial later to create and join sessions through C++ if you would like
which also includes steam
@keen surge Maybe do you know how to execute smth on the server when a client connects? In Blueprint
No clue, I don't work with blueprints for MP
Does this work as a switch to allow certain "threads?" through?
It does. But it's some weird assumptions.