#multiplayer
1 messages Β· Page 230 of 1
Here's my GameState
But just as a confirmation on the conversation I mentioned (it was 2 years ago). It look like there was a problem with prediction when trying to put stamina on GAS and sprinting on CMC. Have that changed in todays unreal? (I still need to search how to do it though)
I did add my custom PlayerState class to the GameMode btw
Maybe I just don't understand how the GetPlayerState node is supposed to work
Why are you registering player in game state?
don't think begin play is the correct place too
I'm a complete beginner in multiplayer stuff and I'm just doing a small prototype to understand how everything works
Where should I register the players?
Not that I ever tried but im pretty sure you also can't call server RPC as client in game state
it is not owned by client
GameState is replicated to all clients no?
What do you want to do? The game state should have an array of player states
depends when you check it
I tried giving it 1s of delay after beginplay and it was still empty
as client, you can just wait for the server to replicate the array using OnRep
Aight let's start over
I want to give my players a UID and some basic variables at the start of my program
What's the best way to do that
you can track incoming player on the server using Game Mode
Oh that's neat
I can't remember what the event is called though
I'll do some research
Thanks
one sec
Event OnPostLogin?
Yep that seems to work
btw when you said the array is empty, do you mean the Player Array?
nah it works on pie
just tested
huh, weird
It was showing empty for me
@thin stratus Sorry for ping. I'd like to ask a few questions about your tutorial, if that's okay. (https://cedric-neukirchen.net/docs/session-management/sessions-in-cpp/)
1-) Why are we binding/unbinding constantly? It's always same C++ functions. Are we trying to avoid other code interacting with OnlineSubsystem triggering our callback? If so, then we don't need it, if we don't have other code doing that, right?
2-) Do we need to call TryTravelToCurrentSession after we call JoinGameSession? If yes, why it's not a single function? If no, why do we need it then?
3-) I'm following the tutorial in 5.5, is that okay?
- It's usually good to clean up after yourself.
- The whole thing is about Sessions. Connecting to the Server isn't necessarily related to Sessions. Epic Games does it both in one swoop when
OnJoinSessionCompletedcalls back. You can do the same if you want. - Probably. I haven't tested it in a while, but not much has changed as far as I know.
1-) So It's okay, if I bind once and don't unbind ever? (again assuming no other code interacts with online subsystem)
2-) So sessions are like a lobby to determine who joins the game and after you got everything, then you connect to server? Can this support following approach:
- ListenServer hosts the game
- Clients can join
- ListenServer can start the round, nobody can join mid-round.
- Round ends
- Clients can join
- ...
- In theory, yes. But wouldn't know why you would want that.
- Sessions are just blobs of information in some backend. (ignoring LAN for a second).
Something creates a Session on the Backend with some information.
Something else can search for that and join it.
And yes, you can disable joining when the Sessions has been started. At least if said backend has an implementation for it.
But that's still not the same as joining the Server. You could join the Server if you have the address, even if the Session is started.
But you can also block Clients from joining the Server itself in UE code.
To be clear I don't mean I wanna block joining after session start. I mean I wanna block, if something game specific doesn't allow joining at that specific moment. Like mid-round
Sounds complicated tho :d
You can Update the Session, and what you do in the Game Server itself is totally up to you
You can block everyone in GameMode::Login etc.
Oh, right. GameMode also has a chance to block. Separate from session interface
Yeah that's what I meant
^
One last question. How would joining via steam overlay happen in that code?
Like joining a friends game on steam
I know this is for OnlineSubsystem Null, but do I need to do something extra for this?
Hm, I know for Invites to Friends you need to actively hook into SteamAPI. That's not available in the Interface.
That also runs on a different Thread and then has to be pushed back to the GT to show e.g. UI.
Interface should have functions to join a specific user though.
Not sure how the connecting vai "JoinFriend" works, but best is if you would check the Steamworks API
Got it, thanks π
normally via IP, you'd specify which level to host and it would open that level. With CreateSession + StartSession, do you need to open that level before/after CreateSession + StartSession? Or is it supposed to travel to that level when you host?
You need to still do that.
Sessions and actively hosting in UE are two things that work in parallel
One can we used without the other basically. For whatever sense that makes in those cases.
So let's say I'm in "MainMenuLevel" and I'm trying to host with "GameplayLevel", how would it look like? Like this?
1-) CreateSession (wait until succeeded)
2-) StartSession (wait until succeeded)
3-) OpenLevel("GameplayLevel");
- with ?listen option
You can probably laso swap step 2 and 3, but I think native nodes don't do that either
Oh, I see. Sessions are just a way to advertise that there is MP session going on.
In the end, it just ends up using IP stuff
That makes a lot of sense now π
On an unrelated topic I'm having an issue about steam overlay...
- PIE: No overlay
- Standalone: SteamOverlay
- Packaged: No overlay
Any idea why this is happening?
My config file contains this:
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
bInitServerOnClient=true
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
and I got the Steam OSS plugin active
My .build.cs contains this:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "DeveloperSettings", "OnlineSubsystem", "OnlineSubsystemUtils", "OnlineSubsystemNull", "OnlineSubsystemSteam" });
As far as I understand with this config file and enabled plugins, I should see steam overlay on SpaceWar game even If I don't ever interact with steam
Or even if I don't do anything related to MP
Adding non steam game to steam doesn't display SpaceWar, but afaik I shouldn't need to do that at all
--
Creating steam_appid.txt file within same folder as game binary seems to work, but I shouldn't need it, right?
This is too exposed as a txt file, I don't like it
Hey, does anyone know how I can make my enemy BT work for multiplayer? it only works for server player I followed Gorka's BT and Enemy AI tutorial's (I orginally made it for BP only but later changed to BT's
(roams, chases player, attacks, walks and attacks, camera works correctly when close and does not clip, anim montage for enemy attack works with server and client screens)
only a few things don't work (health bar appears only when directly in front of enemy and does go down when hit enemy, but healthbar doesn't appear when on the side or behind it, and enemy does not attack client player only server even if enemy sees client)
Ok so kinda new here but wondering if anyone has any experience with UE2? If not, does anyone know if it's possible to replicate actors or animations through a non-inherited class like the gamemode or playercontroller?
Does anyone happen to know if this causes/can cause race conditions? Replicateion isn't guaranteed before DoSomething is called, correct?
I usually use RepNotify for stuff like this but I'm just wondering
That's what I do in general, but I just wanted to confirm because I've never tested it
Thank you
What would be the best to dynamically change player max walk speed ?
Is there a way to rep it and get taken into account for saved moves, or should i have multiple bools/one enum and use that in saved move to decide speed
Attempting to rotate a player towards a mouse, both server and client, then do a capsule trace.. melee attack.. etc. Server is working perfectly. The Client however is not. The rotation is not updated prior to the melee attack. So it is one swing behind. Any ideas?
Using GAS... so should I throw this into a "WaitTargetData" GameplayTask, etc?
Create a GameplayTask... that would rotate the character similar to how I am doing it in my PlayerController?
Hello im looking for advice. Im trying to brain storm a way to make a walkie talkie system. I already have a proximity chat system via steam advanced session. Anyone know a good way to go about this?
ugh also as far as i can tell i cant find any documentation for the voip talker comp
Just multicasted my happy new year message, will late joiners get it? Wait... I might need to replicate it!!
Happy new year multiplayer pals :)
would there be any issue with setting a structures health on it's begin play variably ? i have a *lvl variable i'd like to be able to set and have it set the health on begin play
No, why?
Honestly just wasnβt sure if I needed a switch or how reliable it was relative to making children and setting the variable there
Joining a dedicated server joins successfully but character not spawned in a big map which has world partition enabled
testing with a small map works fine
Any suggestions/ideas are welcome to tackle the bug
client can see the world can move the camera
solved: the solution is need to override the game mode in the map which is selected to start a dedicated server
this is because the dedicated server don't respect the game mode selected in projectsettings->mapsmods-> ...
kudos for posting your solution
Did anyone got Steam OSS to work with UE 5.5? Default Interface or AdvancedSessions?
As far as I understand Epic broke it in 5.5
I can't find and join games... Something always fails on joining side
(I'm using 480 app id, maybe that's why)
One of the issues is about a setting mismatch between bUsesPresence and something like bUseLobbiesIfAvailable (I don't remember exactly)
The other one is whenever provided any custom parameter, it straight up fails and says something like Can't read PARAMETER_NAME
I have an Actor with UFloatingPawnMovement who's controlled by an AI controller which sets its Velocity to say 300 m/s on the server. The actor is just some sphere that's flying through the air in a totally predictable line for say 5 to 10 seconds.
I'm seeing that on clients, once the latency goes into 100-200ms range, the Actor ends up being pretty choppy, even with no packet loss. I'm assuming it's because its position is only updated so many times and it will not look buttery smooth on that client.
I naively tried to experiment with having the AI set the velocity on the client's copy of the Actor as well just to see if that would somehow smooth it out, but no luck, still choppy, doesn't seem to make a difference.
What am I missing here, is this working as by design? Is there a trick to having it look smooth on both ends given how predictable and fixed the movement is? Feels like there's something obvious here I should be doing.
Interpolate from current to target position? Imagine if your computer can handle 140 fps and the net can only update 30 times in one second. Instead snapping to the data given by the server, you interpolate to the target location.
Awesome, thank you. Couple of questions there:
-
how often can I reasonably expect a client to get updates from the server? I have
NetUpdateFrequency = 100.fbut I imagine that doesn't actually mean the client gets 100 updates a second once high latency is involved? Seems like the number is much closer to the single digits than 100 in practice? -
what's the most straightforward way to accomplish what you suggest on the client? I naively attempted to just set the velocity there but it doesn't seem to do much. Do I manually lerp the position on tick on the client, or is there a more elegant approach?
Not sure what data actually get send to the client. If you replicate the location your self then OnRep location VInterpTo will do
I pretty much have to interpolate everything related to movement
E.g. aiming
Rotation, etc.
Not doing so will be choppy even with tiny ms
Huh, yeah, that was not my expectation at first, but that makes sense. And yes, that confirms what I'm seeing, choppy even with low ms. Is it fair to say that you want to turn off the default movement replication then since you won't be using it?
I never use pawn but I'm using cmc out of the box with replication ticked.
They already handle everything better than I could. The point to use cmc is to benefit from the network movement.
Any particular reasont to use pawn?
That was just my first guess based on the fact that I needed to give the Actor an AI controller on the server. The Actor randomly picks a location to go to every few seconds, and then floats there.
Nope, just a floating sphere, it's an enemy NPC ish type of thing that a player can jump on, kind of like a cloud.
Did you select the actual server gamemode there?
Or actually there is only one iirc but one can select server map there hm.
Strange that it doesn't use the gamemode
Exi can I have opinion with damage system using GAS. Do you locally predict a hit react? Mine is done after post attribute changed, which is done on the server.
Should I just be content with it or can I predict playing the montage using GAS framework? The context here the montage contain root motion. If there is a de sync, there will be a lot of correction.
Would it just be best to let server handle the hit react and be done with it?
I have no issue predicting montage when it comes to client initiated abilities but when it comes to hit react on A.I should everything be handled on the server?
Personally I think in terms of feel, it probably feels better to see that you're actively hitting the actors than seeing a delay in them getting hit, even if no damage is done until a moment later from the server catching up.
From another prominent member here:
Thanks, maybe I will take out the root motion, play the montage visually and have the knocked back initiated by game play effect.
So, I've come across an issue to where integration of the Steam advanced multiplayer plug ins are working on my local machine when playing as a listen server for hosting and joining a session. But, live on steam I'm not able to find the hostel game. I have my own app ID, which it set in the default engine.ini and steam app txt per instruction. Is anyone else running into this issue??
Yeah there is only one BP_GameMode derived from my custom cpp Base_GameMode
for the small map i overrided it before few month's and thats why it was spawning character in small map
i got an i dea to override it for the big map too and see if it works
and it works π
It's kind of a complex issue that just sort of works when you split it out into areas of interest.
The first area of interest is damage application. We don't really want the client to predict this in a lot of cases because this is where code can get severely tangled and messy. Regardless of whether you're fully simulating on the server, or allowing the client to tell the server they hit something and doing validations, the client shouldn't do anything as far as actual application here and should simply rely on the server's replication of health or client RPCs afterwards to know something happened.
The second is player immersion. This is secondary to what is really happening and it's okay if the local player predicts this stuff. They'll see bullet hit sparks, hit react montages and such. These will mostly sync up with what the server is doing but it's mostly okay if they don't. We just want to give them a relative feel that something is happening here.
The last are critical indicators. Most notable for shooters is the hit indicator at crosshair. This is NEVER client predicted. If this goes off, server has confirmed a hit for the player. This is usually like a client rpc when server determines this player has damaged something. Similar effects include damage numbers and the like. Server should be notifying the client what these were to avoid non real numbers.
You mix all of these together and it seems messy that they're not interconnected but in a real world situation they just mostly work, and it's the simplest way to handle the fact that physics exists and that there's a latency between player and server. While you can get around some of it with clever coding to make it feel smoother and better, this can easily backfire and cause player outrage.
Do you guys know any projects that only contain ground work for multiplayer? Like kind of a base for more complex games?
lyra is a thing but it's a lot to take in
and some of it's design choices are questionable IMO (albeit functional)
but really any "complex games" are going to require you to make your own solution. not really sure what that means
the "ground work" is handled by the engine
Is there something special to keep into account while coding local multiplayer? Is it just like normal multiplayer or is there something to be aware of?
All things like Advanced Sessions and other wrappers do is expose stuff to BP. it all exists within the engine, you can create sessions already.
Itβs just up to you to determine if you would rather drop $100
You have multiple local players instead of just one. Some people hack up widget implementations and such with the idea that there's only ever one local player even in a multiplayer game. In local multiplayer that's not true though.
Also this depends if there is any online multiplayer at all. If not then a lot of your code ends up not networked anyhow, so in that regard there can be a huge difference to local vs online.
Ok cool, do all players have their own hud if i use split screen?
And is the game instance shared?
When you say hud, do you mean a widget, or the AHUD actor?
I think there is a setting for making a shared viewport. But normally each player will have their own viewport, and AHUD.
Even with the shared viewport, each player can still have their own set of widgets, and they will always have their own AHUD.
I got it, so seems like you ended up replicating it lol... HNY GOAT!
So I'm working on a MP game and I have this BP that allows players to place a resupply order. I'm using widget components to the ordering process interactable in the world.
The order details are stored in the resupply console BP (Which is replicated) The function for adding/removing order items is stored on the resupply console. Thus clients can't tell the server "hey I wanna add an ammo box" because they don't hold ownership over the resupply console so it never fires the 'run on server' event that adds to the order.
How could I fix or get around this issue?
Route it to what the client owns. E.g. the controller.
So, calling "Server Add To Order" from the controller, or run the order processing on the controller?
Calling , ClientRequestOrder and pass in any param that you need.
Server validate and check if the order is valid. Then replicate what ever neccesary if the check is passed.
Client ask for a box of ammo from controller, server check if the requested ammount is valid (not exceeding max). Then checks for player money, etc.
If everything is in order then server can add an ammo box item to a replicated array (supply in ordering machine)
ahhh okay. I got that to work! Thank you! I was trying to keep all the ordering process inside the resupply machine but I guess I can't quite do that
They r not owned by the clients and only one owner can be set at a time.
It's normal to route them to else where.
If you think that will bloat your player controller or character then maybe you can manage it in a component that the player controller own π€·ββοΈ
I don't think it'll bloat it. Just wanted to keep it as 'self contained' as I could if that makes sense
But thank you again! That helped a lot!
Ok, I don't get this bit:
Say I'm replicating a moving Actor's transform from the server 100 times a second, or whatever that is by default for a high priority Actor. The client knows nothing about the Actor's movement besides what the server tells it, it doesn't have a local simulation of that movement.
Why is the client, assuming a higher latency of 100-200ms, seeing the Actor all jittery on the client's end rather than exactly as smooth as if you were only a few ms behind the server? The server is spraying the client with 100 updates per second about the Actor's position, why does it matter if the client is 200ms behind or 0ms behind the server as far as jitteriness goes? Shouldn't the client be receiving the same number of updates per second regardless of where those updates are coming from, in an equally steady stream of packets? Assuming no local movement prediction or interpolation.
Is it basically all about the fact that the bigger the latency the more chance there is for packets to arrive out of order, or slow down for some reason, or get lost? So under perfect conditions maybe you wouldn't tell much of a difference, but in the real world it's going to be a mess?
Did anyone do steam multiplayer in UE 5.5?
when I run it standalone it says my steam name but when I package the game and open it from steam it says my computer name instead of steam.
no problem setting up the server and connecting to the game, but can't get names from steam
Is there a way to set a mesh's visibility for only one of the local players in split screen?
Only owner see / Owner no see?
Idk if it works for split screen
Uh yeah might work, thanks
That would only happen if steam isn't actual utilized in the packaged game
It works on standalone. For packaged game I had to create a steam_appid.txt at the same directory as game executable
Assuming you got your config correct
You need to add the app Id text file if you use shipping
Because it expects you to distribute the game via steam then
Which then does the appid stuff for you
But if you start the shipping build by hand you gotta manually add the txt file. If you don't want that, don't package shipping or properly distribute via steam
I don't think it worked on Debug or Dev either, but I'm not sure
As far as I understand that's only if you wanna upgrade sdk version
Docs aren't great. They are a bit vague on a lot of subject
Yeah that doesn't sound necessary by default
Pretty sure it's mostly just enabling the plugin, changing the ini file and off you go
I added steam_appid.txt but it still doesnt work
Did you actually write anything in the file? You are supposed to put id in
480
Then check your config ini and if you enabled Steam OSS or not as a plugin
Also if steam isn't running at background, it might not launch it
I just experienced that
What would be the best to dynamically change player max walk speed ?
Is there a way to rep it and get taken into account for saved moves, or should i have multiple bools/one enum and use that in saved move to decide speed
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
bHasVoiceEnabled=true
[Voice]
bEnabled=true
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName=OnlineSubsystemSteam.SteamNetConnection
[/Script/UnrealEd.CookerSettings]
bCookOnTheFlyForLaunchOn=False
Isn't everything true?
Seems okay unless there is a lil typo or something else wrong with your setup. Here is mine for reference:
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
bInitServerOnClient=true
bRelaunchInSteam=true
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
I'd check logs for warnings and stuff
if it's broken, shouldn't it be broken in standalone?
Yeah
but it works in standalone
Are you sure you are putting it under correct folder
It's supposed to go YourProjectName/Binaries/Win64
Not at root folder
I'm talking about steam_appid.txt
I know, I just wondered if there was a mistake here and I wanted to show this too.
I already showed the steam app id here
I'm also sure steam is open because I added it to the steam library and open it from there
It should pickup without doing that
I tried without doing this, but when it didn't work, I tried it in my steam library
You should see Spacewar in your activity section
If you add outside game, it will show something different
spacewar doesn't show up. steam pop up doesn't show up either
shift+tab also doesn't work if I open it outside the library
could it be related to advanced steam sessions plugin or something
I don't think so. Even if you don't do any sessions, steam overlay should appear
Singleplayer exists π
I told chat gpt about the conversations here and asked.
Shipping and Development Build Settings
It is common that Steam Overlay works during Development Build but not Shipping Build.
Check the correct settings for Shipping Build:
Make sure steam_api64.dll is in the Binaries/Win64 folder.
You may need to add this file manually during packaging.
no steam_api64.dll file as it says
yeah, I downloaded and added it but nothing changed
Did you try to check your logs? SteamSDK should log at startup to say it's either successfull or failed. It might be helpful to see if it's failing or not trying to startup at all
That might require source build engine to enable shipping logs afaik though
I'm using both without any visible (I guess) issues. Sprint is implemented with flags, deciding the base speed between walkSpeed and sprintSpeed. I also have a replicated multiplier to use for effects and stuff which is being multiplied with the base speed on OnMovementUpdated
Since when does loading level instances can kick clients
Any idea why I can't join via steam?
I'm not even searching for sessions, just joining via steam friend.
Code:
bool UBlacksmithGIS::TryTravelToCurrentSession()
{
const IOnlineSessionPtr sessionInterface = Online::GetSessionInterface(GetWorld());
if (!sessionInterface.IsValid())
{
UE_LOG(LogTemp, Warning, TEXT("[TryTravel] - Fail1"));
return false;
}
FString connectString;
if (!sessionInterface->GetResolvedConnectString(NAME_GameSession, connectString))
{
UE_LOG(LogTemp, Warning, TEXT("[TryTravel] - Fail2"));
return false;
}
UE_LOG(LogTemp, Warning, TEXT("[TryTravel] - Success (%s)"), *connectString);
APlayerController* playerController = GetWorld()->GetFirstPlayerController();
playerController->ClientTravel(connectString, TRAVEL_Absolute);
return true;
}
Logs:
I got it working. I think steam sockets did the trick, but I'm not sure: https://youtu.be/iM0sBDBnVC4
In this video I will show you how to configure Steam Sockets for OSS Steam and fix Steam Sockets related issue.
OSS Steam - https://dev.epicgames.com/documentation/en-us/unreal-engine/online-subsystem-steam-interface-in-unreal-engine
Steam Sockets - https://dev.epicgames.com/documentation/en-us/unreal-engine/using-steam-sockets-in-unreal-engine...
My problem is something not getting replicated the way i want in C++ to work, basically the server's widget doesn`t appear to the client (Listen-server)
so the way I want things to work is like this:
when a PlayerController gets created it calls in BeginPlay a function from the game mode ,
the function from the game mode, in here to the player controllers assigns a ThirdPersonCharacter(ACharacter), in here the constructor will create an DefaulSuboject for a UWidgetComponent, and in the begin play here it will set Widget class the widget i want to show and sets its visibility to false, and in the gamemode it also calls a function from the ThirdPersonCharacter in which will has to make the visibility of the widget true, to both server and client, but right now i can see from the server pov both the widgets, but from the clients pov, I can see only the clients widget visible, not the server's too,
My question is, what is the best way to make the widgets visible for everyone?
Right now I am doing it this way, in the function I call from the gamemode in the ThirdPersonCharacter, i am doing an updating a RepNotify Variable, which is the PlayerLobbyInfo, which should call the OnRep_PlayerLobbyInfo function, and in case for the server i am calling with an HasAuthority another function which is NetMulticast, in order to call itself the Onrep Function
I have a feeling this is the wrong way to do it, and I can do it a better way, which one should be it?
Quick and hacky solution. Go to your character and do this:
hmm i am doing it in C++
Doesn't matter, same code
okay, construct none should create the widget?
It's a CreateWidget node without class specified, so yeah
No, you need to specify class. Mine hasn't. That's why it says Construct NONE
and where should I createDefaultSubobject, still in the constructor? basically I don`t use CreateWidget in my case
Wait is this widget component?
yes
So like nameplate or something?
yep
Forget what I said
You just need to do Component->SetIsReplicated(true) in constructor
after creating and attaching
Example:
CameraComp = CreateDefaultSubobject<UCameraComponent>("CameraComp");
CameraComp->SetupAttachment(RootComponent);
CameraComp->bUsePawnControlRotation = true;
CameraComp->SetIsReplicated(true);
hmm still doesn`t appear for the client the server's widget
basically the server see's both the widget for the client and the server,
but the client see`s only it's widget
and the problem is the way i created this stuff
Do you mean widget doesn't appear at all or data on the widget isn't updating?
Also does clients see each others?
neither
i am using only 1 client in my game
You mean you specifically design game for 2 players?
neither update, neither show
If not, it's probably a good idea to test with 2+ player
yep
But i think mostly it`s because of the way i am doing the replicating
Just to be clear, you are setting widget class at constructor right?
So from the gamemode i pass in here in the ThirdPersonCharacter a struct, and based of that struct it should populate the widget with the information,
so in this function I am updating a repNotify variable which is struct type, when it`s updated it calls a the OnRepFunction, which from what I know, will only work for client, and in the repNotify, it will make the widget visible and populate with data,
also in the function i call from the gamemode I am calling another function with HasAuthority that will call this onRep funciton to update for the server aswell
yes
ass I just showed you in the picture
So what happens when you make widget visible by default?
it will show on the client the server one, but it won`t be populate by the data
Are you calling a function from Character or just setting Characters variable directly?
in the first picture is when they are visible set to false by default,
Second picture is when they are visible set to true by default
(Please don`t mind them by being inverted)
well I am calling a function from Character, i am getting the widget, and in the widget basically i am populating the data
Are you doing classic replication?
MyFunction_RunOnServer() -> MyFunction_Multicast()
well, what should I set to RunOnServer and what I am setting to Multicast?
When you want something to be replicated to everyone, you just call a RunOnServer function. It's only purpose is to call Multicast function
in the first picture the function changes thee OnRep Variable, which is set to Server Reliable,
Second picture, I have the Multicast UPdatePlayerLobbyInfo which is multicasted,
and the OnRepPlayerLobbyInfo function is the way it is UFunction()
Then Multicast function does the actual work
basically this is the way i have done it
Show me header
And you are calling UpdatePlayerLobbyInfo() from game mode?
yeah
Idk, seems okay to me
bro I been having on this problem for 2 weeks, i am going insane
loosing hope in life
A little suggestion to spot MP mistakes easily. Instead of logging or printing to screen via GEngine, try using Blueprint version of PrintString
It shows which client printed the message
UKismetSystemLibrary::PrintString
ouuu
Most BP nodes can be called from C++, if implemented in C++
this is intresting, i needed this
how do i initialize it, do you have an example for me?
Only weird thing is you need to pass world into it
Just a normal C++ function otherwise
UKismetSystemLibrary::PrintString(GetWorld(), TEXT("Message"));
damn bro I have been searching for this for a long time my friend
I got used to program in blueprints here
and I was searching for this
Now I will only use this
β€οΈ
Just pay attention to logging variables. It's not same syntax
An example from engine:
UKismetSystemLibrary::PrintString(WorldObject, FString::Printf(PrintStringFormat, InContext.GetPublicData<>().GetInstructionIndex(), *Prefix, *String), true, false, ScreenColor, ScreenDuration);
This part is formatting string with variables:
FString::Printf(PrintStringFormat, InContext.GetPublicData<>().GetInstructionIndex(), *Prefix, *String)
--
You basically replace this:
UE_LOG(LogTemp, Warning, TEXT("String: %s"), *MyString);
With this:
UKismetSystemLibrary::PrintString(GetWorld(), FString::Printf(TEXT("String: %s"), *MyString));
np
okay so my client side when it should replicate from the server the information it has to the client, the server's widget, it won't get past this line:
UKismetSystemLibrary::PrintString(GetWorld(), TEXT("Zambuia"));
// Get the widget instance from the component
UUserWidget* UserWidget = PlayerLobbyInfoWidget->GetUserWidgetObject();
if (UserWidget)
{
UserWidget->SetRenderTransformAngle(180.0f);
UKismetSystemLibrary::PrintString(GetWorld(), TEXT("zang zang"));
It will print Zambuia, but won`t print zang zang
when it has to replicate the widget's version
How do i make an hidden mesh cast shadow to owner only in local multiplayer?
I tried OnlyOwnerSee + HiddenInGame + CastHiddenShadow, but both local player see the shadow.
For some reason widget isn't created at clients
Show constructor
You aren't setting widget class in constructor
Which you said you did
Why do you even have PlayerLobbyInfoWidgetClass ? You can edit component in BP editor
so basically in my ThirdPersonCharacter class in the unreal engine editor i have the widget that i want to use
well i get so confused
sorry:(
basically in the construct i create the component to hold the widgeet
and in the begin play i add the widget in the component, if i am not mistaken
The widget component also has one
You are just taking long road
You can directly edit widget component in BP editor
If you are referring to my first reply I thought you were doing normal UI
Not widget component
so i don`t understand, what do you recommend me to do?
directly add the widget in the editor, not create it in c++?
Click the widget component in editor
There is widget class here
You don't need to add a variable to your character
oh shiet, you are right
LogSteamShared: Display: Loading Steam SDK 1.53
LogSteamShared: Steam SDK Loaded!
LogOnline: Display: STEAM: OnlineSubsystemSteam::Shutdown()
LogOnline: OSS: Unable to create OnlineSubsystem module Steam
this is what it says in the logs of my project
when I start my game standalone in the editor the steam overlay comes up and it connects to steam but not when I pack it. can anyone help. I created steam_appid.txt and thats my defaultengine.ini
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
bHasVoiceEnabled=true
[Voice]
bEnabled=true
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName=OnlineSubsystemSteam.SteamNetConnection
yeah bro but still doesn`t help with anything, the client doesn't get past this line:
UUserWidget* UserWidget = PlayerLobbyInfoWidget->GetUserWidgetObject();
if (UserWidget)
Basically I understand that the client canno`t reach the server's widget, but the server should make it visible to the client too, why doesn't it happen this way
π¦
Hi can you help me pls, I tried everything and I don't understand, I made a multiplayer game in UE5.4 with the steam appid 480 the first time I built the project and tested the multiplayer with another person, it worked but since then nothing works except the steam overlay, I tried to build in shipping, development but I don't think it changes anything
try asking in #packaging brother
sorry i didn't see the channel
Hello everyone, I want to learn more about Iris but TBH couldn't find good directions to look for. Any advices?
Most likely just Source code and commits. It's not production ready yet (imo), so it's a lot of manual work and you gotta figure out the problems you might encounter yourself.
Donβt even get me started on creating descriptors for structures you already implement custom serializers onβ¦
So uhh.. Loading level instances with replicated actors in them breaks their replication?
Well, I'd check widget creation code in widget component. Maybe it does something weird that doesn't work.
Also you said widget renders if you set it visible by default, so widget should be there and valid
You are seeing something like this right?
[Server]: Zambuia
[Server]: zang zang
[Server]: Zambuia
[Server]: zang zang
[Client 1]: Zambuia
[Client 1]: zang zang
[Client 1]: Zambuia
With 2 players you should see each one doing it twice
Yes It does... Had a project I really needed this for.. Coop game with random level sequences in between. I opted for some really dirty workarounds like marking some actors to destroy themselfs and respawn with the needed Settings or Sending Interaction calls with the exact Details though a midddle man Actor component wich then tries to find the correct non Replicated Actor based on its World Location to trigger an Event...
Widgets are complerly Non-Replicating this means not even the Server can access a Clients Widget in any way. Each Instance only has access to their owned Widgets. You want Widgets to Read Replicated data from other classes like the Gamestate, PlayerState, Character and its Components
i still don`t get it, like doing it this way in blueprint's works easily
but in c++ it's fuckt up
I understood your Problem wrong did not Read the whole thing. I feel like your Problem lies in the order your Code is executed
try to delay it until both the server and Client are fully initialized just to see if it works
okay bro, but why does it work in blueprints and in c++ it doesn`t?
okay i went further
the problem was that it wasn`t initialized, and I did a timer to re-call the on rep function for it
my problem now is that the client doesn`t have the information of the struct from the server
Could folks here advise on what I could tweak in our project in order to make session connection issues clearer and more inspectable when they happen?
Basically we often run into a situation, on weaker connections, that a client will be able to retrieve a session on Steam through the AdvancedSessions plugin, but then the client will fail to join the session for some reason, and the logs don't say much on the subject.
I'm hoping there's some log level I can tweak that's specific to this session negotiation part of UE multiplayer that would tell me more about why the connection failed to materialize. Any advice?
I dont know about any special logs for it but you can try Adding the: Event Travel Error and Event Network error into your game instance. (Together with a print string)
After a client connects, you can request that info from server
It's fixed 2 players anyways. Won't be too much trouble
hmmm how?
But wait...
I don't think widget should be invalid even if you mess up the order
Something else must be going on
well the widget is not invalid anymore
i just had to do a timer for the client to wait for it`s creation
This is how the RepFunction looks now, and it will get the widget, cast to it, and after call a function for it with the struct as a parameter, but aparently the struct which is supposed to be the information of the server is not valid ( second picture)
bro I am hella desperate right here:)) been working on this for more than 2 weeks i told you :))
Then you can do the following:
1-) Call a RunOnServer function from client
2-) Get PlayerController 0
3-) Get that controllers character
4-) Run a Multicast function on that character
5-) Within that function, update widgets information
PC 0 would be servers character after RunOnServer
It's simpler in your case cause you have fixed 2 players
You can hardcode these stuff
btw, I assumed your struct correctly replicated and contains correct information
That's on you
well isn`t the struct allready replicated?
well in my header file is marked as a RepNotify variable
so I suppose it`s replicated, right?
It should be, but idk
That's just a possible reason why my approach wouldn't work
Something to be careful
when I start my game standalone in the editor the steam overlay comes up and it connects to steam but not when I pack it. can anyone help. I created steam_appid.txt and thats my defaultengine.ini
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
bHasVoiceEnabled=true
[Voice]
bEnabled=true
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName=OnlineSubsystemSteam.SteamNetConnection
Hi, I'm having some difficulty understanding how to communicate between clients in multiplayer
One PlayerController needs data that resides on another PlayerController
If I ask the server via the GameState for that data, I can't use a function to return the value since I can only do server functions using Events, which can't return anything
Is my approach wrong, or is there a simple way to solve this?
My first thought was to ask the server to fetch the value and set it in a variable in my PlayerController, but that seems maybe a little convoluted
What value are you after ?
If the data should be shared between players, it normally shouldnt be placed in the controller class
Playerstate is usually a better option
I'm simplifying here, but the data I need is in the PlayerState yeah
I'm making a card game and I store hand info in the PlayerStates (including hand size, which I need to display the number of cards in the opponent's hand)
Handsize should be a replicated variable
OnRep
Possibly also some 'lastAction' but maybe you already got that covered
Yeah that's probably for the best
I'm still trying to display cards correctly, I haven't even started on trying to play them x)
Online sessions will only find same BuildID right?
Meaning different games won't be discoverable no matter what I do?
I don't understand why I get an "Accessed NONE" error when I'm trying to get the GameState from a client
GameState is replicated yes?
That is correct. Where and when are you trying to access it?
I want a HUD to get a replicated variable from the GameState
From the HUD, I call a PlayerController function that tries to access the GameState to retrieve that variable
Looks something like this
when?
Well
Yeah that was the issue
Added a delay before starting the game to let the GameState be created and I don't have the error anymore
"replicated player info" seems like a redundant array.
You have the "playerstate" which is the replicated actor that is meant to contain replicated player information about a specific player.
You have the "player array" in the gamestate which is an array of playerstates in the game.
You're right actually, I could simplify this
Thanks for the help, everything works correctly now
if i create a dynmaic material instance in the construction script of an actor would that be replicated ? would i then be able to use that for vfx in the future on like a repnotify or multicast where i use that instance ?
Material Instances aren't replicated and can only be referenced on the machine they were created on. Anything you do in the construction script is normally executed on all machines, however, you still wouldn't be able to reference the DMI across the network. You can promote it to a variable when you create it and manage its values locally as needed.
ahhh ok , i was thinking to promoting to variable in the cons script and then on say updating that variable when activated via a repnotify, whcih currently i ust have it creatinga. dynamic material instance in the repnotify, which does work, but there's other times where i'd like to reference the material and it would just be easier to be able to pull from the variable rather than creating a new one for each thing
You can promote the creation of the DMI reference in the construction script. The OnRep should then be able to modify it as needed. The key here is that it's all local - nothing about the DMI would be shared across the network, but you can manipulate it locally based on replicated values.
Ok nice that works. Never used the construction script wasnβt sure if this method would work
But like.. there got to be a way to do this properly, right? Right??
Why would that break replicated actors ?
I'm loading level instances separately on server and client with ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr(). Is this not the way to do it? I made a simple test actor to increment a replicated int with looping timer, clients doesn't receive the value change
I'm pretty sure we loaded level instances in The Ascent just fine. But not sure if we had to do that manually on server and client anymore
There is not world partitioning fyi, I'm just trying to load/unload scenary in the same location
The whole game was using level instances (loaded ones, not spawned ones) to cut the huge map into smaller parts
And I can't recall there being problems with replicated actors. only thing you gotta make sure is to use the right world as the owner when spawning actors if you want them to clean up if the map unloads
I will have a look in a few minutes. Got an empty project for editor plugin stuff open anyway
Were there streaming sub levels as well? The issue started with sub levels (that are marked with always loaded) were not showing up when the persistent level was loaded as a level instance in another world. I then tried to get streaming levels from UWorld and loaded them as level instances too, which started to kick clients with MissingLevelPackage net error. So now I changed sub-levels as level instances. Disconnection issue is solved but now the replicated actors are the problem
What do you mean with Sub Levels exactly?
In the context of good old level streaming, you only really have 2 things: Persistent Level and Levels you stream in and out.
+- Levels you spawn duplicated, but haven't used them in Multiplayer yet
Okay so you do LoadLevelInstance not LoadStreamLevel, right?
This works just fine. Had to squeesh the nodes a bit to get them on a screenshot on my laptop >.>
This, only on the Server, does not seem to work.
Doesn't spawn the level on Clients. So I assume that's what you are struggling with?
What unreal version? I vaguely remember we had some issues like this in maybe 5.1 or 5.2...
fwiw, mine is 5.3 atm
But this also might just be expected. I'm trying to see if there were some project settings for this
Loading it on both Server and Client seems to also work. You do need to give it a unique OptionalLevelNameOverride.
I can't seem to Unload it anymore though.
Ah, wrong function.
That works just fine.
Calling the Multicast from a Timer.
I'm doing the same in 5.5 and it works perfectly. The issues we had were in the previous project where it seemed that the server would try and send an update about an actor that was not yet loaded by the client. The client would error and close the actor channel and never open it.
This was in the early days of World Partition, not manually loading/unloading though.
IIRC we merged some patches into our source build to fix it.
Blue/Cyan block is in a Loaded Steaming Level (so not an Instance, but just the Sub Level that is in the List of Levels loaded).
Pink block is in a Loaded Level Instance (so spawned runtime with the Multicast).
Both have the Actor in them with a Timer that loops once per second, incrementing the int.
The int is printed on tick. The Loading and unloading is always 2 and 5 seconds apart.
So yeah, don't see any problems. @upbeat basin
@mossy hedge
Thanks for giving the time to test it out. For the questions and clarifications, I meant streaming levels by sub-levels, yes currently using LoadLevelInstance, not LoadStreamLevel and also on 5.3
I'll double check everything to see if I'm doing something wrong
That setup looks exactly like mine but my client always says 0
Make sure you have a unique name per Level Instance that is the same on both.
Otherwise, the Client and Server can't communicate the Replicated Actors properly.
And for what it's worth, the Client will actually get kicked.
What does this mean? The name of the asset or the level name override?
The Override on the Node/Function.
Hmm let me try that
I assume that, otherwise, both of them will generate a random number for the name.
Ah that might be the reason why I was getting disconnected earlier
And then the Actors aren't stably named anymore.
Yup it was the naming
It's working now that I have given override names by hand
Thank you very much
Hey all, is there a performance difference between "ok tier" code using Iris and code using Replication Graph?
hello guys, how do you send and replicates movement animation like my idle,walk,run depend on ground speed but how do you handle that in multiplayer ?
I'm facing some problem with this
with c++
same way you will handle it in single player because you are just accounting for the speed of the character.
the replicated stuff would be the velocity, etc. Which you don't have to worry.
it's handled in CMC
so why when calculating direction to implement 8 directional movement it doesn't work like other players can't see the changes
direction is not ground speed though
but then again, unreal already replicate most of the thing you need to get player direction.
There is a function called CalculateDirection or something like that in anim instance.
use that to get the direction of the character
which you can then hook to blend space
I'm using same as yours , but yet
gonna try again
@half bluff you haven't really describe your problem btw.
what "doesn't work"
jaggy animation? wrong values? nothing playing?
Actually for my self , I didn't know where is exactly the wrong I'm trying my best to figure out .
I will try to make it basic to figure out , if didn't work will record a video and send it here.
LoL, I just set everything back to it's default, calculation of speed and direction in anim instance with out replication and stuff like that , and that work :p,
Unreal already replicate where the character is looking at. Look up get base aim rotation.
Calculate direction probably just getting the aim rotation then accounting for the character rotation.
because I remember that I tried to make it in anim instance and directional movement not replicated .
speed work fine
Calculating direction will use replicated value
The client needs to get the data from the server otherwise nothing will be in sync.
Ya , I see
You should interpolate the direction for proxies character ( characters you don't control )
Otherwise you get jaggy blend space because the data isn't updating fast enough.
Picture your computer with 140 fps.
But the server can only send you 30 times a second.
You will end up snapping to the incoming direction.
I got what you mean , but how about interpolate the direction please ?
like interpolated with previous direction ?
Interpolate between current to target
Target being the output value from calculate direction
oh okay I get it , thanks for your advice
I am planning to dive into Iris today, any tips or things to watch out for?
It's highly experimental and not crash free, that's all to say really. Be prepared to have to fix stuff
@upbeat basin There 100% is a problem with Level Instancing at Runtime. Try spawning it in at a Set location and Rotation and randomize the "Replicated" Actor color on the Server wich the clients then should adjust to im fairly Sure that epic did not fix it even in the newest Versions its a Problem that has stuck around for ages
Important Level Streaming works completly fine as far as I know I'm just talking about the load level instance Node (Level Streaming and loading) are two completly different systems
I am currently loading the level as a level instance actor on runtime, without issues about the replication so far (as long as we ignore the fact that loading a map for a second time still requires a different level name override than the first time)
Well good luck that you do not encounter anything. If I really spread false Information im sorry about that. But I checked my old project today setup Was exactly like you described. Loaded in a Level Instance with a unique Name on the server and afterwards with the exac name on the Client and replicsted Actors completly broke
That's what was happening with me without the name override. I don't know what's happening on your case if you're also giving the custom name
maybe im the one in need of tech Support then xD
Well good luck to you then, wish I could help
Yeah I tested both. I wouldn't see why what you said would cause anything.
Randomizing the Transform of the levels would need to be kept in sync of course.
I can try what you wrote later
See if that breaks
Could be the version youre on. I designed a game around level instancing years ago, it was buggy as hell. Then i looked in the source code and found a bunch of //todos lol. Turns out it was an unfinished feature and I had to scrap my whole game
If you arent fully up to date, could be that your level instancing in the engine is a bit buggy
Well if they find a repro for their issue then it should be possible to just submit a bug report
Same maybe they fixed it in the newer versions latly updated to 5.3.2 and i think it still had that issue
So basically really quick setup the event is getting called by a Repnotify. I was wrong originaly I DID NOT overwrite the level name however that does not seem to change anything in My Case/ (I also did a bunch of A/B testing back when i couldnt get it to work so im almost certain I had a setup with it properly back then anyways
Next here is just a really quick setup of an actor that should only change material if the server tells it to
That's a bad test though
Authority doesn't properly limit to Server
And a Multicast can be missed like this.
and here is the outcome
You'd need to make sure that this is guarded by IsServer and using a RepNotify
its not a multicast its repnotify
The material is not a repnotify
as I said quick setup i waited for the inizialization
but if you want to ill change it
Again, that setup itself is flawed though. Multicast on BeginPlay is not a good idea
imma change it and its gonna be the same outcome
that was just a test actor i created in 2 sec
changing permanent state with multicasts is unreliable and can (will) introduce issues in synchronizing state
Specially on BeginPlay where the Client will just miss the event
I know normally I wouldnt have choosen to do that
I made sure to wait until everything is fully inizialized HOWEVEr
I was wrong
Updating my example actually fixed the issue if the Overwrite name is set correctly I guess I was just an Idiot
One last thing I get why Multicasting on begin play is horrible but what is wrong with the has authority check? Replicated Actors getting spawned are automatically owned by the Server thus it should directly have authority over it
Despite some initial lag for the client to actually react to the OnRep, this works fine.
This is now a randomized (by server) Location and Rotation and a randomized (by Server) Material (picked from an Array) via OnRep in an Actor that is in said Level. And that "loops" Load and Unload every 2 and 5 seconds.
Cause you are spawning the level locally, I would assume the Actor also spawns locally.
You can check if Authority prints true for both in that special case of spawning a replicated actor via spawning a level instance
In other cases you'd be probably right
The initial replication lag that is visible in my video can also be skipped by simply setting the actor to NOT NetLoadOnClient
That way it will simply not be loaded and only spawned through replication, similar to how a runtime spawned actor would behave.
I assume the visible lag comes from the RPC to spawn the level being processed first before the OnRep data comes in a bit later
You are right that does make sense (Even tho it didnt make a differrence the is server check definetly is better in this case 100%)
I feel like a fucking Idiot now lmfao tried to get this to work a year ago for so fucking long turns out im just beyond stupid and got completly lost
Hey, no one said there aren't any actual bugs in this system.
And it's also not really documented well enough to not make these mistakes.
Don't call yourself stupid. If at all inexperienced in this specific topic.
Thanks for the kind words.. The Documentation part is definetly true... Stuff like that just happens the stupid part was mostly aimed around the tons of systems I developed to work as a "work" around and the time i have spent to create them
since the fix literally was just a string and a button press that takes like 5 sec
lmfao
Glad that you find a fix for your issue as well!
Bro I am crying literally,
In the picture you have a function that will basically print as a server/ a client if it has access to a data from the Struct that each player has, initially the client has the data of the server's struct, but doesn`t have access to a widget from the server carachter , after it recalls for a bit the same on Rep Function, the client won't have the server's struct, but will have access to the widget of the server character, how the fuq is this even posibbleeeeee
this is cursed
Do yourself a favour, remove all of the code there relating to the UI.
Widget should be updating itself, not waiting for gamecode to tell it what to do
what do you mean it should be updating by itself ?
A good practice you can choose to follow is that game code should be agnostic to UI, thatβs what he means
You could just as easily broadcast a delegate there and have your UI listen for it instead. Observer pattern works really well for UI
Wouldn't even bother with a delegate
Tick it
ez
get the info from whatever character the widget is assigned to
Im following a course, yet theres something i dont understand the instructor is doing.
In the course a section of a cpp file is written like this:
void USCombatComponent::SetAiming(bool bIsAiming)
{
if (PlayerCharacter && PlayerCharacter -> HasAuthority())
{
bAiming = bIsAiming;
}
ServerSetAiming(bIsAiming);
if (PlayerCharacter)
{
// The ternary operator if __________ is true or false
PlayerCharacter -> GetCharacterMovement() -> MaxWalkSpeed = bIsAiming ? AimWalkSpeed : BaseWalkSpeed;
}
}
void USCombatComponent::ServerSetAiming_Implementation(bool bIsAiming)
{
bAiming = bIsAiming;
}
We first check if its a server, if it is, we can just set bAiming to bIsAiming, but if its a client we need a server side rpc, so that the server gets a message that client wants to do this, if its a client calling the set aiming func. So then the first if-statement is not done, and move on to calling the RPC. But if its the server calling we do both the if-statement cuz its true, but we also call the RPC, isnt that stupid and more expensive as we call an RPC, dont we then set bAiming to bIsAiming twice, cant we rewrite the code to this:
void USCombatComponent::SetAiming(bool bIsAiming)
{
if (PlayerCharacter && PlayerCharacter -> HasAuthority())
{
bAiming = bIsAiming;
}
else if (!PlayerCharacter -> HasAuthority())
{
ServerSetAiming(bIsAiming);
}
if (PlayerCharacter)
{
// The ternary operator if __________ is true or false
PlayerCharacter -> GetCharacterMovement() -> MaxWalkSpeed = bIsAiming ? AimWalkSpeed : BaseWalkSpeed;
}
}
void USCombatComponent::ServerSetAiming_Implementation(bool bIsAiming)
{
bAiming = bIsAiming;
}
Or am i missing something?
It all looks weird, but you have the right idea. The first way didnβt make sense.
You could also just call the server RPC anyway because a server RPC in the context of the server has practically the same exact cost as any other script function call. It doesnβt send over the network or anything
In your second way youβre also checking if PlayerCharacter is valid in the first if statement, but then if that if statement fails ( meaning it may be invalid), your else statement gets called and would endure a nullptr exception.
Okay thank you for clearing it up π
Hello everyone. I was experimenting with replicating subobjects inside my actors/actor components, and I was able to get the basics working. But what if I have a TArray of object pointers? is replicating the array enough, or do I manually need to iterate over the array elements and call Channel->ReplicateSubobject inside the ReplicateSubobjects function?
Each object inside of the array needs to be added to the replicated subobject list
It was made by someone who was already very popular in the Roblox community and already had a fanbase. (I know, very late response, but I honestly don't know how my #multiplayer channel ended up on this part of the chat)
So, not really "luck" per se.
Hello! I am having an issue with setting up my replication. So, I have implemented dashing )launching the character) and wallrunning. I can do every movement just fine on the server version, but on the client, I cannot dash or jump off of walls. Are there ways to fix this?
Thanks for the info
I'm not entirely sure this is where to ask, but can anyone point me to learning material or general info on player data storage and loading for online games running on dedicated server? I imagine local storage, ie save files, are easy to manipulate for cheating.
It depends on how you're intending to operate the game.
If the only way the players can play is by playing on dedicated servers that you are in control of and are hosting, then you'd probably want to use some kind of database system and all data is read and write from your servers, never directly by players. This is the most secure means of handling persistent storage of player data and prevents players from directly modifying any of their, or other player's data, but because you are the only one hosting the servers, it can be very costly since you have to pay for those server costs.
If you're going to be distributing the server executable so anyone can run their own dedicated servers, then you would probably want to use save game files, but then the data would only be present on that particular server. In this scenario only the player hosting the server could potentially manipulate the save data, but since it's on that one particular server, it's not really a problem.
If you're wanting players to be able to continue with their character on any player hosted servers, then you would have to let them save either locally through save games and then RPC their save data to the server when they connect, or I believe you can use Steam or EOS to store some player data, but either of these methods could potentially be compromised. Since a player has to tell the server the data, that's an easy attack vector for telling the server fake data without having to manipulate their save file at all.
Rule of thumb:
If you want your player data to be completely secure, you have to be the one in charge of the servers that save and load the data. This way, you know what the servers are doing is legitimate since you're in control of them.
If you want players to be able to host their own servers or even use single player and upload their data somewhere, the data could be compromised or spoofed, no matter what you do.
Tyvm for the detailed response.
I suppose the second option would be what I aim for on this. Though I would still be interested in learning more about the first option as well at some point.
As for using save game files, can you point me to any material on this if it's not just saving through server rpc as opposed to local lol.
I have no idea how to phrase any of this so currently my research has been pretty useless.
If you're going with the second option, then you'd usually only save data that the server already has and save and load on it like you would a regular single player game and any resources about saving would work for your goal, just be sure that you're only doing saving and loading on the server (no RPC should be needed!). Generally speaking, you'd probably have either a timer set up running on the server to save at regular intervals or by some sort of trigger that clients wouldn't have direct control of - like if the player is logging out of the game you'd probably want to save their details when they're logging out, and loading their data you'd handle when they join.
Hi, I'm having some trouble with a replicated variable
I have a struct that's set to replicate, and I give it some data via a server function
I check the BP debugger, and the data is indeed correctly replicated across all clients
However, when I try to acces that data from the HUD class of one of my players, suddenly there's nothing in the data anymore...
You sure you're not just failing at the start?
you aren't checkign that the cast is ok
if this is a binding, it'll be spamming at the very beginning of the game and playerstate might not be replicated out yet
the cast can't fail, the PlayerState is set to be of class PlayerStateCustom in the GameMode
And it's not a binding, I am calling "Refresh Own Hand" at the end of the draw
and it fails all the time?
It doesn't fail, it says the hand is size 0
It doesn't seem to make much sense that you're adding a card and then calling a server RPC when this loop is completed.
If you want things to replicate, it has to be done on the server to begin with.
that looks like a gate on LocallyControlled
How do I get the number of public connections of a multiplayer session? I know how to get the number of connected players, but I want to disable certain interactions until (number connected players) = (public connections)
in-> locallycontroleld? -> tell the server to do it (back to in on server)
Show more of this
the event being called RPC is a naming fail, it's not actually an RPC
It says right on it... "Replicated to Server (if owning client)". That's an RPC. Either way, the rest of this code is running on the server to begin with?
Curious on this as I have a similar interest in this topic, when you say RPC isnβt needed, would that imply that the saving would be handled by the game mode for example , say on post login or something like that ? Or maybe even on begin play of a character send the game mode a messgae to load the data ?
To ask the server to do something or send it any info, an RPC (run on server event) is needed somewhere.
This problem is either some array-within-BP-struct shenanigans or the code path doesn't actually result in what they'd want. Impossible to tell without seeing more of the code. I wouldn't rely on the BP debugger.
Events can trigger on the server independently from a client telling the server. If your intention is to allow a client to arbitrarily tell the server to do something, then you'd use an RPC to do so. Saving isn't something you probably wouldn't want to put in direct control of clients. And yes, something like Begin Play on the GameMode is one place that is certain to only trigger on the server, but almost all events you can use some testing to ensure that you're executing on the server.
- GameState asks both PlayerStates to draw cards
- PlayerState executes the drawing logic, then notifies GameState that cards have been draw
- The GameState then asks both PlayerStates to update their HUD
- The PlayerStates asks the HUD to update, and the HUD executes the "Refresh Hand" function
GameMode doesn't exist on clients, so they can't RPC values to the server that exist on the game mode.
I'm not using the GameMode here
Why is this within a function that'll only ever run on server?
And you're letting the client tell the server the max number of cards which is also a problem.
This function is executed on server
Yea all makes sense. I assumed doing saving / loading in the game mode would be one of the only methods in doing something like that , and thought of the on post login event as an example.
It looks like you have a lot of stuff that's set up as rpcs that doesn't need to be
yeah I'm still really confused about the whole thing tbh
Then this funciton here shouldn't be marked as an RPC. Nesting RPCs is bad form and you can end up with unintended behaviors or ways in which the client can ask the sever to do things that you didn't intend for them to be able to.
If it's a server-initiated draw then nothing needs to be. It can just be code running on server and an onrep to let clients know something changed. Multicast to play the anim can work but onrep will be more reliable
I see
I don't see anything here that'd actually break it though, I think the run on server events would still work.
It looks more like they're trying to update the UI via a client RPC which may not have the replicated property by the time the RPC is received.
yeah
too bad BP onreps don't have all sorts of nice stuff like timestamps or whatever
@stuck hareStart by printing the hand or size of hand on tick or a timer locally everywhere. You gotta find out if you're just trying to check before the data changes, or if the data isn't changing.
But yeah, this could be 0 rpcs and a RepNotify here
you'd basically change from:
"The data changed, I will now broadcast to everyone to update UI, and hope that they get the new data before the broadcast message"
to
"Hey, update your UI when this data changes. Thanks"
Damn, it works
Simplified the whole thing and used OnRep to notify the HUD
Now it displays the hand correctly
Thanks for the help
wait C++'s one do? how do you get the time stamps
Anyone here using mover in first person perspective? Have you solved the jitter at all? I see that epic has a smoothing method and I've got my camera attached to the mesh that the system is smoothing out but I ran a test at low frame rates and its not smoothing things out at all it seems.
Here's a video I stitched together with the fixed tick set to 15, 30, 60 & 120 fps
does mover have some heuristic for how far it can smooth? it might be unaware of the tickrate
In my fixed tick sim I just always smoothly lerp between the previous and the next without any idea if it was a teleport or not ( will need to change this soon)
you may need to see if mover tries to guess at teleports that it should not lerp
is this meaning the tick rate is set to these values or the fps is locked?
I think the problem might be that it is only smoothing over a single frame. And After looking at the code in FinalizeSmoothingFrame it seems to just update the component to the smoothed out location. I'm guessing that is teleporting but not 100% sure
The fixed tick rate in the network prediction settings is set to these values
{
if (PrimaryVisualComponent)
{
if (SmoothingMode == EMoverSmoothingMode::VisualComponentOffset)
{
// Offset the visual component so it aligns with the smoothed state transform, while leaving the actual root component in place
if (const FMoverDefaultSyncState* MoverState = SyncState->SyncStateCollection.FindDataByType<FMoverDefaultSyncState>())
{
FTransform ActorTransform = FTransform(MoverState->GetOrientation_WorldSpace(), MoverState->GetLocation_WorldSpace(), FVector::OneVector);
PrimaryVisualComponent->SetWorldTransform(BaseVisualComponentTransform * ActorTransform); // smoothed location with base offset applied
}
}
else
{
if (!PrimaryVisualComponent->GetRelativeTransform().Equals(BaseVisualComponentTransform))
{
PrimaryVisualComponent->SetRelativeTransform(BaseVisualComponentTransform);
}
}
}
}```
This is what is called after the Smooth service smooths out the state from the previous frame into the current state
which smoothing mode is it in
Visual Component Offset
Which component here is the visual component used for the offset? I assume the mesh you have the camera attached to?
do you have a special player camera manager that moves the camera in a unique way relative to the pawn root location etc?
Its smoothing the 3rd person mesh and the camera is attached to that
this kind of thing is a great case for visual logging imo, I use that a lot with camera debug
You might be onto something here. Thats what the lyra camera does I believe
it's hard to log jitter otherwise imo
Running a test right now where the pivot for the camera uses the smoothed mesh location instead of the actor location
THIS WAS THE ISSUE! Thanks man!
I'm glad it was that and not something evil in Mover π
Camera managers in multiplayer can be frustrating as there's a lot of competing things and overloads that all want to say something similar but different
like the various ways of getting the view location etc can be used for both where the camera is for... replication prioritization but also for where bullets come from in most games
I didn't even think to look there. Funny thing is earlier in the day I set my smoothed component to be the camera and my camera wouldn't move which should've gave me a hint that it was the issue.
They don't but you can get the old value. Build a timestamp into your data and you'll have a time delta
π
yea I just relaised there's no way to get the old value in bp π
you could just get the local time each time the onrep shows up?
or cache the original value yourself if the timer is from the rep and not local
I wonder if that's somewhat easy to add. hm.
Frustrating because that seems like it would be fairly trivial to add to the engine
I used 0 bp on rep soo far, I don't like the fact it's get called on server.
I would love Epic to auto generate all OnRep functions that exist in C++ and have a supported type for BPs...
OnRep_Owner, OnRep_PlayerState, OnRep_Pawn. Like gimme pls.
The fun thing is that, given they aren't actually OnReps but just "PropertyChangeNotifiers", you could even use them in singleplayer.
Do OnReps in C++ call if the Client changes the value? π€
Probably not, but maybe?
They do in Blueprints iirc.
Also OnReps in Blueprints with Arrays are annoying, cause I think the Add/Remove/etc. nodes don't trigger it properly.
Always had to call the Set w/ Notify on it.
no, not unless you do so manually
Maybe that's fixed by now. Been a long while since I had to do that
and perhaps from a client replay
Yeah makes sense
there may be some onrep flag I am unaware of there
I wonder if the bug is still in the Engine that causes the OnRep to not work if:
- The Blueprint has a boolean (easiest repro) that is false
- The Instance of the Blueprint in the level has the boolean as true
- The Server on BeginPlay sets the boolean to false
Iris might store the previous value differently
Last time I checked that was broken cause the comparison for if the value changed was done with the Archtype and not the instance.
FPropertyReplicationFragment
At least for the first replication something something
Yeah we are a bit far away from using iris atm
And there shouldn't be a reason to set the boolean to false on BeginPlay in this scenario anyway.
So it's an avoidable bug. Still funny.
Let's try
It's honestly tempting to just abuse the hell out of onreps for almost everything
There are some cool concepts in C# that would probably remove the need to abuse OnReps
The only risk is if you lose out from skipping over in-between changes
Like what? I'm in the process of making my own property serialization and I'm open to ideas lol
Pretty sure they have a lot of built in stuff for property changed notifying
Where we in C++ always have to write a delegate
Although I think UMG ViewModels also use this by now
If that matters for a given property, one could always wrap it in a struct and add a uint8 that gets incremented.
Then you'd at least know if the in between change is missing.
I do this a lot but this isn't perfect as you can still risk priority dropping it
of course if it REALLY mattered it could be a reliable π
or a buffer of multiple
it's still by far the best way I've found to mark splits in things that should declare when they are not contiguous
Variables with FieldNotifies or so
a bool bitflag is cheap but you can't really turn it on/off if it gets turned on twice
and it's frustrating to track a local value for an onrep
There must be something you can take for your system @nova wasp
I wonder how far the ViewModel system is by now. But that's a #umg discussion.
Last time I used it it wasn't supporting some things, like Arrays, and I had to drop it again cause I couldn't get to work what I wanted to do with it.
Last project I worked on also has ViewModels but they coded it themselves.
I already have on-set delegates but those are a bit too slow to do en-masse
I could queue them I guess
Yeah so that bug still exists the same way.
- Replicated Actor with InstanceEditable RepNotify Boolean
- Set Boolean to False by default in the Actor BP
- BeginPlay, SwitchHasAuthority, set boolean to False
- Hook up any visualization for the boolean in the OnRep
- I choose to offset a StaticMesh upwards by 50 units if it's true
- Drag two instances into the level
- Set the boolean on one of the instances to true
- Play with 2 Players, ListenServer
Background is the Server, window is the Client.
Left Cube is the one that has the boolean false, right one has it true.
Given the Server sets it to false on BeginPlay, both should be lowered.
Client however doesn't trigger the OnRep because it never gets the false value.
Printing the value on tick shows true for the Client and false for the Server :D
Only gets "fixed" if one delays the Set call long enough for the client to fully setup the Actor locally.
1 second delay, in PIE, is for example not enough. Iirc I debugged this once and the client does receive the data, but doesn't update the variable and thus doens't call the OnRep because it compares the data that comes in with the default value in the class first instead of its own instance value.
Other way to fix it is to not mark the actor as NetLoadOnClient fwiw
But yeah, not that anyone needs that but I recall someone having a setup like this for some Street Blocking Pillars that come out of the ground.
And they had that bug that they set one of them to true on the instance and reset them to false on BeginPlay.
Still a "wrong" setup, but well.
Hi, having some trouble with my multiplayer setup
I have a card game and players can put cards on the field
The data for the fields is RepNotify, and in the OnRep I get both PlayerStates, and ask them to update their HUD to reflect the new data
The issue is that when I run the game, the code that tries to get the PlayerController and the associated HUD in my "RefreshFieldDisplay" doesn't work (accessed None)
Here's the Macro that gets the HUD
From my understanding, OnRep is supposed to be executed on the client only
So all of this code should run on client, and there shouldn't be any issue with trying to access the PlayerController or the HUD
@stuck hare You are, for whatever reason, looping over all PlayerStates as result of the OnRep
The OnRep, given its in the GameState, will execute on each Client (and the Server in Blueprints).
That means that each Client here will loop over all PlayerStates, try to get their PlayerController, the HUD, and Refresh it.
That's totally redundant, cause you are basically trying to refresh another player's HUD that way
Oh I see the issue yeah
Players only have access to their own PlayerController
Also this whole setup is a bit cursed
You shouldn't need to get the HUD like that. Your HUD should get the GameState when it gets created, get the current Field values and then bind to a delegate that you can call from the OnRep
Creating direct call dependencies like you do is not a good idea
That's helpful to know, thanks
I'm running into an issue when implementing this, because I'm trying to bind a delegate in the BeginPlay of the HUD, but that delegate is in PlayerState, which isn't yet created at that time
What I want is for the PlayerState to broadcast the delegate in the OnRep for the hand data, and for the HUD to listen to that and display the correct hand
I'm having trouble finding a way to make that work
Why the PlayerState though if the GameState holds the data
@stuck hare
Your OnRep_Field1 is in the GameState
Put the Delegate/EventDispatcher in there
If the PlayerState isn't valid yet, and you really want the callback to be in there, then you need a callback for when the playerstate becomes valid.
Which usually can be placed into the PlayerController
In theory there is already the OnRep_PlayerState for that, but you'd need C++ to override that
The GameState delegate for the field works, I'm trying to do the same thing but with the hand data, and that's in the PlayerStates
why gunpartspawn is not triggering
Hi, it's me again
I have this function, which modifies the values of my Field variable, which is RepNotify
This works correctly, and the OnRep is called
Then I have this function in the same class (GameState) that also modifies values inside the Field variable
But for this one, the OnRep doesn't trigger
And I don't understand why
I don't think the for loop gives you a ref
So you are modifying a copy
The array isn't actually changed
ooooooooh right forgot about that
Struct arrays in blueprints are really annoying to work with
You might want to put a SetArrayElement node behind the set member node
Also, make sure to submit often to your source control if those structs are blueprint defined
Blueprint structs are still largely breaking projects
Print the spawn rate variable value
Might be 0
Timers don't work with 0 rate
Yep, that was exactely what the problem was
Thanks a lot
How so?
Pretty sure you can find enough info on the Internet about that
Mostly happens if you alter the definition
Struct nodes then suddenly become littered with guid strings
It's generally adviced to move structs to cpp
Even if you don't know or otherwise want to use cpp
Good to know
Hey @thin stratus remember when we talked about deciding to put stamina on GAS vs CMC because of prediction issues if you put stamina on GAS and kept sprinting on CMC and had to keep them seperate? Is that still the case? We chatted about it 2 years ago and you gave such good advice. I implemented it all on the CMC. wanted to check in before I gave bad advice to Psycode here
Gonna drop this here as well just in case someone else still thinks this is a replication issue or something: #animation message
Yeah, don't think anything changed about that.
hey guys, i have crashes on "findFunctionChecked" from multiple blueprint implementable functions, those functions are on a player controller tha i use for the lobby only which also has steam callbacks implemented. From talking with other used on cpp i assume that the PC is being destroyed before those functions get called and the crash occurs, is there any way to limit steam callbacks? is there any way to check for the existance of the PC before it being destroyed inside itself? do i have to move the steam implementation to another class and if yes what class would be a good one?
You need to check the validity of your PC before calling anything on it
i know that, but those functions are inside the pc itself
would something like "if(this)" even make sense?
Cursed but possible
Who is calling them ?
That is like the worst place to put those
i am assuming they are bing called before initialization and after garbage collection
well i didnt know 
Make a GameInstance subsystem for that
i never messed with subsystems, cant i just put them in the game instance?
well ye, it is my first multiplayer game
Hence why they belong in a subsystem
and im learning by hitting my head on the walls
Online subsystems are completely abstract (kinda- since its also a UE implementation of a SDK) from UE framework, like Matt szid it should all be in a GI SS
how long will it take to get a grasp on ss?
10 minutes
so what do SS have to do with OSS?
Nothing
so its only the name that is similar
Yes
They "subsystem" part is just an indication that they are part of a larger system.
GameInstance Subsystem, is a subsystem of the GameInstance
LocalPlayer Subsystem, is a subsystem of the LocalPlayer
You can have as many Subsystems as you like.
They share the lifetime of their owning system.
A WorldSubsystem is a subsystem that will be created when a World is created.
Are you using rider ?
And destroyed when that World is destroyed.
nop
docs are telling me that there are no world subsystems
are u using that just as an example?
The docs are out of date
maybe the docs are not up to date, i can indeed see that wordl subsystem in the classes
There is absolutely a WorldSubsystem
It even has a Tick function
Well, the TickableWorldSubsystem does
(read benui's subsystems page, not the official docs)
so assuming that im gonan use a game instnace subsystem for steam that means that all those callbacks are gonna be active the whole time, is there anything i need to lookout for because of that?
Quick question: If an online interface doesn't exists for platform, will it return nullptr?
It should, yes.
Or is it guaranteed to return a valid object so I can call .IsValid() ?
Doesnt hurt to just check both.
Cause examples uses IsValid check
Not really. You might just want to verify that Steam is available first etc.
i already have that in my code so it should just be copy past then
it never is but in theory
ye i shouldve used something like that but i started thins project 5 years ago i dont think that it was available back then
weird thing is, why is a EOS plugin being providade by some one other than epic
Epic also provide their own, but like most things with Epic, its incomplete and not well supported.
The RedpointEOS plugin is very very user friendly and extremely well written with extensive documentation and far more additional features than what Epic would ever provide.
Well worth the money.
by the way, steam doesnt have a proper "party" implementation from what ive could find in the documentation, does EOS have that?
What do you mean by "proper"?
people here have suggested beacons
i mean a group of people that join a lobby, in steam lobbies = parties
at least from what i could gather from their documentation
The RedpointEOS plugin solves that for you.
It uses EOS to create "synthetic" parties.
They act identically to parties.
in steam if i join a lobbie im automaticly joining a party
for example if i leave a custom game i am still inside the party because that lobbie was the party
ye i am, its a bit confusing
It is, so stop doing that
Fair enough
Party management is on you though as the developer, nothing in UE is setup to automatically do those things for you.
Thats got nothing to really do with EOS
More to do with latency of the clients
But its responsive as any other service
im asking because i recently started playing age of empires 4 and it has cross platform and the invites seem to be slower
I wouldnt worry about that stuff if I was you.
If you are running on Steam, its going to use the Steam subsystem anyway
but i was using eos and sent an invite to a steam friend
wouldnt there be a delay?
wouldnt the 2 systems have to comunicate?
im asking out of pure ignorance really
Well yeah, but thats all abstracted away from you.
Thats the point of EOS
EOS is agnostic of the platform
Which is what makes it easy to implement crossplatform functionality
Some games in steam offers a player count in friends list. For example "In Lobby 3/4", is that a feature or just updating session description with plain text?
from what ive see its jsut plain text
Thats all on you, you need to update the rich presence stuff
Thats not automatic
So like, if you want it to show up in Discord, you need to add the Discord SDK to your game and push rich presence updates to it as a platform.
Same with Steam.
Same with EGS (if thats even a thing)
Etc etc
Those things are what RedpointEOS plugin makes easy for you
It has features for managing that stuff
On your behalf.
So you mean it's manual? Like no interface for it?
No, i mean its not just going to magically do it for you because you are running the game on Discord
You use the OSS API for the platform to update those things
I get that, I just wondered if that's a separate feature that I need to deal with or just something like session description
Its like updating the session information yes.
But instead of for a session, its for a user.
Like, the Host might want to display "Hosting a Game on SomeMap"
Where connected clients might want
"Playing a Game on SomeMap"
You update the users presence information to reflect what should be displayed when someone views that information.
Like in a friends list or whatever
I think I'm gonna take a look at both RedpointEOS and AdvancedSessions source code to figure out some of these stuff
I don't need it to be too advanced, I just need a few specific feature
RedpointEOS has a free version
Cant remember what restrictions are applied to it though
Probably no source code access.
How can a plugin be installed without source code tho? Is it even allowed by UE?
Getting started with the EOS Online Subsystem plugin for Unreal Engine.
Its not distributed through the Marketplace
Its just a compiled Binary.
You can only use it with the Launcher Engines
Its designed to be a demo basically.
so im implementing the subsystem, what would be the equivalent of beginplay in the ss?
Initialize()
ty
Tho it's not exactly same thing as beginplay
If you specifically need beginplay you need to bind it afaik
if it doesnt behave as expected i will look for something closer to begin play
it should probably be fine
Yeah, just it will be called before any world is created
So you can't do actor stuff
You should not need BeginPlay if you are doing Steam integration stuff
i was getting the current lobby ID evrytime i went back to lobby but it shouldnt be nescessary now ye
im just copy pasting code to be safe hahah
...or MP in general 
Not sure what you mean exactly
That makes sense, but what I don't get is:
It is designed to be C++ only, right? How it can be used without any source code?
I didn't even see header fles
i rarely use beginplay in MP stuff because of race conditions
hey, I'm having an issue that's probably easy to solve, but I'm just missing something. When I call ServerTravel, all works nice and smoothly for the Host, Essentially on BeginPlay in that level I run a sequencer with a cutscene. But for the Client, It first shows a view from 0,0,0 location, I can see the whole world loading, and then only after a while it loads into a cutscene. The easiest solution, would be to just hide it behind a fake loading screen widget, but the PlayerController loads after a while, so I still see the world loading. Any idea what to do? I'm using the loading screens plugin as well, but it doesn't seem to do much help, as for the client, it stops before everything is loaded
Generally speaking its a good idea to force clients to wait a few seconds after they are technically loaded into the world before bringing down the loading screen.
Because of stuff like texture streaming etc
It can still appear as though they are loading, when they are infact just streaming and have been loaded already.
You might want to also then trigger the cutscene when the LS comes down
Instead of on BeginPlay
Loading into a level in MP is a tricky buisness to get right.
ill try to mess around with the settings, and maybe I'll be able to modify the plugin a little bit, and add extra time to loading screen after it's technically loaded, could work
Not sure which loading screen plugin you're referring to. But if you're not I would recommend using CommonLoadingScreen from the Lyra project. By default it will show a loading screen for any transition reason. And on top of this you can very easily(even in BP) create a LoadingScreenProcessTask which will keep the loading screen up. You can have one or many tasks, so each system can request the loading screen and it will only drop once every system has initialized and removed their loading screen task.
does anyone know if you have an array set to repnotify if "adding/removing" fires the event ? or would i need to be having the array already populated and then anytime 1 of the already populated indexes changes it would fire?
why does this work when its connect to a keybind?
when Player loaded is called on Event Begin Play it only seems to properly work on the server and not the client. (doesnt work correctly)
Players To Load is set at 2, thats why key bind calls it twice (it only calls once on event begin play)
any help would be great, thanks!
If I remember right, it does. Easy thing to test yourself.
lol yea thought of that right as i hit send, and did, and it does in fact fire
Don't use multicasts to replicate state. Use replicated variables or OnReps if you want something to happen when the replicated value is received.
This is also kind of a wierd set up. You have Begin Play of PlayerState to know when players enter the game. You have the Player Array in the GameState to get a list of all players in the game and the length of that array should be the number of players.
Hello everyone π What is the best way to handle continuous events in UE5? For example, if I need to send an event to signal the start of a series of blueprint nodes, that's relatively straightforward, but how can I manage the position of a monster that changes in real-time on the map? Is it necessary to send the monster's position to the clients every tick and update it just as frequently (or at a frequency aligned with the information packets being sent)? Or is there a more efficient approach to synchronizing this type of real-time data between the server and clients in UE5? Thank you so much to anyone who can help me π β€οΈ
Yeah, I am just setting the variable for testing reasons.
I was doing this in the GameState, still your suggestion doesnt change much.... it seems ive tried a lot and no resolution
What is it you're even trying to do as it's not exactly clear from your screenshots.
Begin Play fires on both the client and the server... If you have it triggering on Begin Play of the character, then every client will be attempting to send RPCs to the server on actors they can't send RPCs on as they won't be the owner of....
You don't necessarily need RPCs even from the client to the server... The sever will already know how many players there are in the game and you shouldn't rely on clients telling the server that another player joined, lest you end up with clients telling the server too many times, or not enough times at all (clients can spoof and block RPCs from being sent)
The multicast doesn't make sense seeing as it's meant to set what looks like a replicated variable and then do things with it - only the server would likely need to execute this.
i got it working
the client also needs to know when all players have been loaded?
multicast would let the client know the server has made those changes?? unless im misunderstanding.
i've switched to using the player controller begin play as its local apparently and that seems to have worked!
thanks for your help :)
You're relying on communication between clients to tell other clients that they've joined which isn't reliable - again clients can spoof telling the server that more players joined or prevent the message from going to the server at all.
Begin Play of playerstates will happen on clients and the server when a player joins the game.
The server creates and replicate PlayerStates as needed for each player in the game. This also means you don't need the server to explicitly tell everyone that someone new joined as you effectively can tell this is happening already when the PlayerState begin play fires on a client.
Players being "loaded" is also not really what is happening here - all you're basically doing is allowing the clients to tell the server "hey" when their begin play fires and that's about it which is mostly useless. It means nothing in terms of actually loading that player on the other clients, and it actually being ready anywhere else other than on that one client, so it may not be ready on any other clients.
The only reliable way you can know if a player exists on a client is if their playerstate is present.
got it, that makes a lot more sense.
i just need to keep all players in sync, same audio being played at the same time, and same time other events are called.
ive read that the best way to do it was like this
@errant charm time relevant to what though? Certainly not real time as delay exist.
synchronizing events as close as possible despite delays, the server was already ahead and the client spawned in a a few seconds later. all i want to do is make sure all players are ready and connected before starting any gameplay.
i might be misunderstanding your question tho
Yeah in multiplayer, you'll never usually be 100% in sync. You can usually only rely on the current state on the server and that means having the server enforce that state via variables, not by events (like RPCs and Multicasts).
The way around this, if you're basically in the map where players are going to be playing, you would probably want to start up a timer that can briefly wait for players to join before starting the match, but if they aren't ready by the time the timer is up, too bad, start the match anyway as you can't rely on clients to actually send you that they are ready.
When a player joins, you can have them RPC to the server on their playerstate and have it set a ready to play bool. You can then check if the correct number of playerstates are present and if they all have their "ready to play" bool set true and if so, end the timer and start the match then so that players don't have to wait for the full duration of the timer. Under normal circumstances, assuming everyone has a sufficient computer, the delay should only ever be brief before the game starts up.
Unreal netcode in the common case is based around sending replicated properties intermittently of the latest state from the server + RPCs with data
being in sync 100% is not really a thing as much as being close enough... It definitely makes sense to wait for clients to be ready to start gameplay though
I agree with Datura's idea of a timeout that can be skipped if everyone says they are ready somehow
Ok! That sounds like a much better approach, Iβll give it a try
Thanks for your help guys :)
Can I get some help on this conversation? It's a few messages
#cpp message
Why do you have to use it?
Each machine will have their own GI and it is not replicated.
I wanna manage the online interactions like Host, Join, Leave for game running on local machine
When a computer run unreal application, a GI is made for it and destroyed when application terminated
Isn't it same lifetime with LocalPlayer assuming no split screen?
Yeah but you don't really need to replicate the GI?
No idea with local player I don't use it. But gi life time is through out the app
I thought I could interact with something else for parts that needs replication. Like PC
Hosting , browsing, that's all local. You are not in any server
You just run codes to get the session info
Or to create one
Only when you join a server or host one then replication matters
Yeah, my thought was more like "If I need replication for some parts..."
Which probably won't be related to sessions, but relevant to that local player
I prob don't have the answer but if you can be specific on the some parts, maybe someone can give a pointer
For example chat messages. You'd want a chat for in game UI, but if online stuff is managed by that GI, you need to get back into replication somehow
For that you'd need to be in a MP game so state needed as well
Chat massages in game only? Or are we talking about Chat massages in game browser where players haven't join a server yet?
You can use anything I suppose. Even an actor
Or world subsystem?
I would probably just use an actor because it can be replicated
But assuming online stuff is abstracted by that GI
Not sure I'm following because you only can chat with people in the session
Why do you need to involve something that have lifetime outside of the level?
Basically I want something to abstract online related stuff except gameplay reflection
By abstracting I mean abstracting it for that specific game, so you don't need to interact with generic interfaces
If I use GI SS for that, then for some stuff requiring reflection, I need to get back into reflection (assuming something requires it)
I thought best way to do it would be telling PC to do it since it's replicated
--
With that setup, In UI code, I wouldn't ask for SearchServers(PlayerCount, Settings, ...);
Instead I'd do FetchServers();
Does that makes sense?
In other terms abstracting boilerplate into a single class
That's beyond my basic knowledge, hopefully someone else have 2 cents
The reason to use a LocalPlayer Subsystem is that you may have multiple local players on a single game instance, which is the case for any local multiplayer game.
You can use the GI or GI Subsytems for handling online things not pertaining to the actual connection to a game server since it isn't replicated.
If you want to communicate to the server from the GI or GI Subsystem you have a couple of options, like Beacons (which can make connections to game servers before having the client actually connect to the game server for the game-related stuff), other third party connections (having data transferred via socket connections, or communicating through REST APIs etc.) or once connected to a game server like normal, route your data through a replicated actor.
As far as I understand beacons are a lightweight connection before the full blown one? But why do I need beacons, if I join and don't travel to the level?
Correct... It's a means of communicating some data between a client and server before a full blown connection.
What type of data would that be, that doesnt already exist in a session result?
My immediate thought was ping check but thats already in the session result π
Anything really and it can continually be updated where session results I don't think are without additional polling. Could potentially be used for a chat system prior to joining the game on that server, facilitate communications of a lobby system before players are foced to travel to the server...
I've never really messed around with them myself so I'm not sure of the really good usecases.
Sounds like you found some already
They are mostly used for 2 things:
- A lobby system into which you can invite your friends while staying in the main menu. Think of Fortnite, Overwatch, etc.
- Reserving slots on a Dedicated Server
Now the second one I haven't used, but I think James used them for Hell Let Loose or so.
You basically create the quick connection to check if the Server is actually full or not (cause people could be connecting), and if it is full you can stay in the lightweight connection, waiting for a slot to open up. Once the slot is open, the Server can reserve it for you (decline everyone else) and tell you to connect.
Something like that. Probably some more things one can do with them.
Unreal Tournament on GitHub has some old sample code for that.
replicated subsystems would be really nice
i find myself using actors that really only exist to allow replication of messages and such
Do you really need lobbies? I mean for matchmaking based games, sure they makes sense. But for everything else, why would you have them?
Also for second use case: Joining and travelling to the host's world are 2 different steps, right?
So why do you need to reserve space?
Does anybody know how Lyra does aimoffset replication? I have a top down game with aimoffsets and turn in place animations, and even though I got it to work well enough on the server, it's completely messed up on clients. And I'm definitely spamming the network.
You need lobbies if you need lobbies. Not sure what the question is.
Don't know how that exactly works but it is what it is
AimOffset is usually done via GetBaseAimRotation function of the pawn and then the animation blueprint should have a node to calculate the offset
Thanks @thin stratus , I will take a look at that
just make a gamestate component
@thin stratus I looked at the function you pointed out, but I'm not sure it fits my game. It's a third person top down game, so the aim offset is not calculated using the controller rotation. But that's ok, I already have a function that calculates the aim offset. My question is more along the lines of how to replicate the calculated value, since it depends on the gamepad input/mouse position, and that's not available on the server. Currently, I'm using an RPC to send the calculated aimoffset to the server, but I'm concerned it might be spamming the network since that happens on every tick, and I'm wondering if there are ways to optimize that. Plus, there's a really weird bug that happens when the turn in place animation kicks in. Since it changes the character rotation, which in turn changes the aim offset, that causes a bizarre cascade effect in simulated proxies
You won't get around sending information to the Server that the Server doesn't have.
Only thing to optimize here is to minimize the amount of data you need to send for this.
I see. Is there perhaps a way to throttle RPCs? Or do I have to build some timer myself? I don't really need to send aimoffset to the server on every tick, I suppose. I suppose I could send it every X milliseconds and then interpolate things on the server or something to make it appear smooth π€
Doing something expensive every frame vs every 5th frame doesn't make it less expensive