#multiplayer
1 messages ยท Page 227 of 1
you want to avoid replicating them to avoid cheaters?
if you want to get around that you will probably have to add and remove stuff per client with RPCs
yes, this too
and just have smaller network footprint
ok, fair enough, I think having an actor with custom relevency for those items is a good idea then
yea, I will try to do it
shouldn't be hard
anyway I actually need to attach this equipment somewhere, so this is the way. thank you ๐
bool ACOR_EquippedItem::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget,
const FVector& SrcLocation) const
{
const ACOR_Character* PlayerCharacter = Cast<ACOR_Character>(RealViewer);
if(!PlayerCharacter)
{
return Super::IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation);
}
if(PlayerCharacter->IsBlinded())
{
return false;
}
if(IsInvisible() && !PlayerCharacter->CanSeeInvisible())
{
return false;
}
return Super::IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation);
}
what is ViewTarget here?
according to the header comment:
RealViewer - is the "controlling net object" associated with the client for which network relevancy is being checked (typically player controller)
ViewTarget - is the Actor being used as the point of view for the RealViewer
RealViewer = player controller
ViewTarget = player pawn
I guess
I have never actually used this function - we had a custom NetReplicationGraph which we used instead for custom relevancy
if i use ServerTravel on a standalone PIE instance, will it correctly create a listen server? or is it to late since only engine will make one if having the correct play net mode?
You can create a listen server after pressing play in PIE, but not via server travel
The usual open level or client travel with ?listen is for that
oh im dumb
thanks
but for the client join, will a simple clienttravel 127.0.0.1:17777/Map/Path work ?
from what i could test it doesnt look like this is the way
and i cant find how the client PIE instances joins the server
it's just the IP:port and nothing else
you can send args, but not important right now
well im dumb, i mistyped the port
typed 17777 instead of 7777
i wonder how much hours i would of saved if i wrote it right since the beginning
wdym with not important now ?
an irrelevant detail
you don't need to specify the map name
the server will tell the client which map to load
ah yeah
Hello. Anyone have any idea in the Lyra project how i can return the team ID in BP ? i would like to have skin specific for each team instead a random system. I tried the listen for team function but nothing came out ...
this just dont work . I tried a listen for team nothing too
You might want to ask over on https://discord.gg/HPGay5VX
I'm having a very strange issue. I'm using steamcore (not sure of this is relevant) to create game lobbies. All is swell and working. But! a particular actor is sometimes being replicated to clients from other lobbies.
it's a very odd issue.
I'm trying to use PCG Runtime generation, and even when the placed meshes are identical, when a client player is touching a PCG placed object I get this spam warning in the log.
LogNetPackageMap: Warning: FNetGUIDCache::SupportsObject: InstancedStaticMeshComponent /Game/Raiders/Maps/UEDPIE_1_MAP_Hub.MAP_Hub:PersistentLevel.BP_PCG_Clutter_C_3.ISM_SM_Canister01_0 NOT Supported.
Any ideas on the best way to hack around this?
The PCG BP is placed in the world at editor time so this should be stably named. The ISM is generated at runtime but it also has the same name on client and server.
Are you trying to generate from Game state ? Runtime Multiplayer stuff good to generate from GS
With replication turned on that actor class
This is specifically an issue with the PCG Plugin from Epic
But I've seen it before with HISM/ISM built at runtime. I think it's becuase the CMC is not able to replicate a reference to the mesh the capsule is colliding with, because the ISM is not "Supported For Networking"
but I'm not sure how to fix it!
UGH! It was because the BP I created was Movable ๐คฆโโ๏ธ . Setting it to Static and now there is no warnings about collision!
I'm trying to trigger achievements when eiter player reaches a point. But sometimes only the Server/Host only gets the achivements while the Client gets nothing. But it seems random.
My Idea was anybody calls -> server call -> mc call -> triggers on both.
i have my sprint hooked up with prediction and confirmed it works, but im stuck trying to limit the sprint angle, cant seem to get a proper rotation from forward to the input direction
Multicasting this on a character wouldn't be reliable as players can be outside of relevancy range and may not receive the multicast. You're likely better off multicasting something like this in the gamestate and having that multicast call an event dispatcher that other objects can listen to and then apply the required achievements.
Other things of note:
You shouldn't be using the "Get Player XXX <index>" in online multiplayer games. Assuming this is a controlled pawn, GetController > Cast to PlayerController would work to get a reference to the correct player controller that shouldn't break anything.
You may want to consider moving your achievement management code to something other than directly in your player character, like into a component.
You shouldn't really need to call a server RPC for most things relating to achievements as the server should probably know about the events that would trigger it happening anyway - so if you can detect it on the server to begin with, you don't need the client telling the server that the client detected it.
Hey folks. So I'm using the player state > GetPlayerName node to populate the player list for my lobby UI but it just keeps populating it with my computer's names rather than my steam name. I was under the impression that Get Player Name was supposed to pull your nickname from the platform your project is using.
Did you try in a build? If you launch from editor Steam is disabled so it falls back to Null which is a random number after computer name.
@silent valley I haven't tried in a packaged build but I have tried in standalone which has steam functionality so I thought that should work
Yes it should do. Check the logs to see if Steam initialised successfully.
ok. I will. I guess I just assumed that it did because Steam Overlay was working properly
That's usually a good sign. I don't know why else your names wouldn't be working...
You creating and joining a session correctly?
@silent valley That's my flow
And in the LobbyGameMode I'm doing this to get the player name:
It could be that the name has not replicated at that point...
I can't remember exactly how that is set.
ah. ok maybe a delay in the game mode would set it right
Might be worth a try. Or hook a different delegate that happens later.
Right. I'll try the delay as a quick debug and then make a delegate if that works.
Just a heads up, you don't need to do the below. All playerstates in the game are kept in the PlayerArray in the GameState which is managed for you automatically, and from the PlayerState you can get its owning controller when necessary.
Additionally, the structure you're trying to replicate would probably make more sense to replicate through the PlayerState of the player using an OnRep property rather than attempting to RPC it out to everyone.
It's also a bit redundant to replicate the playername. The PlayerName is normally replicated on its own.
Hmmmm... ok so... if I want to update a list of connected players in a session whenever a new player logs in or out of the session, and it needs to update the Widget that everyone is seeing, using your logic I would still use OnPostLogin and OnLogout in the GameMode but instead of making an array of "connected players" in the GameMode, I would set a variable in the playerstate that has an OnRep and then do my updating from the OnRep
Nope.
The GameState has an array of connected players, the PlayerArray.
You can use Begin Play of PlayerState to know when someone joines.
You can use End Play of PlayerState to know when someone leaves.
You can use a reference to the player's playerstate to get information about that player - so like their player name, their pawn (if it's relevant) or any other data you want about that particular player so long as its replicated.
An easy way to go about it is to:
- Create a couple of event dispatchers in the GameState, called OnPlayerJoined, and OnPlayerLeft, both with a PlayerState reference input.
- On BeginPlay of your PlayerState, get the gamestate and call the OnPlayerJoined event dispatcher passing reference to self in.
- On EndPlay of your PlayerState, get the gamestate and call the OnPlayerLeft event dispatcher passing reference to self in.
Now you have a single centralized place to know when players join or leave the game, and it contains the list of players as well, and that list is also a reference to those players.
So your widget just needs to get the game state bind to the dispatchers to know when players are joining and leaving, and otherwise read the current list of PlayerStates in the PlayerArray and create widgets for any present in the game currently. You can also create a widget when a player joins and feed it a reference to the PlayerState it belongs to and the widget itself can read whatever data it needs from that PlayerState. When they leave, you can have the particular widget that is associated to that player destroyed.
That's so clean. Alright I'm gonna attempt to implement that. Thank you for taking the time to type that out. I really appreciate it.
Oh, and I assume I don't need a different game state and player state for the lobby vs. the actual game if I don't need specific functionality between those two game modes.
Technically no. If you did, it may be smart to make at least this part of it as a base class, and then if you needed to extend it from there you can always subclass it.
Makes sense. Again, much appreciated
So far so good. I'm having trouble figuring out how I'm going to find the widget associated with each player to delete it when a player disconnects, without knowing it index in either the Player Array or the scroll box widget it's being added to as a child.
When creating the widget for the player, you can create a TMap of PlayerState>Widget and look it up when needed, or, you can have the Widget itself bind to the event dispatcher in the gamestate to listen for leaving events, and then check if the associated PlayerState fed into the widget == to the one that is leaving.
Right. Binding to the event dispatcher should have been an obvious one. dur. Thanks.
Man. I don't understand sometimes why dumb stuff happens. I am unable to test this because suddenly the widget that shows connected players isn't showing up. I didn't change the way it was being created or added to the viewport but suddenly its just not there.
I have it being created and added to viewport from my HUD class OnBeginPlay
Did you create a new gamestate class?
yes
Did you make sure it was made with GameStateBase or GameState based on whether your game mode is GameModeBase?
uh.. I think I used GameState instead of GameStateBase
Do I need to make a new one or reparent it to GameStateBase?
ok. Yeah I reparented and now it shows up. Weird. I'm not gonna ask you to explain why that happened but thank you.
@sinful tree I recall you telling me I should have On as a RepNotify in my parent blueprint and leave it as empty for child blueprints. How do I access Rep Functions from a child blueprint? I don't see it under functions, nor in override.
Guess I'm doing something wrong because this implementation doesn't seem to be working.
it's just in the master
So there is no way to edit a repNotify function from a child blueprint?
well you can, in the parent one. assuming your children have some sort of differentaition to them, you can use that to check what child it is from that parent onrep function
Can always have the OnRep call another function which you can then override in child classes.
Oh, So in parent BP OnRep_ON, I can call ItemTurnOn Function, leave it empty, and then for every item I can use the ItemTurnOn function
When players join, don't clear the list. Just create a widget and add to it. If you want the existing list when the widget is constructed, move this up to where you're binding and instead of getting index 0, loop through them and create.
I'd maybe call it "PowerStateChanged" but yea.
You can have a branch within the OnRep if you want and have it call separate functions for on or off... etc.
Creating an Inventory System
I have an Inventory that Contains 5 Inventory Slot Groups
Each Inventory Slot Group has a Array of Inventory Slots (length is editable in instanced in BP)
an Inventory Slot contains a Inventory Item Instance
and Inventory Item Instance contains a subclass-able Item Instance, that is basically a container for an items functionality/information (think Weapons data, Consumable data, Armor data, all are sub-classed from Item Instance)
do I need to Replicate all the Subobjects with GetLifetimeReplicatedProps? or will just replicating the top Inventory or Inventory Slot group be enough?
this is attached to a Character/Pawn.
this is designed like this because of the way the different Items need to be handled, I have all the logic for the inventory, just need to make it replicate-able
is there a way to know if a level is listening for connection locally (for eg before doing a client travel) ?
What do you mean?
Can you explain your question in another way.
if i attempt a client travel with a URL like LOCALURL:PORT/Map/Path but nothing is hosted/listening there, it will result in a fatal crash
i was wondering if i could do a "check" if anything is hosted/listening here
(im only doing this in debug mode, otherwise im using EOS and this cannot be done without using a valid connection string so i dont need a check for this specifically)
The map path seems a bit sus?
simplified it
Why does a travel url need a map path
Game/Some/Folder/L_Game for eg
Why does the client care?
because im doing a local travel
not using sessions or anything in the debug mode
the server just starts listening in a map using the Listen arg in OpenLevel
and i join clients with that
Try just travel to server ip and port
wdym with that ? isnt what im already doing ?
Show the command the client is actually executing
you want to travel to LOCALURL:PORT ?
Client yes
Why would clients specify a level, the client just says hey, load up whatever the server has going on
because i didnt know it wasnt required ๐
I don't know if it wasn't or not either. But I know just opening the URL is enough
always saw engine using the path so i just reproduced it in my code
but wouldnt this still crash even with no map ?
I have no clue. But the client specifying a map seems redundant at best and wrong at worst
Travel is a very different thing.
It connects to the server and loads up whatever map the server has loaded
okay, but is there a way to check if anything is hosted at LOCALIP:PORT on UE "side" ?
with nothing hosted it sounds like it just opens self, coulnt trest if its act like a standalone or client or anything
If anyone can help #ue5-general message
No Crossposting please.
Character Number Is selection Item number From Structure to Apply Character material On that character
- image is UI
2 and 3 is from character blueprint
Character is not possess It's spawning only ( PC have Character Reference)
It's Only Work For server not for Client
Can any one tell me what to do ?
Hello everyone, can you tell me if it is possible to run a map for a dedicated server using the world partition with loading only one area?
I conducted a test with the Titan project and it turned out that it will consume 10 GB of RAM for a dedicated server
I'm trying to make a system of areas with binding (one area - one dedicated server), maybe there is some setting to run only one area?
Get rid of multicast
Client can request server to change the variable
If the variable is replicated, everyone will get the server's value eventually.
but it's not even updating on server
In addition to @dark parcel 's answer: The Variable should be a RepNotify one, not just a replicated one, so you can trigger your local changes from the OnRep function.
The reason this doesn't work currently might be due to the ServerRPC being dropped.
You said the Character is not possessed. Where are you spawning it, can you show that?
Haven't used WorldPartition much yet, but I don't think the Server should have everything loaded by default either way.
The LevelStreaming system also allowed only loading a level when needed. Server does of course need to load all levels that have any player in them, even if x players are in x different levels, but if they are all in the same level, it should only require that one level to be loaded.
And with level I mean the streamed level, not the persistent one.
oh
If you want to have Server (and Client) RPCs working in the Pawn/Character, even if not possessed, you'll at least need to set the Owner to the PlayerController of the Player already.
Where do i set character as owner
on PC ?
You don't set Character as Owner.
You need to set the PlayerController as Owner of the Character you spawn
Either when spawning (Owner pin) or afterwards via SetOwner (has to happen on the Server)
hmm
You said your PlayerController has a reference to the Character.
Where is that happening?
That's in the PlayerController?
Right, the last node is wrong here.
The Character is NOT the Owner of the PlayerController
It#s the other way round.
This needs to be replaced with just "Self"
Aka the instance of the PlayerController the code is currently executing in.
If you need a reference to that ActorLocation then add a custom variable in your Character, mark it as "InstanceEditable" and "Expose On Spawn", and set it here.
ok so instead of own i use location for spawn
and make it self
Yeah the main point here is that the Owner (NetOwner) of the Character needs to be the PlayerController.
Otherwise, your ServerRPC will be dropped.
Also, side-note: If SpawnPlayer is called from the GameMode, it isn't needed to mark it as an RPC.
You only need it to be an RPC if the Client is supposed to call that method and have it execute on the Server.
By default World Partition loads every tile on dedicated server. Epic are adding support for dedicated server streaming but it's very experimental last time I looked in 5.3
There's this CVAR for example wp.Runtime.EnableServerStreaming - you could try enabling it and see what happens.
Is it Okay now?
I meant still IT traning to access none from Client side
i am taking this character variable
Make sure the character variable is marked as replicated
oh lol i forget i knew it
Lmao It's working
I have learn Owner things that's what i missing
What do you thing what i need to learn?
Look through the compendium pinned in this channel.
Can I specify this parameter in the start line right away?
Yes, same as any cvar if you google it. Can use ini file or commandline.
Hey guys, I need some help, I have pawn that loads its meshes on Runtime and some meshes through ADD STATIC MESH COMPONENT Like in the 1. image, when I play my game, nothing gets replicated, the meshes created on runtime are not even visible, even though I set them to "Should Replicate". I have an event that calls a series of functions to Load my visual meshes from a DataTable or a struct variable. Like in image 2.
How can I replicate it so the other players can see my Car, wheels and everything
Where do add component and set asset functions being called?
@upbeat basin When I call Load Event, it has 3 different functions that sets meshes. In Image 2 I call this event at the end of begin Play calls.
Is your asset already available/determined in BeginPlay?
Hello guys, I am very new here. I am network engineer and working with multiplayer in UE. But I am very new to UE in general.
I am trying to use Network Managers, concept, where instead of using actor with replicating properties, create a few "proxy" actors for replicating the properties for other actors. The "proxy" actor will have a replicated FastArray of data for individual actors in a game.
This way it improve a server performance, as otherwise the server has to check if any properties has changed on very individual actor and this process does not scale well for a large amount of actors in the game.
The issue I am having is related to send the initial state of these proxy replicated FastArray. As these array can get pretty big, the amount of data which have to be send on a client join, gets too big and exceeds net.MaxConstructedPartialBunchSizeBytes.
Does any of you have dealt with such issues before and know a good way to handle this?
Thanks in advance.
Yeah, I load the assets from an already selected Struct from a data table.
Okay but how do you know which entry you need to select from data table? If your entry is predefined do you need it to be replicated? If your server determines the entry, you might be missing the replication of that information in client BeginPlays
That sounds unnecessarily complicated. And missing out on relevancy range etc. There's several mechanisms in Unreal already for managing this. NetUpdateFrequency, dormancy, push model.
Well from my Main Menu I determine what I want. Then mhy GameMode spawns my pawn and then it goes on and do the other stuff. If I set this Variable to be Replicated, it does not do anything, If I set my Load Car event to Run on Server, it just mess everything up.
yes, but none of this help, if you have let's say a 1000 actors in the scene. The server will have to check each of them for change in any of the replicated properties and it is a "death by a thousand cuts".
You can use net update rate and manually call ForceNetUpdate when something changes. Then the server will never check that actor for changes unless it's marked dirty.
Well I don't know what your exact structure or any other stuff you do (screenshots are cropped and doesn't have any information). But from what I understand, what I would do is creating an RepNotify FName which server sets as the desired datatable entry. And inside the RepNotify function (which will run on everyone) setup the visuals
Hey I think you need to check Replication Graph. Epic has made it so it scales well with high number of replicated actors. I am not sure if that serves your purpose.
Let me share some screenshots.
do you mean use PushModel?
Also how do you made your GameMode to obtain selections of players from the Main Menu? Are you sure you have the correct values?
@upbeat basin The first image, I do this on Begin Play, THe car config variable it is stored in Game Instance and is propogated from GI to my Pawn(the data table is just for not going back and forth to main menu and all). The second and third image is the Load Car event.
I don't know much about how to use the Push Model, but forcenet update is a kind of poor man's push, but it's very easy to test out.
Hello,
I'm doing something in my project and wondering if it's a good practice or if there's a better way, basically when I make a Server RPC for example, I make a function named SVF (Server Function) that contains the actual working code, the reasoning being if I am already in a server context, I call the SFV function instead of the Server RPC, thoughts on that?
I tried and didn't see any effect, maybe there is a converter of the world partition into separate layers, then I could control these layers
It's a little redundant. There's nothing wrong with the server calling a server RPC. What is more concerning if whether it needed to be an RPC at all in the first place if it's only ever going to be executed within the server anyway.
I only do this with functions that are needed in both cases
bool bWantsToPickUp;
{
if (GetOwner()->GetLocalRole() == ROLE_SimulatedProxy) return;
// Log the event for debugging
UE_LOG(LogTemp, Log, TEXT("PickUp event triggered in C++"));
if (bEnableDebug && GEngine)
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Yellow, TEXT("PickUp event triggered"));
// Check if the player can pick up more weapons
if (!CanPickMoreWeapons())
{
UE_LOG(LogTemp, Warning, TEXT("Cannot pick more weapons"));
if (bEnableDebug && GEngine)
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, TEXT("Cannot pick more weapons"));
return;
}
bWantsToPickUp = true;
if (!GetOwner()->HasAuthority())
// Client side calls the server
PickUp_Server();
// Perform the pickup trace
PerformPickUpTrace();
}
{
// Corrected the condition to properly check if the local role is not AutonomousProxy
if (GetOwner()->GetLocalRole() != ROLE_AutonomousProxy && bWantsToPickUp)
{
GEngine->AddOnScreenDebugMessage(
-1,
3.0f,
FColor::Cyan,
FString::Printf(TEXT("MontageNotFound at line %d"), __LINE__)
);
// Perform the pickup trace
PerformPickUpTrace();
}
}
if the server picks the other sclient doesnot receive the data
i am not sure what is the
problem
Let's just continue here and delete your other post just in case if you want to
sure
I didn't see OnRep call in your code, where is it?
do i actuallty need to call on rep or if i call same function in the server will it worj
i called perform pickup tarce from in server directly
If you want it to run on server as well, yes you need to actually call it
It only runs on clients automatically, once the value replicates
{
if (GetOwner()->GetLocalRole() == ROLE_SimulatedProxy) return;
// Log the event for debugging
UE_LOG(LogTemp, Log, TEXT("PickUp event triggered in C++"));
if (bEnableDebug && GEngine)
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Yellow, TEXT("PickUp event triggered"));
// Check if the player can pick up more weapons
if (!CanPickMoreWeapons())
{
UE_LOG(LogTemp, Warning, TEXT("Cannot pick more weapons"));
if (bEnableDebug && GEngine)
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, TEXT("Cannot pick more weapons"));
return;
}
if (GetOwner()->HasAuthority())
{
bWantsToPickUp = true;
//PerformPickUpTrace();
OnRep_WantsToPick();
}
else
{
// Client side calls the server
PickUp_Server();
bWantsToPickUp = true;
PerformPickUpTrace();
}
// Perform the pickup trace
//PerformPickUpTrace();
}
like that
{
GEngine->AddOnScreenDebugMessage(
-1,
3.0f,
FColor::Cyan,
FString::Printf(TEXT("On rep pick started at %d"), __LINE__)
);
// Perform the pickup trace
PerformPickUpTrace();
}```
updated onrep
That'll make your OnRep run in server as well yes. I don't know if that will solve your issue though, in case there are other problems
lemme check
nope
not working
if (GetOwner()->HasAuthority())
{
bWantsToPickUp = true;
//PerformPickUpTrace();
OnRep_WantsToPick();
}
else
{
// Client side calls the server
PickUp_Server();
bWantsToPickUp = true;
PerformPickUpTrace();
}
Why do you need else part though, is it doing some kind of prediction stuff?
It'll make PerformPickUpTrace() run twice
it skips owner
OnRep_WantsToPick();
if i add this the rep function does not work for server
if added not work for client
{
if (!TemporalPickWeapon)
{
// Print on screen
if (bEnableDebug && GEngine)
{
FString DebugMessage = FString::Printf(TEXT("Temporal pick up weapon not found, cannot pick up (Line: %d)"), __LINE__);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, DebugMessage);
}
return;
}
UWeaponComponent* TempWpComp = UWeaponSystemFunctionLibrary::GetWeaponComponent(TemporalPickWeapon);
if (!TempWpComp)
{
bWantsToPickUp = false;
// Print on screen
if (bEnableDebug && GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Weapon component not found, cannot pick up"));
}
return;
}
TempWpComp->Picked(GetOwner());
OnPickedUp.Broadcast(TemporalPickWeapon);
// Print on screen
if (bEnableDebug && GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Weapon picked up successfully"));
}
bWantsToPickUp = false;
/*if (Weapons.Num() - 1 < 1)
{
Equip(TemporalPickWeapon);
bWantsToPickUp = false;
// Print on screen
if (bEnableDebug && GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("Weapon equipped after pickup"));
}
}
else
{
Swap(EDirection::Down);
bWantsToPickUp = false;
Equip(TemporalPickWeapon);
// Print on screen
if (bEnableDebug && GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Swapped weapon after pickup"));
}
}*/
TemporalPickWeapon = nullptr; // If needed, uncomment this line to clear TemporalPickWeapon.
}
preety much tahts all the code
may be i am missing some sequence
Well I'm not sure if using the flag with OnRep is the best solution here
what should i do then
Ah okay, no I was going to warn that changing replicated variables' values in same frame might not be replicated to clients at all. It's for the fail cases where it's set back to false. So I guess that's not the issue
probably not actually
Upgrading from 5.3 to 5.4 or 5.5 replication broken
A mixture of almost all replication methods. RPCs, Rep Notifies, etc..
Any idea? We can compensate well for help fixing.
Dm me
so should i run a timer then
or use a multicast
Well I'm not sure what your expected result and actual results are to be honest. All I can understand from the code is that it just plays an animation, if there is one, for the target weapon
yeah it works for the animations
but not without it
What are some pros and cons for attaching a weapon system to the cmc?
I am losing my sanity trying to predict weapon reload, cause the time spent reloading might not be the same for client and server.
Example:
For what i understand, if the client starts the reload while under high ping, and as soon as reload is done, switches weapon, and by chance the ping drops to almost zero right in that moment, the reload and switch weapon rpc might arrive at similar times, resulting in the server thinking that i did not complete the reload before switching weapon.
The idea is to make my weapon manager component tick with the cmc and send through cmc all the data needed.
Is it a bad idea?
Wouldnt the client pack a reload complete bit to the server along with the current equipped weapon something something ?
Server verifies time +/- some
if you slightly trust the client you can send the "starting reload" RPC to the server with a timecode
when the server receives it he can see how much time passed and decide if the reload time is elapsed
idk why you want to use CMC tho
I thought about this, but my problem is that the animation would not play for the appropriate time for the host, or even other clients.
So i would have to delay the swap till the reload is done on the server, ending up queuing all actions and stuff
well for the cosmetic stuff (here animations) you cant be perfect
Yeah but wouldn't a player be caught off guard if the opponent reloads almost instantly?
Well ok still wouldn't really matter since i'm implementing rewind for hit confirmation. So you might see the player reloading and be dead already
Anyways, the other idea i had when proposing to use the cmc was that weapons and movement would be in the same simulation, so i could in theory have stuff like knockback from firing heavy weapons or something
i have a projectile with a regular colision and a larger box collision around it that is used to play flyby sounds of projectiles, the idea is that if it hits the projectile colision it does the regular sound but if the projectile misses and insted this larger box overlaps than a flyby sound is played. My issue is that i cant see to find a good way to play it ONLY for the player that it overlaped
nvm just found the solution in a forum post
for any1 wondering, i was doing the first check but not the second one and testing it on the server
I'm noticing something incredibly weird.. when doing APlayerState* PlayerState = GetWorld()->GetGameState()->GetPlayerStateFromUniqueNetId(default unique ID struct);, even if GetPlayerStateFromUniqueNetId returns nullptr, the PlayerState will point to the owning client's APlayerState??? wth
anyone know why this happens?
are you sure this isn't just some weirdness with variable shadowing
Are there some cases where it's particularly difficult for the game to smooth out the jitteriness introduced by latency?
E.g. objects falling, players driving a car, bullets flying, all of that either follows a predictable trajectory or the changes in trajectory are slow enough that local misprediction and reconciliation don't look that bad.
But what are the scenarios where it's hard for this to look smooth? Are there certain types of games or actions within games that developers will avoid because they will always look janky?
I'm not sure what variable shadowing is, but I do know that I had to write a special getter on my controller that tests for this and nullifies the return value if it equaled the controller's own player state to get back on track with development
Which I'm still scratching my head about
variable shadowing is when you introduce a local variable the same name as a member variable
Oh, I'm confident this isn't the case
Yes, the hardest cases is where timings are off
Since mp gameplay usually involves at least 2 different 'timelines': predicted client timeline, and authority timeline
whenever those two have to meet in some way (for example, a predicted bullet hitting a server authority actor), the solution is non-trivial and is up to you to figure out
since in that example the server auth actor should respond to the predicted bullet somehow. Does the client also predict the damage effect? Does it wait for the server to play the damage effect? Those kinds of questions
A more practical example that has to do with your question that focuses on smoothing stuff
Is what happens when say, in a racing game, your car is hitting another player's car
In this example there are 3 timelines, your predicted timeline, server timeline, and the other player's predicted timeline
the scenario of resolving a collision so that everything looks perfect is impossible
and so developers bullshit their way out of it using lerps and whatnot
especially with physics solvers that don't really let users perform rollback or other types of prediction mechanisms
@unkempt tiger thanks, super helpful!! Are there some scenarios where, with everything you said above, prediction becomes even harder? E.g. two players in a FPS game are holding an object at the same time and flicking their mouse around to try to move it. Unlike cars and bullets that have some degree of predictability to them, here the position of the object is almost entirely wired to the player input, and two players are both adding their inputs to this object at the same time.
Correct, keep in mind that this is much like the car hitting car scenario (since both cars are also directly wired to predicted input), the only difference being that something players grab can be much lighter (in mass) than a car, and so it'd need to be more responsive, so any weird jitter-induced deviation would be far more noticeable
In this scenario, you're going to want to use what I call semi-prediction
basically: bullshit prediction, using context aware lerps and whatnot to try and minimize the grabbed object's jitters
and, if it affects player movement, make sure player movement netcode will play nicely with 'soft corrections'
is multiple process PIE still better than single process PIE in 5.4 to properly test MP ?
Roger, that makes sense!
Never thought of it in terms of mass, but that makes sense in retrospect. More mass, less immeidate response from that object to input, less jitter. I'm thinking of the chains in Chained Together where every player gets to yank on them at the same time and they end up flickering all over the place.
Yeah, that's tricky business and could ruin gameplay if handled without care
If player movement netcode is robust enough (idk about CMC, just speaking generally)
then it is very feasible to just have authority manipulate player state without any special 'care', and the clientside netcode will apply the correction in a relatively seamless manner, ideally a single frame 'pop'
this can go completely unnoticed during gameplay if many small pops happen, many times a second, or even a very large pop, once in a while
one thing is certain, no matter your solution, the faster you eliminate error buildup the better the experience will be for your players
i've seen some solutions where devs decide on letting errors build up and only correct them if they're too big
if im calling this line "UGameplayStatics::GetPlayerCharacter(GetWorld(), 0)" on tick with 2 players in the editor environemnt, it should trigger twice with a break point right?
Does anyone know the reason that steam overlay would work fine when launching from a .bat file but not in standalone mode from the editor?
i think thats just how it is if i remember correctly
probably some internal stuff
Hmmm. I've had it work in standalone in the past. Maybe there was a change.
Right, if you're using PIE I know that was true but it used to work if you launched it in standalone mode
maybe that isn't the case anymore
Depends on what actor the tick is running on.
Follow-up question: does anyone know how to use advanced sessions Server Travel node? It moves my server player but it does not move everyone in the session.
exactly but if i have 2 windows it should run for both right?
Depend on the actor.
can you be a bit more specific?
Does the actor replicate? Is it replicated to all clients?
Is tick enabled on all clients?
should be but let me check
The better question is... Why are you using that gameplay static on a projectile? Getting a character by index doesn't guarantee you which particular actor, meaning it may get a different result on each client.
isnt the first index always the one that you are controlling?
No
well, what would be the better option to get the character?
Depends on the relationship of the character that you care about checking on and how it relates to the projectile.
ok so let me explain the problem, im doing a raycast for the actual hitscan, and a larger raycast for flyby sounds
i want those sounds to play only on the players they fly close by
so im trying to get the controlled character and check if its the same one from the raycast
You can have a sound that loops playing the flyby sound and have attenuatiion on it so you get the appropriate doppler effect.
Otherwise...
i tried using the doppler in the sound cues, its very hard to get something thats sounds right
also if im hitscaning i would have to calculate the closest point to the raycast in relation to the player
and that is way too much math
or else the sound would be in the wrong position
i will probably have a similar issue with this aproach and sound positioning but it seems way more simple
If you must... Use an overlap on the projectile. "Other Actor" gives you a reference to the actor that overlapped it. Cast to Pawn. Check if it is locally controlled - if it is, then playback the sound. Now it should only playback locally for players that were within the overlap.
Thats what i did for actual projectiles, not for hitscans. Is there any advantage to doing that compared to what i am doing?
i just went with what made more sense, not saying that it was the best aproach
if do the overlap thing again since my ray changes sizes im gonna have to mess with scaling the sizes and thats probably not the best idea
well, now that ou mention it, i can just check for "isLocallyControlled()" on the character hit by the raycast too, or is there something i should be aware of?
You could make a multisphere trace that overlaps to the hit location. Loop through the hit results, get the HitActor, Cast to Pawn, check if it's locally controlled, and if so, play a sound for any of those players.
ye thats what i did
oh, Server Travel won't work unless its in a built game correct? It's not gonna work even in a standalone version from the editor.
forgot to say thank you
closest point on line to a given point is super easy
there's probably a built in function for it.
If you want to do bullet flyby sounds with hitscan, I'd do it like this.
Server:
multicast shot event
Line trace for actual hit, multicast hit event
multi Capsule trace for flybys, call a run on owning client event on any character you hit, passing over the location they should hear the sound from (nearest point on trace line)
Run on owning client event -> play flyby/crack sound at passed location
If I want to add a UFUNCTION(Reliable, Client) function, do I need to mark the component as SetIsReplicatedByDefault(true)? I know I need to do that if I'm replicating properties, but is it needed for UFUNCTION(Reliable, Client) too?
ive never explored that side of math i mostly stick to simple trigonometry, im gonna give it a search
whenever possible, don't use trig
get comfy with vector math
Both the owning actor and the component need to be replicated, and yeah, it'll be needed for RPCs too
well, my vector math is ok, and i was aware that i needed to project the vector some how i just didnt wanna bother with it if i could come up with a simpler solution
i was looking for the math for it on google but i guess that makes things easier
thanks
Do I also need to implement GetLifetimeReplicatedProps?
I changed from having a replicated property, to calling a UFUNCTION(Reliable, Client), so I removed the GetLifetimeReplicatedProps
// MyComponent.h
UCLASS()
class UMyComponent : public UActorComponent
{
GENERATED_BODY()
public
UMyComponent(const FObjectInitializer& ObjectInitializer);
protected:
UFUNCTION(Client, Reliable)
void SendMessageToClient(const FSomeStruct& Struct);
};
// MyComponent.cpp
UMyComponent::UMyComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SetIsReplicatedByDefault(true);
}
void UMyComponent::SendMessageToClient_Implementation(const FSomeStruct& Struct)
{
// This never seems to be called on the client when `SendMessageToClient` is called on the server
}
that's only for properties
is the owning actor owned by the player you want to send the RPC to?
Shoot, no it's owned by the server.
I was previously telling the player some state had changed on the server with a replicated array, but then I realised I don't need to care about a list of stuff, just the most recently changed one, so I thought I would make a func that gets called on the client
I guess I could just make a single replicated struct instead of a replicated array of that struct...
if this is a one shot thing, you probably want NetMulticast rather than Client
that gets broadcast to all clients the actor is net relevant to
anyone noticed DateTime difference between dedicated server and client? i remember the issue was the client was -20 seconds behind the server or something like that
well yeah there's no expectation they'll be in sync
that'll be at the mercy of how in-sync the system clock is
how would you pass the time to the client then? like a count down? maybe convert the datetime to seconds and pass the seconds to the client to turn into datetime or what?
the server world time seconds from the game state, it's reasonably in-sync these days since epic made it update frequently
Bumping my question from yesterday
do you guys know a good and comprehensive guide/YT video on networking?
Just want to learn the C++ and Editor stuff, so I'm more aware of that and wonder if you have any recommendations? ๐
I tried adding an impulse in the opposite direction on overlap but it bugs out alot, also the player is able to actually stand on the cylinder too for some reason
Launch character on overlap
If itโs 100% physics based, add force (and I believe override velocity or whatever the Boolean is on the add force node)
and is there a way to make it so the player just slips when they try to stand on it?
I messed around with physics materials but no luck
maybe make step height in character movement like less than 5 degrees (height or angle, I think angle my bad), or put triangles at 50 degree angles on top of the bouncer
I found this option which fixed it
Yep, walkable slope, that's the type of stuff I was talking about ๐
ah thanks
I have a widget component attached to my base character that acts as a display name above the character,
clients can see it for other clients and the for the server user
however the server cant see the clients widgets
everything is there some sort of weird setting in the actor class or widget that would be causing this?
Are you in Listen Server or Dedicated Server config?
It sounds like a replication issue, but not sure
listen server
Package a build and see if it still happens. Sometimes PIE is just... not always accurate
Somehow, your clients are pushing to each other, and your server is pushing to clients, but clients aren't pushing to server? That doesn't seem possible with Listen server, but maybe?
yea i should try that, ive been looking at this for an hour, it makes no sense, if a package doesnt work ill post the rpc flow
Anyone seen an issue in which, only on listen server, leaving a physics volume (Water volume) won't trigger a movement mode change?
It only happens when leaving the volume, works fine when entering.
Its only an issue on the listen server. If running client it works fine
๐ค
Is the movement mode not changing, or does the client not realized it's changed because the server hasn't told it that it has?
Took a break because I got discouraged trying to make a mulitplayer lobby. Does anyone know of any good examples in the UE store? I just want to have 1 person set up a session, 1 person to connect as a client, and enter the game transferring some basic information for the game.
It's not changing on the server. Event OnMovementModeChanged isn't triggering at all
Which is really weird because it triggers for everything else fine. Just not when leaving the physics volume.
Make sure the movement change event is running in a custom event, that is "Run on Server" - and make sure it is running from the controller
You can try that
ah interesting. Let me try putting it on the controller instead
Controller talks to the server
Player State talks to the server
THose two things can "Run onServer" with custom events
Everything else will fail - drill this info into your head, because I recently forgot it, tried to do a listen server thing, and lost hours because I didn't realize the pawn couldn't fire the event on the server lol ๐ ๐
ya for sure.
The problem is OnMovementModeChanged isn't a custom event. It comes from the movement component.
Right
so somehow, instead of firing on the character or pawn, it needs to fire from the controller
Like... you need a custom event that changes the movement mode, that runs on the server... I think you can do something where "On Movement Mode Changed" or something, might be an override function? Idk
CmC talks to server just fine
Ownership (mostly) defines wether or not an actor (and its components) can do RPCs
nevermind, I see where I done goofed ๐
Was it related to the Collision volume? ๐
I was being a genius and setting Water Volume to false on the server when I entered it. So it worked fine on the client because the client can't set that ๐
Can someone help me figure out why my multicast isn't firing on clients?
The multicast fires when a pawn dies and it's supposed to play a death animation, but when the animation starts on the same frame that the death is started it doesn't run on the client, however if I put a tiny delay between death / death animation it does work properly
- That led me to think the multicast was being culled because of the network
However when investigating the network there really is hardly anything being broadcast. I'm pretty new when it comes to multiplayer, but I really feel like the data here isn't enough to cause a multicast to not work
Maybe I'm just reading it wrong, let me know if there's any other data that I should show that would give me a better picture, but even though there's a small spike on the player death I really don't think it's enough to stop the mutlicast from firing (but maybe it is, that would just be surprising to me)
I prefer to do death as a repnotify instead of a multicast. I've found multicasts to be hit or miss in some cases.
Plus RepNotifies run on new clients whereas Multicasts don't, depending on if that matters.
I would think something like dying was 100% controlled by server
In theory it should be if you use the default damage events.
But if you want to say, keep the body around by changing a mesh, etc. You can't do that for server and client directly from that.
Unless you change the notify settings
Hm yeah I was potentially going to try that, I guess I just figured that was more of a workaround and because I'm just getting started I was trying to do it the 'correct' way to make sure I at least understand the concepts
If that's the accepted way of handling it to make sure it gets properly propagated though I guess that's fine
The other thing is though that this death animation should theoretically be unreliable and that should be ok, I don't want to turn it into unnecessary traffic, I'm just confused why it's already being culled in such a low-traffic scenario
From everything I've read and how I've setup OWSC, I use RepNotifies unless it's one and done things like sound effects, etc.
For example, if you change a mesh through a multicast, it's not gtd to be changed if a new client joins after that multicast has triggered. The RepNotify will as long as the actor is replicated.
My mistake, i thought you ment something else ๐ repnotifies for anything atate related is the way to go for sure
That makes sense, I think this qualifies as that one and done scenario though so I probably shouldn't use a repnotify
The functional part of the death is being handled with server logic, but I'm trying to broadcast a multicast to make the dying character play a little falling over animation
I read it as if you were using ANIM_notifies* for some reason.. its quite early here lol
This is my ability that triggers on-death, and here's the death animation logic
When I add the delay it looks fine to the client when someone else dies, but without it it never plays
Hmm so that one you're calling the multicast more than once
I think... ๐ค
You check local controller, then send both to a has authoity, which then multicasts from a server event
๐คฏ
What is this intended to be?
The multicast should only be called once though, no? Only the server side goes through, and I call the server event so that no matter where that function gets called from it makes sure the server fires the multicast
If you're using GAS, this isn't the way to go about things. The whole point of GAS is to avoid having to use many of the built in methods of replicating events.
That's a good point actually, I didn't really consider that but I could probably play the death animation from a cue or effect or something
Still kinda confused why this isn't working though
What triggers that to play?
This is from my character's death ability, which essentially gets called through C++ when the death event/tag is triggered
So it's triggered on the server by the character detecting it's out of health
and the mutlicast is just a what? play montage?
Oh sorry, the multicast is just doing a stupid falling over timeline lol, this is just for proof of concept
You should be able to just call the multicast directly, you don't need to event --> server event --> multicast. You've already confirmed authority from a server event.
Let me give that a try
ha, I wonder if it's cause you have it plugged into Play
rather than Play From Start
So it's not playing because it already did
Unfortunately directly calling the multicast didn't work (I kind of figured that would tbh but i guess there techinically wasn't any network traffic reduced?)
And lol I actually got hopeful for that timeline fix, but sadly it didn't fix it either. Would have been really funny tho
Yeah I'm not really sure, I think I've fairly confidently narrowed it down to a network reliability issue because directly calling the multicast only gets called on the client when there's a delay
Just brings me back to the traffic and it doesn't seem like there should be enough going on to make it not fire, but idk maybe it's just because I'm testing in-editor and it would be more reliable in a build
Sounds strange that that would be an issue
Tried adding a print instead of delay?
Delay requires the multicast to be triggered so that itself will not change anything regarding the multicast
As you're on the receiving end of the multicast
Yeah adding a print to the multicast only fires when I add a delay before I trigger the multicast
Logs saying anything ?
No doesn't look like it, just the print strings
If there's any other way I can confirm it's the network I'd be curious to check that out, idk if there's a log of lost events or something
Currently trying to determine if the reliable buffer is overfilled, looks like it's defined as 256 which I'm not getting anywhere close to though...
Yeah those don't fire until a bit after, these are the active rpcs during the frame which it looks like traffic increases / the damage is applied
I just tried lowering the player state net update frequency (it was set to 100) but that also didn't seem to help
I'm starting to think it's less likely a network traffic problem but I really don't know what else would cause the multicast to fail when called immediately but succeed with a delay
It's like pending RPCs are being cleared out or something
Could this cause it? This is being broadcast on death
ah that actually doesn't fire until like after the animation should play actually it happens right before it too
Nah that didn't seem to fix it either, I'm gonna try clearing out some of the stuff in the cpp files though to check that they're not interfering tho
Going to go to bed but ill try to update here if I ever figure it out, thanks for the help talking about this ๐ซก
If call two RPC from same component at same frame, does the order of RPC is the same on target machine.
RPCs called on the same actor should be received in the order they are called, according to docs. Should include the components on same actor as well
@meager heart why not just use PlayMontageAndWait node?
that node will handle all the replication. Called on the local machine first, replicated to server then server replicate the montage to other clients
is stephen uillibari's multiplayer course good to start with for beginners
well it's not gonna cover C++ basic, you should learn there else where. But if you know C++ basic then his multiplayer covers a great deal of important multiplayer concept.
E.g. client prediction, server rewinding, reconciliation, round trip time, etc ,etc
yep i know c++ basics. thanks ill try his course then
are you getting GAS or the shooter?
i have both and planning to finish both.
GAS is more about the GAS framework than multiplayer concept. If you want to learn multiplayer I would suggest getting the shooter one.

@pseudo wagon yes
reliables AND unreliables within the same actor context will execute in the order they were called.
But you can't strictly rely on unreliables because they might not arrive
does the GameplayDebuggerCategoryReplicator has any special relication behavior / lifecycle ?
i would personally not rely on the order of RPCs
anyone else experience just horrible PIE performance, especially during replay playback?
Basically a rain of fixed intervals mega macro stutters
With the editor running at like one frame per second
while in standalone, but even more so in a packaged game, performance is consistently good
We are seeing many issues on 5.4 and 5.5 vs 5.3 with performance and replication issues..
Do you know if we can get Google API 34 with Unreal Engine 5.3?
so im getting a crash on the server when doing a seamless travel with specific conditions:
what i found so far:
- PIE (multi process +
net.AllowPIESeamlessTravel true+ only a listen server) : No crash - PIE (multi process +
net.AllowPIESeamlessTravel true+ a listen server + client (new process)): Crash on server - Standalone : Crash on listen server
the crash happens on the listen server, here is the callstack:
UnrealEditor_CoreUObject!UObjectBaseUtility::GetPackage() [...\UObjectBaseUtility.cpp:198]
UnrealEditor_Engine!FNetworkObjectList::Remove() [...\NetworkObjectList.cpp:152]
UnrealEditor_Engine!UNetDriver::RemoveNetworkActor() [...\NetDriver.cpp:3906]
UnrealEditor_Engine!UNetDriver::ServerReplicateActors_BuildConsiderList() [...\NetDriver.cpp:5029]
UnrealEditor_Engine!UNetDriver::ServerReplicateActors() [...\NetDriver.cpp:5815]
UnrealEditor_Engine!UNetDriver::TickFlush() [...\NetDriver.cpp:984]
UnrealEditor_Engine!UNetDriver::InternalTickFlush() [...\NetDriver.cpp:2021]
UnrealEditor_Engine!V::TBaseUObjectMethodDelegateInstance::ExecuteIfSafe() [...\DelegateInstancesImpl.h:667]
UnrealEditor_Engine!TMulticastDelegate<void __cdecl(float),FDefaultDelegateUserPolicy>::Broadcast() [...\DelegateSignatureImpl.inl:956]
UnrealEditor_Engine!UWorld::Tick() [...\LevelTick.cpp:1659]
it always seems to fail when calling RemoveNetworkActor(Actor); where Actor is a GameplayDebuggerCategoryReplicator
last lines of logs before the crash:
LogGameMode: Display: Match State Changed from EnteringMap to WaitingToStart
LogGameState: Match State Changed from EnteringMap to WaitingToStart
LogGameMode: Display: Match State Changed from WaitingToStart to InProgress
LogGameState: Match State Changed from WaitingToStart to InProgress
LogGameMode: >> GameMode::HandleSeamlessTravelPlayer: PCBP_Lobby_C_1
LogGameMode: << GameMode::HandleSeamlessTravelPlayer: PCBP_InGame_C_1
LogNet: Warning: Actor None was found in the NetworkObjectList, but is PendingKillPending
the Actor mentioned is the last LogNet warning is a WorldDataLayer
tried multiple times and the debugger always returns that
so i wonder why the issues comes later on the GameplayDebugger, i wonder if Rider just giving me false debug info for either of them
okay, disabling wolrd partition on current-transition-destination maps seems to fix the issue
wtf epic
guys, BeginPlay is going to be called everytime Actor is being created on Proxies? In terms of going in and out from relevancy?
Yes
so I think it's a good place if I need to register it somewhere on client side, right?
Yea, should be ok.
anyone have any thoughts on smooth sync ?
I can check if it's being called on AutonomousProxy right?
if (GetLocalRole() == ROLE_AutonomousProxy)
is this correct check?
That would only work on actors that are currently possessed by the local machine.
So like... PlayerController, their controlled pawn.
Also wouldn't work if it's the server, as they have authority for local role, in case you're thinking of running listen servers.
I'm running dedicated server. It spawns actor, I actually don't know who it belongs to. Probably to server and none of the connections. Damn, it's kinda complicated.
What I want to archive is to notify player controller I guess, that item appeared. So it can propogate more events, to UI and so on.
Item is aware of who it belongs to, but it's only a property. Nothing about ownership or something
Damn, not sure if it's correct :/
The Item who spawns the Actor I'm working on is an ActorComponent of Pawn controlled by PlayerController. Will it give to this Actor any ownership?
You define ownership. NetRole is something managed by Unreal based on whether the actor code is executing on the server or not, and if it is controlled by a player or not.
How can I define ownership?
When you spawn an actor you can set the owner of it.
That's a setting you can choose I believe.
Like use only owner relevancy and use owner relevancy.
Not sure how to best approach what it is you're trying to do.
Can probably override IsNetRelevantFor() if it comes down to it.
yep, already doing it
I'm doing so that invisible Actor won't be replicated on clients who doesn't see invisible
Its not gonna help you with authorative networked movement
yea i kinda see what its doing now. seems more suited for a co-op game
Even for a co op I would still use server authorative
Im having issues with AddUniqueDynamic, but i cannot figure out what Iโm missing
I have this delegate in my โInteractableComponentโ class
UPROPERTY(BlueprintAssignable, Category = "Interaction")
FAvailableForInteractionSignature AvailableForInteractionDelegate;```
Then in my InteractionComponent class I try to bind it to โOnInteractableAvailabilityChangedโ
```InteractableComponent->AvailableForInteractionDelegate.AddUniqueDynamic(this, &ThisClass::OnInteractableAvailabilityChanged);
UFUNCTION()
virtual void OnInteractableAvailabilityChanged(AActor* Interactable, bool bAvailable);```
Whats the issue?
You failed to mention exactly what the problem is
Oh yeah lol
It says
candidate function template not viable: no known conversion from 'const FAvailableForInteractionSignature' to 'TBaseDynamicMulticastDelegate<FNotThreadSafeDelegateMode, void, AActor *, bool>' for object argument
Does changing it from a .AddUniqueDynamic to .AddDynamic help?
Nope
Also i'm fairly sure it worked fine before updating from 5.3 to 5.4.
But i might have made changes that i overlooked
Can you post the .h and .cpp entirely
InteractableComponent header where i define the delegate
https://github.com/XyloIsCoding/XyloInteractionUtil_Plugin/blob/main/Source/XyloInteractionUtil/Public/Interaction/Interactable/XInUInteractableComponent.h
InteractComponent header where i have the function declaration
https://github.com/XyloIsCoding/XyloInteractionUtil_Plugin/blob/main/Source/XyloInteractionUtil/Public/Interaction/Interact/XInUInteractComponent.h
InteractComponent cpp
https://github.com/XyloIsCoding/XyloInteractionUtil_Plugin/blob/main/Source/XyloInteractionUtil/Private/Interaction/Interact/XInUInteractComponent.cpp
a plugin to implement interactions with actors. Contribute to XyloIsCoding/XyloInteractionUtil_Plugin development by creating an account on GitHub.
a plugin to implement interactions with actors. Contribute to XyloIsCoding/XyloInteractionUtil_Plugin development by creating an account on GitHub.
Oh god i need more sleep! Thanks a lot for the help
Was wondering if anyone could assist with this, multiplayer replication seems relevant: #ue5-general message
Hello all, does anyone know of a resource (or just have ideas) with respect to how I might go about implementing a truly "seamless"/"hidden" travel on the client when going from one server to another (assuming both servers are running the same map)? I've currently got a half baked solution in which I've overridden UGameEngine::LoadMap and am keeping the old UWorld around and destroying / respawning replicated net startup actors but it's getting a little unwieldly. I'm pretty sure Sea of Thieves is an Unreal Enging game that does this.
does anyone know what Server Streaming Mode , Server Streaming Out Mode and Use Client Side Level Streaming Volume do?
the world parition settings
i don't have world partition enabled but my actor count is getting too high. thinking about enabling
my intuition is telling me:
- Server Streaming Mode enabled = don't load any actors at startup. When players connect, load actors near players
- Server Streaming Out Mode enabled = when players leave an area/DC, unload the actors near it
- Use Client Side Level Streaming Volume disabled = client receives data from the server on what to load (even static level actors?)
Did you just set your character's animation mode to animation asset and playing like that or is it an ABP which uses the current speed/velocity to play/switch between idle and moving?
First thing that comes to my mind is using a blend space with idle and walking, blending between animations according to your speed
So if you somehow change your speed locally but server (and/or other client) is not aware of it, might end up like that
But I'm just spitting an idea, don't have any clue what exactly is causing that
I ended up fixing this by switching root motion to montages only in my blueprint and it fixed it
when i add a widget to the players in my game, it adds twice, so there is 2 of the same widget on the screen of the players, does anyone know how to fix that?
Yes, you need to add it just once
You should debug and search why it's being created twice
Any time I ever run into an issue where something is happening twice (if its a multiplayer game) its because you are doing the action on both the client and server, and you should only be doing on the server and replicating it to the clients.
yeah i see thats where its coming from now, ill try to fix. Thanks for the info
fixed it!
turns out the problem was that i set a custom event to be 'multicast' instead of 'run on owning client'
should be neither
should be a repnotify
unless it's just a temporary throwaway widget
Ah I see
hello, im trying to make an actor im spawning on the server Replicate to the clients
while the actor itself does replicate, i have a property exposed on spawn that im setting when spawning which isnt replicating/not working as i need it to
on construct, i do some stuff with that variable i get on spawn
but on replicated clients that construct fails because the variable is still empty
so my question is, are variables not replicated with the object itself even when exposed on spawn? do i have to use repnotify to do the operation instead of construct?
What type of variable is it?
a data asset
i just confirmed using repnotify works but id still like to know if there is any other solution or anything
RepNotify is the way.
I have an actor that replicates, and when a player enters it's box collision it calls SVR_GenerateLootForPlayer, picking an item to generate and then calling SVR_SpawnLoot to spawn that item in the world. The item spawned also has bReplicates true. For some reason, connected clients do not see the loot spawn, but the server does. The clients can also interact with the interaction box on the spawned actor but cannot see it. What exactly could I be doing wrong here?
If you're making "GenerateLootForPlayer" a server RPC, then that's probably part of the problem. Clients can only call server RPCs on actors that they own. The collision should probably only be detected on the server and the server can then just do whatever it needs.
Anyone know the best way to pass a GameMode class through a ServerTravel command line, or any other method to set gamemode on level change?
?Game travel arg
you usually wouldn;t, you'd replicate the running state
Does anyone know if UE5 automatically drops unreliable packets (or bunches) if it arrives out of order? Would like to know how it behaves in the case of replication
Unreliable RPCs aren't guaranteed to arrive in order
I wouldnt trust any rpc to be in a guaranteed order
i am trying to create a save system so i want this system to save when a level is cleared and be able to load the level you last cleared (the last one that is saved) via a "continue" button at my lobby level i also want this to be compatible with multiplayer so the people in my lobby should be able join my last saved level- im kinda new to this developing stuff if anybody can make a simple explanation about this it would be really apreciated thanks
simple explanation, saving is just storing data to a machine. To reload a game or a level, you basically need to store every neccesary data/info to re-create the same state..
For example, you would need to store every player's character attribute and associate it with their steam name.
When you open the level again, you can set the attributes to the respective players.
It doesnt specify what effect dropped packets in between the
MyActorsPtr->Rpc1();
MyActorsPtr->Rpc2();
MyActorsPtr->Rpc3();
Can it guarantee that they are sent as a singular package ? And if not, does it wait with all 3 rpc calls untill the dropped package of rpc1 is successfully recieved?
have you read full page? Unreliable rpc do not retry on fail, reliable does as well as guarantee order.
I have read the entire page, and im exclusively talking about reliable rpcs which they claim are guaranteed, and i wonder how they actually solve that
The only way i can think of sounds rather insane as it would be a blocking rpc call
But if thats what they do, then thats what they do
Well shiet ๐
Reading with kids around my feet isnt good readingz that ill admit
Halting sounds rather crazy to me
I guess thats only on the actors channel level and not socket level
you can simulate packet loss in settings
I guess channel only
so the only thing i want to store is the level you last cleared (the last level saved) nothing else like inventory or anything else would it be hard for me to do like
with gpt and tutorials or kinda stuff
So I'm still having trouble wrapping my head around how player controllers work in regards to networking and how to properly get said controllers
the pawn/hud/playerstate/widget has a ref to the owning controller
Other actors which may be owned by a certain player may have it through the "Owner" reference
Gamestate got a list of playerstates and their owning controllers
Okay, I see
I mainly want to figure this out so I can implement a co-op capable dialogue system that can allow only the host to select options or players to vote
Dialogue is one of the harder things ive personally tried in multiplayer
Does anyone know off top if the owner see/no see attribute change if the mesh is processed on the client?
I think the main thing is just knowing all the players connected in a session and which is the host or in the case of voting when one makes a dialogue selection the server knows which players have voted and which haven't
Your setup is a tad different than mine, i was trying to have 1 player 'owk' a conversation with an npc, allowing others to listen in, but not interupt
you are not gonna get far with GPT, maybe you should just dive to SaveGameObject now and work out a simple save / load system.
do you know any source i could use i think i might be able to it with an okey source
since its not a really complicated save system
thank you i will check it out to understand the logic a bit but i am using blueprint
i found something like that throught the forums
it seems way too simplified ofc but i think it is a head start
that looks terrible already
prob but i gotta start somewhere i think
i found a tutorial https://www.youtube.com/watch?v=7gfA-QO5pA8 i think its best to try and adjust this to my project
In this tutorial we will be creating a very powerful and easy to use save system.
Let's create systems playlist: https://www.youtube.com/playlist?list=PLNBX4kIrA68lvWElEzhRaCOtCjZ7L05xv
Join the Discord server here: https://discord.gg/zBeebU7uv3
Support the work of LeafBranchGames on Patreon here: https://www.patreon.com/LeafBranchGames
seems like the only option for now
I have no comment on blueprint tutorials
I do watch and use them at the beginning of my journey
but later on I would scrap everything and re-do everything my self
i would rather use c++ but i have no knowledge on that still trying to learn
i just know c#
my opinion of blueprint youtubers is really low
you can learn one or two things but be prepared to unlearn a lot of bad practices as well.
yeah i learned that the hardway
right now my systems are all working but its all noodle code and unnecessary stuff
you gotta start from somewhere, whenever we start a new project, we always found another way to do things. It's normal
i just wish i could figure out this save system it is essential for the game
i dont want the project to fail because of this
you just gotta learn what you gotta learn
yeah
if you know c# you can probably use c++ in unreal pretty effectively
Does this flow of player data from the lobby to the game map make sense?
- When a player joins the lobby, I do an RPC to register the player on the list of registered player data. This data includes their name and color. It is stored on the game state so that it is replicated to all of the other clients.
- When the game map load is triggered, I copy all of the player information from the game state onto the game instance, and then back onto the new game state when that is created.
It seems like I could store this information on the individual PlayerState objects, but I would still need to store them somewhere (eg the game instance) during map transfer.
I'm trying to have a windup portion of my ability where the player can't move -- but when I disable movement, I get a server correction and a jitter on the client unless I'm perfectly still beforehand -- what am I doing wrong?
Player specific data that you want to be replicated to other players should be registered on their playerstate otherwise you're having to manage the data about a specific player more than you really should need to. If their PlayerState goes away because they disconnected or whatever, then you don't need to manually manage an array in the GameState for example.
You can read up more about how to persist data through travelling here, which can help you retrieve information from PlayerStates through the transitions.
https://wizardcell.com/unreal/persistent-data/
i actually figured out to do a simple save system
it has flaws of course but
its a good start
I built my project and ran it using steam subsystem multiplayer, worked the first time. Coming back a couple hours later it no longer works? any reason for this
still has steam integrated and working just no longer able to find servers
Heyo,
sometimes when a new player spawns he is not the configured first person character but a random flying camera which still colides with everything but cannot do anything since its not the proper FirstPersonCharacter. Does anybody know why and how this can happen ?
Update: havent made any changes but now a server is available. but when any other servers are created they are able to be found
Hi is passing TSharedPtr in an RPC not possible? I get an error when I have a TSharedPtr parameter in an rpc function:
Unable to find 'class', 'delegate', 'enum', or 'struct' with name 'TSharedPtr' [UnrealHeaderTool Error]
RPC parameters must be serializable
Oh okay then that explains it, thank you
tfw when you need 3 computers to debug a problem
Greetings. I noticed that Game Animation Sample is poorly working when network lag simulation enabled (30-60 ping)
I tried SmoothSync plugin, but now its not working well with motion matching. Is any specific network setting or custom character movement replication?
Does anyone know how to get the visual logger working with PIE dedicated server config where the server is launched as a separate process?
Usually everyting should stay within PIE, including the DedicatedServer.
You mean this config doesnt work with visual logger?
I imagine it should and maybe I am missing a setting or a command line arg for the server?
Totally possible
Play As Client with the Server being part of PIE should work though
Unfortunately the project is not well setup to handle that, it causes some other issues
I can't really suggest anything else but getting the Project set up to work with that again.
https://youtu.be/hWpbco3F4L4?t=1275 This talk seems to imply that it works when the server is launched as a seperate process, but they dont discuss if there is anything special needed to get it working or not, they just immediately show it working. I imagine its possible and the problem lies with me
The Visual Logger, built into the Unreal Editor, is an incredibly useful tool for recording, visualising and tracking objects, locations and data in gameplay, but itโs rarely used outside of AI. Letโs change that!
In this talk by Rare's Principal Gameplay Engineer Andy Bastable, you'll discover practical tips and examples from Sea of Thieves, ...
Browsing around the code a bit I found a cheat manager command "ToggleAILogging" which RPCs the server and runs "FVisualLogger::Get().SetIsRecordingToFile(true)", toggling that again will save the file out and then I can load that in the visual logger for inspection. It's not the runtime visualization I was hoping for, but for now this will definitely do what I need
Yeah I can imagine that you can trigger the recording and load it, but not that you can visualize it. At least not without the Server somehow sending teh data back to the Editor.
I'm having an odd issue, i'm working with a single (rather large map) but everything is fine other than when my client moves too far away from the host(server) player the server players seemingly stops existing for the client. Other actors also stop existing for the client when too far away.
Example, i have indicators on both shops and players, when the client moves too far away (edit* from the host) it start despawning other players and actors from it.
Anyone has an idea where i should be looking at the problem?
Those Actors are no longer Net Relevant.
This is based on a Distance value
AActor::NetCullDistanceSquared
Each Actor defines how far away from the observer it can be before it leaves Net Relevancy range.
After which, its Actor Channel is destroyed for that Client and the Actor is removed.
When that Actor comes back into range, it is recreated (its spawned again and BeginPlay is called).
If anyone could take a look at this, its relevant to this channel: #ue5-general message
You are right on the money! i had to set them to "always relevant" and that fixed it. Thank you for pointing me in the right direction!
Keep in mind that means that data is always being sent to that client, even if it really shouldn't. Just checking that box may be a hack, depending on what you're doing and how many actors you're marking as always relevant.
hey guys Im using UE5.4.4 compiled by source code on visual studio, and my project cant connect to the mapserver which I've packaged, it is working only if I package and connect through the client, but not on the editor, gives Failed .
[2024.12.16-03.09.37:476][763]LogNet: Actor channel failed: [UActorChannel] Actor: bp_Enemy_2_C /Game/TopDown/Maps/1.1:PersistentLevel.bp_Enemy_2_C_8, Role: 3, RemoteRole: 1 [UChannel] ChIndex: 9, Closing: 0 [UNetConnection] RemoteAddr: 127.0.0.1:55662, Name: IpConnection_2147482406, Driver: Name:GameNetDriver Def:GameNetDriver IpNetDriver_2147482520, IsServer: YES, PC: BP_Controller_Test_C_2147482397, Owner: BP_Controller_Test_C_2147482397, UniqueId: NULL:Alex```
the connection used to work normally on UE5.3
ah finally got ability activation working for my GAS+NPP frankeinstein im doing..
the amount of gas prediction i removed to be able to make it somewhat working with npp simulation ๐ตโ๐ซ
still doesnt show on simulation proxy though.. autonomous proxy does show similiar to gas server 1 and client1 message
miss predictionkey already
also why tf npp have auxstate,inputcmd andsyncstate is call every frame liek why
think its unrealiable, which should be good but doesntmake sense to call every frame even though nothing is being sent
If you set random variables on begin play, will it be the same for the server and client? Is there a need to use switch has authority?
for example on the game state begin play
to use switch has authority
for what?
Values will be different, unless you are using sameseed
also you can generate values on server then replicate them to clients, though in this case you can't rely on BeginPlay(client's) to access replicated props which is not guaranteed at that moment
to workaround later issue use on_rep functions
I see. Another question. Say I have a Run on Client Event, and at the end, I'm getting a different replicated actor and I set a RepNotify Variable. Why doesn't the OnRep work for everyone else? I know it's being set in a Run on Client event, but I'm setting a RepNotify on a Replicated Actor so I figured it would work
Is implementing a custom NetSerialize for a replicated struct only necessary if you're trying to implement atomic replication, and otherwise structs get delta-serialized otherwise by default without you having to implement anything yourself?
Only server can trigger OnReps
Ohh, ok. I was trying to see if I could run on client a line trace for a certain duration instead of on server.
I also tried to set it for the owner of the actor to do it, but for some reason it didn't work for the client
Hey, im trying to persist my player inventory within the playerstate from one level to another. Im using seamless travel and the Event CopyProperties. Everything works fine if i persist an array with class references, but i cant persist arrays with object references? The array with object references is always empty on the next level.
Does anyone know something about?
might need to add them to the travellist
what is the travellist?
AGameModeBase::GetSeamlessTravelActorList
You can add any Actors you want to persist through a Seamless Travel to this list.
They will not be destroyed when the World is unloaded.
Thanks, i will try that
Hey guys, how do I set input mode for only one local player? I am setting input mode ui only and all of my players or switching even though I feed it the specific player controller
You run the function only on the target machine
its local multiplayer
Then it's running using the same processor. I am not familiar with how local multiplayer does U.I
Because NPP was created with a specific goal in mind for the Simulations that are run with it.
Most notably Movement Simulations. And for those you usually send the Input from the Client to the Server every Frame (unreliable).
Simulations that only provide specific input once in a while, like GAS when it tries to Activate an Ability, start to show, that not everything can be implemented with just one Prediction Backend.
NPP also flips the whole reconcialiation process around, compared to e.g. the CMC.
Server always replicated the State back to the Client(s).
And when the AutoProxy receives the State it checks locally if it needs to apply a Correction and resimulate the already (and still) predicted "moves".
Pretty sure either you or someone else already talked with me about GAS + NPP and I already said back then that it's not really compatible.
On top of that, even if you manage to get GAS into the flow of NPP, you will still find yourself in front of a wall when trying to affect other Simulations and Instances with GAS. E.g. applying an Effect to GAS that slows down Movement simulated via Mover. Cause the communication between two Simulations or two Instances of the same Simulation is kinda non-existent, given that any of the Instances starts and finishes its SimFrame before the next one starts. You'd need to alter how the NetworkPredictionWorldManager and the Services handle this stuff (imo).
Iirc you can't set InputMode per Player. You'll need to update it to Game&UI whenever one of them needs UI Input.
But that's based on a very very long ago LocalMultiplayer game I worked on.
void APlayerController::SetInputMode(const FInputModeDataBase& InData)
{
UGameViewportClient* GameViewportClient = GetWorld()->GetGameViewport();
ULocalPlayer* LocalPlayer = Cast< ULocalPlayer >( Player );
if ( GameViewportClient && LocalPlayer )
{
InData.ApplyInputMode( LocalPlayer->GetSlateOperations(), *GameViewportClient );
bShouldFlushInputWhenViewportFocusChanges = InData.ShouldFlushInputOnViewportFocus();
// Keep track of the name of this input mode for debug purposes
#if UE_ENABLE_DEBUG_DRAWING
CurrentInputModeDebugString = InData.GetDebugDisplayName();
#endif
}
}
void FInputModeUIOnly::ApplyInputMode(FReply& SlateOperations, class UGameViewportClient& GameViewportClient) const
{
TSharedPtr<SViewport> ViewportWidget = GameViewportClient.GetGameViewportWidget();
if (ViewportWidget.IsValid())
{
const bool bLockMouseToViewport = MouseLockMode == EMouseLockMode::LockAlways
|| (MouseLockMode == EMouseLockMode::LockInFullscreen && GameViewportClient.IsExclusiveFullscreenViewport());
SetFocusAndLocking(SlateOperations, WidgetToFocus, bLockMouseToViewport, ViewportWidget.ToSharedRef());
SlateOperations.ReleaseMouseCapture();
GameViewportClient.SetMouseLockMode(MouseLockMode);
GameViewportClient.SetIgnoreInput(true);
GameViewportClient.SetMouseCaptureMode(EMouseCaptureMode::NoCapture);
}
}
Main reason iirc is that the concept of InputMode counts for the whole GameViewport.
The local player part of it are the SlateOperations, and that only does focus related stuff.
void FInputModeDataBase::SetFocusAndLocking(FReply& SlateOperations, TSharedPtr<SWidget> InWidgetToFocus, bool bLockMouseToViewport, TSharedRef<SViewport> InViewportWidget) const
{
if (InWidgetToFocus.IsValid())
{
SlateOperations.SetUserFocus(InWidgetToFocus.ToSharedRef());
}
if (bLockMouseToViewport)
{
SlateOperations.LockMouseToWidget(InViewportWidget);
}
else
{
SlateOperations.ReleaseMouseLock();
}
}
And apparently LockMouseToViewport stuff, but not sure how that works with usually only one cursor.
You are better off writing some logic somewhere that keeps track of your players opening menus and then switching to Game&UI instead of Game (or UI), and only use UI if you are sure that all players will not use Game Input.
And handle focus via SetUserFocus by hand.
You should also not use the SetKeyboardFocus function (in theory) as it assumes the first player has the Keyboard and will always assign focus for that one.
Best to always use UWidget::SetUserFocus(APlayerController* PlayerController (BP exposed) to ensure only the specific player gets focus to the specific widget.
It's a bit of a pain at the start, and it's highly suggested (from my side) to get the focus under control very early on during your UI/UX development, otherwise you'll have a really annoying time.
there are other reasons too to use NetSerialize, but yeah any property in the struct marked as UPROPERTY will replicate (if the type is able to replicate)
Sorry to revive this after months but did you ever figure this one out?
Pretty much, or if you can pack it tighter than delta replication would allow.
delta replication is the big reason to NOT use NetSerialize, but you may not always want that
don't know details. but here is source code:
Yeah I was looking thru their code trying to understand. It seems like a very niche detail that I cant quite wrap my head around atm. Still digging trying to understand how that gets triggered to begin with. Because it's not every time sadly.
Like we had 100s of connections to a server over the course of 1.5hrs, and roughly 30 of them got this error. Difficult to replicate.
Also sidenote I'm pretty certain that should be an Error instead of a Log as it seems to be related to triggering a disconnect further down the line
but it has return right after log
Yeah but every time this log fires, there's a disconnect after roughly 1 minute
also it's inside tick, so looks like eventually condition will flip and it goes further
Yeah, but then it would miss SendOpenBunch(), I think
oh let me find out where that bool is being set to true
Also in PostTickDispatch() it's returning early if that same condition is true, but this time no log
bah! I'll figure it out
So yeah I guess at this point I don't seem to have direct proof that it's causing a disconnect but there is a strong correlation in the logs.
posted before but ive hit a wall with ACharacter, where is the actual input sent to the server? its supposed to be in savedmove, but i don't see a vector input parameter in that struct
Oof it's been a long time since I've been in this code and I think it's been refactored since I last deep dived. But most of the code is under the CharacterMovementComponent. But the actual RPCs are under Character (to get around the component header, saves bandwidth).
Check in source what happens when you call AddMovementInput
iirc it gets processed each frame
I believe what it's actually sending is FCharacterServerMovePackedBits
// ACharacter.h
UFUNCTION(unreliable, server, WithValidation)
ENGINE_API void ServerMovePacked(const FCharacterServerMovePackedBits& PackedBits);
ENGINE_API void ServerMovePacked_Implementation(const FCharacterServerMovePackedBits& PackedBits);
ENGINE_API bool ServerMovePacked_Validate(const FCharacterServerMovePackedBits& PackedBits);
This is called by the CharacterMovementComponent, and I believe you will find most of that code in CharacterMovementReplication.h
FCharacterNetworkMoveData::Serialize()
You will see in there FVector_NetQuantize10 Acceleration; I believe this is basically your movedir
ya i see in the FSavedMove struct that there are a few acceleration named parameters but nothing really clear on which is the input or not
literally just the input value that addinput ultimately ended up with
thats easy enough on the client, but on server it seems much harder
in this example im checking the input heading angle
I think you should start here for the server:
ah server move is the combined results of similar saved moves, i see it
Yeah this is taking in the packed data ultimately sent by the client
ya that would be where to start i agree
Remember that Serialize() is both a serialization and a deserialization function
depending on context
I guess you just get out of bandwidth, therefore disconnected
Yeah I'm going to try boosting bandwidth limits
in gamemode event override LogOut i am calling this from game state, so what is the perfect time delay to put?
void ACoreGameState::NotifyPlayerLeaved_Implementation(AController* NewController)
{
if (HasAuthority())
{
JoinedControllers.Remove(Cast<ACorePlayerController>(NewController));
CurrentAmountOfPlayers = GetNumPlayers();
GetWorldTimerManager().SetTimer(PlayerCountTimerHandle, this, &ACoreGameState::Delay_UpdateCurrentPlayersCount_UI, 1.0f, false);
}
}
.5sec returns an infinite loop for delay retries
1sec is too big
delay driven development 
because the player widget is not yet ready when the player joins
if i update it directly, nothing updates
what stuff do you need inside widget?
there is a player counter text which updates on player login/logout
Just a hunch but it's probably more reliable to do this in PlayerState::EndPlay
so the player state is available once the player UI is available?
- Server updates PlayerState.AnyVariable
- clients listens to corresponding
on_repcallback - notify widget (i.e. widget subscribes to delegate to be notified)
this is what i am doing exactly, i am just using gamestate instead of player state
so i have to change its mean to player state
tbh I dont really understand the symptom of the problem you're running into
and i am using interfacenotify instead of delegate for this change
Create delegate inside ACoreGameState so widgets can bind to it
it's impossible to find perfect delay
i have interface binded to the widget in C++ , so i have to change it to delegate?
@little pumice
in any case widget has to read value when it's "spawned", so it can't rely on "value changed" event. Which means it requires "way to access" GameState to get value, and if it already requires it, so why not to use delegate here, bc we don't need extra coupling between entities/systems i.e.
- Widget
knowsabout GameState - GameState
knowsabout Widget
we don't need both 1 and 2.
If im using steams advanced session plugin and lets say a user is on an outdated version of the game can they see session from other versions?
Don't know the exact answer but I think you're looking for anything in the docs to do with BuildId
@gray blade The way the default Steam OSS works is your game client gets a list of sessions and connection info from Steam in Json format. This will contain all sessions for every version. Then, the game client will ping those servers. Somewhere in that whole process it's filtering out older versions before the API presents you with the session search results.
ok thank you
@nocturne quail by know I mean keep reference as member property. When you get reference inside a function as input argument but never save it as member property, then it doesn't count as knowing. So you can get GameState during widget's initialization, bind to it's delegate and then widget forget reference to GameState when function finishes it's execution. So only GameState would have widget inside it's delegate(list of objects "to notify").
This is the whole script, i have no idea why it needs delays to update the user widget
since the player postlogin only calls once the player spawns afaik
and if the player spawns it should have the hud ready.
void UPlayerCount_Widget::NativeConstruct()
{
Super::NativeConstruct();
ACoreGameState* NewGameState = GetWorld()->GetGameState<ACoreGameState>();
if (NewGameState)
{
NewGameState->RegisterPlayerCountWidget(this);
}
}
void ACoreGameState::RegisterPlayerCountWidget(UPlayerCount_Widget* NewPlayerCountWidget)
{
if (NewPlayerCountWidget && !PlayerCountWidgets.Contains(NewPlayerCountWidget))
{
PlayerCountWidgets.Add(NewPlayerCountWidget);
}
}
void ACoreGameMode::PostLogin(APlayerController* NewPlayer)
{
Super::PostLogin(NewPlayer);
if (NewPlayer)
{
ACoreGameState* CurrentGameState = Cast<ACoreGameState>(GameState);
if (CurrentGameState)
{
CurrentGameState->Execute_NotifyPlayerJoined(CurrentGameState, NewPlayer);
}
}
}
void ACoreGameState::NotifyPlayerJoined_Implementation(APlayerController* NewController)
{
if (HasAuthority())
{
CurrentAmountOfPlayers = GetNumPlayers();
OnRep_CurrentAmountOfPlayers();
}
}
void ACoreGameState::OnRep_CurrentAmountOfPlayers()
{
if (!HasAuthority())
{
if (PlayerCountWidgets.IsEmpty()) { return; }
for (UPlayerCount_Widget* Widget : PlayerCountWidgets)
{
if (Widget)
{
Widget->UpdatePlayerCount(CurrentAmountOfPlayers);
}
}
}
}
get reference inside a function as input argument
same about access to global variables or via another objects e.g.owner-X->Y->Z...
I guess it's spawned on Server
while widget is a Client's thing
hmm so i have to try player state, let see how it goes
yeah thats why i was using gamestate
if it's not listen server
yea i am on dediserver
logic inside OnRep_CurrentAmountOfPlayers is correct, but it has reverse knowledge (GameState -> widget) which works but poor design. Also widget which is just spawned might miss initial replication and would be doomed to wait for next value change or ask for latest value themselves
So better approach:
- Widget spawns and asks GameState about current value (might be default one i.e. not replicated yet)
- binds to delegate inside GameState to get new values
you may show placeholder or progress indicator for default value which will be replaced with first/next replication
The key here is that Delegates do not require info from server in order to be created (i.e. listeners can start binding very early), it requires server only to propagate updates i.e. delegate.broadcast()
Thanks, i will try this approach now, it needs little change in my existing code
You shoudn't need a variable specifically for the amount of players in the game. GameState has an array "Player Array" that contains all the playerstates in the game and this array is managed locally for all clients. The length of that array should be the amount of players in the game.
yeah i have custom function for it in C++ equivalent to the bp version
uint8 ACoreGameState::GetNumPlayers() const
{
if (PlayerArray.Num() > 0)
{
return PlayerArray.Num();
}
return 0;
}
i use it to set the variable to exec onrep to update UI locally on all clients
So why are you OnRep_CurrentAmountOfPlayers?
to update the player count on UI
You don't need to use a variable to store or replicate that value.
Clients can locally call GetNumPlayers.
If you want to know when a player leaves or joins, then create an event dispatcher(s) in GameState for Join/Leave that has a PlayerState input. BeginPlay and EndPlay of PlayerState can call to your gamestate and broadcast the event dispatcher with reference to self as the PlayerState input.
Now your widgets can bind to that event dispatcher(s) on their construct or intialize to know when players join or leave.
so at the time when BeginPlay and EndPlay calls in player state, the UI is already constructed at that point?
Doesn't matter if it is or not. The begin play only triggers the event dispatcher.
if your UI needs to construct itself with the current list of players, then you'd just get the player array and loop throught hem to construct widgets for those particular players already in the game.
So if your UI happens to get constructed before the playerstate begin play, it'll be bound to listen for new players. If it's constructed after the begin play of the playerstate, it would've contstructed some UI for that particular player already from the PlayerArray.
i will now try all these approaches, i am sure one will work ๐
event dispatcher(BP) and delegate(C++) are the same things
sow now i am on this stage, is this what your script means right?
void ACorePlayerState::BeginPlay()
{
Super::BeginPlay();
if (ACoreGameState* NewGameState = GetWorld()->GetGameState<ACoreGameState>())
{
NewGameState->OnPlayerJoinEvent.Broadcast(this);
}
}
void ACorePlayerState::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
if (ACoreGameState* NewGameState = GetWorld()->GetGameState<ACoreGameState>())
{
NewGameState->OnPlayerLeaveEvent.Broadcast(this);
}
}
void UPlayerCount_Widget::NativeConstruct()
{
Super::NativeConstruct();
NewGameState = GetWorld()->GetGameState<ACoreGameState>();
if (NewGameState)
{
NewGameState->OnPlayerJoinEvent.AddDynamic(this, &UPlayerCount_Widget::HandlePlayerJoin);
NewGameState->OnPlayerLeaveEvent.AddDynamic(this, &UPlayerCount_Widget::HandlePlayerLeave);
}
}
void UPlayerCount_Widget::HandlePlayerJoin(APlayerState* PlayerState)
{
if (NewGameState)
{
UpdatePlayerCount(NewGameState->GetNumPlayers());
}
}
void UPlayerCount_Widget::HandlePlayerLeave(APlayerState* PlayerState)
{
if (NewGameState)
{
UpdatePlayerCount(NewGameState->GetNumPlayers());
}
}
i am not sure if player state has some kind of array of player counts, that why calling it form gamestate
Yep, looks good to me. PlayerState only deals with the unique individual player - going to the gamestate to retrieve the player count is the correct route ๐
One change, just so your UI gets the current amount of players when it is constructed:
void UPlayerCount_Widget::NativeConstruct()
{
Super::NativeConstruct();
NewGameState = GetWorld()->GetGameState<ACoreGameState>();
if (NewGameState)
{
NewGameState->OnPlayerJoinEvent.AddDynamic(this, &UPlayerCount_Widget::HandlePlayerJoin);
NewGameState->OnPlayerLeaveEvent.AddDynamic(this, &UPlayerCount_Widget::HandlePlayerLeave);
UpdatePlayerCount(NewGameState->GetNumPlayers());
}
}
super thanks, have not noticed it ๐
there is an issue where the broadcast only works for the broadcaster
old players can't update the new value, or i need to loop the array of players states and broadcast new changes
though NativeConstruct might be not the optimal place for initialization, there is also NativeOnInitialized, It depends on context which one to chose, https://github.com/YawLighthouse/UMG-Slate-Compendium?tab=readme-ov-file#53-user-widget-events here is more info. NativeConstruct might be called multiple times, so it make sense to unbind in NativeDestruct,
also iirc Construct might be called in editor (design time)
I'm not sure what you mean by "only works for the boadcaster" - it's all handled locally for each player that joins the game and each player that joins the game gets their own unique PlayerState object created for them.
Widget is constructed whenever and binds to those events on the gamestate.
When a player joins the game, Begin Play of PlayerState tells GameState to broadcast its Join event with reference to self so other things can know which playerstate it is that joined. This will trigger on each client individually when a player joins.
I mean first player joins, he updated the playercounter = 1, second client joins he updated playercounter = 2, but the first player still see it = 1
and the playercounter widget is created by the AGameHud when the game started
widget can ask for info at initialization (besides binding to delegates)
yes this part is working correctly
the problems is with new updates when a new player joins
new players calls playersarray.num and set it to the counter, it gets the correct player amount
ah, you meant first player
yes, the first player don't know about the second player since it init the widget before the second player joins
and the second player inint counter with correct data since it calls player array num from game state
I'm trying to add a bit more logging or visibility into why sometimes some our players are unable to connect to one another's listen server. We're using Advanced Sessions. They're able to retrieve the session from Steam, they attempt to join it, but then it appears to time out for no good reason. Others seem to join the same session just fine.
Is there any additional logging I can do to understand better what's going on? Not getting a ton out of whatever gets logged by default. Would love some advice here.
put logs with client id in PlayerState::BeginPlay to see it works as intended.
like this:
UE_LOG(LogTemp, Warning, TEXT("[%s][%s] BeginPlay"), *GetDebugStringForWorld(GetWorld()), *GetName());
compiling...
Either breakpoint or print out some log messages in the binding part here...
void UPlayerCount_Widget::HandlePlayerJoin(APlayerState* PlayerState)
{
if (NewGameState)
{
UpdatePlayerCount(NewGameState->GetNumPlayers());
}
}
NewGameState may not be valid when this is being executed, but there's little else I can see that would prevent the value from updating when a player leaves or joins. In my own project I bind to my delegate in blueprint, and see no such problem :/
have you tweaked existing EOS log categories?
i.e. verbosity level
I have not, happy to look into it. How does one even find out what they are? Is there a doc somewhere out there listing all log categories?
Ok added logging in here too
Understood, thank you!
joins first client
[2024.10.17-20.59.46:044][109]LogTemp: Warning: [Dedicated Server][BPPlayerState_C_0] BeginPlay
[2024.10.17-20.59.46:157][109]LogNet: Join succeeded: DESKTOP-DevelopmentPC9C3
joins second client
[2024.10.17-21.08.44:454][687]LogTemp: Warning: [Dedicated Server][BPPlayerState_C_1] BeginPlay
[2024.10.17-21.08.44:554][687]LogNet: Join succeeded: DESKTOP-DevelopmentPC9C4
it prints valid gamestate
yes it only prints valid gamestate when the owner of the playerstate broadcast it, else its not accessed on other clients
and prints nothing
PlayerState BeginPlay should also be called on clients

check logs on clients (different log file)
usually suffixed with number _N
not sure how it store logs if run under one process
@nocturne quail
i looked for the suffic _N and didn't find any call
there are two log files log and log1
log1
search for BeginPlay inside file
any modern text editor has fancy search
e.g. vs code or sublime text
Compiling... ๐
also you can log PlayerArray.Num() from timer with 500-1000ms interval to see when it gets updated (before/after our callbacks)
i logged handle player join already,
void UPlayerCount_Widget::HandlePlayerJoin(APlayerState* PlayerState)
{
if (PlayerState)
{
FString PlayerName = PlayerState->GetPlayerName();
UE_LOG(LogTemp, Warning, TEXT("%s has joined the game."), *PlayerName);
if (NewGameState)
{
UpdatePlayerCount(NewGameState->GetNumPlayers());
UE_LOG(LogTemp, Warning, TEXT("Valid"));
}
else
{
UE_LOG(LogTemp, Warning, TEXT("NewGameState NotValid"));
}
}
}
it prints valid on the joining client only
and on other clients it prints nothing
its the same not changed it yet
void ACorePlayerState::BeginPlay()
{
Super::BeginPlay();
if (ACoreGameState* NewGameState = GetWorld()->GetGameState<ACoreGameState>())
{
NewGameState->OnPlayerJoinEvent.Broadcast(this);
}
}
but where is the log statement? 
i removed it since it no need anymore, its already done its job to show us that PS is valid
have you put it inside if?
no it was right after beginplay super
like this
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("[%s][%s] BeginPlay"), *GetDebugStringForWorld(GetWorld()), *GetName());
put right before broadcast
Ok
LogTemp: Warning: [Dedicated Server][BPPlayerState_C_0] BeginPlay it prints it again
it's server
only look at clients
we want to verify:
- Broadcast is called
- HandleJoin is called
- PlayerNum return correct value
on the same client widow
[Client -1][BPPlayerState_C_0] BeginPlay
[Client -1][BPPlayerState_C_1] BeginPlay
what's about HandleJoin?
looks like broadcast is called, but list of subscribers is empty 
now i added this to the handle join
UE_LOG(LogTemp, Warning, TEXT("[%s][%s] BeginPlay HandlePlayerJoin"), GetDebugStringForWorld(GetWorld()), *PlayerName);
re compiling
do you use live coding? if you have modified body of the function in .cpp it should work fine without Editor restart
i am not even running editor
comiling dedicated server and testing it
by starting/joining it using command line
yes broadcast has been called but the list of subs is empty
the loggings are called on all clients
log "binding place"
NativeConstruct inside if (NewGameState)
maybe also outside to do not compile twice
though with modified log text
void UPlayerCount_Widget::NativeConstruct()
{
Super::NativeConstruct();
NewGameState = GetWorld()->GetGameState<ATSLGameStateBase>();
if (NewGameState)
{
if (NewGameState->OnPlayerJoinEvent.IsBound())
{
NewGameState->OnPlayerJoinEvent.AddDynamic(this, &UPlayerCount_Widget::HandlePlayerJoin);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("OnPlayerJoinEvent is not bound"));
}
if (NewGameState->OnPlayerLeaveEvent.IsBound())
{
NewGameState->OnPlayerLeaveEvent.AddDynamic(this, &UPlayerCount_Widget::HandlePlayerLeave);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("OnPlayerLeaveEvent is not bound"));
}
UpdatePlayerCount(NewGameState->GetNumPlayers());
}
else
{
UE_LOG(LogTemp, Warning, TEXT("NewGameState is not valid"));
}
}
compiling...
i want to log error to see it it even try to bound on right time
I guess this check is for broadcast() caller not for verifying whether subscriber had already bound, at least it doesn't accept any args so it can't compare subscriber's this with it's internal list of subscribers
examples from engine proves that:
you can maintain your own "isBound " flag inside widget or use another OnInitialized collback which is called only once
yes, but it confirm one thing in logs which will help to solve the issue
[2024.12.17-22.23.20:432][726]LogTemp: Warning: OnPlayerJoinEvent is not bound
[2024.12.17-22.23.20:433][726]LogTemp: Warning: OnPlayerLeaveEvent is not bound
[2024.12.17-22.23.20:460][726]LogSlate: Took 0.003465 seconds to synchronously load lazily loaded font
[2024.12.17-22.23.20:572][736]LogTemp: Warning: [Client -1][BPPlayerState_C_0] BeginPlay
if you want some log based on this if clause then fine, just move bind logic outside that if block
shoot me in the head
just noticed i forgot to make them UFUNCTION

but VS should not compile it if someone try to bind !UFUNCTION to some delegate
@little pumice @sinful tree finally it works now perfectly, it was fun debugging this issue ๐ Thanks alot for help
Should my 'Max score' variable which determines when somebody wins be stored in the GameState or GameMode? (Current scores are already stored in the gamestate)
If it's the GameMode, how would a client query what the 'max score' is for something like a widget? Because the gamemode isn't valid there
There is nothing that says it HAS to go in the GameMode, if the Players need to know about it, the GameState is fine.
The GameMode can still use that MaxScore variable defined on the GameState to manage the "rule" that when Score reaches the MaxScore, the game is over.
Anyone have a good turn-in-place solution for first person multiplayer? I'm struggling to get it to work correctly.
Thanks! That makes sense, I think something I've been struggling with is that ambiguity there so I've just been trying to figure out what all the best practices are and separating them from the grey areas (like putting max score in the player state would be a bad practice), so this is helpful
I think just because I want to have some of these as changeable mid-game at least for testing I might just put all this info into a data asset that can be referenced in either one
Static data (like a MaxScore) would be something you can put into a DataAsset. Its good you are thinking in those terms.
Id setup some kind of "Ruleset" asset.
Yeah I think that sounds right, also because it felt a bit weird to consider splitting up the 'base' values between the gamemode and the gamestate
Thanks for the feedback on that! ๐
Its not unsual to do that though.
Even though you might have something like a "Ruleset", which could do stuff like define default teams etc.
An Actor like the GameState will still need to instantiate that information
When you say instantiate that information, you mean like actually creating the teams? I think that makes sense, I'd probably try to keep any defining rules in the ruleset though (like max teams, etc), the gamestate like you said would just be in charge of the game's current state but wouldn't have any boundaries defined in itself I don't think
Unless they were like really internal limits that didn't need to be exposed/accessed by anything else
When you say instantiate that information, you mean like actually creating the teams? Yes
Unfortunately it seems like my ruleset variable isn't being properly replicated to the client gamestate when that client is spawned, am I doing something wrong here? I figured it would reflect the value from the server (it might not work because it's a pointer to a live object)
If it's a GameMode object, it doesn't replicate.
What is the Ruleset object type?
Ruleset is a data asset object, that's the one I'm trying to have replicate - and yeah this event graph is within my Gamestate
It's a data asset that's within the editor, yea? Not constructed at runtime?
It is constructed at runtime actually yeah
That's the problem.
It then exists as a UObject which doesn't replicate on their own. DataAssets that you create before the game is running have an asset reference that can be shared across the network.
Hmm alright that makes sense, I'll need to figure out how I want to solve that. I was dynamically creating it because I wanted the values to be changeable at runtime
Thanks for pointing that out, helpful to know that it wasn't me just misunderstanding something about variable replication as well
Anyone know if thereโs a good way to debug the reliable buffer overflowing? Getting an issue where if a client joins late in the game they fail to connect to buffer overflow. Trying to find out what all is being sent to cause that. We do have a lot of data that gets sent when they join but it would be nice to know exactly what needs to be spread out or cut.
network insights
We are on 4.27, I got insights working with it but was having a hard time finding anything for the client that failed to join. It showed the server sending basically nothing and the client receiving also basically nothing
I guess you could make your own actor channel output info, not sure what other options you have for dumping rpcs sent and payload sizes unless there's some verbose thing built in
Is the buffer stored as something human-readable if i were to breakpoint somewhere in the code where the client is disconnected?
Or is it literally just a counter
not sure... if it was a buffer overflow from a bad packet I would say you want to breakpoint the actual overflow call and not the disconnect as it could be deferred till higher ont the stack unless I'm wrong
Yeah I plan on trying to figure out where that is but Iโm concerned it will just be โyou have 257 packets in flight oopsโ and no good way to tell what those are
@vivid seal imo with network profiler it can be grabbed relatively easily, start profile before join on server, it will store outgoing packages. ofc can be started on the client too for more info. use these console commands:
netprofile : toggles recording on and off
netprofile enable : start recording if not already recording
netprofile disable : stop recording if currently recording
https://dev.epicgames.com/documentation/en-us/unreal-engine/network-profiler?application_version=4.27
when you find the data causing it , it can be streamed like in this tutorial
https://vorixo.github.io/devtricks/data-stream/
my adventures :
once I tried something similar, I had to send a graffiti board large render target through somehow on late join, but it was too many data simply, and we use dedicated server, so 1st from one client to server, then from server to new client, but finally I sent through only the paint player inputs from dedicated server, it was more lightweight to store and send only it... I mean not always an easy and trivial thing to solve it , sometimes you have to rethink what data you really need and when and where
I assume if you put a TMap in an actor that replicates like the gamestate it won't replicate?
Tmaps aren't set up for replication :/
Yeah i'm aware, just had to ask for a sanity check :p
Is there a list of what containers support replication?
Hello, I interesting to learn more about how mmo shooter (such as destiny, elder scroll online, fallout online, planet side) do hit registration, just simple trust the clients and simply verify by distance? I think it should not store a lots of hitboxes history and do rewinding
Array. You can also have a struct with a key and value pair.
On rep array , populate the TMap
I don't believe so, most of them replicate just fine unless it's something very specific
O
I misread the question nvm
Pretty much all containers do except for Sets and Maps
So I have an AI system when I run standalone. I get 70fps. WHen I add a client in multiplayer mode, FPS drops about 5-10fps per client. How can i fix that?
Maybe it's trying to replicate stuff it doesn't need to?
Question, is it realistic to expect to be able to have ~200 players max on a huge landscape and have good performance?
For most people, no.
It can be done, but it's really hard to do it
What makes it hard?
I was thinking of using Mass for performance, i don't see a lot of documentation about using it for multiplayer though
I see there's mass replication but not a lot doc about it
Replicating the movement of 200 players aside, also excluding whatever replicated variables they have, and other possible replicated components of those players...
You also need 200 player worth of content, which most will likely need to be replicated in some way
I think there's network culling, like a player only receives events about the nearby players
if it's a survival game, I'd just forget about it altogether. The list of things needing to be replicated quickly rises to like 10,000+
without network culling you'd probably not make it past 50 players :P
and that's assuming the game is barebones
It's inside the engine right?
yes, it's built in
Yeah so if i switch it on it should be ok?
not even close
it's not that simple
the default options for almost anything in unreal engine is entirely unoptimized
I'm pretty sure it's to help beginners have the best chance at getting something done
if you don't know anything about multiplayer replication, you won't make it past 20 players if you're going for an actually good open world or survival game
So what's the solution if i want a lot of players on a good large open world? And yeah i'm inexperienced, i know i'm naive
It won't have as much stuff to replicate as something like Ark survival but definitely more than just player positions
there isn't one single solution to fix the problem, it's a ton of optimization, and utilizing many tools unreal engine has, and tweaking of settings
then that's half the battle, the other battle is completely unrelated to replication
and that's just making sure your code is optimized and running as efficiently as possible
that one is probably gonna kill you before replication does
I'm good at optimizing shit in C++, never optimized network shit though
you'd be surprised how much every millisecond count when there's 200 players running around
that aside, unfortunately, there's not many tutorials on how to optimize networking in unreal engine past the beginner level
you're gonna have to start doing a lot of reading
and first and foremost learning to use the networking profiler, as well as unreal insights
Thanks, do you have ressources?
This week we'll be joined by Ryan Gerleve and Dave Ratti to discuss general server optimization in UE4, as well as techniques and solutions to improve your Actors' performance in a networked environment.
NEWS
Unlocking Breachโs combat with Unreal Engine
https://www.unrealengine.com/en-US/tech-blog/unlocking-breach-s-combat-with-unreal-engine
...
I think I watched this video like 10 times to try and understand some things
there's also
This compendium is meant to give you a good start into multiplayer programming for Unreal Engine.
Thanks
and ofcourse you need to know literally everything in this video
https://www.youtube.com/watch?v=JOJP0CvpB8w
Btw since there will be latejoiners, i essentialy want to OnRep Notify everything right?
you essentially want as little replicated variables as you could possibly have
but yes onrep is helpful for syncing up late joining clients
Would making my own networking solution hand-made for the game be faster to dev and faster at runtime than optimizing the fuck out of unreal's one?
If you're talking about going full Valorant and completely rewriting the network code then ofcourse not
but unreal has the tools for you to essentially make your own logic for replication
like when things get replicated and how
Mass would help with perf right? I have experience with the ECS paradigm
Mass is for AI
From what i've seen you can do gameplay logic and other stuff with it
Push model is an option for more control over when things get replicated
https://www.kierannewland.co.uk/push-model-networking-unreal-engine
I think making your own Network Manager Is king though, you can get pretty far creating one with unreal engine's Built in FastArraySerializer
https://www.aclockworkberry.com/custom-struct-serialization-for-networking-in-unreal-engine/
I have no idea, Mass is really complicated and not very well documented yet
Mass isnt going to help you with networking.
Outside of being a more efficient mechanism for managing large numbers of things. Saving CPU cycles.
But that all depends on how good you are at optimization
I know ECS runs faster but does it replicates faster?
Mass doesnt replicate?
As I said, its not going to help you with anything network related.
Apparently MassGameplay has MassReplication which brings replication support for mass
Never tried though, i'm still cloning the repo
Taking forever to clone the UE github repo
What do you even think Mass is going to give you that you need?
Better performance on the logic side of things, and maybe on the network side of things
Like when someone does an attack, the logic of finding everything it hits and the networking of replicating it
And have it magically make everything super fast
Yes i kinda know how making games work ๐ญ
How will Mass help you with that in a more performant way than a normal approach?
Because ECS is faster than the typical OOP approach
๐คฆโโ๏ธ
And maybe it replicates faster?
Sure, good luck my friend.
It sounds like you are hoping for one off solutions, and it's just never going to happen unfortunately
Is it not?
No i'm just wondering if using mass can be in the bag of things to do to have it run smoothly