#multiplayer
1 messages · Page 13 of 1
hmm ok thanks. I'll try adding some logs there, maybe that will help
There is a bug in the engine where that doesn't happen if you set the NetUpdateFrequency to 0
But you said you're using the PushModel so should not be relevant
You might want to show what URL you're specifying on travel
It's possible to create a World Settings Class ? 🤔
When I try to create a new BP it doesn't give me a "World Settings" Class when I search it, so I'm not sure to understand correctly
It might be you need to create a world settings class in c++ first and then make it blueprintable.
Instead of FString("blah") you should probably do TEXT("blah")
or FString(TEXT("blah"))
I'm not that well-versed with session code, but you definitely want to debug that. There's a high possibility he's ignoring that and trying to travel to some other default map that for some reason doesn't exist
So debug
I can't find where I put that class in the Project Settings 🤔
It definitely used to work. Maybe they foiled my world settings plans for 5.0...
Nevermind I found it 👍
Thanks that's the best option and I was looking for a way to create a World Setting tab and didn't know that it was possible, thank you so much 👍
Yeah but I think it's because it's only available through C++ creation tool and not through BP creation tool
Maybe.
How did you do it?
Did you make it all in c++ or create a c++ base class that could be made into a blueprint?
I had to create a c++ class to see it in the Creation Window (where you click on "All Classes"). Now I need to create a child of that class to make it Blueprintable
Erm. You really don't.
class ABPWorldSettings : AWorldSettings
{
GENERATED_BODY()
}```
shoudl be all you need
(plus headers)
But what if I need some settings to be displayed in the Details Panel ?
You just add them to your BP
The only c++ class you need is the bridge to make it so you can create your blueprint
All the ones from the base c++ class are still there, you just simply can't make a blueprint from it.
The settings are still UPROPERTYs
But I need to write c++ stuff anyway like something like possible with c++ which is the "EditCondition" specifier to make a certain property only writable if a boolean is set to true/false
If you have a custom WS class - is that the one that gets created for you?
Yes.
And all its properties are accessible via the world settings menu in the editor.
Nifty indeed
And you can link, safely, to map assets and access those links via the world settings object in c++/bp
@latent heart Another question :
Is it possible to fill dynamically a TMap that would be displayed in the Details Panel. Let me explain what I mean. So I have a struct named "Health Granted On Elimination" (it's not the best name so I think "Resource Granted on Elimination" would fit better) and it contains these properties that the user can fill :
- Health
- Shield
- Gold
- Wood
- Stone
- Metal
I have a struct containing these resources and I want if the user decides to add other resources (Let's say he adds "Mana", it updates the struct and it adds these 2 options to Resource Granted on Elimination struct :
- Mana Granted
- Mana Removed
And the user can modify the value of those properties.
Like I'm trying to get the first result (but what you see there was hardcoded, the keys were hardcoded)
Just set default values on the class that contains the tmap.
That won't make it look like #1, though.
Tbh, the details panel isn't great at stuff like that.
If you want those 7 entries there all the time, just create 7 variables.
That's the issue, I want it to by dynamic, and the first screenshot was made using a struct and structs are immutable. Like I have a section in the Details Panel called "Resources" (second screenshot) where the user could add Resources there (like wood, metal, stone, gold,...) and it will be displayed in the "Health GRanted On Elimination" section (first screenshot) like this : NameOfTheResource Granted to make it dynamic and fill the TMap like that
Can't really do that with tmaps, sadly. You can specify a "header" (or osmething) property, but it still isn't displayed very nicely.
Are you actually using a tmap in that second screenshot?
Looks more like an array!
Yeah my bad it's an array, but I think it's an array of TMaps but I'm not sure anymore as I did so many tests to make that work
BeginPlay on the second actor will be called when all its vars are replicated. The notify for individual varibles can be called before others are replicated. I think.
@latent heart Do "World Settings" class have a "BeginPlay()" and "OnConstruction" method ?
it's a regular actor, so why not?
They will if they are actors
Whether OnConstruction is called for world settings... no idea.
Heu how to know if it's an actor ? 🤔
When the NetGUID is resolved into a replicated actor.
Header for AWorldSettings
It inherits from AInfo which is a known actor
And again A prefix
I have an error 🤔
That means independent actors replicate at their own rate. No guarantee a replicated actor that reference another replicated actor will have that one replicated by the time the former has replicated. That's why OnRep is really needed.
You haven't created those functions? Do so.
@vagrant grail you would want an array of tuples/structs or a map of stat name/enum/whatever to int/float
Eventually you'll end up with something that looks like GAS
If they are POD types you can tie them in a struct and implement NetSerialize for them and they will replicate at the same time
Or you can track their callbacks client-side
Already tried that but I don't like the way it displays. And also I tried using Gameplay Tags and I'm still wondering how to make the user only select the lowest children because right now he can select the most upper category
Yeah something similar to that, though that is susceptible to cheats 😦
You can have them both tied to the same OnRep btw
No other way but to wait for their OnReps to be called
It doesn't want to let me have a constructor 🤔
You can check in each OnRep
solved
First OnRep checks of the other actor is valid
Second OnRep check if the former is valid
Try not to use ticks
Yes
My Unreal keeps crashing each time I modify something in the c++ files
Otherwise known as Hotreloading which is best to be avoided unless you like running into blueprint corruption issues and crashes. If you need to compile C++, you're best to just leave the engine closed and open it again after its compiled.
I don't have hot reloading or live coding enabled, I just press" build" in VS and most of the times it updates the changes in the details panel without crashing but since I write my code in the World Game Settings class, it crashes more
that's hot reloading...
Bumping this for more visibility.
Have you tried net insights or the profiler? Seems like you are replicating too much data oof
It'd be kind of hard to think that replicating 3 meshes is overkill.
Agreed. And you tested it for 1 client it seems
I would use the profiler to figure out what's the cause of the hitches
Maybe you will end up doing it at stages 
https://pastebin.com/pN5UEDKs This is the relevant .h stuff in case you're interested
Can't you have those attached at compile at time and set them locally?
That way you will replicate much less data
The configuration?
I'm not following. By having them as replicated, the server sets the config values, then tells the clients to set this value. I don't think UE is trying to replicate the entire object
Where does the server sets the config values from? If they are assets, which I'm sure they are, then you can replicate GameplayTags for example and based on that you set them locally on client.
I'm just trying to replicate less data
The mesh components can just be part of the CDO
The weapon is built dynamically through OnConstruction
So if there are only 2 components needed, then only 2 component will exist, not 4.
Ehh - Having to tag every asset with a gameplay tag seems silly and definitely not scalable/maintainable.
Right. But can't you attach a scope to it at later point? I would just have them all part of the CDO than to have to attach a replicated component each time I need it
And ofc you can always deactivate/disable idk what it's called if not needed
Depends on how much weapons/ weapon pieces you have 
What I'm saying is that it would not fit with what I want making these components in the CDO
I don't want 2 lingering components that just exist if I don't need them.
If I'm just going to delete them anyway - it's a waste to even create them.
I don't know how many attachments will actually be used at a given time.
A quick look at stat NET - things don't seem too obscene.
No I wouldn't delete them, but instead deactivate them...
I don't want them to exist at all.
Not sure what gains you get from that but ofc not delete
The engine doesn't have to move them
Either way - that shouldn't be the issue anyway. If it were, it would only cause the stutter initially. But the stutter only happens when moving around.
Oh the stutter still happens from that point onward??
Yeah
First video - no stutter. Second with stutter.
Stutter only happens when I do the weapon config stuff
oof yeah that's not related to what I said ofc. I thought it was somewhat initial
You are not doing CMC stuff by any chance
Are you?
void AGun::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
if (!HasAuthority()) return;
ValidateGunStats();
ValidateGunConfiguration();
}
void AGun::PostNetInit()
{
Super::PostNetInit();
ValidateGunStats();
ValidateGunConfiguration();
}
This is the setup code. OnConstruction. If I comment it out in the OnConstruction part, no stutter (but no attachments).
Still if you did, what that has to do with replicating components...
ValidateGunConfiguration() is what handles the attachments
Stock = NewObject<UStaticMeshComponent>(this);
Stock->SetStaticMesh(WeaponConfiguration.Stock->PartMesh);
Stock->SetCollisionProfileName("NoCollision");
Stock->SetIsReplicated(true);
Stock->CreationMethod = EComponentCreationMethod::UserConstructionScript;
Stock->AttachToComponent(GunMesh, FAttachmentTransformRules::SnapToTargetIncludingScale, FName("StockAttach"));
Stock->RegisterComponent();
AddInstanceComponent(Stock);
And this is all that does really (except with each potential part)
Nope - not touching CMC at all currently.
That's what I thought too - but if that were true, it'd happen on the server as well. Which it doesn't
Stock->SetCollisionProfileName("NoCollision"); I disable collision here
Plus - details panel says no collision
The body of the gun is a skeletal mesh. The attachments are static meshes. Think that could be problematic?
Looking at the network profile - nothing really jumps out either. Thing that happens most is movement
I'm wondering why you're doing the attachment on client too? AFAIK it's done server-side and it automagically replicates
Also SetIsReplicated there seems sus
Though you said you commented out the OnConstruction part. So I would be amazed to see it's coming from there and not from PostNetInit
Awhile back, I was running into some dynamic issues and jambax and kaos said that you typically do it in both initially (onconstruction and postnetinit) because onconstruction runs before the replicated properties are set
How so? It should be replicated.
Right. But it's called client-side in PostNetInit
WizardCell you magnificent bastard. Commenting that out - no more stuttering.
Yeah iirc I came upon that one
Funny - I had the thought of thinking about the client with postnetinit but not in the actual config validation
Seems like the client was battling server
Yup
Wdym? OnRep is called on its own
BP calls OnRep regardless if it's server or client. C++, server has to call OnRep manually. Will be called on client though
Poor Gumby 
That's against the design of it though
Put a integer into your struct and increment it every time you need it to replicate
in blueprints you never need to call OnRep if the variable is set to rep notify. Also stucts if I remember correctly only replicate the specific piece of data they contain that was changed, so there's no penalty for setting and entire struct to RepNotify
Theoretically, setting an OnRep variable to the same value should not trigger the OnRep. That said I had a bug of that in one of our marketplace packs 2 days ago where it did call even if setting it to the same value. At least on the ListenServer. Relatively sure that was not a thing before
But either way your client should only call OnRep if the value actually changed
should™️
If you need it to call even if setting it to the same value you could work around that by the integer I mentioned. Does require you to increment it every time though
That's probably worse
Right. Unless you do REPNOTIFY_Always. Which does call it on client even if the local value is same
Cause if you flip flop too fast it won't call it either
PostNetInit is only called on client, right?
Well yeah but we are talking BPs
But in BP as Cedric said it's really against design
I'm still a bit confused why setting a variable to the same value would trigger it on the server. But well...
Yeah that's odd on the BP part
I had an infinite loop cause of that
I mean the way cpp and BP handle OnReps is really different and on the BP side it's really funky
My OnRep was calling the same code that ultimately sets the variable. Thinking it would not call the OnRep again
Only crashed in shipping
@fathom aspen Interestingly enough, when I wrapped the SetIsReplicated call behind a has auth check, it still ended up with the jitter issue. 🤔
Probably cause tighter infinite loop numbers
On BP it's just a "value changed" event fwiw
So a client can trigger a local OnRep
Cedric - do you happen to know at what point in the life of an actor it's net role gets set? (Auth vs Remote)
Not without looking it up
There could be a slight possiblity where Roles haven't been quite set/replicated. So I would try using NetMode
What gives the idea that a variable could never be replicated?
Yeah - I thought about that as well, already switched over to that. But it was a curiosity question for Cedric.
Relying on the NetMode works
I'm pretty sure I have seen it set differently (different functions/places) for different GameFramework actors, but in general I'm not sure where that happens
Either way - this works and marks the component as replicated for the server but not client. I can rest easy tonight 🥳
Now - to move on to handling when a client selects a different part 😅
Wait a second
The roles should be set by the time PostNetInit gets called 🤔
fake code
It checks for Remote, not Local
Maybe you can check for Remote if it's set by that time xD
Right, but structs don't replicate atomically by default
Unless they made ENetRole so
Which I doubt it
I would figure the local role would be set to ROLE_AutonomousProxy by the time PostNetInit is called.
Which would cause HasAuthority to return false.
I mean they are different properties and it could be possible that one replicated before the other did
But considering they are PODs they should have replicated by the time PostNetInit is called
That's why the seem to suppose that is the case with there check
But they do it for Remote, not Local, which is weird
Oh wait. LocalRole is set to Authority on server and it's replicated. So that explains why you was getting that on client
I would guess they overwrite that value with Autonomous at a latter point resulting in the model we all know
The Role system is something I'm considering to investigate more so all what I say is pure guesses xD
Well - it turns out I did the netmode check wrong. I was doing > NM_Client instead of <. So it was effectively doing nothing.
So the component wasn't actually being replicated 😠
It was equivalent to just commenting out the SetIsReplicated
hey guys im using unreal engine 5 and i cant seem to find the set controller id node
this is the only controller id i see in ue5
Image
but the one i see in ue4 is
Image
i have virtually the same blueprints but the possess node isnt responding
Natively they are called the same. They changed its name in BP
Same implementation too
The only thing I see they slightly changed is SetControllerId
Which they both call
I don't see any reason to why you would face issues
Your best bet is to debug though
@fathom aspen Figured it out I believe.
Dynamic component replication issue that is
Stock->SetNetAddressable();
Call this before marking the component as replicates. It tells UE that the component can be found by name. So you can spawn something on server and client and kind of link them together like this.
Ahhh
I think I had to do it because the creation method that I'm using
My component creation method is UserConstructionScript
Oh right right, nice find!
Also iirc they already cover/use it in component replication doc
You still don't call SetIsReplicated client-side though
Right?
I do.
Server & client create their own identical version of the component
Then they get linked up because of the SetNetAdressable
At least - that's the way I understand it
I'm sure someone like Zlo or Jambax can come in and clarify. But I definitely intend to ask Jambax some questions tomorrow when they're available.
Right, but I would still argue the replication client-side unless that's needed for SetNetAdressable which I'm not quite familiar with
But I have tested it where the server removes the static mesh and it does remove it on clients as well
Zlo has vanished, so your best bet is James xD
Nice!
I wonder what would happen if you don't do the replication client-side. Seems like an irrelevant call if it works without it
I don't think it matters all that much to be honest.
Yeah as they link eventually
I'm sure James can clear some of this up for us though.
Hopefully. Will make sure to not miss the party
The reason I don't think it really matters is because even if the server was the only one to set it to replicate, when it eventually does replicate - that property will be set to true anyway
Yeah and as long as they link up, so it's good.
Yup - it is a replicated property. I'm pretty sure my assumptions are correct up to this point.
So previously they were semi-linked and one on client it was trying to battle the one on server?
I'm thinking something like that.
The server couldn't replicate anything correctly because it had nothing reliable to replicate to
We should make sure to get an explanation to that too
So it was being all funky
Yeah - it'll be the first thing I do in the morning when I wake up (as that is when James is on)
Timezones and all that
I found this method through the docs and the bottom bullet points here https://ikrima.dev/ue4guide/networking/network-replication/general-replication/
In docs - this paragraph stood out to me.
Then this
Great piece of info!
Yeah Zlo has mentioned this a thousand times here, so I had dejavu while reading
RIP
🤣
Oh
The last words
Lol
I'm happy that we already have answers
Search tool is amazing
Yeah I recall this from the doc. My past experience though tells me to favor Zlo on docs xD
Lol
Yeah either one of them tbh
How these shitty docs are not updated
I mean yeah James's response makes total sense. Why the heck I would make it stabley named if it's part of the CDO
It's already stabely named
Mods pin all the above plz xD
Tomorrow... In James we have faith
Only time i had to call SetNetAddressable() was for spline mesh components created in a Construction Script
net addressable and replication are different concepts
if you decide to use a separate actor channel to update properties on your actors without having them replicated
u need these actors to be net addressable but not replicated
however you cannot have a replicated actor that isn't net addressable
🦆
if we take as an example the network managers we need each actor that registers into the netman to be net addressable (by providing a stable name)
thats why by default it works for actors placed in the map
the key here would be to make it work with runtime generated actors
in such case we'd need to make them netaddressable by naming them consistently client to server
@latent heart It looks like I can't create a derived BP class after creating my World Setting class 🤔
is onrep only on the client? im trying to update health bars by multicasting by it doesnt ever multicast because oprep on happens on the client
Client only in C++, both in BP
I guess so
also think that this makes no sense
btw why multicast when you have an OnRep?
i'm using playfab is it safe to use event without run on server or something? (in game instace)
game instance is not replicated so it does not matter if you make an event RPC there
oh thanks
Thx again,
Trying to create a new Client Policy in the dev.epicgames website, getting "Request failed with status code 403" ?
I'm replicating a ustruct in a normal tarray(not delta serialized) and whenever a new element is added and replicated to the end of the array, the previous elements appear to reset for the client, as if theyre either being zero initialized or reconstructed... any ideas?
Oh, for this answer you will need to ask in #epic-online-services
alright thx 🙂
Only time I've seen that is if the client is messing with the Array.
Hey guys
Is there a clean way to use CheatManager on client side for testing purpose?
@kindred widget this is for a plugin and not my own code, but I do see the client is making changes to it by setting a non-uproperty boolean... know of any workaround?
That shouldn't break it. Normal TArray replication only sends the delta of the array. If you have an array of 20 things on server. That replicates and you end up with 20 things on client. Then the client calls Empty on the array. Then the server adds a new item for 21 total. The client will end up with 20 blank entries and a 21st correct entry. That's the only thing from replication I know of that will cause blanked array entries.
you are correct, it was clearing the entire array on the client in another place... alright, it makes sense now, thanks!
There is. You have to call EnableCheats on the client in question as explained here: https://wizardcell.com/unreal/persistent-data/#gameframework-actors-creation-cycle
Incredible! Thanks a lot! I will take a look at that
Even if you add Blueprintable to UCLASS?
Trying to get UDP traffic into unreal, but it doesn't seem like the UDP port is being opened. Some settings i'm missing?
Trying to send basic UDP test packets from my own computer, but nothing going through, on any ip. either localhost, 127.0.0.1 or the computer ip
using this plugin: https://github.com/getnamo/UDP-Unreal
I see. I'm wondering if the same goes for components created in C++ OnConstruction as it's the equivalent of BP ConstructionScript?
I mean the CreationMethod EComponentCreationMethod::UserConstructionScript is for components that are created in BP ConstructionScript as it's said in the source docs
/**A dynamically created component, either from the UserConstructionScript or from a Add Component node in a Blueprint event graph. */
UserConstructionScript,
So I'm wondering why @quasi tide had to to tell that is the creation method for his component 
IsNameStableForNetworking() checks that the creation method isn't UserConstructionScript
So idk if OnConstruct() would be the same
but likely, doesn't sound very stable
Yeah I would guess so. I will have to check source as to how these CreationMethods are assigned
So NetAddressable means this actor/component can replicate but not by it's own ActorChannel/Owner-ActorChannel but by some other ActorChannel. Ok that cleared some of the things as to why I would need an actor/component to be NetAddressable but not Replicated. I'm still wondering if there are other uses?
Also say for example I delete an actor/component that is NetAddressable but not Replicated server-side, does it get deleted client-side?
it means u can address it over the network
ie: being able to pass its pointer reference through an rpc and solve its reference client side
Oh I see
So it has a NetGUID that can be resolved into a valid actor/component on the other side
But still there is no way to replicate it through its actor channel
Amazingly explained vori, thanks!
Nice now I can create a BP child of the World Settings. However there's no graph editor somehow 🤔
Because I am using OnConstruction. Otherwise there is some wonky behavior that happens.
Especially if you try and move the weapon around in the level
@chrome bay I've hit a snag and would appreciate your insight if you don't mind. The situation is as follows:
I have a modular weapon system. The components are built from Data Assets. I set up the meshes on the actual BP class inside of OnConstruction. Everything works fine server wise. I have it successfully replicating to clients as well. However, when it does replicate to client, the client becomes exceptionally jittery. When I don't replicate it, it runs smooth as butter - can anyone think of why this would be the case?
The config stuff is wrapped in a struct FWeaponConfig. The struct is replicated. I've tried setting up the stuff in PostNetInit as well (for the client side). (original comment: <#multiplayer message)>
.h file: https://pastebin.com/pN5UEDKs
The stutter can be seen from the videos here: <#multiplayer message>
Setup code that I use: <#multiplayer message>
Then the code that actually sets the meshes and creates the components and all that: <#multiplayer message>
So, I ended up commenting out the SetIsReplicated(true); line and no more stutter. But this also means no more replicating. After some more lookin' around - I found SetNetAddressable() and when I use that with SetIsReplicated(true); - things work as expected. However, in the past, Zlo has mentioned that doing that is redundant and I've seen more comments about using SetNetAddressable() being a code smell pretty much.
This is where I tell WizardCell that I think I've found the solution to my original problem: <#multiplayer message>
So that should hopefully get you up to speed. My questions are:
-
What are the ramifications of using
SetNetAddressable()and how are you supposed to properly use it? -
From what I gather - it makes it where UE can look up the component by name, does this mean it doesn't rely on the net guid at all? If not, does it make it more expensive network wise?
-
How are you supposed to properly set up a dynamic component that needs to be replicated? I've tried various ways, and they all ended up with that stutter issue from the video. Using the
SetNetAddressable()method is the only way that has worked smoothly for me.
(Sorry for the wall of text 😅)
-
SetNetAddressable basically forces the item to be addressable over the network by using it's object name - which will almost certainly break in a non-editor build if you don't use some kind of method to deterministically generate the objects with the same names.
-
It can't lookup the component by name if you're spawning them at runtime.
-
A dynamic component would be spawned on the server and replicated just like any other property
So 1 & 2 I do kind of understand-ish. I do have a deterministic way of setting the name.
But for 3 - that's what I thought as well, but I was getting that stutter issue I showed in the videos when I just spawned the component and called SetIsReplicated(true);
I spawn a runtime component for my vehicle docking system, and that's as simple as this:
check(NewClient);
NewClient->RegisterComponent();```
The component has SetIsReplicatedByDefault(true); in it's constructor but calling SetIsReplicated on it before registering it should work fine
You have other problems though
You're setting properties when spawning it which are not replicated, such as the collision profile
So no doubt the clients' version of that component is very different to the servers
Very good chance IMO that the stuttering is caused by the client constantly miss-predicting it's movements because it's colliding with those components
So are you creating components independently on server and client?
That's what WC and I figured out last night because I'm also doing the setup calls in PostNetInit.
So I thought SetNetAddressible would sort of "link" them together.
Like it was the solution to having different game instances sync up locally created things.
No it won't do that automatically. SetNetAddressable just forces it to be network addressable, it doesn't actually do anything functional besides that.
To make dynamically spawned objects "link" up like that, you have to spawn them independently, ensuring they have the same names, and I suggest overriding IsNameStableForNetworking on the object
That's how I do my inventory slots which works well for me
Saying that, you should be able to skip the last step if bNetAddressable is set as that bypasses it
So - if I'm creating the component in OnConstruction, am I supposed to then do an RPC (for clients) at a later time to finish setting it's properties or something?
No should just be regular replicated properties
I don't know what sort of spooky things happen if you don't have that object client-side when you receive a server update for it
Hi! i'm thinking on using time handlers for abilities cooldown, since "Datetime" seems to be extremelly broken on UE5.
Does anyone have a better idea?
I just need the static mesh component though. Maybe I should make the component pointer variables onreps 🤔
If you're creating the components individually at each end why do the pointer properties need to be replicated?
Well - I'm trying to get it where only the server creates everything. Using OnConstruction for the dynamic creation aspect. But I recall you and Kaos mentioning before, that ya'll typically do setup in both OnConstruction & PostNetInit for clients.
But when I set everything up in OnConstruction, only on the server side, things don't actually replicate down to clients.
Okay so if you're doing it where only the server creates the components that makes more sense, but in that case - the client should not be spawning components of it's own
Yeah - that's how I did it at first. But the clients weren't getting the attachments.
Then I recalled the PostNetInit discussion from some time ago.
And it's just been a rabbit hole since.
I'm not sure what that discussion is tbh
If you are creating replicated components on the Server, the client should NOT create them
If they aren't replicating properly, then something else is broken
It was somewhat in the same vein - but that project is dead 😅
I have them setup in OnConstruction so when the items are placed around the level, you can actually see them.
Agreed. This part, there is no debate/confusion on.
If they are components serialized into the level then the Server and Client both have them already and they should then already be network addressable
It's just when I was doing it that way, the clients weren't getting the values they were supposed to. So I thought maybe something was funky with doing things in OnConstruction
If I read the code above correctly, right now it looks like during PostNetInit() you are creating a new set of components client-side and setting the properties
Yes
Yeah in which case, that's the problem
Without PostNetInit - clients did not have the stuff configured.
IE - they couldn't see the stock
The client now has it's own duplicated components which are not the actual replicated ones
So I would remove all the postnetinit stuff, and first figure out why the components created by the server aren't being received
AFAIK all sub-objects should have been created by the time PostNetInit() is called
But you could also just use OnRep to be extra safe
But obviously the components you receive from the Server will not have perfectly matched properties client-side, because not all of those properties are replicated
Where could I start digging into why the comps aren't being received? Because again - it was my first path, just set up in OnConstruction.
Wonder why something like collision wouldn't be something that would be replicated 🤔
Because it's expensive to replicate all of that redundantly if it's not needed, and to disable it you'd need to create a whole new component class
The only property replicated by static mesh component for e.g. is the mesh it's using, and it's relative transform to it's parent.
Well.. all this crap from USceneComponent:
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, bAbsoluteRotation, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, bAbsoluteScale, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, bVisible, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, bShouldBeAttached, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, bShouldSnapLocationWhenAttached, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, bShouldSnapRotationWhenAttached, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, AttachParent, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, AttachChildren, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, AttachSocketName, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, RelativeLocation, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, RelativeRotation, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, RelativeScale3D, SharedParams);
DOREPLIFETIME_WITH_PARAMS_FAST(USceneComponent, Mobility, SharedParams);```
Yeah - so for some reason those replicated components are not being received
So there must be something broken there
I would move that logic out of OnConstruction, do it in BeginPlay or PostInitializeComponents or something maybe
So - I removed setting the creation mode to user script, and the other components came over. But the main body still didn't though.
That's a CDO and the mesh gets set in the OnConstruction method as well.
Moved everything to BeginPlay behind a HasAuth check, body still didn't come over
Is the mesh being set driven by some other replicated property?
OnConstruction will run before any replicated properties have been read-in
So the client might be doing something it shouldn't
Wait a sec here - I didn't have that comp as replicated 😅
Meh - didn't change anything
Is it a skeletal mesh?
Yeah
Skeletal Mesh Component doesn't replicate the mesh
I was amazed to figure out that StaticMeshComponent replicates it's UStaticMesh though
Yeah I figure it's a convenience thing for stuff placed in the level or something.. but it does seem odd
How does it replicate it though? Same technique you have in your post?
It's just an asset so it's identifiable by name
So we need to have properties, along with pointers to the skeletal mesh, that specifically point to the mesh that is being used by the skeletal component?
The mesh itself gets set by a DA
Because I can't find a function like IsSupportedForNetwroking there
The Skeletal Mesh Component itself does not replicate what mesh asset it's using, so you would have to replicate that yourself independently
But if you have a data asset that can drive all these properties - why not just replicate the data asset? It's just an asset, so you trade all those replicated properties for a single property
That's what I am doing
So now I'm extra confused - why replicate the mesh components etc. at all?
If the client already knows what meshes to use, what data asset drives weapon creation - just do it entirely locally. If you want to reference the components, just be sure to generate them with stable names
I do exactly this for my inventory slots
Would you have them be part of the CDO, or you would spawn them locally at runtime on both sides?
At that point I would need the net addressible, right?
The only thing you then need to replicate is the data asset reference for that weapon
Yeah, that would be needed to convince the engine they are the same object.
Also the name only needs to be unique relative to it's outer too
Yeah - it's pretty easy to guarantee a unique name in this case
I guess either would work just fine - if you always had the same components, I'd make them CDO objects
Runtime spawning is a bit more work and prone to error but definitely still doable
Right right, perfectly answered!
The only thing I would want to understand is how you guys deterministically generate the objects with the same names?
Okay - so, if replicating the component (skelmesh), I would need to replicate the component property & have a different skel mesh property that is also replicated via onrep probably
Is there some technique I'm missing?
{
if (ConfigAsset)
{
// Spawn comps with stable names and shiz
}
}```
I would use an OnRep for this btw - because PostNetInit() would be called after all replicated properties are read-in, Including the properties for currently non-existing subobjects client side
For my case I define the names of the objects in the asset
e.g. like this:
* A set of inventory slots.
* An inventory will create it's own slots from these settings.
*/
UCLASS(NotBlueprintable, BlueprintType, Const, MinimalAPI, meta = (DisplayName = "Inventory Slot Set"))
class UST_InventorySlotSet final : public UDataAsset
{
GENERATED_BODY()
public:
// Constructor
UST_InventorySlotSet(const FObjectInitializer& OI)
: Super(OI)
{}
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "Slot Set", meta = (ForceInlineRow, ShowTreeView))
TMap<FName, UST_InventorySlot*> Slots = {};
};```
Yeah - I have my base body as a DA that is in the class itself. Then I have 3 other DA's in a struct for additional configuration. I'd need to onrep both of these probably
Then when creating them:
{
const FName SlotName = Iterator.Key();
UST_InventorySlot* SlotTemplate = Iterator.Value();
if (SlotName == NAME_None || !IsValid(SlotTemplate))
{
UE_LOG(LogST_InventoryComponent, Warning, TEXT("InitSlots:: Slot [%s][%s] Invalid!"), *SlotName.ToString(), *GetNameSafe(SlotTemplate));
continue;
}
// Duplicate + mark transient
UST_InventorySlot* NewSlot = DuplicateObject<UST_InventorySlot>(SlotTemplate, this, SlotName);
NewSlot->SetFlags(RF_Transient);
}```
The slots are created independently on server + client. But you must do this from an OnRep in this case, because otherwise if the slots themselves have replicated properties they will fail to resolve
planning to release this plugin one day 😄
Please do!
You got yourself two buyers already
Amazing explanation tbh. It's stuff that you and Zlo go over too much here and I have never fully understood till today xD
tbh I agonised over this quite recently because I hated the original system I had so it's still fresh in my head
Haha good timing then, good that we asked now!
I still wonder what a function like IsSupportedForNetworking mean. I mean it's doc says that this actor can be referenced over the network, so I guess it means that actors are always assigned a NetGUID?
Because that function always return true
But that NetGUID isn't guaranteed to resolve into an actor on the other side until it's stably named?
IIRC IsSupportedForNetworking is basically an on/off switch for whether that object can ever be networked at all
But that doesn't mean you can't send a reference to that object via network if it's stably named
The name being stable != whether it's supported or not
It's just a different way of resolving the object
Right. That's why I guess it means if they are assigned a NetGUID or not
So it could be not supported for networking, but be network addressible and still work?
And it's only relevant for dynamic objects, as static are always assigned ones
Yeah. For example a UMaterial is not supported for networking - but you can absolutely replicate a reference to a material because it's a stably-named asset
Kind of - the first time you reference any object via network it always uses the full path name (e.g, an asset or a class) - but usually that will then be assigned a NetGUID by the network driver and it will use that from then on
Ah. I thought it had to be IsSupportedForNetworking too
But for dynamic objects, the class name must be sent when it's initially created - the client then creates their copy of that object locally from that name, and maps the NetGUID to that new object
The netguid is the same across machines?
Got it - makes sense. Considering clients only talk to the server and not each other
And the server routes stuff around
So, does the server send the guid that it should be created with?
So, initial connection happens - server sends name of object and the guid the client should create it with?
I believe so yeah
The maps you're referring to are those I guess?
TMap< FNetworkGUID, FNetGuidCacheObject > ObjectLookup;
TMap< TWeakObjectPtr< UObject >, FNetworkGUID > NetGUIDLookup;
yeah
And all this started because I was going with the dartboard strategy to get my components replicated.
Your question saved us all
Ah this is it: UActorChannel::ReadContentBlockHeader
Oh sorry no, UPackageMapClient::SerializeObject
Yeah this one calls the one underneath
Thanks again for all the help, insights, and general knowledge sharing @chrome bay.
Or that might be some other function with the same name
I'll redo my approach after work today (I still work in enterprise web dev 😭)
That monolithic, thanks James!
As a recap for my situation:
- OnRep the struct and weapon base DA
- In there, create the components locally, set the names to be unique, set the components as netaddressible (in this specific case)
Yeah start rooting around from there and it explains a bit mroe 😄
Yeah AFAIK that should work
And you shouldn't need to replicate the components, or even references to them
Right
Just make sure the generated names are the same on server + client
yeah
So long as the actor is addressable (which it will be if spawned by server), then you should just be able to use simple names
NewObject<UStaticMeshComponent>(this, FName("Stock"));
yeah
For sanity, should SetNetAddressable be called on both sides?
Yeah - the actor is 100% spawned by server.
yeah on both
This new approach will also minimize bandwidth ❤️
yeah, makes it much simpler to do
Will actors that are kept during a seamless travel be re-created on clients, or will they stay "alive"?
Does anyone know if there's a way to pass a parameter on a repnotify? (i have one array on RepNotif and i want to know the index i last updated)
no - the only parameter you can pass is a const-ref to the previous value of the property
So when I OnRep my weapon config struct, I guess I would need the previous value and check each value to see which one needs to be updated? @chrome bay
hmm i have an array of "CoolDown" information, I want to know what item got updated so i can notify the ActionBar slot that has the same ID registered.
Any way to do this or a better way of getting that behavior?
I don't think so, the previous one would be a "nullptr" data asset right?
Yeah - it's a DA
Well you can either compare every entry in the array manually, or perhaps use something like FFastArraySerializer which gives you per-item callbacks
There are actors that are kept on server and there are some kept on client and there are those that are kept on both. I explain all of that in my last post
So I guess my question comes down to, if my struct is onrep'd, how do I actually only update the correct values?
So, I change my stock - in my onrep, I don't know which part of the struct was changed without comparing the current value to the old value
Because if I only change the stock, I wouldn't want to update the optic as well
yeah then you could I guess compare to the previous entries
https://wizardcell.com/unreal/persistent-data/ @solar stirrup
I would throw caution to the wind about adding/removing those custom-addressable components at runtime - you'll get issues when packet loss occurs
Maybe even potential crashes
If it were me, I'd probably just create all the components I'd need as part of the weapon actor CDO and just modify the properties of them
Yeah - that's what WC said last night, but I didn't want the comps to exist if they weren't being used.
It's probably just easier overall to have 'em as CDO
Yeah, the problem is if you destroy a component that has pending replicated properties - the client will fail to resolve the object - that's a real problem if you create a new object with the same name
wack
There are limitations to this technique either way
that's what I get for forgetting to check it out
So basically if on the gamemode I tell it to persist an actor
It won't be persisted on the client?
Nope, it won't
What if I tell it to persist the same actor on the PC
Is that correct or will the engine murder me
You will have to use the other version of the function
That seems like an overkill if the actor is replicated
I just didn't want UE to have to update the scene transform of these components if they weren't actively being used. Wasted operations and all (I know, premature optimization and all that jazz).
If it's not then it seems okay to me
Just detach them. tbh if you disable overlaps, that transform update cost becomes pretty damn small
I knew it'd be negligible overall to be completely honest.
And I know the next question is "why care then?"
And my response is quite simple and Neanderthal-like. Just cause....
I guess Deactivate would help too
I found a quicker way maybe, Add another variable that it's not an array item with OnRepNotif and modify that one when changing the array
FFast would be the best, but i'm on BP currently, thanks anyway!
And what if you want to change more than one element in the array?
You are going to miss changes if you set that property to different values in a single frame
For this setup is okey, i'm never going to change more than 1 at a time, it's for skill casting
Then I probably wouldn't have the array replicated at all. I would just keep it in sync.
But yeah either way should be good
This doesn't seem like a question but a request. #volunteer-projects is where you should look for
It says in
NetConnect.h
enum { RELIABLE_BUFFER = 256 };
and for more context in
DataChannel.h
const bool bOverflowsReliable = (NumOutRec + OutgoingBunches.Num() >= RELIABLE_BUFFER + Bunch->bClose);
This is per channel right, so technically 2 different actors combined can have a larger output than 256
as each channel is its own thing
Correct
By the way an amazing article I found in this regard: https://www.reddit.com/r/Battalion1944/comments/844s5a/our_lead_programmer_james_tatum_explaining/
108 votes and 12 comments so far on Reddit
Really cool of them to just be up front about it
Yeah, I'm amazed they share such info with the community!
wow cool nice 😄
This cat is cuter @twin juniper
Eren changing from the cat pic is a crime imo
I can't recognize him anymore
@fathom aspen do you know why 1 actor channel can't just send the data for both actors and exceed its limit? i.e) manually change the limit from 256 to say 2560. Like in the reddit post why does having 1 actor send that many RPC's vs 10 actors sending same amount matter.
Data is not sent from actor to another actor but to a connection. It's just how things were set by Epic. Why 256 I have no idea, but an actor can't send more than that to a connection
10 actors can send 256 each
But one just can't send 2560
so how epic sets it up is that theres just a connection for each actor and that there's no special connection that has any more than 256?
Right. There is an OwningConnection to a UChannel. That is the one in question
smartie pants, is this knowledge also shared knowledge ?
Tbh digging through source
These are knowledge that is hard to find out there
So it's either tribal knowledge or digging through source
256 is a significant number as that's the highest number of values 1 byte can represent. I imagine that they are probably keeping track of specific RPCs using a bit mask, so they save a bunch of memory by only using 1 byte to represent a reference to those 256 RPCs. I could just be completely wrong though 🙂
It's tbh. If you scroll up a bit you will see how rough this conversation we had today
A lot of things I have to dig through now
would make alot of sense, too bad its not documented anywhere though 😦
hypothetically i could make a channel b 2byte then to include many more but that option does not seem to be out there
had a brief skim over but
if I'm sending an RPC with a string that will have characters with accents, should I send an FString or an FText?
FText because it's localized?
Yeah that's an FString already in PlayerState iirc
I see
I had a chat on that lately and my take was that replicating FTexts is not that rough as people think
Or for example you can replicate an FString and set it in an FText property, say a text widget
I thought you were of those who hate replicating FTexts for some reason xD
I tend for this approach tbh
Right, I was aware there is a function, didn't know its name ^^
the unreal build tool parser specifically looks for INVTEXT, LOCTEXT and NSLOCTEXT
i used to put FText::FromString instead of INVTEXT all the time
what does INV stand for?
👍
might not actually be looking for that one, no reason to
if I have inventory array on server, how do I get them to the client so I can display them on the inventory widget
take a look on jambax post on how to do replicated inventory system
alright thanks I'll take a look
alright thanks for saving some time too I was searching at the wrong place
np
since I did it in blueprint I fried my brain trying to understand this, but I think he replicated the items that the server has to the client, however when I try to replicate my array with json files they return empty
maybe that is my problem and I will have to think about it further before returning here
I'll PayPal you 20 bucks if you can find the line of code that actually calculates the velocity for a Character within 10 minutes.
is the answer UCharacterMovementComponent::CalcVelocity but not actually
@fathom aspen @chrome bay Reworked the components the way we spoke about. Whew - definitely a bit more code 😅. Took a bit to get the logic right for the DA onrep stuff though. But it is working now, with no stutters, and faux replicated 🥳
Glad it worked for you!
Had to handle the case where the old config was completely null and future cases where it wasn't, as well as only changing the things that actually did change.
Ah so the OnRep was called with the config being null?
Yeah. Pretty much the very initial case.
Heck.
So on startup, the old config doesn't really exist.
Because the client is just waiting for that info.
Ah right
Then they get it and the "old" config is just completely empty, because well...there was no old config, lol
Haha
So what you ended up doing is having replicated components?
Or made them part of the CDO?
cdo
Nice
James was talkin' about the risk in a packaged game across a real network being that the game could crash with me spawning/destroying the components.
Due to packet loss or delayed messages, etc...
So the client destroys the component, but the server is trying to send it a message. Nothing to send it to. Game could crash.
Ah fair enough
Or the server destroys it, but tries to send a message like one frame later, same problem.
Stuff like that.
So putting it in CDO is just safer
I know exactly where I would need to do it.
Yeah the hard part is already behind you 😅
Hmm, it depends on game design
// if we have no mesh, we want to use w/e is coming in
if (Stock->GetStaticMesh() == nullptr && WeaponConfiguration.Stock != nullptr)
{
// only change the stock if we actually ARE changing it
if (!(WeaponConfiguration.Stock == OldConfiguration.Stock))
{
Stock->SetStaticMesh(WeaponConfiguration.Stock->PartMesh);
}
}
// we are removing the stock
if (WeaponConfiguration.Stock == nullptr)
{
Stock->SetStaticMesh(nullptr);
}
This is pretty much the logic that I ended up doing. For each part. So, to detach/deactivate, I'd just do it when I set the static mesh as nullptr.
Ah that works nicely
lol - just realized I did the complicated version of "not equal" 😅
You mean the ! before the thing
Yeah
Heh
Working brain - that's what I blame.
Im spawning an actor on the server and then storing a reference to the actor so the clients can use that actor. I have an input action that calls an interface for that spawned actor where eventually i set the state of an enum. The problem is that when i use an on server rpc inside the spawned actor to replicate that state being changed because I need other clients to know that state, the on server rpc doesnt call. How would I fix this?
Sounds like an ownership issue
If the one calling the server RPC isn't PlayerController/PlayerState/Pawn/some other client owned actor then that's normal
Well the clients trigger the input locally, which then uses an interface for an event in the spawned actor, then in the spawned actor i try and call a server rpc to replicate the enum being set, but the event doesnt call when i debug with print strings. Ive used switch has authority and it says the client is is calling the event. The actor is the basic actor class
If it was clear to me it wouldve been answered
It was already
The spawned actor isn't client owned
Meaning you can't call server/client RPCs on it
So you use one of those dudes instead
The player pawn would run a server rpc on ITSELF telling the server that it wants to interact with the spawned actor. The server then runs w/e behavior you're expecting.
Thank you
Does someone have a chart that I could use that displays the networking logic for a turn based game?
UI normally doesn't replicate at all, and it would appear only on the server as you're calling this in an event that's "Running On Server"
So you can't replicate a reference to the widget you're creating, nor can you replicate variables within the widget.
i try to use a switch on authority but the client ui never comes even when using run on owning client
What blueprint class is this in?
the player pawn
Not a good place to put it if it's a "Main UI" as there's no real "single" pawn in the game and "Begin Play" fires on all player pawns when the go out and in relevancy. Also, does that really require any replication whatsoever, you can just have your clients create the main UI themselves in say, the player controller or a HUD class?
alright ill try in the hud class. the main ui is the player health and stuff like that.
push model for BP only vars?
Hello i have a question, how can i change pawn class of a player when the server/client travel is called, or more specifically when the character join the world ? using UE5 C++
In GameMode there is DefaultPawnClass
Hey, movement mode on character movement component is not being replicated?
How the multiplayer server works in PIE ? I don't have any BP hit on the game mode
Hello im working on a battle royale game and want it uploaded to steam i use this kit: https://www.unrealengine.com/marketplace/en-US/product/battle-royale-template-inventory-minimap
but any one have a tutorial or course where it explain what u need as host how to set it up and stuff
hey guys, What is the right way to switch pawns in a multiplayer game and from where should I do it? For instance I have an NPC in the level already and when I spawn my controlled character I want to be able to switch back and forth.
At the moment I'm calling an RPC from the player controller and do the switch but I'm often getting "No owning connection for actor".
Any help is much appreciated
You need to RPC to the server on a player owned actor, like player controller, playerstate or their existing pawn. Once running on the server you can then call whatever you need to on any actors.
Trying that now thanks
Game mode only ever exists on the server, so if you're trying to call something on Game Mode while the code you're running is on a client, it won't work.
The PIE is supposed to start a server ?
Yes, either a listen server which is one of the clients hosting, or a dedicated server (play as client) is launched in the background.
Mhh i have different behaviours from packaged games and PIE, there is nothing special to configure ? listen server should just work in PIE ?
So I have tried to RPC from the player controller to the owned character but I still get the same behaviour : the ability that was running cannot cancel and won't reactivate.
UNetDriver::ProcessRemoteFunction: No owning connection for actor BP_Demo_Character_C_0. Function ServerCancelAbility will not be processed.
This happens after I unpossess a character. Maybe it has more to do with the gameplay ability system itself
It does.
I mean everything else seems to work fine
hey i'm wanting to make a online vr game and i dont know where to start can anyone recommend any tutorials or anything?
That's sort of like asking if anyone has tutorials on building a car. You don't start by just building the car you've always dreamt of
Just make some projects, play around with ideas that have to do with the concepts you want to implement later
hi, I couldn't find any good source on which ports to forward when your dedicated server is behind a proxy... do you know a good source?
hi! my own game is about to get finished finally but theres some bug with matchmaking! my goal is to have more than two matches in one single server just like in any battle royale. also i have a bug where new players keep joining the ongoing game when it already started (and they shouldnt, just like in any br game). When using AWS Matchmaking. AWS will try to fill the amount of players the match is set for.
Always.
So, we tell AWS to stop back filling players once game has started.
Here it's not listening to our request.
We are using Manual instead of auto fill
Player Sessions get updated everytime a Player Logs in the Game.
Any suggestions?
I haven't used AWS matchmaking but be sure your session is set to not allow players to join a game once it's started
is there a method of replicating an array of JSON objects? trying to replicate the array with pass by ref just returns an array of nulls and I've thought about making the JSON objects into strings and replicating an array of strings but I have no clue how to turn the strings back into JSON objects
#rules No crossposting, no unsolicited DMs, be patient.
is this the best way to get my local controller in multiplayer? note that im doing this in my game isntance
Objects don't replicate by default. Information about how to replicate a uobject can be found at the below link. If you wanted to convert the JSON Object to a string and back again on the other end, that's possible too, but it would require some C++ or a plugin to handle.
https://jambax.co.uk/replicating-uobjects/
In the game instance that is fine as the game instance isn't replicated at all.
thanks
alright thanks, I'll try to understand this
Does FastArray requires any additional serialization setup or NetSerialize does it iself ?
Check pins, #3
It does. Check NetSerialization.h for reference
Lyra did not do additional serialization 😐
I meant you shouldn't do
oh ok 👍
Is there an official RECOMMENDED way to replicate things on UE5&4? I'm always learning with tutorials but I'm always wondering "is this a good method tho?"
Yeah it's to mark "things" as bReplicates
I don't think you need any tutorials but the one you find in this channel pins
Is it possible to use beacons in PIE ?
It goes by the name multiplayer compendium
Ohhh, I'll make sure to verify these
tysm!!!
Try it. Why wouldn't it be?
I don't know why it's not working, that's why i'm asking
Does it "work" in a non-PIE environment?
Yep
Just trying to test multiplayer stuffs in PIE, without having to use standalone
The AOnlineBeaconHost::InitHost fail
Because the NetDriver is null
Have you traced CreateNetDriver_Local?
It seems to return an ipnetdriver
So it's not null 
I was talking about AOnlineBeaconHost::InitHost
Yeah that calls AOnlineBeacon::InitBase() which creates a NetDriver
Trace the function that creates the NetDriver
See why it's returning null
The first call create a driver, the 2nd returns null
The game net driver is fine, but not the beacon net driver
Maybe it's another PIE limitation, dunno
Yeah could be. I keep away from PIE for such functionalities tbh
I know it's tempting but not that reliable
I'm trying to find a way to test multiplayer without having to run standalone games on 2 machines, that's kinda annoying
I mean can't you have two standalones on the same machine?
Not with steam
Ah heck
And you have to package first
Yep i'm using a VM
But that's so many step just to test one multiplayer stuff
Definition = Engine->NetDriverDefinitions.FindByPredicate(FindNetDriverDefPred);
Is null for beacon driver
The steam net driver is null in PIE but it should fallback to the ipnetdriver
Hi, is still relevant to learn the Replication Graph plugin for large actor counts or are there any newer systems nowadays?
I'm looking at articles and videos from 2018/2019 and just wondering if this is still the way to go.
It is. Though with RG you still have too much replicated actors, meaning too much of server cpu usage
That's why Net Managers come in as a great optimization in this regard
Check pins for an idea of how they work
The post there goes over preplaced actors as they are net addressable by default, but not dynamic ones. For the latter you will need to make them net addressable
So you fake the engine into thinking they are by overriding IsFullNameStableForNetworking to return true, and also deterministically name them on all machines
So you end up replicating too many actors, not through their own channels but through some other few actor channels known as Net Managers
Has anyone developed a way to use listen servers properly with world partition? (Basically the server loading only around every streaming source rather than having the entire map loaded)
yes
take a look at Main in Unreal Engine GitHub, epic got that implemented very recently
btw got mine working over eos in pie
This is bad.
- "Begin Play" fires on both the server and the client, so everything you're seeing there is attempting to execute on both the server and the client.
- It's using an RPC event (Executes on Server) to trigger the health regeneration. Now, again, as this is firing on both the client and server, that means the server is triggering that event, and the client is also triggering it asking the server to execute it - so it's going to happen twice! It's also bad as someone with know-how could potentially spam that RPC call forcing their health to regen even faster.
To fix:
- Make the HealthRegen event just a standard event, it doesn't need to be an RPC.
- You can probably use a "Has Authority" switch on Begin Play with the "Authority" path connected to the timer. This will make it so only the server calls the timer to regen the health.
thats what i was seeing, it was duplicating health regen. thanks for the help
any idea about death replay system in UE?
I think this qualifies as "any"
Don't have anything else than that link
speaking of which, anyone got it working?
Mhh how did you define the BeaconNetDriver in the ini ?
in my defaultengine.ini ?
NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="/Script/OnlineSubsystemRedpointEOS.EOSNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
Mhh
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
I think it should be fine
Did you configure something specific in the editor ?
I will take a look thank you.
So i've been trying the invite system from the advanced sessions plugin, but it doesnt work. My friend can accept the invite but the joining proccess fails. This is the error for it in the log:
[2022.09.11-12.18.40:570][794]LogOnlineSession: STEAM: Search result 0: LobbyId=Lobby[0x1860000EF23538F], LobbyId.IsValid()=true, CSteamID(LobbyId).IsLobby()=true
[2022.09.11-12.18.40:570][794]LogOnlineSession: Warning: STEAM: Session (GameSession) already exists, can't join twice
[2022.09.11-12.18.40:570][794]LogBlueprintUserMessages: [BP_BaseGameInstance_C_2147482601] Joiningg failed!```
Do i have to destroy my current session first or is this error strictly related to steam?
It's indicating that the player attempting to accept the invite is already in a session. The subsystem prevents anyone from joining a session while already in one.
so i should call destroy session before trying to join?
Did you purposefully put them into a session to begin with?
I'm trying to call getcontroller on my character in a server RPC but it always returns null. Is that normal or am I doing something wrong?
playing in editor as client
does the player controller only exist on the owning client?
nvm, I was assigning a new character to the controller in the same function prior to the part where I needed to call GetController 🤦
Hey
How could I do multiplayer player names over the head of each player?
I have the widgets setup above the players head
Just not sure about how to get the info to display
As widgets are local
You have it working locally already?
I think if the widgets are replicated actors, if you spawn them on the server they should just replicate to all clients
Widgets are components. They don't have to be replicated components, but just be part of the CDO.
You already have a name property on the PlayerState, and OnRep_PlayerState in pawn iirc. Wait for the OnRep to be called, pull the name and set it to the widget
But if i set it to the widget then other players won't be able to see it
They do, if you do it like I said
Replicate the seed with an OnRep and generate it client-side when the OnRep is called
Do I understand correctly that game mode class is for establishing rules / logic of the mode and game state is for storing all data related state?
You do
Since gamemode is only on the server and gamestate is on shared between clients and the server, what place is better for storing each individual player score?
gamemode or game state?
I see. Thank you, much appreciated. I'm trying to get into multiplayer gameplay programming in ue
There is a property in that class that already goes by the name Score
Cool. While you at it, you'll find the compendium is a valuable resource. It's found in 📌
Okay, now i have problem with spawning characters. All clients appear correctly, but not the host
Hi there, using blueprints, I am trying to run a listen server. Player 2 (The client) has no control, and sometimes controls player 1 for some reason. Player 1's movements appear to player2 but player 1 cannot see whatever player2 does. I'm new to networking
I smell GetPlayerController(0) used server-side
Also if you open TPS template that doesn't happen. So it probably means you are doing some custom movement stuff

I have 10 thousand tabs open lol. What should I send you?
And yeah from blank project
FloatingPawnMovement isn't networked afaik
Hmm. I've been having a lot of trouble with floatingpawnmovement
void APhobosGameModeLobby::OnPostLogin(AController* NewPlayer)
{
Super::OnPostLogin(NewPlayer);
// Cast to PhobosPlayerControllerBase
APhobosPlayerControllerBase* InNewPlayer = Cast<APhobosPlayerControllerBase>(NewPlayer);
// Add to PlayerControllers
ConnectedPlayers.Add(InNewPlayer);
for(const auto Player : ConnectedPlayers)
{
if (Player == InNewPlayer) continue; // Skip the player that just joined
// Notify the existing players that a new player has joined
Player->ClientOnPlayerJoined(InNewPlayer->PhobosPlayerInfo);
}
// We send the full list of players to the new player, including themselves
for (const auto Player : ConnectedPlayers)
{
// TODO: Maybe we can do this in a single call ?
InNewPlayer->ClientOnPlayerJoined(Player->PhobosPlayerInfo);
}
}
this this is how i handle new players joining to a lobby, but the last bit, where i "send the full list of players to the new player, including themselves" does not execute on the joining player, they only get the player list after someone else joins after them. I'm suspecting that OnPostLogin calls the stuff there before the clientside is initialized?
Yeah that's why people end up using CMC
And tweak it to their liking
How can I add this? It's not appearing in the list
by parenting to Character class
How? I am still new to unreal sorry
You don't need to build any lists like that
You already got PlayerArray
Ahh tyty
Also Player (PlayerController) of some other player isn't net addressable
Client-side there's only one PlayerController (of owning connection)
yeah true i guess, i was avoiding casts by building that one, but my problem is onpostlogin doesn't seem execute the events on the joining playercontroller
Well if you are seamless traveling then yeah it won't
It only works for hard traveling
Ah I thought OnPostLogin wasn't executing at all
Well you should be able to call RPCs just fine at that point
On the PC
the server hard travels to lobby level, which should list the listen-server player on the lobby's player list but it does not
then if a second player joins, the listen server's UI will get updated and display the 2 players
then the newly joined player's lobby displays nothing
that updates when a third player joins
Wait so I cant test this on one machine?
Is "Play as Listen Server" unreliable for testing networking? Really struggling to make this print only run when on the local client, and it keeps running even if I check if an actor is locally controlled, and controller[0].
I'm passing in the instigating actor, and if I try testing out printing the location it's definitely showing me that it isn't passing in the same character.
blue = p1 red = p2
I can't for the life of me figuring out what I'm doing wrong to not trigger firing on other clients.
// We send the full list of players to the new player, including themselves
for (const auto Player : ConnectedPlayers)
{
// TODO: Maybe we can do this in a single call ?
InNewPlayer->ClientOnPlayerJoined(Player->PhobosPlayerInfo);
}
so i'm sending the existing players to the joining player, but the ClientOnPlayerJoined event does not fire on the joining player
Print string is only debug info and displays on all windows. The fact that it says only client2 indicates that only client2 is actually calling the print.
Well what concerns is me it passes even when I compare controllers.
Even "IsLocallyControlled" passes
When it's not the controlled character
Controllers only exist on the server and on the owning client. So client2 doesn't have a reference to client1's controller. So getting the controller of a character while executing on a client will only return a valid value if it's the local player's character.
Wouldn't I want to avoid that when testing multiple clients and a server?
Listen server can muddy the water as the sever has a reference to everyone's player controller. That's why GetPlayerController is usually ill advised in multiplayer - just use IsLocallyControlled, and if so, continue if you only want it executing for that particular person.
How do know it's the client RPC isn't executing. Is it because you debugged it or because things are not working as expected?
Ah ok.
Ok now I'm curious.
does not hit breakpoint + client UI does not update, the lobby blueprint subscribes to ClientOnPlayerJoined() and when it fires, it updates the lobby UI to show the players
I thought server would replicate the changes to the clients.
Unless I just had to just not check is locally controleld
But yeah without debug it works now as I expected.
@.@
So debug must of had me thinking I did something wrong this whole time
Ok no now I'm just confused.
I tried firing world rotation right off.
Server doesn't replicate
And I have replication on
cc: @sinful tree
Everything is here.
So the order is:
Character (Fires ShowPrompt) -> Prompt (Show function runs) -> Show Function (Fires Delegate) -> Blueprint (On Prompt Shown)
So no RPC to the server?
Well I wanted to avoid that, the thing is I just triggered it from the "Server" character.
Which is why I'm confused.
Unless I need to make the server specifically tell the clients to replicate/fire that change, from maybe a state?
i think you want a multicast
why is it that when I use restart player at transform everything is ok but when i user restart player at player start, the host will not spawn.
they are created for everyone using this code
I can show all the blueprints by screen sharing
okay, my fault, incorrect using of "FindPlayerStart"
Another question. How to use the FindPlayerStart correctly for spawning at specific PlayerStart?
PlayerStarts have tags which you can utilize
Where i can find tags?
It's public, so you can set it just fine
Though from the sound of it you want to set it at compile time
Thank you so much!
hi everyone, im really struggling on figuring out how to replicate this, i basically have my game setup to start as a spectator then transition to the player character once the match has started. it works great in single player, but doesnt work in multiplayer. I suspect its related to MustSpectate_Implementation not being replicated, so I tried to use a replicated variable to set it, but it did not work. Any help would be appreciated.
Oh snap - I forgot Ashes of Creation even existed 😅
I remember getting excited about it a few years ago though. Just kinda fell off the radar
I see, makes sense thank you
IIRC ShooterGame already does it. You can take a snap
im essentially just trying to start as a spectator and switch to a player
Im gonna try 1 thing in the player state then ill check out shootergame
is it the old one with the orignal ue4 guns
Its Lyra's ancestor
I need a static shared camera for 2d multiplayer game any thoughts?
If possible I would like to change the default player camera manager's camera also if possible I would like it to stop spawning camera with every player spawn
I ended up figuring it out btw, thank you
tho i notice something strange happening with my gamemode, when i spawn in multiplayer, only 1 player controller spawns for 2 players
and it causes a bunch of errors in anything that references the PlayerController
just curious, how do most of you handle playing an animation for all players? for example a player reloading a weapon; do you choose to send a multicast or do you have a replicated variable like bReloading and handle that OnReps instead ?
yea I thought I about it the same way, but what happens when a player joins the server while someone is reloading their weapon? do they see the reload animation playing?
No - but it also doesn't really matter imo.
Big whoop, they missed like 2 seconds of an inconsequential animation
hmm yea thats what I thought
but I guess for very long animations that could be an issue
so I was thinking about a replicated boolean in the playerstate since that is always relevant, but I guess that would be weird, I assume the norm here is multicast rpc's
Not playerstate - just the character. If the character isn't relevant, then you don't care if they're playing an animation anyway. It's fine to use a variable to control an animation, but at that point you may want to make it part of your animgraph state system rather than say having it play as a montage - you run into a similar problem that if the player joins in late and starts playing a 10 second animation but the originating player was already playing it for 7 seconds, then the joining player would be seeing it for longer unless you're also calling a multicast to stop the animation when it's supposed to be finished.
hmm yea thats a good point
If a continuous motion like "hold a shield while RMB is pressed" exists, the variable/onrep approach might be better than start/stop one-off multicasts in the long run
putting the reloading example aside I wonder how people deal with this issue for longer/slower animations, multicast has the issue of players who join late wont see the animation, but replicating a variable has the problem of the animation not being synced for the player who joins late
and sending a multicast to stop the animation is also not great because it will stop playing suddenly when its not near the ending
Does the animation really matter to the gameplay?
well I dont have particular problem/scenario that I'm trying to solve, I'm just curious about how people solve these types of problems
maybe start playing the montage from a certain point instead of always starting at the begining, if that is even possible
but then that has the issue of keeping track of where to start playing 🤔
Most players won't really notice whether an animation was supposed to look a specific way when ending.
Again, different if it's something gameplay specific that players would be looking for.
I can't speak for everyone but I think most people would accept the desync in that scenario.
If we assume that players do actions/animations in a match nearly all the time, then you could argue it auto-fixes itself by players overwriting the late-joiners animation.
yea for short animations like reloading I dont think its a problem
hi, during the network replication based on distance when I approach the actor A with my character, it gets replicated. But when I approach actor A with another actor B I own ( owner of that actor B is set to my player controller ), it doesn't get replicated. What is the logic behind this, any docs?
would it be smart to do an onrep for death
as far as server is concerned relevancy is calculated from whatever client sent it during ServerUpdateCamera
there is a downside to it, like dead enemies standing up so they can play their dying montage when you walk into relevancy range
we use a synced network clock, and we don't replicate bool bIsDead but rather float TimeOfDeath to be able to differentiate just died from died a while ago
Yo Zlo is back 🥳
3 weeks vacation ❤️
thanks, but imagine there are two teams (1,2). Team1-actorA is close to Team2-actorA, Team1-actorB is close to Team2-actorB. ServerUpdateCamera() with which actor's location is meant to be sent to the server so both actors from Team2 are replicated?
thats a controller function, iirc
its not per actor
you might want to look into replication graph and its buckets for this
Hey guys quick question. Does set player location or teleport player trigger actor relevancy?
Lets say I have a player like 5km from me. Of course they wont be relevant to each other due to the distance and thus wont be able to see each other.
But if I was to teleport one player to the other would the relevancy trigger and them be able to see each other?
(I ask because I tried it and it did not work inside a built version of it, was wondering if I did something wrong).
I was wondering how networking is implemented in racing games where lap times are measured down to the millisecond (for example trackmania). Does the server register the start and end of the race and calculate the difference? If yes, ping affects these results so how would they handle this? Or is it a completely different way (that allows no cheating)?
If you're worried about cheating you probably want the server to be the be-all end-all authority on everything
So ping wouldn't affect anything
The server measures the time and logs it
How does that work roughly in terms of what the server tells the client and client to server in a racing game? It's been a while since i developed a multiplayer game. (i'm not planning on making a racing game, i was just wondering)
there is a ping between the client telling the server it's location right
Latency doesn't matter much. The server's car will pass the starting line say 50ms after your press the "start" button on the client, but what matters is end time - start time
Ping is irrelevant to the duration of the race, since it doesn't make the car faster or slower
The input is just delayed on the server
i think i understand what you are saying
but not 100%
so lets say like you said i press forward and my ping is 50ms, the server will start driving 50ms after i press start, lets call it T1. Now a bit later, the car is standing still 1meter in front of the finish and i press forward again (and instantly finish), but now my ping is 250ms. The server will register the end (T2) 250ms later, no? then it can't just do T2 - T1 because of the last ping. That last bit is what i don't understand
In reality you'll be pressing start before the round starts and so the car will start at exactly t=0 on the server because you started pressing it five seconds earlier
The arrival time should have nothing to do with latency at all - imagine a straight line where you keep pressing A on Mario Kart
It doesn't matter if you have 50ms ping or 1s ping as long as the car stays controllable
Multiplayer racing is quite complex but these issues aren't a thing
The main problem in multiplayer racing is always going to be physics
Random thought I had
Would it be possible to have RPCs in a UGameInstanceSubsystem if you override CallRemoteFunction() and GetFunctionCallspace(), and make it net addressable with a stable name?
Assuming you use an actor in the world as a proxy
Okay i think i understand it now ty
hello, how can i transform my offline vr game to online or lan vr game?
How will you make it stably named? Sounds like you need an engine modification

