#multiplayer
1 messages · Page 103 of 1
Oh welll I created combat systems , kinda fixed the scaling problem ,and the other problems . just want to know about the dedicated servers , and I am kinda using the listen server type now
I'm joking
Free to play MMO is probably the most difficult type of game to make and operate successfully.
Is there a way to make a dedicated server without leasing a server from someone?
And therein lies the thing - don't worry about packaging a dedicated server yet if you're not even sure that's what you're going to be able to do or what your game actually needs.
You have only 3 options in terms of "servers" for Unreal
A) You are going to create dedicated server executables yourself for running on your own hardware (whether rented out from a hosting provider like AWS or DigitalOcean, which'll end up costing you $$$$$) - this also has the extra fun work of having some kind of back end that can start up instances of your dedicated server executable for you, such as AWS GameLift or PlayFab.
B) You are going to distribute the dedicated server executables so the public can run them and they can run it on whatever hardware they want (which'll end up costing you nothing) - this also means that player data can't be saved online anywhere and each server would have its own save data.
C) This can be used in conjunction with B above, and that is allow players to host listen servers which may have limited capabilities, especially so trying to do so with Android.
Again, as it stands, you may want to start looking into #online-subsystems which is a means for finding (not hosting!) games that players are running. Online Subsystems are what provide you with the server lists you see in multiplayer games that allow players to easily connect.
You sort of need to know how players are going to connect before you can start making the thing they are going to connect to.
Also if you have an extra PC at home then you can turn it into a dedicated server but just a heads up your Internet connection will suffer.
B , C are nice , And yeah I know about online subsystem , I'm using redpoint's eos sub
oh how?
by building a dedicated server target
and how to do the B
..?
A "dedicated server" is nothing more than an executable in terms of Unreal. That executable can be run on whatever hardware you want.
there's pages on the unreal engine docs about that
im making lunch right now but im sure you can find it yourself
oh
How to do the B here?
You really need to go off and read things
All of the questions you are asking are very googleable
Well I did , I got confused
Datura and Lawlster seems like they are very experienced guys , What they say are more understandable and less confusing
People also don't like hand holding too much
Some of these questions you ask take an in-depth answer.
Distributing a server executable is just like distributing your game's executable
When ready to release your game, you'd make a dedicated server package. After you've packaged it, you give it out, probably through a website. Players then would download and launch it on whatever hardware they want. The more difficult part comes in with making sure that your game is actually set up to handle using dedicated servers (eg. a dedicated server would need to broadcast to your online subsystem of choice that its active, you need a means for players to configure their servers, etc.)
To be honest, I don't really know the process for packaging a game but I imagine using an appropriate guide somewhere it would be easy enough to do.
@keen hound a dedicated server can support as many players as the hardware and Wi-Fi connection of the equipment the server is running on can handle
So just to clarify Server travel is the only way to have a dedicated server travel n bring the clients correct? Anyone have an example of this?
Enabliing Seamless Travel will cause Players to follow the Server to the new Level
Otherwise they are disconnected.
You can execute the console command ServerTravel in Blueprint or alternatively simply call the ServerTravel function in C++
There maybe even a Blueprint node for it now, I dont know.
@fossil spoke unless I’m doing something wrong. I have a dedicated server with 2 clients joined. Within the GameMode bp after 5 seconds just to test I call Open Level with a given map name n no options. I have seamless travel enabled and when I open the level the clients never join. I know this because I have the server print in intervals the current player count
Oh so I should use the execute command bp
Instead
Yes use ServerTravel not OpenLevel
Ty
OpenLevel is for ClientTravel
I used open level previously for listen servers but I imagine that’s a different process
If a server crashes, it won't - that's the whole problem with a crash. You probably want to automatically save periodically so too much data isn't lost.
Anyone have any experience with the general movement component? Is it (or something like it) needed to ensure proper multiplayer movement replication like everyone I see online say?
The Character Movement component that is included with Unreal handles basic movement prediction and replication for you already.
You can add to it as well, but it does require C++ to do properly.
yes but i've just heard from other game devs that it wont be as smooth/professional feeling if there isn't additonal network prediction going on. I've been recommended the GMC (general movement component) although, it is quite expensive. and i don't know C++, so something like the GMC may be needed for myself. but only if this is actually needed for proper character movement for say a shooter game mulitplayer?
CMC handles prediction and it does pretty well, smooth even with 250-500 ping 4% packet loss.
You probably would still need to modify any movement component if you're trying to advanced forms of movement, like wall running or even sprinting. The GMC may handle some additional forms of movement, but I doubt that it's something you can do in blueprints alone. Their tutorials they have are also limited to things that the CMC already does (like Grounded and Swimming movement modes). Their "Advanced" grounded movement tutorial is a "Jump" tutorial - again something built into the CMC already and is already handled in blueprints easily.
If you're attempting to do multiplayer, you should be willing to dive even a little bit into C++ as there's some things you just can't do well or at all without C++, and it's not just about optimizations, it's also about features that you'd probably want to use or functions and events that you need to handle in your own way that you can't do in blueprints.
A basic shooter could just need walking and sprinting, with crouching optional (which I believe the CMC can also handle). It's when you expand beyond that where it gets muddy. If anything, before investing $500 into a plugin that you're not even sure about using, try building with what is freely available and see how it works out. There's nothing wrong with refactoring if you eventually decide that you need to use the GMC.
Now, I can't speak about performance in larger games with more players or anything like that... They may claim that the GMC may do it better, but I wouldn't know any better.
anyone able to quikcly help me set up my messaging system cause this doesnt work properly
i have a chatbubble component on my pawn(this is pawnBP in pic). i have a chatbubble widget (parent class is the chatbubble component) and chatbubble result widget(shows text written) and it is added to chatbubble widget as a child. currently if i enter a message it spawns on owning chatbubble component on owning players screen, but on other clients screen it spawns on their chatbubble component. On top of that, it only works for the first message written, then stops showing any more messages in the bubble.
This is all very helpful. I appreciate your thoughtful responses. I’m actually using sprite characters , they really only jump and sprint. I would be willing to learn some C++ but I have yet to run into anything that requires it (not including performance)
Only thing I can see is there is no owning player on the widget but it might not be relevant, but then again not sure what’s going on enough to know
Player Inputs Chat Message > Message is RPC'd to Server through Component (hopefully the component is attached to the character or playerstate) > Multicast the message through the component > Multicast is received on the client, the component updates its widget with the new text value that was sent, sets its visibility, etc.
Your first issue is again stemming from Get All Widgets of Class - you don't know which widget it is that you're getting if there's more than one in memory.
The second issue is if the reference is valid (which it would be after the first run through) you're just removing the widget you created from the screen - you're not doing anything to update it.
If you're using Playfab for chat though, I'm not sure what their process is for handling any sort of chat messages through their system (if they have any such feature) and you'd have to figure out what player sent which message so that you can properly get the right player's widget so you can display the text properly.
alright thanks let me do some thinkin
the top row is for a public chat box that shows everyones text, the bottom row is the chat bubble im trying to set up.
this is the rep notify message 0
its still doing the same thing
shows message on opposite player not the owning player on client 2's screen
It's still doing the same thing as you're still using "Get All Widgets of Class".
You need a reference to the specific chat bubble that you want the message to appear on.
wuts the deal with this
Question, how do y'all deal with replicating the shooting of automatic guns to other clients
i.e. player tap fires twice, how do you replicate exactly two shots
i'm trying to steer away from multicast rpcs in this scenario
but i feel like a simple shooting flag might lead to players seeing more than two shots
for the owning client's shot replication im thinking unreliable rpcs sending shots with timestamp & any necessary data to the server
re-sending them until ack'd
I have multiplayer survival game similar to Rust, Dayz or Ark. What server speeds are usually good?
[/Script/Engine.Player]
ConfiguredInternetSpeed=500000
ConfiguredLanSpeed=500000
[/Script/Engine.GameNetworkManager]
TotalNetBandwidth=1000000
MaxDynamicBandwidth=100000
MinDynamicBandwidth=20000
[/Script/OnlineSubsystemUtils.IpNetDriver]
MaxClientRate=1000000
MaxInternetClientRate=1000000
NetServerMaxTickRate=30
These are my.
And for tick rate how small I should go? For example some fast games like warzone can run 12 tickrate. My survival game involves combat and shooting but you see enemy players like couple times per hour.
if i gotta message struct and a chat bubble widget, how do i replicate it properly
over the proper client
Ain't Jambax got an article on the subject?
A Multicast/Client rpc will do it. You could also replicate what needs replication of that struct.
iirc GameMode has a function called Say that emulates that
this is rpc'd and its spawning the entered chat over the wrong user on the other clients window
in the entered chat owning player window, its over the owner as it should be and on the other clients window its on that owner
If it's totally unrelated plz forgive me
(I never read it, but I know it exists)
Nah it's perfect
Gives me some ideas
Tyty
any ideas
Sorry dude, I don't do homeworks
Hey I have a client playing a sound, I want to multicast it but exclude the client, as he gets his own client sound
this does not work, it plays twice still
although it should work?
Hello everyone! Do you tried to make same function as AIMoveTo, but for player character? We have SimpleMoveToLocation but it works on a client only
Sorry, just to go back to what we were talking about earlier. I'm still not 100% sure what I should be doing with my code to make it so the clients/server have the respective winner/loss screen
I assume you have those onreps on something like a playerstate or pawn etc. right? You could store a non replicated variable indicating whether or not to display the name, health or whatever and then use that 🙂
If it needs to be persistent you could still do the same but then you need to make sure players are in some way identifiable.
If you for example have 3 players you would have 9 player pawns in total, despite that I’m aware that might sound a little strange at first. Each client/device has its own version of a world with 3 pawns in that case. If one client says I want to hide “player 2”’s name then they set for example that bool to false on that specific character. Because the variable is not replicated only they will ever see that variable being changed.
if i call a multicast in the gameState, does it get called in the local machines? im asking this because im not sure if theres any wonership and there has to be some sort of ownership for rpcs to go through
As long as the multicast is called from the server it will yes. Ownership does not matter for multicasts. Keep in mind that relevancy is still important though.
so the game state is a server owned actor i assume then?
or not owned at all
I don't think it has an owner at all yeah. But it's maintained by the server yes.
im just trying to figure out the best way to let player know some one joined
im a bit confused, i thought about running the rpc in the game mode, but the game mode doesnt exist in the clients so it would run right? am i missing something?
It depends on what you want to use that information for I suppose. Normally you would wait for something to happen. If for example a new PlayerState object is created a client can assume that a new player has joined. If that's all you need you don't need to use a RPC at all.
The gamemode does indeed not exists on clients. It's server only.
is there an event for that creation?
what i need is the player controller
so i can get the uniqueNetID and mute players
If you only care about if it exists you can use BeginPlay. If you care about the data it may get a bit more complicated depending on what it is.
Player controllers of other clients are not available on regular clients. Only the server has all player controllers in a world.
my idea was to call an rpc from the game state through the gamemode
player join on the login or any similar function that has the PC in the game mode, i then "getGamestate->myRPC(dataThatINeed data)"
something like this
What kind of data are we talking about? This kind of sounds like the wrong approach depending on that data 😛
its just the unique net ID
shouldnt be too heavy i think
i am not sure if it is the wrong aproach thats why i am asking
I think only the server can do that.
i could also do it on the existing player controllers instead of the game state
Then I would not use a RPC. For the reason that what you're sending is a "state". Take the following situation:
- Client 1 joins the already existing server.
- The server sends a RPC to all people to send Client 1's Unique ID.
- Client 2 joins the server.
- Server sends the RPC again.
However now you have the problem that Client 2 does not have the Unique ID of Client 1 because they joined later.
What I would recommend is that you use a replicated variable for this instead @limber gyro 🙂
There is another way to manage that right, i forget the name.
Going to boot up UE5.1 a mo, as I find this kind of intersting.
@limber gyro are you using BPs or C++?
this is not as much of an issue as u think since i need to only mute the player once, but it reminded my that i also need to mute the players that are already in the game
both
for now im just trying to get the best aproach
Ok, im using BPs specifically, but will attempt to see if I can construct it.
I am fairly new to UEs networking architecture myself.
Then it's still an issue, no? 😛
Regardless of that or not it's still not a great decision to have state in RPCs. Simply because what if you decide you later on want to re-use that Unique ID again for something else? You already have send it, might as well use it again right? Only to then realise that some Unique ID's are missing.
so u think i should put those unieNetIds in the player state?
@cedar tangle Regardless of what version you're using Unreal uses either "RPC's" or "Replicated Variables", they go by different names depending on C++ or Blueprints and have a couple of different names in general but those two are the fundenmental part of everything network related in Unreal.
I my self would put them in the player state yup. If Unreal hasn't done that already, sometimes they do things like that. I don't exactly remember if they do or not with this. But either way yes, I consider this "state" as it's not something you access once and never again because clients can join after someone else has already joined. Even if you don't immediately care about that problem I described above it's still good practice and may be useful later on.
Yeah, I not done any C++ with the Authoritive network layer.
Sticking to BPs at the moment.
If I remember correctly, there is an area of notification.
So if the player is not in that range then the valuable data is not replicated, but there is a way to store that state persistence so then the player is within range then they are updated.
ok so here's what i am thinking, when a player joins the server first he mutes every one and then he unmutes team mates:
after that he mutes new players that join if they are from a diferente team.
Where would u guys think would be the best place to mute the new ones that join?
What you're referring to is what I usually call "OnReps" in C++ land. I believe they are called "replicated events" in BP or something(?). Maybe they are called OnReps, not sure. I mostly use C++ 😛
Not a direct answer. But why does the server send that data to clients? If a client has to immediately mute other people upon joining a game why does the client need to take care of that? If cheaters matter for your game in specific, what would prevent someone from not muting an opponent and hearing or seeing what they say? 🙂
im only working with what i have haha, documentation for steam voice chat is non existant so i am only guiding myself by the BP nodes
and im probably not doing a very good job at it
im using advanced session and they give some support for voice
and by some i mean very little
im just trying to understand how everything works and trying to put together a good aproach
ive asked here twice and no one answered too
Right, I guess that's a limitation of that then. A quick Google search tells me Steam does not directly send that data them selves yup, so I guess something in Unreal does. However I would still try to see if you can fix that. Even if not for the reasons listed above. I would "expect" that if you only mute other people on clients them self that the server still sends that data. Which sooner or later is a lot of data.
I just opend up an older project, classic case of, wtf, where is everything.
Give me a moment want to shwo you something.
from what i found in google i got the oposite impression, that steam sends it directly peer to peer in lobies
https://partner.steamgames.com/doc/features/voice
Sending
Once you have the voice data, you'll likely want to send it to the other players. The Steam Voice API does not provide the means of doing so directly but, this can be done with any networking library of your choice. The Steam peer-to-peer networking APIs are a great option for this.
The last part is referring to a more general system that accepts basically everything you send over it. Unreal has an implementation for that so you can provide easy online support on specifically Steam. However that still means that something in Unreal, whether or not that's the engine or your plugin is sending that data.
Sending voice data is not exactly the "cheapest" thing. Especially because it exponentially scales up the more people need to hear everyone else at once.
yes but this method of voice chat only works if ur running a session, so i am assuming that the data is going through steam some how or else it work without sessions thorugh the IPnetDriver
the documentation is just very very bad
its all guess work
@limber gyro this is something I made recently, all you need to take form it is the following,
The players ammo/storage is local to the player, however the function is only executed on the server, in-turn of the function being run then the replicated variable is updated (the clients only ever sees what the server is allowing them to see):
Steam's documentation is fine. Not sure about the plugin you're using. Unreal's documentation is not great yeah.
its jsut the advanced sessions plugin, every one and their mom uses it
I have not used it. C++ is perfectly capable of doing those things within not a whole lot of time so I don't want to depend on a plugin for things like that 😛
yes, i know this, im just trying to figure out the best way to go about it
i know what u mean, im usually like that for bigger stuff too, but the advanced sessions is so widely used and has so much support from the community that i figured it would be fine
Depends on how you mute them I suppose? I made the assumption by the way you were explaining it that it was some kind of button to mute someone.
Were you using C++ at all or only BP? If you're also using C++ you can override the following method in the PlayerState:
/** Called on both the client and server when unique ID has been modified */
virtual void OnSetUniqueId();
```That's invoked after the Unique ID has been updated in a player state.
i was just looking for something like that
A PlayerState is created for every player on a server (or in a standalone game).
but couldnt find anything
That is handy. So one could have client based code and server based code to run in a decoupled way?
What version of Unreal do you use? It seems to indeed not be a thing back in 4.27 yet.
im on .26
It depends. Sometimes Unreal does provide ways to do so, other times not. It's unfortunately rather inconsistent throughout the entire engine 😦
Then you can override this method:
UFUNCTION()
virtual void OnRep_UniqueId();
I get you, wont get into it. I wonder if it just sends an RPC 🙂
ok but thats going to be for my id only right?
As much as I hate to say, it depends once again x)
A lot of the time Unreal uses Replicated Variables / OnReps because a lot of the engine it self has things that are considered "State". E.g. a player name. Sometimes they decide to properly expose the callback when that value changes so that so you can override it rather easily as is the case with the UniqueID thingy. However very often this is either only C++ and not in blueprints OR only work on either the client or server. Hence why it unfortunately is inconistent.
That's just for when your Unique ID has arrived yeah.
For me personally, I would follow the Auth architecture provided by UE and probably build everything from Client to Server only. Keeping the client as the observer.
This has some other advantages to, one being clarity.
is there a callback for when the player array changes in size that i can override?
Right, but here comes the problem. That is indeed how Unreal already works. However we try to not duplicate code as it ultimately is just annoying. So take the following example:
What if I change a replicated variable on the server that eventually everyone will see change and will invoke a callback. But what if I want the logic for that in specific to run on both the client AND the server? A lot of games use a listen server model. What if a player changes their nick name in the game? Then both the listen server needs to update that and all clients right. The problem with that is that Unreal does as I pointed out not always properly do this for the engine defined variables and that's when it can get annoying if only C++ can do it or if you need to hook into seperate callbacks for the server / clients 🙂
AGameStateBase has two methods for that yeah:
/** Add PlayerState to the PlayerArray */
virtual void AddPlayerState(APlayerState* PlayerState);
/** Remove PlayerState from the PlayerArray. */
virtual void RemovePlayerState(APlayerState* PlayerState);
```Make sure you run your code after calling the super though, but that's definitely a common thing 😛
i was just looking at those lol
they should've added a nice little event for bps tho
like "OnPlayerAdded"
cause now i gotta override and add my own haha
"Should" is unfortunately often not the case in Unreal regarding things like this. That's why C++ knowledge is kind of a must for multiplayer games in my opinion. Despite that blueprints allows a decent amount of things there are soooo many things that aren't available in Blueprints compared to C++.
But yes, in an ideal world Epic should fix things like this and make it more consistent 🙃
I have to eat soon btw so I have to go for now. If there are still things unclear feel free to ask in here of course and see if any others maybe jump in 😛
thanks for the help
Hmm, your probably seeing the situation with more experience than I am.
I am under the impression that clients stay state synced with the server, a player name change, in my eyes, looks is like this:
Client (sends name)-> Server (validates the name/text) -> All Clients updated (all clients observing the synced Player names Array or re-renders parsed JSON text value possibly).
Hmmm, I am also assuming here, a listening server would seamlessly pass the synced data to another client if closed. Again tho, I personally would do dedicated only, for clarity reasons.
how can i take the last login time variable from this and make it so other clients can retrieve that variable
My be I am off track here, but this is what I found, this would be under a Game Mode BP and would be a server side only.
In terms of networking, yes. That is indeed exactly what happens. However in C++ (which is basically the only thing the actual engine uses internally for 99% of code) the problem is that OnReps / callbacks don't automatically get called on the server. So they have to manually invoke it. If one of Epic developers does not properly delegate that callback further down the line it gets messy. Despite that the nickname will probably update just fine what if you wanted to play a sound specifically in your game but then figure out that Epic does not provide a proper override for that callback? That's also why sometimes only a client calls a certain function or only the server, simply because the engine does not do it 😛
You would probably want to create a replicated variable in some object that all clients can access and then once you get that client login result thingy you assign it to that variable and it will eventually arrive to everyone who needs it. I would my self probably put it in a player state.
You could also use a RPC, hence my "probably" in the first sentence, but that depends on the use case.
Interesting. That I didn't know.
To access the virtual functions for example the OnRep_UniqueId are you overriding/extending the method (function) of the base class via inheritance (guessing is the case).
If you want to directly do that with an OnRep then yes. You need to inherit from the class with that OnRep and then override the method. Assuming it's virtual, Epic unfortunately still does not have all of them marked as virtual 🙃
However, it again depends on if they even call the OnRep in the first place on the server. It may or may not also be the case that the implementation of that OnRep from Epic calls yet some other function that then provides access to blueprints or similar. It's a mess overall.
@twilit radish it is interesting. I haven't done any C++ development with epic games codebase yet. But it would make sense that the C++ is more functionally rich than the Blue Print (Kismit, or what ever its called now).
This isn't really related, but I wonder if there is a way to async watch a value for a change (sorry for my lack of C++ knowledge here). I am a fullstack developer by profession and something I can do (but avoid) in JS is watch a variable value for change.
I just wonder if something like that would work well in authoritative network architecture, because the server is the only one broadcasting the change.
If you want to, yes you absolutely could just constantly check if a value changes. Some "blueprint only" projects that are multiplayer do this if they are unable to hook into an OnRep directly. However the problem with that approach is that you're making a trade off between performance, extra latency and possibly bugs. If you want to "immediately" get notified of a change you would need to check every single frame if the value changed. That's fine with a couple of variables but with more you get problems. Blueprints that use the "tick" function are already not necessarily the best for performance, some projects even straight up disallow their employees to use them because of that reason. So then you might think "What if I check every 0.2 seconds or so instead?" which is something you can do and more performant, but then you're introducing extra latency on top of the network layer depending on how often you check. Which in a turn based game could be fine but in a FPS like Counter Strike, Valorant or whatever is not great. You also in doing so introduce the issue that you might "miss" values. What if within 0.2 seconds your variable has been updated multiple times? Then you missed one of the values sent from the server, which could lead to unwanted behaviour.
So generally I think what seems to be the most accepted solution in games in specific is to just provide a callback.
Yeah I agree I don't think the Tick event would be solution due to the resource usage.
I was thinking of something else. One moment I will have a google.
Ok so, to my understanding, an EventListener via C++ would be the best approach.
And from my experience, when dealing with event listeners, it is a good idea to centralize the events as it results in much less spaghetti to deal with.
@twilit radish thanks for the info.
anyone able to help subtract this 2023-07-22T15:40:20.06Z from the "now" datetime node to show days hours minutes elapsed between the two
how do i make a non owning client actor send data from client to server?
like if i have a player open a door, and the door is not owned by any clients, but the door is requesting open, how do i make the door actor send the open data to the server?
The way I've typically approached this kind of thing is to have an RPC on the player controller (or player pawn) that tells the server what the player is trying to do and passes the other actor as an argument. Something like:
void AMyPlayerController::OpenDoor(AActor* Door)
{
// do any kind of necessary validation etc.
Door->Open();
}
well rather than doing that you can use a generic interaction interface
and have the door implement such interface
but the idea is the same
Does anybody know of a good way to replicate structs/classes for which the actual replicated data is very simple, but the struct/class itself contains a bunch of non-trivial (non-replicated) state? Imagine I want to write something like the following:
int SerializeReplicatedStateToInt(FMyComplexClass C);
FMyComplexClass DeserializeReplicatedStateFromInt(int C);
USTRUCT()
struct FMyComplexClassWrapper
{
TSharedPtr<FMyComplexClass> MyClass;
}
// inside some actor somewhere...
UPROPERTY(Replicated)
FMyComplexClassWrapper MyClass;
I've spent the last couple weekends going down a rabbit hole trying to figure out how to accomplish this with NetDeltaSerialize and I'm still running into weird behavior that I can't explain - in particular, it is very inconsistent whether the initial value on the server gets replicated to the client or not. Does anybody know of either a simpler way to replicate data like this? Alternatively, would anybody be able to help talk me through what I need to do inside NetDeltaSerialize to ensure that initial values replicate reliably? Thanks!
You can netserialize the whole struct to make it replicate atomically
if you'd like member within your replicated struct to not replicate onto your blob, you can simply use the NotReplicated UPROPERTY specifier
Ah, I should have clarified; FMyComplexClass isn't a USTRUCT, so I can't directly use UPROPERTY markup on it.
thanks, yeah i realized i had to use the player controller as a bridge, which is kind of ridiculous, why not just have the RPC function directly on the actor blueprint O_o
its kinda tedious having to make duplicate functions on the player controller
A bit of an update on this actually - I tried modifying my NetDeltaSerialize by replacing a call to BitWriter.SerializeInt(Value); with BitWriter << Value; (where Value is a uint32) and suddenly I'm seeing the initial behavior be more reliable. A bit of debugging has revealed that operator<< winds up calling FBitWriter::Serialize(void* Src, int64 LengthBytes) as opposed to FBitWriter::SerializeInt(uint32& Value, uint32 ValueMax). I'm honestly confused as to why the former would work an the latter not, but the implementations of those two functions are fairly different so... 🤷♂️ ?
I'm gonna poke at this a bit more to understand whether this actually reliably solves my issue or if it's just a fluke.
ah I see now, you are trying to serialize the data within your FMyComplexClass to rebuild it locally
i mean honestly there are other approaches like using FMemoryWriter to write to a bit array buffer from which you can encode/decode your data
its a bit more explicit, used it here
a bit funky to debug state serverside as its a bit array but works reliably enough
see:
TArray<uint8> UHealthComponent::Encode()
{
TArray<uint8> Payload;
FMemoryWriter Ar(Payload);
Ar << Health;
Ar << Shield;
return Payload;
}
void UHealthComponent::Decode(const TArray<uint8>& Payload)
{
FMemoryReader Ar(Payload);
Ar << Health;
Ar << Shield;
}
FInstancedStruct my dudes
Supports object references properly then too
5.2 and above
(ur welcome)
Where's that blog post Jambax?????
in my infinite backlog 😄
Using AdvancedSteamSession I can't see my dedicated server on the packaged version,
Steam overlay is ok, and I also can see the server in the steam server list. Any idea?
UE 5.1.1
ah yes that, been using it for a while now, explendid
Thanks for the suggestion! This makes sense; having a single network manager that handles the replication of many actors seems useful, although I don't expect the scale of what I'm doing here to exceed that which I can comfortably do by replicating each actor on its own channel. In your example, it does seem like there needs to be one central point from which you can call NetworkManager->UpdateActor(). I'm trying to avoid having to make FMyComplexClass internally aware of any kind of centralized network manager, as there are plenty of places where I use it in a non-replicated situation. The USTRUCT wrapper I alluded to above is specifically for the sake of enabling this to replicate. 😅
Do I need to replicate Game Mode reference in the player character if I'm only using the reference to run server events?
Nope. In fact, you probably can't replicate it, since game modes are server only.
note that i was pointing only to one specific part of the article, the FMemoryWriter
i wasnt suggesting you to use network managers hehe
Ah, I understand. Yeah, I'll take a look and see if that would make things easier. I'd thought that FBitWriter was simply a special case of FMemoryWriter, but I haven't actually looked too closely at the difference.
but what Jambax said, take a look at FInstancedStructs
what I was suggesting is instead of storing your complex data structure inside ur struct
you have a bit array that represents your data binarized
and then you build translators for the encode and decode operations
nesting replication levels are not very well supported in struct replication
I've been taking a look at FInstancedStruct, and not 100% sure I understand what it's for. It seems like a wrapper that can hold an arbitrary type of struct data, which could be useful if I didn't know what kind of data I'd have at runtime (or I needed to store an array of heterogeneous structs or something). But I'm not quite sure I see how that applies to this case.
No, the inner struct is a known type. It's a type of state machine that tracks both a state and a set of things that care about that state being set to specific values. It's a bit more than just an "OnChanged" delegate, but conceptually that's close enough. I want to replicate the state itself, but the associated delegates etc. are all non-replicated (i.e. client/server have a different set of things that want to react to the state).
Maybe? That type itself has some template arguments and up until now I've found it sufficient for my needs to say using FMyIntType = TMyType<int, some, other, arguments>; But one path forward would be to make a copy of TMyType that is specific to ints solely for the sake of making replication easier.
That, and the fact that this type depends on some data that needs to be passed in at construction time, so I find it cleaner to have those as constructor arguments than to track whether it's been initialized correctly or not.
But getting rid of the template and adding in a zero-argument constructor would let me make it a USTRUCT, which would get rid of the replication headaches, so maybe that's a worthwhile tradeoff.
that's what I would do for simplicity shake, yes
otherwise you'd have to write and mantain serializers
Fair enough. The first time I found myself needing to replicate one of these, I cobbled something together with a separate replicated int with an OnRep that poked the value back into the client-side version of this struct. Now that I've found several places I need to replicate one of them, ease-of-replication is moving up my priority list relative to where it had been before. So yeah, I'll consider a rewrite there when I have time.
Thanks for the advice! 🙂
still have this issue
Is this multicast/sound playing on a player controlled actor?
Possibly. Do you set ownership of the actor?
If you don't, then all clients will see it as simulated.
Question, do subcomponents of a component also replicate if the parent replicates?
or does each component need to be set to replicated individually
Each component needs to be marked as replicated if it needs to replicate data (ie. it has replicated variables or has RPC calls within it)
K so yea they need to be marked individually
LogNet: UPendingNetGame::SendInitialJoin: Sending hello. [UNetConnection] RemoteAddr: 3.81.38.142:7778, Name: IpConnection_7, Driver: PendingNetDriver IpNetDriver_7, IsServer: NO, PC: NULL, Owner: NULL, UniqueId: INVALID
what is the issus ?
Since 5.1 I can't find my dedicated server (Advanced session - steam), while I can see it in steam server explorer.
Anyone know anything about it?
are your client and server running the same version?
Yes
Does either the client log or the server log (terminal?) mention anything?
I am new to using replication but not to UE, and I'm having a bit of a weird issue. I've got montages playing for attacks, and they have blend times set in the montage. On the server, the player character smoothly blends into the montages, but on the client, the player does not. Everything seems to be working perfectly except that blending not happening on the client. The client player from other clients/server looks blended correctly too, so I'm really at a loss. Is there something obvious I'm missing? Client is left in this video, you can see the jank no-blend montages happening
That's on 4.27 (and tested on 5.2, same issue)
No, server is ok I can see it in the steam list, problem is the client cant list external dedicated servers
Also I have an old version of my game (ue 5.0.1) and I can see the server, that's why I really suspect its the upgrade to 5.1/5.2
Hi, I have a widget3d which cannot be clicked on clients, but can on listen servers. any reason why it wouldnt be clickable on clients? it's just spawning a generic actor with a w3d button inside
clients controller input mode is game & UI
im getting my playerstate in the player controller and casting to my custom player state, unfortunately the cast is failing, why coudl that happen?
second cast fails
doesnt reach "player joined cast 2"
Well where is that replicated player state variable being set? Did you debug to see what actually comes through from it at runtime?
its a default unreal variable
If a cast fails, it’s because the object you reference is not of the class you are checking for
You know how to use breakpoints to debug?
You can hover over the input pin of the cast to see what value is coming through
i cant debug it in the editor, because its multiplayer running through steam
Ok, well if you put a print string on cast failed and it fires, you have your answer
Idk when and where that variable is being set, but maybe it happens after your cast fires?
Playerstate may not necessarily be valid if this is happening right at the start of the game as it can take a moment for the appropriate playerstate to replicate from the server.
Do you see the same behaviour if someone joins after everything has started up?
i have not been able to test that yet, im gonna add a delay (i know this is not ideal) and see if it fixes it to confirm this is the case
Ideally rather than using the player joined notification, I'd recommend using the Team OnRep in the playerstate to control the muting.
why is my rep notify not being called on the InMainHand Variable, here is my code for reference
Header File
AItem* InMainHand;
UFUNCTION()
void OnRep_UpdateMainHand();
UFUNCTION()
void UpdateMainHand(); ```
.cpp file
Constructor{
InMainHand = nullptr;
}
void ATGB_ADW_UProjectCharacter::OnRep_UpdateMainHand()
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("OnRep Called"));
UpdateMainHand();
}
void ATGB_ADW_UProjectCharacter::UpdateMainHand()
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("UpdateMainHand"));
if (GetLocalRole() == ROLE_Authority) {
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("Test"));
InMainHand = Inventory[CurrentSlot];
}
UE_LOG(LogTemp, Warning, TEXT("In Main Hand: %s"), *InMainHand->GetFName().ToString());
// Attach the weapon to the First Person Character
FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);
InMainHand->AttachToComponent(GetMesh(), AttachmentRules, FName(TEXT("GripPoint")));
btest = true;
}```
the OnRep_UpdateMainHand function is not called on the client
the Update Main hand function first gets called on the server where it sets the in main hand function which should call the rep notify
im overriding "addPlayerState" in the gameState to call that player joined event
should be about the same no?
its only being triggered when a new player state is added to the player array
Hello, since unreal create a session at the beginning of my game, I can't create one, so this part C++ SessionInterface->CreateSession(*localPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings)
Is alwways printing "Cant create a new session if one already exist"
Any way to get the current session ?
Well again, that array is managed locally on clients, so their "starting" playerstate that is created is always a non-replicated version, so then that event is likely being triggered for the player themselves as soon as they're joining, but then their playerstate may not be valid. I'm not sure when the AddPlayerState function is called, but i would imagine for properly replicated players it should work fine. You still have a dependency on the team being replicated though - it still makes a lot more sense to not worry about when a player is joining though, but rather when their team is received.
I want to add a log command from a plugin to the development build dedicated server for debug how can I do that?
its a multicast RPC so i am assuming that its going by the server version unless i am missing something here?
What's a multicast? AddPlayerState?
(cuz it's just a function)
multicast is a function that runs on all clients from the server
wait
I know that...
XD
sorry
letm e check the function hierarchy
addPlayerState is overriden which is in the GameState, then inside that i call the multicast rpc
CallPlayerJoinedOnPlayerController(PlayerState);
which passes the state
then in that function i just get the player controller and call the event
its pretty simple
And that's even worse. The multicast doesn't guarantee that the playerstate has been replicated before the multicast is received.
thats a very good point
ok so your suggestion was to do on rep on the team, would that be the same as the on rep for the playerstate itself?
i assume yes
No. Like, I'm not sure if you want players to be able to change team mid match, but if they could, then you may want to mute/unmute certain players when they switch. Additionally, just because the playerstate has replicated doesn't necessarily mean the team value has.
ye i do indeed have that option to change teams in custom games
thanks for the help, it did help a lot
I've replayed the pinned Overwatch netcode video a few times and I feel pretty comfortable with how it's doing client prediction via buffering, rollback, etc.
one thing I'm still not sure I understand, though, is how it works with non-client-controlled actors. for hitscan, I get that you can use latency compensation to fire a shot at your time T and, some time in the future, the server will process what happened at T and run it from the perspective of what your client saw (which was, say, T-5) to register the hit
but what about projectiles? if I shoot a rocket at a certain direction because I think an enemy will be there soon, the server can't change the angle of the projectile to compensate, right? now I'm shooting a rocket at time T against another player's position at T-5 and there's no way it will intersect and hit them, right?
(or does the server spawn the projectile at time T but tick it forwards 5 times to compensate for the delay? or something else?)
why is my AActor object reference not replicating?
the repnotify just never gets called
please, i dont understand enough about multiplayer yet to figure this out
is it just some code im missing in AItem that will stop it from replicating?
I assume your AItem is marked for replication?
Projectiles are by default not predicted. So server spawns it at the given location RTT/2 after the client asked to fire it.
If you want to predict it you'd need to spawn it locally and offset the location forward on the server side to match the client. And then fix that the client will have 2 projectiles, its own and the replicated one.
For hit registration you could make the hit component bigger and instead of instantly accepting the hit check if that hit even makes sense, similar to the line trace
hmm are you sure? the impression I got from the Overwatch video is that they predict all abilities, including spawning projectiles
I’m mostly wondering how you fire a projectile while still being able to hit moving targets if they’re based on previous enemy locations (particularly in the Overwatch implementation)
Is it normal that the server calls print string on clients too? when executed locally
If you're talking about seeing "Server: ...." while looking at a client screen, that's only because its in the editor.
Prints will only execute on the instance that they're called on otherwise. So if you're running on server and do a print string, you should only ever see
Server: ...
But this can still show up in other editor windows.
If you're printing in something like a multicast then you may see
Client1: ...
Server: ...
If you're printing while running on a client then you should only see
Client1: ...
thats what i thought, thanks
yes
sorry
here it is
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
//Replicate Inventory Items
DOREPLIFETIME(ATGB_ADW_UProjectCharacter, CurrentSlot);
DOREPLIFETIME(ATGB_ADW_UProjectCharacter, InMainHand);
}
yes
the character is the default unreal engine character so it should replicate
and Item has BReplicates set to true but it doesnt have any replicated variables
i can send AItems code if you want it though
it is spawned in by the level
does it need to be spawned in by the server?
mabye its ownership problems
oh that was a test trying to get the mainhand to replicated
its not needed
the inventory array is set by the server and is server side only, the inventory is never needed to be visible by the player
let me send that code as well
character cpp
{
if (GetLocalRole() == ROLE_Authority) {
if (Inventory.IsEmpty()) {
Inventory.Add(Item);
CurrentSlot = 0;
UpdateMainHand();
}
else if (Inventory.Num() < 5) {
Inventory.Add(Item);
}
}
else {
UE_LOG(LogTemp, Warning, TEXT("Someone Without Authority Attempted to Add Item To inventory"));
}
}
Item header
UPROPERTY(Category = Character, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* Mesh;
bool bIsDestroyed;
public:
virtual void Interact(ACharacter* Character) override;
virtual bool IsSupportedForNetworking() const override { return true; }
item cpp
{
bReplicates = true;
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
Mesh->SetupAttachment(RootComponent);
Mesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
Mesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Vehicle, ECollisionResponse::ECR_Ignore);
}
// Called when the game starts or when spawned
void AItem::BeginPlay()
{
Super::BeginPlay();
}
void AItem::Interact(ACharacter* Character)
{
ATGB_ADW_UProjectCharacter* player = Cast<ATGB_ADW_UProjectCharacter>(Character);
player->AddItemToInventory(this);
if (!bIsDestroyed) {
bool btest = Destroy();
}
the index being reped is currently redundant, i was trying to see if the int would rep_notify when the mainhand variable wasnt and it did
so i shouldnt replicate the pointer?
or does it make sense that im replicating the pointer
DOREPLIFETIME_CONDITION_NOTIFY(ATGB_ADW_UProjectCharacter, InMainHand, COND_None, REPNOTIFY_Always);
Think ya gotta do it like this if you want the OnRep to fire.
Ah ok
i use the pointer to draw the item in the players hand when it is held
on all clients
i can try this
well the rep notify fired this time
i think that fixed it, thank you very much everyone!!!
usually i close the editor and relaunch in debug mode from visual studio, or if it is just a minor change like adding a print/log statement i will use live coding
oh yes... i can tell that from experience 🙂
having to rebuild everything a few years ago 🙂
also now there is a new problem that i didnt relize earlier, i added dakturas repnotify thing and now the repnotify calls, but the variable remains a nullptr instead of a valid reference
why would that be a problem?
Hey odd issue
This on rep doesn't function properly
it does not set the collision to ignore, which debug confirms is what it's set to
maybe I'll try migrating it to a bool
see if that helps
nope
it works with multicasting, but not in an onrep
yes
2nd node is not needed
debug thing
to force it to be no collision
Are you sure collision is even replicated?
I'd assume so
Never assume.
none
yes
oh well, it seems it was simple
function was not being called
I used print instead of blueprint debugging now
prints showed it not hitting
blueprint debugger showed it being hit
it's an enigma to me
I would like to pretend I know why, but I have no clue why debugger is hitting it
well thanks, it got me on the right track
What do you mean by "see" ?
Probably an rpc tbh, unless you simply want to reply on the health repnotify.
But then you'll lose out on damage types and have multiple amounts of damage being merged into a single change.
Yeah.
That too.
sounds visual
multicast
gameplay cue is just the GAS equivalent which is neater to use if it happens inside a GA
Damage numbers showing being important for game events seems odd.
Important: Mob health being replicated.
Not so important: Seeing a floating number above the mob's head to show that they lost some HP.
At least, that's how I view it.
And depending on the game and how often numbers are popping up, they become less and less important (albeit fun!) to see.
Depends on the type of game, tbh.
You take something like WoW or whatever and those rpcs (basically teh combat log) become extremely important.
If you're looking at Tranek's example, he did it through PostGameplayEffectExecute in the Attribute set itself, albeit, it's only running it on the source actor's player controller. With some modification I bet you could get it to display for everyone.
Possibly no extra RPCs needed.
The change you made causes the OnRep to call even if the value didn't actually change. So in case it's e.g. an Integer and you set it to 5 while it is already 5. Same with the nullptr. Usually that not causing the OnRep to trigger.
So your actual issue is not how the variable replication is declared, but that the Item is nullptr on the client.
Which would again mean it's not actually set to replicate. Are you sure your blueprints are set to replicate and not overriding the CPP parent default?
Can only 1 pawn be possessed by the controller? I need 2 Pawns to be possessed! Is it possible?
For example, by 'w' key, Pawn 1 moves, by 'I' key, pawn 2 moves, like this..
Hello, since unreal create a session at the beginning of my game, I can't create one, so this part C++ SessionInterface->CreateSession(*localPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings)
Is alwways printing "Cant create a new session if one already exist"
Any way to get the current session ?
How unreal can create a session at the beginning of a game? I think it always depends on when you call the function...
this is my function:
void AMenuMode::CreateSession(FSessionDefinition NewSession)
{
if (const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
const IOnlineSessionPtr SessionInterface = OnlineSubsystem->GetSessionInterface();
if (!SessionInterface.IsValid())
{
OnCreateSessionCompleteEvent.Broadcast(false);
return;
}
LastSessionSettings = MakeShareable(new FOnlineSessionSettings());
LastSessionSettings->NumPrivateConnections = NewSession.PrivateConnectionNumber;
LastSessionSettings->NumPublicConnections = NewSession.publicConnectionNumber;
LastSessionSettings->bAllowInvites = NewSession.AllowInvites;
LastSessionSettings->bAllowJoinInProgress = NewSession.JoinInGame;
LastSessionSettings->bIsDedicated = !NewSession.AllowPlayerHost;
LastSessionSettings->bIsLANMatch = NewSession.UseLan;
LastSessionSettings->bShouldAdvertise = NewSession.Advertise;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = true;
LastSessionSettings->Set(KEY_SESSION_NAME, NewSession.SessionName, EOnlineDataAdvertisementType::ViaOnlineService);
CreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
const ULocalPlayer* localPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->CreateSession(*localPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings))
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
OnCreateSessionCompleteEvent.Broadcast(false);
}
}
}```
Feel a little bit weird for what is this block for?
`if (!SessionInterface->CreateSession(*localPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings))
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
OnCreateSessionCompleteEvent.Broadcast(false);
}`
if it can't create a session, cacll the delegate with "success = false"
I think the delegate for the createsessioncompleted will have success or failed output, then just use that?
That's what I bound in my own code
but I always get this error
That's what I said. You probably shouldn't use create session in the if condition, just looks a bit weird for me. Just wait for the delegate from the interface is okay.
But it's my delegate, so it will be called only if it's successful
Yes, so what I mean is you need another function that it is called from the SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
Then from there, you check the callback is success of failed then decide to do the thing next. That's what I think.
the error is fired before the call of the delegate
Ok, then you need to check where called createsession function being called. Checking the calling stacks. I mean you couldn't have been a session without created it.
I manage to understand why it's called and it's because the game session with the name "GameSession" (which come from the 'NAME_GameSession') is already running, so now I have to update it with the right settings, but I really don't understand why it's already running ?
Yeah, you can have only one NAME_GameSession at the same time. But still, it is a created one, not like creating itself at the beginning.
So, is it "multiplayer open" if it's created at the beginning ?
What is that function or option you mentioned about? Any code or blueprint node?
so the game session "GameSession" is running, but why can't I get its FOnlineSessionSettings ? I tried this :
LastSessionSettings = MakeShareable(SessionInterface->GetSessionSettings(NAME_GameSession));
if (LastSessionSettings != nullptr)
{
OnUpdateSessionCompleteEvent.Clear();
OnUpdateSessionCompleteEvent.AddDynamic(this, &AMenuMode::UpdateIfExist);
UpdateSession(NewSession);
}``` and
LastSessionSettings is always null
Would you like to try SessionInterface->GetNamedSession(NAME_GameSession)?
It seems to be the way to get the session exists or not.
Oh ! Yes ! I get the session but its settings are null, I should be able to add settings to it and make it hosting
I think you might still need to figure out when this session is being created. But sure, if you just want to implement something quickly, just update the session settings would be okay.
Or quit the current session and create yours😅
The problem is I never create it, Unreal do it or I should find something in the project settings
Yeah, that's the reason why I suggest you to figure out where it is created (maybe not by your code though. Like some plugin doing it for example)
Not even using plugin. Can it be set in project settings ?
I'm not sure. But the only way is to set the break point for create session function called everywhere by those onlinesubsystems if you don't have a clear idea which one called it.
It sounds stupid but it could be the fastest way.
Already put one and it's only called when I'm firing the function
Are you sure about any onlinesubsystems?
yup
That's werid.
really weird, that's why I'm disappointed
So I'm trying to figure out how to bypass this by updating it
How did you create your project? From scratch or from some samples?
from ThirdPerson sample
Hmmm, it could be created somewhere because I think this project is supposed to be online multiplayer sample.
Is EOS on?
I added it
Maybe try to disable it to have a test?
Sorry, I didn't do any project with EOS for production, hence I'm not really familiar with its pipeline.
I might have misunderstood, are you talking about EOS Online Subsytem ?
Yes, that's what I was talking about.
So no I haven't installed it, I'm only using this
They are the modules you neede for online multiplay. It is fine. Hmmm, if you don't want to check where the session's been created, maybe just update its settings.
Exactly, that's why I misunderstood.
I'm really trying to figure out why the session is already created and digging all the project sources but nothing is network related.
Plus, I had to add the OnlineSubsystem and the OnlineSubsystemUtils to the build.cs
I understood.
When you're in the editor, even if the you're in standalone or in selected viewport, because unreal is open the session is still running
Oh, you tried it run as client? That's probably the reason.
I tried different things, and all has beed tested, but I'm in debugging it so unreal engine was still open
Yeah, the best way to test create sessions probably just make a package and test it. It is a bit pain but it could be the most close to the user environment.
Kinda hard to debug from a package, that's why I kept it in client
I agree. So make it client is better for testing gameplay stuff because it is easier. But for sessions, hmmm, maybe still gotta make a package.
I got you, thanks a lot for the time you took to help me
Not at all. Hope you could get your game sessions running smoothly.
(I now have a check to create or update one)
hello, if i spawn a actor with defer and set a replicated variable with a certain value before the begin play on the server, if that variable has a beefy value (like a big array), will the begin play on the client be deferred until that initial beefy value has been replicated? or begin play will execute and then the on rep would fire?
OnReps will always fire before BeginPlay for whatever is in the initial packet
so the begin play will be deferred?
It won't be "deferred", OnReps are just called first
and to set that initial packed needs to be done with a spawn deferred?
or can i spawn it normally and if it's in the same frame
then it will work the same
You can spawn it however you want, the properties just have to be setup by the end of the frame to send them in the initial spawn packet
right, thanks 🙂 another question, if i have just spawned an actor on the server and i call a multicast or client RPC on it immediately after, will it wait for the actor to exist in the client to trigger the RPC or there is a chance it will never trigger because it didnt exist on the client?
I've never done it, but from what I understand people do have trouble with it.
In theory, the RPC would just be added the the actor channels' buffer and executed after construction
since the OnRep executes always before the beginplay then i shouldnt need the RPC, but i'll test it on an empty project just out of curiosity
thanks 🙂
Hey, I'm currently trying to find all session but none is found:
Any idea about what I miss ?
this is my query:
LastSessionSearch = MakeShareable(new FOnlineSessionSearch());
LastSessionSearch->MaxSearchResults = MaxSearchResults;
LastSessionSearch->bIsLanQuery = IsLANQuery;
//LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
const ULocalPlayer* localPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->FindSessions(*localPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef()))
{
OnFindSessionsCompleteEvent.Broadcast(TArray<USessionEncapsulation *>(), false);
}
And these are the settings I use to create my session:
LastSessionSettings->NumPrivateConnections = NewSession.PrivateConnectionNumber; //equal to 0 during my tests
LastSessionSettings->NumPublicConnections = NewSession.publicConnectionNumber; //equal to 5 during my tests
LastSessionSettings->bAllowInvites = NewSession.AllowInvites; //true during my tests
LastSessionSettings->bAllowJoinInProgress = NewSession.JoinInGame; //true during my tests
LastSessionSettings->bIsDedicated = !NewSession.AllowPlayerHost; //true during my tests
LastSessionSettings->bIsLANMatch = NewSession.UseLan; //true during my tests
LastSessionSettings->bShouldAdvertise = NewSession.Advertise; //True during my tests
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = true;
LastSessionSettings->Set(KEY_SESSION_NAME, NewSession.SessionName, EOnlineDataAdvertisementType::ViaOnlineService);
Whatever you profile to be the bottleneck
If you have to ask you're probably too far gone
Hi, im having an issue replicating the collision data from a niagara particle system, I have an axe the player can throw and when it hits a character it'll spawn a BP_BloodSpurt actor at the location of the hit which plays the particle system and then I use the Receive Particle Data event to get the collision position and spawn decals at those locations, i changed it to just 1 particle so its easier but in the images you can see the server and client are registering 2 slightly different collision locations, and on the client screen you can see where its trying to display the decal that the server is seeing.. How can I make it so the collision is in the exact same place for everyone?
Ive tried multiple different ways with rpcs or repnotify's but couldn't get anything working
i think particles are not replicated by design so its normal that the particles are ending up in diferent places, your gonna need to get that position, send that position through a server RPC and then use a multicast RPC so that the blood decal is spawn for everyone at the same position i think
256 is the max count in the buffer iirc, more data here https://vorixo.github.io/devtricks/data-stream/
I did this but its still not working, still prints in 2 different locations, how do i need to set it up?
not sure man, things look alright
only thing that i can point out is, if the particle actor is already spawned in the server u dont need the rpc that executes in the server i think
u can just call the multicast directly
well actualy if ur actor replicates u might not need the rpc's at all
bsicly ur particle system that exists in the server will create a bunch of replicated actors that will create the decals
so in theory i dont think u need rpc's
But then thats what i had it my first post tho isn't it? im so confused lmao
ye i didnt think of that when i answered, my bad
try adding a "isServer" check to ur first aproach
that event might be running on the client aswell
yeah i think the receive particle event is running on both, goes both true and false for the is server check
is this cosmetic event that importat? usualy games dont care about particle position that much
is it only cosmetic?
Pretty much yeah, i dont mind the decals spawning not exactly in the same location for everyone but if you look at the in-game image from my first post, i made it so there is only 1 single particle so can only be 1 collision but on the client screen (on the right) it spawns a decal that it see's but then spawns the decal's default material thing at the location of where the server's one is so i need it to not do that lol
So where the weird square is, is exactly where the servers decal got placed
If i can avoid that then where exactly the collision is isn't that important
so in the client theres actually 2 decals that are spawned?
or did u add that square manualy somehow?
Yeah, it spawning the one that it should see and then its trying to show the decal that the server player is seeing
so its working
lol
u just need to not spawn the thing in the client
using the server check should work no?
So the is server check does make it stop spawning in two locations for the client and the decals are spawning in the exact same place for everyone, however client cant see the decals
well thats an entire diferent issue
check if ur decal component is replicating
that would be my first guess
check its default values
it should spawn with the default values i think
not sure if replication affects the variables inside
ahhhh that was it, i had the BP with the decal on it replicating but not the decal component itself, that seems to of fixed it, thanks mate!
is the server client for a listen server counted as an "owning client"?
or is that always server
like is there a PC without authority for the player hosting the listen server
i guess so since the widgets are there
just trying to check my understanding
If you were to call a client RPC (aka Run on Owning Client) on a listen server host's player controller, it would work, but it would still technically be executing on the server.
ok ok cool
just for clarity: ticking replicated on a GameMode blueprint variable does nothing because the GameMode isn't replicated
right?
yep
I would like to replicate my GameMode and see the world burn
does the listen server not call postlogin?
for itself
should i just use the other handle start node instead?
Why calling a RPC from PostLogin crashes the client?
The listen server doesn't login to the server... it's the server
Too generic to be able tell
makes sense so have to call that same setup functions on beginplay for the server / lobby host
cool cool
I mean HandleStartingNewPlayer is a good starting point
Also calls on seamless travels
yeah i was using it for seamless which is why i figured it might work here
thanks
trying to rework my lobby stuff to make sure i understand everything
why would a print from tick on the playercontroller not run on the client?
It will, just not on the remote client
Since player controller is owning client only and server
I have such function, that I call from the server to the client during PostLogin. All it does is just printing a string:
void ACavesPlayerState::Test_Implementation()
{
UKismetSystemLibrary::PrintString(GetWorld(), "CALL FROM THE SERVER!!!", true, true, FLinearColor::Red, 5000.0f);
}
Then this happens(second screenshot)
wouldnt my own run tick though?
It would
is there something about this that keeps it from printing on the client?
the lobby widget and gamestate are there
Not that I see
im hitting this node
But the check that's failing has nothing to do with the rpc. Seems like you are binding to an object that gets destroyed? Or the function is just no there?
I never use BindDynamic
But AddDynamic
I'm not binding anything
And the callback function should be a ufunction
This only happens if I call RPC
Look at the callstack
Neither one of the photos you sent are really helpful
Right
Seems like it has problem with widgets from some reason
Or, just one of them
wow ok was the 0 second time on the prints
Yeah basically you can't add a widget to a non locally controlled client
OnRep_PlayerState will run on remote clients as well
Usually you do an IsLocallyControlled check before you add widget/input
But that function can't be called from anywhere, and in calling it in the above context might end up in a false negative
You want to call it when you know that the pawn has been possessed
Which is usually NotifyRestarted
But it works perfectly if there is no RPC call
And line 301 doesn't crash
Also, there is check for dedicated servers, so it won't run on remote
It won't run on dedicated server, but it can run on client on remote pawns my friend
Client rpc again has nothing to do with your actual problem
Damn I forgot about it
But still, there is just one player there
It might be just forcing a net update, and then crashing things faster
In nativeconstruct is your problem
You are binding to a delegate
I've checked callback again, and it got me there. Why does it have problem with binding when calling an RPC?
At the failing check macro
Check what's failing
Is it the object that is null
Is it the function
I have no idea
I mean I would argue for hours why this code looks bad, but I'm trying to get you to the culprit
I'm willing to read why it looks bad, and what can be upgraded
First don't use the static index 0 getters
Just don't
Filtering paths based on owning client
And the list just grows
You mean GetPlayerState?
Read the multiplayer tips and tricks artcle if you haven't
Yeah any of these static functions that come from gameplay statics
Instead
GetOwningPlayer->GetPlayerState
Looks semantically much better and effectively more reliable
But again I would never count like that on the PS being valid when NativeConstruct is called, because who knows we got a PlayerState
In your example maybe it is...
But in a general environment, you start listening to when these actors replicate even at the widget level
"because who knows we got a PlayerState" What do you mean? Should it be called after PlayerState is replicated and that means it already exists?
Aka OnRep_PlayerState
Which you already got
But will this widget be only added in OnRep_PlayerState
I doubt.
Again these are multiplayer code practices, and I can't be as inclusive in an online chat
Tips and tricks article will do a much better job than I
Reading it rn
Hello!
Noob question. I have a multiplayer ( LIsten Server ) game and in my Character Blueprint, I want to load widgets on the player screen on BeginPlay.
I created a custom event and made that to run on owning client only,
Connected that to my begin play but it seems to fire off even from the server
Started playing around with the Is Locally Controlled condition and was still firing twice
So I added a secondary condition with Is Server and on false to execute,
Had it working on my server client but then all my other clients it would work ...
NOw im hella confused
Begin Play can fire on the server and all clients for something like a character, and even worse, begin play can actually call multiple times as a character goes in and out of relevancy on other clients.
IsLocallyControlled is checking whether the target pawn is possessed by the player controller of the game instance where the code is currently running. So if the current client's player controller is posessing the character, then IsLocallyControlled would return true, for all others it should return false. Same for the listen server host, if the character is the host's possessed character, IsLocallyControlled should return true, for all others it should be false.
I've noticed that there are some limitations to when FastArrayReplication can work. E.g. When I run this code:
FEquipmentSlotWrapper EquipmentSlotWrapper;
EquipmentSlotWrapper.EquipmentSlot = NewObject<UEquipmentSlot>(Owner, UEquipmentSlot::StaticClass());
//EquipmentSlotWrapper.EquipmentSlot = NewObject<UEquipmentSlot>(Owner, ARegister::GetRegister()->ItemsList[ItemId]->EquipmentSlotClass);
Owner->AddReplicatedSubObject(EquipmentSlotWrapper.EquipmentSlot);
Items[Index] = EquipmentSlotWrapper;
UE_LOG(LogTemp, Warning, TEXT("A: Current: %s"), *ItemId.ToString());
Items[Index].EquipmentSlot->EquipmentSlotData.Icon = ARegister::GetRegister()->ItemsList[ItemId]->ItemData.icon;
Items[Index].EquipmentSlot->EquipmentSlotData.ItemId = ARegister::GetRegister()->ItemsList[ItemId]->ItemData.itemId;
Items[Index].EquipmentSlot->EquipmentSlotData.ItemName = ARegister::GetRegister()->ItemsList[ItemId]->ItemData.itemName;
Items[Index].EquipmentSlot->EquipmentSlotData.InHandMesh = ARegister::GetRegister()->ItemsList[ItemId]->ItemData.inHandMesh;
Items[Index].EquipmentSlot->Children.Owner = Owner;
Items[Index].EquipmentSlot->ItemListRef = this;
Items[Index].EquipmentSlot->Owner = Owner;
AddStack(Index, Stack, EAddStackOption::Prevent);
MarkItemDirty(Items[Index]);
From Player's State BeginPlay, it doesn't replicate
Is there any way to check if actor is ready for replication?
can someone help me if I screenshare?
I can't get my attack to show up even though I have the attack running on mc and ros
Is there anyone on that can help me replicate animation?
I know it's a simple fix?
I just don't know what part I am missing
are you replicating the variable that drives the animation state?
Can I DM and show you my current problem?
I'm not sure if I follow what you meant lol
sure
Is it correct that GameLift 5.0 does not support GameLift Local?
Need to use GameLift Anywhere
What does this warning mean? [2023.07.25-10.13.00:934][255]LogNetPackageMap: Warning: FNetGUIDCache::SupportsObject: SphereComponent /Game/Developers/Yasin/UEDPIE_0_Landscape_01.Landscape_01:PersistentLevel.BP_Lamium_C_32.SphereComponent_0 NOT Supported.
Hey, I'm currently trying to find all session but none is found:
Any idea about what I miss ?
this is my query:
LastSessionSearch = MakeShareable(new FOnlineSessionSearch());
LastSessionSearch->MaxSearchResults = MaxSearchResults;
LastSessionSearch->bIsLanQuery = IsLANQuery;
//LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
const ULocalPlayer* localPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->FindSessions(*localPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef()))
{
OnFindSessionsCompleteEvent.Broadcast(TArray<USessionEncapsulation *>(), false);
}
And these are the settings I use to create my session:
LastSessionSettings->NumPrivateConnections = NewSession.PrivateConnectionNumber; //equal to 0 during my tests
LastSessionSettings->NumPublicConnections = NewSession.publicConnectionNumber; //equal to 5 during my tests
LastSessionSettings->bAllowInvites = NewSession.AllowInvites; //true during my tests
LastSessionSettings->bAllowJoinInProgress = NewSession.JoinInGame; //true during my tests
LastSessionSettings->bIsDedicated = !NewSession.AllowPlayerHost; //true during my tests
LastSessionSettings->bIsLANMatch = NewSession.UseLan; //true during my tests
LastSessionSettings->bShouldAdvertise = NewSession.Advertise; //True during my tests
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = true;
LastSessionSettings->Set(KEY_SESSION_NAME, NewSession.SessionName, EOnlineDataAdvertisementType::ViaOnlineService);
hello.My dedicated server cookOrderFile contains textures as well which are not useful for dedicated server packaging.How to exclude them.Thank you.Plz tag me if you are replying
Hey everyone I am developing a multiplayer game but for some reason I am getting this error even in PIE with play as listen server "LogTemp: Warning: Could not find target for network state message." where I am suppose to start looking did I just messed up some setting or option why does this happen in my main project and not in any other? Any hint where I should start would be more than welcome!
is there a way to disable auto connect to the server?
can you show where you get the first warning?
is looks like something related to replication
maybe you have an actor that doesn't exist on one of the sides client or server, and you want to replicate something or calling a server RPC on it
There might be an option/button that I'm unaware to do this, but when I needed to test that I would open a separate dedicated server, then open PIE in standalone net mode and connect to server manually (or even on a BeginPlay to make it automatic-like)
There is also an option to open more PIE clients during play if that works as well
So you build a dedicated server using source
then run it
and open pie and connect to the server manually?
The Warning shows up directly after starting, yes replication of rollball pawn is not working I am using an plugin called Smooth Sync for better replication of the Physics but at the moment when I turn it off and use the build in movement replication it just works of coarse with that jittering. The strange thing is that thought ok that's then the plugin that does the trouble, but when I replicate this basic setup in a different project it just works, so I am kind of stuck since it is in my main project and not something that is replaceable.
Oh, I just discovered "GameLift Anywhere." Now, I'm curious about how to dynamically set the -authtoken when starting the GameLift process.
i got a quick one. i just tried to RPC some variables over from server to client via Multicast
and it looks like all of my variables and arrays made it over, but my map variable returned empty.
are maps not valid for RPCs
i tried some janky stuff and used a foreach loop and broke the keys and values of the map into 2 arrays.
sent the arrays and then used them to rebuild the map on the other side.
Its jank AF.... but it worked, and the values carried that time.
but if anyone knows why this is. or mabey its a bug. it would be nice to know why the Map variables didnt properly send via Multicast
When I play as client, this plays the sound but returns null instantly. As Server it works as intended and actually returns a value.
Any clue why this might be?
is there a way to create a save locally on clients? or is it enough when i just let them execute the save?
ClientRPC -> Do SaveGame stuff
alright, thanks!
https://docs.unrealengine.com/4.26/en-US/InteractiveExperiences/Networking/HowTo/DedicatedServers/ like they said, there is no "no level", you can have an entry/startup level tho, ignore that its for 4.26, the process is still the same on 5.2, unless you want to use the 5.2 instructions and use lyra...
How to set up and package a dedicated server for your project.
Hello, I am using Set Actor Location for the client and then unless they move other actors are not relevant what could be the reason or what should I look for please
Youwhatnow?
I think what they mean is that they used SetActorLocation on a Client (not sure if on the Server for a Client or just locally) and that probably for quite the distance, and if the Client doesn't move after that, the Actors around it won't become relevant
I'm guessing he's not telling the server that he moved.
Yes Exactly! and it is only called on the server. My issue is when other actors are not relevant to the Client and I teleport the client next to them they will not become relevant until the client moves
Helloo
My Game Lags and Hangs when more than one player joins the game
I tried playing through two machine
It still hangs
And Sometimes the First Player Who joined , Vanishes when the second player joins
Do Anyone Know how to fix this?
Maps are not valid rpc in UE. But you can replicate them manually via TArray<TPair<string, int>> or whatever you need
what would be the best way to ping sync a timeline? i have a replicated timeline but players see it in slightly different positions due to their latency. i can get their ping client side
is there still no way to enable seamless in PIE?
I think if you try to have a replicated component as a child of a non replicated one
There is an experimental cvar you can flip. Search this channel. I forget the name. Something like "SeamlessInPie" or w/e
Hi guys reddit bot told me that you might be able to help me so I'm giving it a shot,
I created a lobby widget for my game and tried to show it on "event handle new player" , but the event executes on start of the game before even the session was created and any attempts of creating a session fail. But the strange thing is when I simulate the game everything runs as expected, so the "event handle new player" is called only after the session has been created. Can someone explain this behavior? And can someone tell me how to make this event behave the same in the "play" mode?
Hm, generally speaking, that event has nothing to do with a Session
Sessions are just containers of information
So maybe you mean something else?
so the event should fire even when not connected to server/not being the server?
Session doesn't mean being connect to a Server
It often goes hand in hand, but it's two different things
You can host a Server without a Session
You can create a Session without hosting a Server
The Session has info about how to connect to the Server and more (e.g. how many players, etc.)
Usually shared via some MasterServer that for example Steam offers
So you probably just mean connecting to a Server
HandleStartingNewPlayer or whatever the event is called, calls in the GameMode for each player.
No matter if connected or not
a MainMenu GameMode that has no Multiplayer context will also run this for the one player that is playing the game
okay i get it now, just figured i can just create separate lobby and main menu game modes and it should work as i want it to, thank you for your clarification!
Correct, you should have a bunch of GameModes for this actually
My usual setup for this would be
- GameMode_Base
- GameMode_MainMenu
- GameMode_Game
- GameMode_Lobby
- GameMode_Gameplay
Base for whatever all of them need.
and Game is useful if you need to move anything between Lobby and Gameplay Levels when Seamless Traveling
And then, if needed, matching hierarchy of other classes, like GameState, PlayerController and PlayerState
okay that's actually all I needed to know. Thank you very much for all your input, it was really helpful
But he uses _ in his names. So 🤮
Main reason I did this is to make sure they don't mistake it with GameModeBase, which is an Engine class.
Do the ol' classic MyGameModeBase 🤣
But yeah, I do use underscores for class names and BPs ¯_(ツ)_/¯
It's okay, I don't blame you. Epic has forced your hand.
Right, in UE that is. Other languages and frameworks of course have vastly different naming conventions
No not a build, you can start a standalone server with the help of editor from a console. Should be something like Path/To/Your/UnrealEditor.exe Path/To/Your/GameProject.uproject -server
Here are some explanations about it, if you would need more options
https://docs.unrealengine.com/5.1/en-US/command-line-arguments-in-unreal-engine/
Whats wrong about using ‘_’ ?
It looks ugly
Its a popular naming style
SpOnGeBoBCaSe
Can we all stop with the prefixes.. MainMenu_GM_BP holds the same info but in order of relevance so I don't gotta read past alphabet soup for no reason
Ah - a postfix kind of person huh
Idk, I like the prefixes because when I search for stuff I don’t rmbr the name of exactly I’m automatically filtering from the first few letters
That being said my game modes are just GM_ not preceded by BP
We should stop using any fixes, whether it is pre or suf - there are filters available in the content browser
Idk I barely use the content browser filters
Cause if I’m searching it’s prly from a context menu
i.e. castTo…
Guys can we get back ontopic please.
Oops sry 😅
I really agree that everyone has their own naming style
should I prefix my files with MP_ to remind myself that I am making a multiplayer game ?
lol of course not
why not ? I would like to have an indepth discussion about naming conventions in the context of a MP game
move to #ue5-general
@whole grove I hope you don't mind the tag but you mentioned sometime ago that you could send an RPC to the server and await the result in an async awaiter using UE5Coro. I wanted to know if it was already built in the plugin. Or how I would go about implementing it if it's not to complex. Thank you 🙏
If I have a replicated custom hover vehicle movement, and the way I'm doing it is by getting vectors from the client and server, then comparing them and lerping them into the server, directed position.
I'm not sure if this is the correct way to do it since it's functional
Is there actually a correct way?
Something I might be missing?
@chrome bay Could likely explain the difficulties you face lol
She's probably talking about the http stuff, not RPC's. They don't return anything.
Ah okay. I must have misunderstood
Yeah. I know these ones.
Which brings me back to my original problem. I'll post again later today. Need to get some sleep
lets say I have 2 clients and a server, and an actor in the level with a beginoverlap event, there is 3 instances of that actor (one on each client and one on the server) and that event will run on all 3 instances. what check do I put in that event to only run the code inside that event on the instance that is local to the client that triggers it ?
- or any actors that they "own" overlap I guess I should say.
thx ill check out the role incase I need it for something else OtherActor->IsOwnedBy(OtherActor->GetInstigatorController()) this actually gave me what I needed aswell
hey bro, did u test AWS Gamelift Anywhere? I want to register my local machine to fleet. But it doesn't seems to work correctly. Is there any additional network configurations need to be set? like Firewall
No, I haven't messed with it myself, I just know about it :/
unreal doesn't actually try to replicate full data from assets like sounds right
i'm assuming there's just some sort of pointer hash that keeps track of the asset id between and then only that asset id is sent over
thanks
Why do you want to setup Gamelift Local?
Are you very early on in the integration process?
Gamelift local is extremely limited.
It is also one of those things where once you have a working process integrated, you will likely never use it again.
I want to test Dedicated Servers before uploading build
Take a look at this video series as well #multiplayer message
We already released a game on gamelift, but I want to try "Gamelift Anywhere" which is introduced recently
I believe it could significantly enhance the development process
Yeah. Uploading a server to GameLift and getting it active takes way too much time. GameLift local was the solution to quickly iterate. With the most recent SDK GameLift local no longer functions and they want you to use GameLift Anywhere instead. Not sure if it is any quicker but I imagine it would be since it doesn't have to do whatever logic they're doing to containerize your server, so I'd hope the server just joins the fleet and can be used immediately.
noob question again XD. With managed EC2 instance, how to pass auth token to game server. Should I write additional c++ code that retrieves authToken before calling initSDK() ?
@regal solar Seems like further down the page it explains what you need to do?
lol there it is XD
Ah, well actually the other way around (root was set as replicated and sphere under was set as not replicated) but yes making the root not replicated makes the warning go away, thanks
hi guys i have a simple chess multiplayer game , it works fine in PIE for multiplayer online , but when i package the project , it just doesnt work anymore
hello, i am trying to find documentation on how to generate the public / private key pairs for a dedicated server, i can't find the docs i read before 🙂 sorry too many long days coding
hi! I cant figure something out. I spawn an actor inside of my player controller. I set an owner of this client to be the player_controller. On the client its local role is simulated_proxy, so i cant call any RPCs from it. What am i doing wrong? Spawned actor is set for replication. Appreciate any help!
What kind of RPCs are you calling, Client, Server, Multicast?
server. I guess the spawned actor should be an autonomous_proxy, but i cant understand how do i set it so
Simply setting the owner should be fine
And you're sure you spawned the actor on the server?
Yeah, i call a server RPC from a player controller to spawn an actor, and set its owner to player controller. Then, when i call an actors function from player_controller that prints getLocalRole i get simulated_proxy
Hmm, weird
let me test something here
I'm getting Authority as role here
which is what it's supposed to be if its spawned on the server
RPCs also work fine
I call the spawnActor RPC from a client. If i call it on the lsiten server i also get Authority. Maybe something is up with my setup =\
You call from client. But is the SpawnActorFromClass node in a Server RPC?
from what i understand it is. You can see it on the 2nd screenshot. Server_spawn_actor "Executes on server"
Yeah, just saw it now.
hold on...
Okay, I called the function on possess instead of begin play. and the local role is simulated proxy but RPCs still work fine
@whole grove@chrome quest not sure if these are what you are after https://docs.unrealengine.com/5.2/en-US/API/Plugins/NetcodeUnitTest/FMinClientHooks/
Delegate hooks for the minimal client - also directly inherited by UMinimalClient
ahh ok, thats a shame
🥲
Thanks for checking! I'll revise things one more time!
https://docs.unrealengine.com/5.2/en-US/API/Runtime/Engine/Engine/FOnSendRPC/ there is only the onSendRPC del I think then, which is not what you want I dont think
ffs... Delegate for hooking ProcessRemoteFunction (used by NetcodeUnitTest) I think thats unit test again, but it was just in the NetDriver docs...
Lol
im not even sure I believe that https://docs.unrealengine.com/5.2/en-US/API/Runtime/Engine/Engine/UNetDriver/ its in this list , and the include for it is just netdriver #include "Engine/NetDriver.h"
may i ask how you call the RPC? So you call it from a client, in an actor that is a simulated_proxy, and it runs fine?
I can only make it work if i add a server RPC inside of controller that calls actors RPC. Like PlayerController-> ServerRPC_that_calls_actors_RPC.
But not if i just try to call the actors RPC from a playerController just by actor reference.
ServerRPC->SpawnActor->ClientRPC Defined in Actor
You must make the actor reference replicated for you to call RPCs directly from the ref
double checked the source, it is in #include "Engine/NetDriver.h", but its wrapped inside #if !UE_BUILD_SHIPPING
#if !UE_BUILD_SHIPPING
/**
* Delegate for hooking ProcessRemoteFunction (used by NetcodeUnitTest)
*
* @param Actor The actor the RPC will be called in
* @param Function The RPC to call
* @param Parameters The parameters data blob
* @param OutParms Out parameter information (irrelevant for RPC's)
* @param Stack The script stack
* @param SubObject The sub-object the RPC is being called in (if applicable)
* @param bBlockSendRPC Whether or not to block sending of the RPC (defaults to false)
*/
DECLARE_DELEGATE_SevenParams(FOnSendRPC, AActor* /*Actor*/, UFunction* /*Function*/, void* /*Parameters*/,
FOutParmRec* /*OutParms*/, FFrame* /*Stack*/, UObject* /*SubObject*/, bool& /*bBlockSendRPC*/);
/**
* Delegate for hooking ShouldSkipRepNotifies
*/
DECLARE_DELEGATE_RetVal(bool, FShouldSkipRepNotifies);
#endif
oof
its also the SendRPC which is not what you need anyway, but I was curious if it was even there. Im still wondering why do you need a delegate and not just another rpc with the return data etc, but I'm not using coroutines yet so I guess I wouldnt understand...
I'm making a request to the server and retrieving it in a client RPC. RPCs are almost like async functions because they can return before the RPC is sent. For example
void Server_Print()
{
Client_Print();
Print("This is server")
}
void Client_Print()
{
Print("This is client");
}
Your expected result would be This is client followed by This is server. But what you'd get in most cases is the reverse.
This adds a layer of complexity when working with non-replicated types. So I use a delegate and a FGuid request ID because any one could make the request at any time.
so its something like
// All of this is in the player controller, or some owned actor that can make RPCs
TMap<FGuid, FOnDataReceivedDelegate> OnDataReceivedCallbacks; // non-replicated, client-only map
void Client_RequestData(FOnDataReceivedDelegate Callback)
{
FGuid RequestID = FGuid::NewGuid();
OnDataReceivedCallbacks.Add(RequestID, Callback);
Server_RequestData(RequestID);
}
void ServerRequestData(FGuid RequestID)
{
auto SomeData = GetData();
Client_ReceiveData(RequestID, SomeData);
}
void Client_ReceiveData(FGuid RequestID, auto SomeData)
{
FOnDataReceivedDelegate* Callback = OnDataReceivedCallbacks.Find(RequestID);
Callback->ExecuteIfBound(SomeData); //Broadcasts to the actual object making the request.
//Cleanup map
OnDataReceivedCallbacks.Remove(RequestID);
}
Even if you can understand what is going on up there, you see how complicated it can get for different kinds of data. I need at least 3 separate RPCs for each combination of data
Does anybody know if it is possible to get server port on client? GetWorld()->URL.Port returns local client port.
BP or Cpp
this is how I normally do client->server->client responses,
UFUNCTION(Server, reliable)
void Server_Request();
UFUNCTION(Client, reliable)
void Client_Response(const FString& response);
void ATDHPlayerController::Server_Request_Implementation()
{
UE_LOG(LogTemp, Warning, TEXT("Request to server succesful"));
Client_Response("response");
}
void ATDHPlayerController::Client_Response_Implementation(const FString& response)
{
UE_LOG(LogTemp, Warning, TEXT("Response from server : %s"), *response);
}
It does take alot of RPCS...
Yeah. This is the usual method. But in my case, the player controller is not even using the data. It's a widget.
But widgets don't exist on server and aren't replicated so I can't just pass it into the server rpc or client rpc to do stuff.
its the same in my case, I type a command on the widget in an emulated linux terminal, widget passes to an rpc on the controller, and then the response passes to another function on the widget, so it does get messy...
Yup - that's just networking though.
yeah...😩
so, there really isn't anything cleaner?
Nope.
You have to communicate through something that both machines have. PC is the most common when it comes to UI stuff.
Right. Oh well, glad to know I wasn't too far off. Now I just have to worry about latency
Fun times 🥲
This is one reason why I've stopped using AHUD for managing my UI overall (for networked games)
It works well enough for some stuff, but I noticed that I ended up just having to route client RPCs through the PC anyway.
Was just a needless abstraction I felt.
I don't even use AHUD. Everything is PC
Replicated client movement is too fast.
I scaled down thirdperson to 1/10 and modified option about velocity at the character movemnt detalis.
These can be reason for the error?
If you’re doing a custom event replication from client to server to multicast, you need to divide whatever you’re using for the movement component by the amount of times you run the actual movement event. For example if you run the component twice for server and client you have to divide them by 2
Essentially get and average
i think i figured it out. The RPCs were not working, because i had a AI_auto_posses set to placed or spawned. Now i have to figure out how do i make use of RPC and controlling an actor with AI controller at the same time 😄
Ohh that's why
any idea how can i use AIcontroller to use functions like AIMoveTo, and be able to use RPCs?
AIController only exists on the server
ahh, i see =\
hi, does somebody know why cable component is not get destroyed on client?
I m calling it via GameplayAbility and my function has UFUNCTION(Client, Reliable ) specifier
Hello, I am trying to figure out why the OnRep_Characters isn't triggering every time i set the CharacterData,
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Characters, Category = "Avalon|Data")
TArray<FAvalonCharacterData> CharacterData;
DOREPLIFETIME_CONDITION(UAvalonCharacterSelectComponent, CharacterData, COND_None);
this seems like it should trigger any time i set
DOREPLIFETIME_CONDITION_NOTIFY(UAvalonCharacterSelectComponent, CharacterData, COND_None, REPNOTIFY_Changed);
@torpid girder
Oh did the syntax change?
I think that's how it has always been for OnReps.
I'm pretty sure you didn't have to specify that back in 4.1soemthing!
It's been like that since at least 4.25 (that's about where I started using the engine)
You don't have to do that for onreps
You do that macro when you want to change the notify conditions
How are you verifying that it isn't triggering?
Is it not tirggering on the server or the client?
i put a break point on where it was set and the on repl function
the set triggered and the on repl didn't
Server doesn't call OnRep automatically
(In C++)
You have to call it manually on the server
i didn't used to
It's been like this for years and years and years and years
err its been working like this for me for years and years
It is only like this in C++, not BP
ok explain to me
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Characters, Category = "Avalon|Data")
TArray<FAvalonCharacterData> CharacterData;
why even define that replicate using if i have to call it manually?
Good to know... Thanks 🙂
Is the OnRep not triggering on the server or the client
If you change this value on the server. The OnRep will not fire automatically on the server. You must call it manually.
Property will be configured for replication. The provided function is called only when the replicated property is received via replication.
so i set the character data on the server, it replicates to the client
that function should trigger after the data has replicated
What class is this property in?
its in an actor component on the player controller
Where is this called?
in the PC constructor
AAvalonPlayerControllerBase::AAvalonPlayerControllerBase(const FObjectInitializer& ObjectInitializer) : Super()
{
bReplicates = true;
AvalonCharacterSelect = CreateDefaultSubobject<UAvalonCharacterSelectComponent>(TEXT("Character Component"));
AvalonCharacterSelect->SetIsReplicated(true);
}
Does it say that it is replicating in the details panel of the BP class?
let me double check
Hey everyone! In a multiplayer game, if a player shoots a gun, where should the bullet be handled so that the odds of cheating are reduced by as much as possible?
Does it matter if I handle the bullet in the player actor, game mode, or other as long as it's handled by the server only and replicated to others after?
Or should I spawn one for the client and one for the server but only calculate damage based off of the server?
I don't know what the best method would be. Any input is appreciated!
blueprint says it is replicated
what is strange it is triggers once
it doesn't trigger if the var is set again
Only matters if the server handles it.
Usually for best experience, people will spawn a bullet client side and do some wizardry to line up with the server one.
How could I do something similar to this "wizardry" 😆 what exactly are they doing to make both match up?
i know lets wrap it in a server test
Hello. Does anyone know why "is pawn controlled" returns false on a pawn that is possessed on the clients but on the server it returns true?
Same response that I see all the time
"Check Unreal Tournament code".
Why would "is pawn controlled" not work on clients? That doesn't make sense at all....
Do you mean is player controlled?
Either way, it likely doesn't return true on clients because being "controlled" usually indicates it needs a reference to a controller which in multiplayer they aren't replicated to clients, so it doesn't appear as if they are controlled to clients.
Is player controlled works fine on clients. I just tried it. But is pawn controlled doesn't work on clients? Why is that?
But why does is player controlled work then? Doesn't that require a valid refrence to a controller as well? o_O
Hmmm that is so weird
Why would is player controlled work then? Doesn't make sense to me
bool APawn::IsPlayerControlled() const
{
return PlayerState && !PlayerState->IsABot();
}
Not checking the same thing.
Oh it checks playerstate, alright ok I get it
playerstates are replicated
controllers are not
aight k thnx
What would I be able to use then instead to see if a pawn is controlled by a player or a an AI controller on the clients?
Guess I could just do the check on server and replicate the result
🤷♂️
Why would a client need to know?
It's an optimization thing for tick
A vehicle that needs to do visual stuff
Don't want it to do said stuff when vehicle isn't being used
hence I need to know if a player or AI is using it
But replicating the result from server works 🙂
so all good
ah it works if i empty the array
i wonder if it didn't update because the values were the same
This is true as well
Hi all. Any idea why when I join a Dedicated Server my character jitters and rubberbands around?
If you want to change that behavior, you use the macro that Datura showed and do REPNOTIFY_Always
If the pawn is possessed by a player, then checking IsPlayerControlled should work.
True == Player possessing. False == AI or None.
Yeah I know. But also need to know if it's controlled by an AI controller
So I need Player or AI -> true otherwise -> false
Gotcha
But yeah the replicated result of is pawn controlled works as intended
Bump
Hello! Is it possible to know whenever we play with server enabled in same process while playing in PIE?
I mean we could play with dedicated server started in separate process, but can play with dedicated in the same process. So I would love to know how to check it
Hello guys, can anyone help me just to spawn an actor on client first, then replicate it for the server and the other players, but not rep for the player who actually spawned the actor.. I tried different things but can't get it
Is there a simple way to make a max player count on a dedicated server and make it a command line parameter or am I stupid for asking?
Now you can use that however you wish.
-maxplayers=16 is what you'd add to the command line for this to work.
thanks, I needed this for a server provider for my game
should I put this in the gamestate?
I'd say game instance on Init. Everything can then read from there and map transitions don't change it.
I'd also set a default value on there in case a value isn't specified.
Keep in mind that this doesn't actually limit the number of players, it's just a means for you to get a value from the command line into the game.
I have a idea on how I can do max players
depending on how you connect, this might not help, if server allows 16 players, but clients think the cap is 8
generally, you'd put it in session settings
the game isn't session based so I think it should (in theory) be good
wait is a dedicated server session based?
all unreal connections except for open ip:port are session based
I know for a fact that dedicated servers have a external computer acting as the server while clients connect to it
that's how I have it
you don't use c++?
I can't handle text based programming lol
Lyra has a fairly decent session implemenation
with DS support
but i have no idea how much of it is exposed to BP
but generally
server opens a map, creates session settings, creates a session with those settings and turns on presence
clients search for sessions, find the one advertised by DS, then JoinSession
open ip:port won't get you far
ah ok
where is session settings?
its a struct that should be MakeSessionSettings-able from BP
doing dedicated servers without c++ support is not a great idea imo
is there a good tutorial on c++ stuff?
there are tons, but i wouldn't know
i've been programming for a decade before i first touched unreal, so i never visited any of them
but generally
building this by hand is also kinda crazy in your situation
there are engine plugins, like CommonUser and CommonSessions
that do a lot of things for you out of the box
Hi, can anyone help spawning an actor on client first, then replicate it for the server and the other players, but not rep for the player who actually spawned the actor.. I tried different things but can't get it, really it's been 2 days.. anyone who could help would be very appreciated, thanks
c++ involved?
I'm using BP, but understand c++
for client spawned actor to sync with a server spawned actor
it needs to be spawned with exact same name
and it needs IsFullNameSupportedForNetworking overriden
(for a runtime spawned actor)
both points require c++
you can set the actors name using FActorSpawnParameters in SpawnActor function overload
in this scenario, after server spawns a replicated actor, it would be sent to everyone, including the original client that spawned it
but, that client would be able to match the actor with existing instance
so it would not spawn another one and it would replicate normally afterwards
not entirely sure now other clients would react to it, might need a bit of hacking, might work out of the box, not a workflow i ever tried
you'd also need to swap roles on original client, as anything it spawns has ROLE_Authority
and if server is taking over the Auth, then client that spawned the thing locally needs to swap the roles by hand
I see a bit, this means that on the client I can manipulate the actor locally (lets says its position) while still being replicated to server/other players right ?
it would not replicate to other clients, no