#multiplayer
1 messages · Page 92 of 1
Unless you're talkin' about only on the server, if it's the server
If the server does the moving, it doesn't need to send a server rpc because it's already the server.
So you do "local" movement on the client and the server.
But if the client is the server, you don't do it twice.
would it work on the server?
It would work on a listen server with no clients.
Yes - IF the server is running that code.
If it is the client running that code - it will only run on the client and not the server.
Because you commented out the Server RPC
ok so if its running on the client it would only work on the client, correct?
but since the projectiles are spawned on the server i assumed that the code was running on the server? does that make sense?
since server has authority over spawned objects no?
This code is running before the projectile even spawns, isn't it?
Nevermind. I've got player movement code on the brain.
Anyway, if it works, don't touch it.
You should try setting up a listen server with a client and doing it on both.
And seeing if it works.
in my mind it makes sense that if i run the local version of that function that the effect appears in the server controller player, since the projectiles are server owned, but its the oposite, if i comment the server part the effect only shows when playing the stand alone clients
I.e. can the server see the client do things? CAn the client see the server do things?
for now it seems everything is working
imma test it one more time with a standalone server
but i am still confused lol
The projectiles are replicated to the client as well.
Probably.
So it's running on both the server and client.
i guess that code was running on the client, its the only option that makes sense
Even if an actor is "owned" by the server, there will be a copy on both the server and client (if it is replicated). Running code "locally" on that actor doesn't mean it always runs on the server.
It will run on whatever instance it is on.
To be fair - I did tell you to get out while you can.
haha
Single player is the way of life.
Each copy of unreal, server, client, whatever, is entirely separate and has its own actors. They are not related to each other at all, except by a little stream of bytes over the network.
single player is fun but multiplayer is just something else
If you don't actually tell unreal to send things over the network then it doesn't do it.
That can be Server to Client replicated variables or RPCs.
i am aware of this, im just not sure when to do it in some specific cases like this one
Follow the pattern we just taught you and you're sorted.
Just be aware that on the internet, there will be a time delay between the client activating things nad hte server activating them.
On your own machine it is instant.
for example, ive been using timers for status effects like poison and stuns with rpcs and they work fine because they are straight forward
the client sends signal to the server to poison an enemy with an rpc
and then proper variables get replicated
It shouldn't do that, but go on.
It should say, "I want to activate this ability" - the server should then say, "Hmm, can he do that? Yes - activate it on the server! No - tell the client he's a bad man."
thats a whole other story lol
im just simplyfing things
On the client, while that is happening you might "pretend" that the server said yes and start doing some visual effects or something, but cancel them when the server says no.
If you don't add in validation from the start then you're going to have to remake your game from the ground up to add it in properly.
u mean because of security concerns?
Correct.
I've narrowed down the issue I think, I changed the event to just print out whose turn it is, and it seems the only reason the client was seeing Waiting for Turn before was not because of the event logic, but because I set that to be the default text. With this new logic, the client sees Waiting for Turn and never sees the text that its supposed to be being set to
well that is indeed an area where i dont know much, but it is a pretty simpel concept at least at the moment, players shoots something, if it hits then it does a status effect
i can see players cheating with aimbots
skill cooldowns are not server authoritative but they could be
so i dont think its gonna be much of an issue, but i might be wrong
Cooldowns especially should be server authoritative.
You may have some leeway by some milliseconds.
Because they are the easiest thing to validate and very easy to stop people cheating with.
is that validation a pattern aswell?
or do u just set the cooldown vars to replicate?
do u just do a check on the rpc?
I would google that stuf. I' have a meeting soon!
One thing I will say, this is why UE has the CMC and GAS. Because it has all this stuff already build in.
And you don't need to "reinvent the wheel" to do it.
Player Controllers are not replicated, so you can't get the player controller from the playerstate on other clients.
even so, on the client wouldn't I still see "Player 's turn"?
I'm feeling like calling the event dispatcher from a rep notify is not the way to go, but you got it to work so im just confused
No, because your cast fails as the return value from GetPlayerController is None.
The player who's turn it is should be a PlayerState
PlayerState PlayerWhosTurnItIs
oh yeah
it is
if i remeber correctly gas wasnt a thing when i started this project or it was very early
ive been on this thing for 3 years
lel
3 years and a half actually
Oh damn.
Hey if anyone can assist me I have a dedicated server that my clients connect to but because the event within the GameMode BP “Event Handle New Player” isn’t asynchronous when multiple players try to connect at the same time only 1 will receive a spawned pawn. How can I handle having multiple logins at once? Thanks all! - put this in general maybe it’s better placed here.
there shouldnt be an issue with multipel connections, the server will handle connections in sequence
ur probably doing something wrong
So you believe it’s a separate issue? Kk I’ll look into that
i have multiple connections on my server working just fine so it cant be that
And your using the basic event handler BP to spawn the client pawns just to clarify?
im not using any BP events, the game mode class should handle spawn by itself ifu dont do anything, if im not mistaken thats handled around login or postLogin
depending on what u are doing you shouldnt have to messw ith that
What is the difference between End Session and Destroy Session?
Gracefulness?
I think End session is complementary to Start Session whereas Destroy session is complementary to create session?
Am I right?
Sounds about right.
Do I need to call Start Session explicitly?
Or you could Join Session?
Yeah, heard that automatically calls Start Session. So I just end session and then destroy it when closing the session, right?
I guess?!
Thank you for the help 😊
I'm not sure I was entirely helpful.
Trying to make a RTS game, so naturally I try Replication Graph, looks like the graph calculates its culling distance base on player's camera location
Problem is, camera is far away from the battle field with small POV to mimic orthographic camera, so that every actor has almost the same distance to the camera, and I need to check if the actor is far enough from the point that camera is looking at, not the camera location itself
Is there any way I can change the default 2D grid other any other settings so they use a location offset from the camera location instead of the camera's location?
What is the argument I need to pass to this function?
Also in JoinSessionComplete before client travel I want to check for number of open connections and num of public connections on current session. How can I do so?
Are there any downsides of using FastArraySerializer?
Having to mark elements as dirty manually is the only real downside.
And should I really use GENERATED_USTRUCT_BODY() instead of GENERATED_BODY() for this?
Ok, I was wondering, as all tutorials related to FastArrays were using them
I believe that’s correct if the server is calling the function. Someone who’s more up to date on things can correct me if I’m wrong
Event*
Anyone?
How can I use NetDeltaSerialize from FFastArraySerializer with more than on property?
bool NetDeltaSerialize(FNetDeltaSerializeInfo & DeltaParms)
{
return FastArrayDeltaSerialize<FItemSlot, FItemList>(Items, DeltaParms, *this);
}
private:
UPROPERTY()
TArray<class FItemSlot> Items;
UPROPERTY()
AActor* Owner;
Make a structure that contains just your array rather than trying to put everything in a single struct.
So, create new struct and put it into oryginal struct in place of array, right? But, isn't there a way to do it with one struct? Would there be any significant downsides?
Oh,okay TY
If I'm modyfing all elements in the FastArray, can I just mark array as dirty, or should I mark every array's item individualy?
Mark the Items Dirty
Also, if I have a FastArray of objects, that holds a FastArray of objects, and if I Empty the first array, I do not need to mark these sub arrays as dirty, they will delete on their own, right?
You only want to mark the entire array dirty when you remove an element
Since you cant mark an element dirty if it doesnt exist 😛
Makes sense
But what about second case?
Yes
I guess fast array inside fast array is not supposred 🤔
I put fast array inside UObject
And the array holds pointers to the same UObjects
This way its possible
thats totaly diffrent because, u r replicating pointer, that fast array is inside object not inside another fast array
Solution:
FOnlineSessionSettings* SessionSettings = SessionInterface->GetSessionSettings(SessionName);
FNamedOnlineSession* NamedSession = SessionInterface->GetNamedSession(SessionName);
int RemainingSpots = SessionSettings->NumPublicConnections - NamedSession->NumOpenPublicConnections;
Then, how should I approach it?
If I'm clearing all these arrays recursively, should I mark them all as dirty?
As no other pointer will be pointing to the object that hold this array, these should delete by itself, right?
I dont remember myself, just see examples
btw I guess you need to override some functions if your struct has UObject*
I already took care of overriding
So I created a FastArray struct, and but it into other struct, but I got this
[2023.06.14-07.01.59:691][127]LogClass: Warning: Property /Script/CCO.EquipmentSlot:Children contained nested NetDeltaSerialize struct '/Script/CCO.ItemList:Items', when this is not supported. Only use NetDeltaSerialize structs at class level. Struct will replicate using non-delta serialization.
Putting it inside replicated UObject instead of FStruct is a good idea?
so in the "Level Bp" i have a Day/Night Cycle, but from testing it yesterday with a few friends it only affected my clients not theirs :/ ??? its a dedicated server so everyone was "remode/clients" ?
How about you launching 2 or more clients locally on your PC?
@small grail erhm ok so it works on my end :/
You can't use it for more than one property. FFastArraySerializer is a wrapper for an array only, and it has to be a class member, it can't be embedded in something else. Split it into two properties at the class level.
Don't wrap it in a replicated UObject, that's just adding masses of overhead/complexity for no real reason
this sounds weird. Should be no reason not working on your friend side.
how do i replicate set material node in ue5?
help pls
Hi guys, In spectatoing mode, I possess a SpectatorPawn, how do I return back to my original pawn when I do seamlesstravel back to lobby ?
Hello, I'm currently implementing dying, I'm not quite sure do I do this right if someone could tell me fast please. So i just Do Die() only on server and it activates dying ability and cancels others -> It will call SetDyingCollisionAndPhysics that sets boolean bIsNPCDead(replicated using OnRep_SetDyingCollisionsAndPhysics). But In my Onrep functions is there something that should happen only on the server or do i do something wrong. It currently works but i think OnRep is wrong. Thank you!
OnRep will never happen on the server unless you call it manually from the server.
In C++*
It isn't triggered when replicated variables are sent.
@latent heart Im also calling the Onrep on server function, so it will happen both on server and client
But like setting the maxwalkspeed to 0 and collision settings, is it okay to happen on OnRep like that?
If the OnRep is triggered by bIsNPCDead, it'll work just fine.
The OnREp seems fine
I would change the MaxWalkSpeed to MovementMode = MOVE_None instead
But that's it
And maybe rename the OnRep. OnRep_IsNPCDead might be better unless the OnRep is used by multiple replicated vars.
hey everyone, i implemented a custom cmc for client side prediction using a whole bunch of tutorials, im still trying to figure things out and ive run into a small issue. the cmc works only on server and not the client, it doesnt run the sprint function ive written on the client. after some printing of messages in log the only clue i could get anywhere close to whats going on is all my flags get updated and the fsaved funcs run properly, i printed a debug message on sprint keypressed to check if the pawn owner has authority and the listen server has authority whilst the client doesnt. i cant tell if its because of the authority that my client's sprint function isnt running or if its because of something else? any idea ? ive tried to search a lot on what hasauthority means and i keep getting more confused as to what authority here has to do with this, im guessing clients dont have authority over their actors?
your gonna be hard pressed to find some one that can help you with the CMC, eXi might but you need to get lucky to find him online
oh wait, he sent a message just before yours lol
guys i need to set this "GetFirstPersonCameraComponent()->bUsePawnControlRotation = true;" on an autonomous proxy
i tried just getting the reference and casting
like so
character->GetFirstPersonCameraComponent()->bUsePawnControlRotation = true;```
but its not working
and i have no idea why
@latent heart @thin stratus Thanks both!
Clients don't have authority on Server spawned replicated actors, correct.
For characters the role will be Autonomous
For the local client
The key press is local already though so not sure why you need that check
Maybe you are running the sprint code in the wrong section of CMC. The way this works is CMC does movement on Client and then the same moves are sent to server to check if the calculations were correct and client is not cheating. At the end, the movement has to be verified by server.
I usually use Movement Modes for different movements such as wall run but in this case maybe you are multiplying the speed by a modifier?
Im just setting the max walk speed as my new walk speed through a function
Thank you for clearing that! Things make more sense with that.
Are you doing that using server RPC?
And also calling the same on client?
No its just a void
That's the problem most probably
Why so? Isnt the character movement replicated by default?
This is not a good way yo do it
Do i do a server RPC then?
You got the wrong idea of replication.
See. Replication and server reconciliation are two different things.
It would take a bit to explain both
Lol
I meant as in, doesnt the server have full control over a character movement because its the server thats supposed to handle movement
That is authority and completely different
All these come into play together
Which series are you following?
Delgoodie?
Fwiw there is a sample by now
Gimme a sec
Pinned to this channel
Uerm i followed multiple videos weirdly, one is from 2019 and one was in the pinned and one is a series doing it on ue5
Right, i think i understand it just a little better ig
I recommend doing the playlist by delgoodie in the order. And also reading UE documentation on CMC and networking
That was enough for me to implement most of what I did
There should be a GitHub repo showing examples pinned
Thats the series i followd
Followed*
Like only the first 2 vids for now
But his sprint works
The same way
He does it using flags Ig. That's the right way to implement it
You can also do it without flags so not so obvious
2 reasons come to mind, one is that the modifier is not being set properly on server or client and 2nd more broader is that calculations are not lining up
Just iterate over and check where it is going wrong but also make sure you are following tutorial correctly.
I did a whole bunch of debug messages like i said
The closest hint i got to it was when i try to run the function on client it runs on a pawn without authority
Not debug with log, iterate step by step.
Ofcourse because it is an autonomous proxy
Only the server has authority for pawn spawned on server
In the end it's your code, so you would know better how to fix it
I might just write this from scratch again
I checked it all the way through with 2 different recent tutorials and didnt find anything wrong or off so i guess thats the best way to try this
Probably should do it all over again. The tutorials ahead are lengthy tho.
And you would revise your concepts and get better at it as you go off implementing your own complicated CMC movements
Yeah ig its gonna be worth it
Doing it the first time kills me though
Cus my brain shuts off lmao
I did understand what all the functions do now so i guess itll be easier to implement
Just a point, the code runs in a networked environment so be aware of even the smallest of details
Yeah i will be, thank you for the help! I appreciate it
Hi all. I'm trying to use a Custom Event in my Game Mode make visible a UI Widget for all connected players. I'm doing this by using an Interface between the Game Mode and Player controller -> then onto the Custom HUD Class which calls the Event to make the Widget visible. I'm performing a For Each Loop on my Player Controller List and using the Array Element in the target of my message to the PlayerController.
This only shows the Widget on the Server Screen and I can't figure out why. Any ideas?
Why are people overusing Interfaces so much?
Which freaking tutorial out there says "Oh, to call a function on a Class, use an Interface!"
You know it's a PlayerController. You even know what Class it must be cause the GameMode defines the class.
Just cast and call the method directly.
ALSO, your issue is that you use a Client RPC on the HUD. HUD is local only.
You need to use the ClientRPC on the PlayerController already.
Pretty much all of them
Because casting is scary 👻
But... Interface calls cast...
I've seen some tutorials make an interface to get a variable value and that's it.
Is it the Interface that is causing this to not work?
oh. I just wondered why you wrote a paragraph about it
ah gotcha
Then try to learn Casting properly
Using Interfaces for everything is simply wrong
It makes it super hard to follow your code
I will do.. once I understand why this isn't working. cheers
Don't be afraid to make a static function that does the cast for you btw.
yup. digesting as we speak
I'll have BPFL that simply get the pawn's controller and cast to the custom PC
Just so I don't have to keep doing the cast node itself.
I think I got into the habit of using Interfaces because it was more efficient to find a matching overlapping character
Interfaces are not more efficient, as an FYI
Interfaces have use-cases
The one in the pictures is not one of them
I'm not saying don't use Interfaces
oh, not even when using the Does Implement Interface?
In my mind, if it doesn't match the critera it won't pass the branch. Wouldn't that be more efficient?
You use interfaces when you have to call a function on an actor that you don't know the class of (so you can't cast) and when you need a function to be called on classes that don't share a parent class
Best example is an Interaction Function
As you can interact with a Character (e.g. to talk to them) and with an normal Actor (e.g. a Chest to open it)
When tracing you get an Actor
You don't know if that's a Character, a Chest, etc.
So instead of casting toa ll options you use an Interface
Or a damage interface works as well.
(If you're not using the built in damage system)
You can call that blindly on the actor. If the Actor implements it, it will call the Interact logic
If not, then well not an interactable actor
But if you know you will call a specific function on a specific class that only that class has, then interfaces are wrong
ok gotcha boss.. It won't happen again
Either way, your issue is still that you made the HUD Event an RPC
I'll put in the hours to make up the lost time 😄
It shouldn't be. The PlayerController Event needs to be an RPC
But since you use an Interface, you gotta create a second event xD
(cause the interface event can't also be an rpc)
I don't get it. so what would be the correct setup for this. Bashing my head against a brick wall tbh
Is it possible for the gamestate to be invalid when a pawn is possessed by a client? im executing logic on the client's pawn when it's possessed, but the gamestate returns invalid
I believe you've answered your own question.
my bad, i did phrase it badly. I meant as in, i didnt think the gamestate could be invalid when a pawn is possessed, so something must be wrong but i cant tell what
Before you were talkin' about the gamestate. Now you're talking about the playerstate. Which state are you talkin' about? 😅
That said - still answered your own question 😅
Replication is wild
I'm in a state of confusion
sorry! i believe i may need more coffee. i meant gamestate
I don't believe there is really any guarantee on any replication thing really. However - I do know that gamestate will be valid during BeginPlay, because that is what calls begin play
i suppose ill have to do something along the lines of a function executing only when the pawn is possessed and beginplay has been called
What are you trying to do anyhow?
but i really didnt think it was possible to possess a pawn that hasnt begun play.
Beginplay happens on each machine at differing times, sometimes multiple times on the same actor based on relevancy, etc.
What I'd do is call a function every time anything relevant happened. Or perahps a wrapper function. That functions checks whether everything is there and whether it's been called or not yet and figures it out for itself.
Depending on when you're trying to possess, initial possession happens like right before BeginPlay if I recall. In one of the postinitializes if I recall correctly.
bind an event dispatcher in the gamestate to an event inside of a widget that populates said widget with children that hold the currently active players.
What does that have to do with possession?
i create and add the widget once the pawn has been possessed
I would urge you to rely on the player's PlayerState from the GameState's PlayerArray to create/maintain the child widget. Then the childwidget can use said playerstate to handle it's own stuff based on when/if said playerstate ends up with a possessed pawn.
You will end up with less messy conditionals than dealing with possession calls.
fwiw the GameState has to replicate. There is no guarantee that this happens before a Character replicates :D
@thin stratus Thanks for the help. Got that UI on all player screens now. Now I gotta go in and fix up all my stupid unnecessary interfaces
Do you mean for the Local playerstate to create the widget and populate it with all the other playerstates,
or for each playerstate (local and remote) to create a widget and send it over to all other playerstates?
ah and that indirectly means that before it replicates initially it will be invalid on clients. that makes sense
Yeah, multiplayer is a bit annoying in that regard, cause there is no clear "everything is valid" event
Put a widget on screen at like AHUD's beginplay. You know for a fact that GameState exists on this client at this point. You can override the Set and Remove playerstate functions in your GameState, and broadcast a delegate. Get all current playerstates and create a child widget for each one and pass the playerstate to it. You can find and remove the widget when the broadcast removes a player, and add a new child widget when the broadcast adds a player. You bind this delegate in the main container that creates the children. In the child, it has a single playerstate. Either tick or put a delegate in the SetPawn of the playerstate and use another delegate here to maintain that one child widget's pawn reference.
yeah an 'all clear' like that that would be very convenient
Is it bad to do delay-on-cast-failed-pin-and-try-again for blueprints for this kind of situations?
What would be the cleaner solution then, are there any notifiers that game state is replicated?
Or is it just do it in the being play of the game state?
Beginplay literally cannot run without a GameState. In any actor. Ever.
The reason for this is because that is the class that calls begin play on all the actors
Level, GameMode, Character, PlayerState, Random actor on level, all of those will never run Beginplay without a GameState. For both Client or Server.
okay i'll try that, thanks so much!
If you don't have a BeginPlay/GameState situation then the answer is and always will be: OnRep/Repnotify
You could also use PostNetReceive mayhaps
And sometimes both Beginplay and OnRep. 😄
Well yeah I'm especially asking for BeginPlay kind of situations and for blueprint where OnRep functions aren't exposed
That's supposed to be called when all of the replicated stuff arrives initially.
Yeah that's just a shitty thing about Unreal
OnRep can happen before BeginPlay xD
And there are things that, if called before BeginPlay, will just silently fail
So you basically gotta litter every single OnRep with "HasActorBegunPlay()"
How does this differ on clients? Do actors just randomly start to appear according to server's replication order?
And also call the OnRep BeginPlay by hand
BeginPlay will call for clients in two ways:
- When the GameState exists on the Client, has BegunPlay and an Actor is created afterwards (may it be delayed due to initial replication or spawned throughout the game).
- When an Actor already exists and the GameState calls BeginPlay.
Both can happen in any order
There is also the additional option of delaying BeginPlay iirc
That's also fun
Just keep doing things until it works™️
bDelayedStart in game mode.
"Just do things until you find yourself paying €€€ for UDN to get that sweet sweet answer that someone already got 4 years ago."
Terrible terrible idea
Ah I setup whole MatchStates with that and Warmup rounds etc.
Works quite well actually
Yeah.
Stopping BeginPlay from being run is what delayedstart does and it's so awful lol.
It doesn't even spawn you a player, it gives you a spectator pawn.
I sometimes wonder what kind of treasure trove of knowledge I'm missing out on by being a peasant 😭
So like, in server, client owned actors are created in an order, Controller -> State -> Pawn (I guess) right? No matter when they got spawned (before or after GameState::NotifyBeginPlay) their BeginPlays should be called in order. But in client, is it possible that GameState::NotifyBeginPlay is already finished, but my character is replicated first so it'll have null controller and state?
Or no wait, I don't think the order of BeginPlays even should be always same, I remember my GameMode::BeginPlay being called after some of the Actors'. So the part where I think they should be called in order, should be wrong
But about the client part, is that possible?
BeginPlay has no guaranteed order
Not for the BeginPlay order, but for the client, it's possible that I can get null controller/state from my pawn's BeginPlay since they might not yet been replicated although they're spawned and set correctly on the server, right?
Potentially.
Okay got it, thanks
Rule of thumb is to just not trust the order of things really.
But GameState will always be valid during BeginPlay (for reasons previously mentioned)
Better get used to it 😄
Not necessarily, but in the majority of cases, yes.
Autonomous proxies will be your local pawns.
But you could, theoretically, get them without controllers.
you can also have autonomous proxies that aren't pawns at all and therefore don't necessarily have a direct link to a controller
hey guys im trying to do a "kill scorebord" like in counter strike or whatever when a player kills another player in the top left corner it displays " Player 1 Killed Player2" for all players
any tips on how to do that or any tutorials ?
thats too broad of a question i doubt ur gonna get much help with a question like that, that said, ur gonna need a widget and a an event that is probably gonna pass through ur playercontroller that is going to eventually populate that widget in all players
yeah i kinda know how im gonna do it however i dont know how to make the names dissapear or stack on the widget kinda
guys isnt the pawn rotation suposed to be replicated automaticly? if not is there any way for it to replicate without calling rpcs?
Gamestate:
KillHappened -> multicast for the feed -> adjust scores on the PlayerStates involved
KillHappened should be on server btw, all the logic before it should be serverside so it'll be serverside as well
how do you handle players joining a server after things have already changed? do most games rely on lobbies to avoid this?
what do u mean?
u gotta be more specific
I was going to but I thought that was obvious, I mean literally anything changing since if a server has already started other players will have been doing things
anything that gets moved, destroyed, changed in any way, will be incorrect if a player joins after it happens
things that are handled by the server and replicated should appear automaticly to any player that joins
even if they are moved
and even if an event fires before the player was there?
I had some things that move on begin play, I didn’t actually try to replicate those but yeah that caused desynced locations when a player joins
there was something about events in the docs and how to sync those but i cant remember exactly what it was
Hi,
I'm currently having a problem with a multiplayer session. I make the server open a map when OnPostLogin is called, the serve does indeed load the map be the client is sent back to the Default Game Map and i cannot identify why. Can somebody help me on that one?
making the server open a map OnPostLogin is probably not a good idea in the first place
it's not exactly on post login but it's after a 10 seconds delay after the OnPostLogin
OnPostLogin is a function that is called just after the player logsin im not even sure the player already has a proper connection
u probably need to use server travel which is something i have not done before sorry
@dark edge ok so i found a quick tutorial about it https://www.youtube.com/watch?v=KOFCvNbJUPA from wich i used and it works fine however got some follow up questions about it tho, its this how you woud do it ?
Most tutorials on how to create a killfeed in UE5 (or UE4) are often very long and use multiple RPC's but in this video I will be creating a multiplayer killfeed using only one RPC and an event dispatcher in Unreal Engine 5. I hope you guys like the video.
For any questions regarding the multiplayer killfeed or anything else for that matter, jo...
There was a really good image that explained the multiplayer gameframework but I can't find it for the life of me
did the compendium that it was in get deleted
is controller rotation suposed to replicate by default?
nvm
this bug is killing me
im starting to think stupid
doesn't replicate by default.
No other variables, other than an array can be replicated inside FFastArraySerializer, right?
Does anyone know if Seamless Travel works with Game Feature Experiences?
You probably would want to multicast the playerstates of who was killed and who the killer was and within the widget read the names from the playerstate rather than RPC'ing the names each time, otherwise, this is the basic idea of how you would do something like this.
Hello, how are you guys? I have a small issue in my game. The thing is, I have multiplayer set up, but the problem is with structures. I first tried creating a variable in a single actor in the level which would hold the data for anyone that wins, then you could grab the data and send it off somewhere else, issue is, from what I can tell, only the server's data is being passed in from the client. This is for a leaderboard by the way, but I don't want it to save and the way I want it is that items are added to the win list array in order. At the moment, I am using player controllers to tell who is who, so surely the host should be BP_PlayerController_C_0, Then the client after that should end with a 1 instead of a zero and so on, now the issue for me is that, first of all, stuff is added to the array, but the client can't read it from the structure, second, anyone that wins always has the controller ending in 0
so I can't tell what to do really
I would appreciate any help if possible
Don't use indexes to keep track of which player is which as it's not reliable to do so. PlayerControllers are only present on the server and the owning client, so you cannot use references to a specific player controller on other clients if that's what you're trying to do. Instead, use the playerstate to keep track of the player if you need info about a player that is replicated.
I see, would it not be possible to make it so that its not player controllers and instead its player names?
or unique net IDs
?
Use the playerstates.
Okay
PlayerState already has player name field anyway
wait quick question about the player state tho, the way I have it setup at the moment is that my Widget BP simply reads the array and adds the necessary information to the UI, if I want to use the Player state, how would I change this? as I would have to keep track of which player comes in which place?
@knotty briar
Interesting
reads what array?
The GameState has an array of all PlayerStates, start there
I have an array set up which adds the player controller of whichever player finishes the race
once that array reaches the length of how many player controllers are in the game, it creates the leaderboard widget
I understand that, but then I face the issue of keeping track of which player is in which position
how would I fix that
if thats possible ofc
On each kill, do a sort
is there a sort function?
Probably.
But you could just write a custom one.
In this case, it's not difficult in the slightest.
A standard brute force approach is more than sufficient.
I see
the thing is, the way I have it currently set up, it adds to the array in order, so if I set it up with the player states, I'll have to probably sort it then, if I understand correctly
Thank you btw, I appreciate the help
Gonna try it rn
The player's pawn has a reference to their playerstate. You can store their playerstate in an array in the gamestate or wherever you like.
Oh
Thats a lot easier in that case
so instead of adding the player controller, I could just add the player state
and get the reference to the name from there
Yep, and because they're playerstates, it can be replicated.
thats awesome
thank you so much
IT WORKED
Thank you so much
I know this is a completely unrelated topic, but say I set up a name variable in the player state, would I be able to send that through to a different level, I don't want to do this in game instance, as It will not always be the same, only gonna be the same in the lobby and the actual game
Thank you
Thats all my questions, sorry for the inconvenience
I appreciate the help
I am working on a multiplayer game. For example, there is a key that will open a locked door. When a player receives this key, only the player who receives that key will be able to open the locked door. Other players will not be able to open it. I tried all modules. I also created multicast, repnotify, interface but it didn't work. How can I do it.?
So, i've setup my game so that its server authoritative, where the input gets sent to the server and then the server processes that.
Im having an issue, though, where i have a lever that i want to activate, and for whatever reason it only gets activated on the server and not on the client. I've tried to add an additional even that multicasts to all clients when the lever gets interacted with, but i think because the event that processes input is only called on the server, that doesn't work. Honestly, im unsure as to why it doesn't really work. Any advice?
so yeah, it goes client presses e -> server gets informed and calls appropriate functions -> only server is updated even with a multicast event called from the server to update the specific object
Well idk that you’d want to multicast or rep notify if you only want it to work for the one player
Maybe something like is locally controlled?
no just normal ı made with get player controller. ı want who take key can be open door.
Ik. I’m suggesting using something like an is locally controlled check
But I could be wrong 😅
May need to look into RepNotify but a Multicast event that executes on all should be the one calling the actual lever operation function
okey thanks. ım gonna try you said.
I was taking a look at a video on how to do this for a simple door, and i was kind of just surprised that you have to do this on a per-object basis, the problem was i was trying to do it abstractly through an interface but yeah turns out just like you said, i have to do it right at the lever's implementation of the interface
It all starts with how your key is picked up. As an example, you could have the player walks into the key and when they do so, it gets picked up in which case you would use an overlap event in the key actor - you'd want to put a "has authority" node immediately after the overlap and use the "Authority" path, and then you would assign the key to the player that is overlapping which you would do by using the "Other Actor" reference in the overlap and casting to your custom pawn class, and setting a variable of some kind on that particular pawn to indicate a particular key was picked up. I usually like to suggest a gameplay tag container for keys as it can prevent you from making spelling mistakes and it can contain multiple values and has an easy means of checking contents like the function "HasTag()". This gameplay tag container can be named "KeyChain".
When interacting with your door, you'd need to do an RPC to the server requesting an interaction with the door actor, and if you use an interface to communicate to the door, you should set up that interface to pass along a reference to your custom pawn class so when you call it, you can feed in a reference to the pawn that is interacting. With the implementation of the interface, you can now use the passed in pawn value and pull from it the KeyChain variable and check against the key required for the door, which can also be a gameplaytag variable defined on the door.
So you'd check if the door's key is not valid, in which case, just open the door on interacting. But if it is valid, you'd check if the Pawn's KeyChain variable contains the GameplayTag assigned to the door, and if so, then you can open it. This should work fairly easily in multiplayer as only the player interacting with the door is being checked by the door to see if they have a key.
anyone know how to convert the last line here from shooter game for >ue5 to avoid deprecation warnings:
for (TActorIterator<AShooterPlayerState> It(WeakGameInstance->GetWorld()); It; ++It)
{
bool bIsABot = (*It)->IsABot();
const TSharedPtr<const FUniqueNetId>& PlayerId = (*It)->GetUniqueId().GetUniqueNetId();
if (!PlayerId.IsValid() && !bIsABot)
{
UE_LOG(LogOnline, Warning, TEXT("FShooterOnlineGameMatches::HandleMatchHasStarted: Player is invalid"));
return;
}
TSharedPtr<const FUniqueNetId> PlayerNetId = bIsABot ? MakeShared<FUniqueNetIdString>(FString::FromInt((*It)->GetPlayerId())) : PlayerId;```
```1>C:\UnrealSVN\Sprawl\Source\ShooterGame\Private\Online\ShooterOnlineGameMatches.cpp(444): warning C4996: 'FUniqueNetIdString::Create': This FUniqueNetIdString Create method is deprecated. Please use Create(FString&& InUniqueNetId, const FName InType) Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.```
release notes just say "Functions that used FUniqueNetId or shared pointers directly have been deprecated. We have added function overloads to UOnlineEngineInterface to take FUniqueNetIdWrapper."
which doesn't explain much
Also, what is that code trying to do for bots? Convert a bot's local player id into a uniquenetid by converting from a number? Is that even valid to just create a uniquenetid out of some random number like that?
I think it could be as simple as changing
TSharedPtr<const FUniqueNetId> PlayerNetId = bIsABot ? MakeShared<FUniqueNetIdString>(FString::FromInt((*It)->GetPlayerId())) : PlayerId;
to
TSharedPtr<const FUniqueNetId> PlayerNetId = bIsABot ? MakeShared<FUniqueNetIdString>(FString::FromInt((*It)->GetPlayerId()), TEXT("Bot")) : PlayerId;
It is assigning a number to each bot, but it is sequential from 0 which is fine as they don't really need the same kind of NetID as a player and the player ones would always be some large number (at least over 1000) or an alphanumeric string.
ah ok, seems to set it from this
int32 AGameSession::GetNextPlayerID()
{
// Start at 256, because 255 is special (means all team for some UT Emote stuff)
static int32 NextPlayerID = 256;
return NextPlayerID++;
}```
had to make it this:
TSharedPtr<const FUniqueNetId> PlayerNetId = bIsABot ? FUniqueNetIdString::Create(FString::FromInt((*It)->GetPlayerId()), TEXT("Bot")) : PlayerId;
Cooldown on that action should work fine.
and for the sake of it also on the server
Out of curiosity how many reliable events is too many? I noticed sometimes even my reliable events fail to work and I'm wondering if it's because I have quite a lot of them.
I think it can get flooded fairly easily depending on how you're calling the RPCs and how much data you're sending in your RPCs.
You can always use the network profiling tool to see information about how many RPCs and how much data is being sent. I think by default Unreal tries to keep data rates down to like 5KB/s per client, and if you happen to go above this, then RPCs can start mucking up.
Using a laser to interact with a 3D menu in vr (widget attached to player character camera, Widget Class set to 3DMenu class)… how do you detect which player pressed a button?
Why the UE5 server doesn't recognize "ServerTravel" as command?
What is a good to test disconnect/reconnect? I have found the settings to simulate lag/packet loss. But not info on how to simulate disconnect/reconnects. I have also found the setting to "Allow late joining", but I'm not sure how to simulate a late joiner either
Just use Add Client button to test a late joiner
For a disconnection, I usually open another level from client, but there might be better ways to do this that I'm not aware
That code will work. Are you sure your overlap is being detected on the server and that the map name is correct?
And then travel back to reconnect?
Yes
I didn't even know that was a thing (the text doesn't show on my screen, but the icon does) thanks!
Ok - thank you!
Yes. What I get from UE server is:
ERROR: The map 'LargeMap' is either short package name or does not exist.
Command not recognized: servertravel LargeMap
But in the Editor it works
For packaged builds you have to edit your project settings and add what maps you want to add to the package.
There's apparently an option there for including all maps too.
Where? How can I do it?
Edit > Project Settings, there's a search bar at the top, type maps and you should be able to find it.
It's under Project Packaging
I'm not sure, I've never packaged anything before, but if I had to fathom a guess, it'd be the top option.
Ok i try
What happens if the server spawns an actor class that does not exist on the client? Does the actor simply do not spawn or a crash?
Yep it works
Thank you 🙂
I am using these blueprint for server travel, with "specific player" connected to get player controller, but every player will be sent to the other map, and not only the one who should. why?
The class itself should exist on both the server and the client, so it'll spawn on the client just fine.
Not in our case, that's why I ask 😛
If I remember correctly, Overlap events fire for everyone, and you're using Player Index of 0, which is the local player. You'll need to pass in what player overlapped the teleport
I wanna know what happens if the Actor class is not available 😄
You must be running different applications then? Or using UE as like a rendered for another app of yours? Not sure what other circumstances would exist where one wouldn't have the same packaged data on client and server.
Either way - I believe it just fails silently - so, no spawn. But I've never tried, so can't confirm
If possible, I'd create a custom SpawnFunction that looks for the actor first and you do whatever you want if it doesn't instead of letting UE handle it.
Can't go into much details due to NDA, but it's currently a problem I'm trying to make a solution for, so server/client are in fact sync with the classes 😛
That's why I wondered
I'd go with a custom spawn actor function. Just subclass GameplayStatics or something so you can create your own version of it. That way you know how it's handled every time
I think I'll go with the client telling the server "hey, I just made this class, now you can replicate that actor of the same class"
Probably nothing happens if it's not replicated. Client doesn't need to care.
There is usually a map somewhere deep in the engine that handles mapping the net Id to the class. If that doesn't result in a class it would not spawn the actor. Might throw a warning. Shouldn't crash though
Because "ServerTravel" pulls all clients along to the new map. The "execute Console Command" node takes the player controller as input and attempts to execute the command as the player controller, but when it is executing on the server, then it doesn't really do anything special with the player controller input. The controller input is more for local multiplayer than it is for online multiplayer.
You can read more about travelling here:
https://wizardcell.com/unreal/persistent-data/
If you create these runtime you might get a lot of problems if you are unlucky. It's mostly expected that these exist already
No other option unfortunately and I can't go into the why 😄
Just gotta be engineered to work
😄
Sure but just telling you you might need to fight the engine a lot
There is def a map somewhere that maps the classes to net IDs. You might need to somehow update that every time. Idk
Try it I guess
Custom engine olé
Yes, we're running source 😄
Ok. I understand, for ServerTravel command, all connected clients will follow. But what should I use then? I would like that only the player who use 'Teleport' will be "sent" to the other map
UE doesn't support that if you mean literally loading a second map.
You have three options:
- The server travels and leaves everyone behind (connection to the server will be lost for all clients)
- The server travels and brings everyone along.
- You have the client move to the new map separately (connection to the server will be lost)
😉
The only other option you have is to use levelstreaming and have everyone stay on the same persistent level
What do you think about start multiple maps on different ports?
and the "teleport" will connect the player to the other port?
That needs multiple servers and you have to travel between them still. Never tried that.
Players wouldn't be able to share data with each other anymore then
Cause 2 different servers
That's when you get into fun things like creating TCP socket connections between the servers to communicate 🙃
xD
If you ever played borderlands you should have encountered the "everyone has to travel together" stuff
One of many examples of UE games having to struggle with this
The Ascent does a mix
They have huge streaming level setups for their tiers. But each tier is a persistent level and everyone has to travel to them
So you have some degree of freedom in multiplayer.
As in where you go and where your friends go
Ok but what if I want multiple worlds in game?
Then UEs server client model doesn't work for you and you have to use something else or code the whole thing yourself.
It's not so straightforward to work around this
You can have multiple worlds running, but it's not really supported out of the box. There's a plugin on the marketplace that can facilitate having multiple worlds running, but it's not replicated.
There is also third party stuff that works around this
But quite $$$
If you have a small team or even are alone, try to adjust your game idea to what UE supports maybe
I have to put multiple worlds in the same level
that is i guess xd
in the same map
multiple map in the same map i don't know
just a question, how can I cast to the listen server's pawn from bp_gamemode
at the moment, my next idea is to put the pawns in an array when they spawn and simply call the event I have made inside it which should work
Streaming Levels fwiw
Allows you to load and unload maps on demand
Server has to load the ones the client load
But despite that you should be able to have multiple at the same time
Wouldn't advice to load "big" levels though. Rather cut those smaller and only load the parts a player is really in
This is what I want to do
ListenServers Pawn should just be the GetPlayerPawn0 in theory
If you are on the ListenServer side of code
I see, that makes some sense, I’ll try what you mean, but in the case that it doesn’t work, I’m guessing it’s gonna have something to do with authority in bp_gamemode
bp_gamemode always has authority on listen server which is not really necessary to do.
I see, but then how would I multicast a single widget to all player pawns?
Wait
That gave me an idea
I’ll try it out now
widgets are always on client side, you prolly can't multicast it. Not sure what you are trying to do. It might be better giving more details.
But these maps have to be in the same level, right?
What’s the best way to get an initial Playerstate replication callback in blueprints?
Where from?
I want a widget to display relevant information about other players in the match. So from the widget i’m assuming.
So like a scoreboard or similar? The easiest method honestly is to add a small bit of C++ code to your gamestate, to broadcast an event everytime the Player Array is updated.
Ive got very little experience with cpp. Could you explain or point me to a guide on how to do that?
Very similar to a scoreboard yes, with it accounting for late joiners and leavers, and late joiners having an accurate scoreboard themselves
The easiest place is to add an event to AGameStateBase::AddPlayerState and AGameStateBase::RemovePlayerState, and just bind to that event in BP.
I’ll look up a guide on how to expose cpp events to blueprint. Thank you!
OFC if you didn't want to into C++ at all, you could also broadcast a global event from you player states BeginPlay or something. It's not ideal, but it'll likely be good enough.
BP just isn't that great for MP. Hard to avoid going into C++ now and again even for the simplest games.
I remember reading Playerstate beginplay can occur before a player is actually assigned to it. Edit: in wizardcell’s multiplayer tips and tricks, specifically 8.1.2 : playerstate’s beginplay is called before gamemode’s postlogin
Altough i suppose that doesnt matter since its just binding delegates that wouldnt fire until a pawn got possessed anyway 🤔
Yeah i do plan on learning cpp specifically for multiplayer code. Shocking amount of stuff just isnt exposed to blueprints lol
Oh and my delegates are bound at beginplay, so they wouldve already missed the playerstates broadcast by then. i could just use the playerarray for initial replication
Anyone got a smart way to access entities on the server from an editor button context? Rn if I iterate over actors hasauthority will never be true
Only in single-process PIE, otherwise no
In single-process PIE you can get all the editor world contexts, get the servers' one, and get the actors from there.
okay rubber ducked myself, cheers got it now
coz GEditor-.GetSelectedActors wont give the server versions i need to get those prolly with the net id or something
which has more overhead?
- reliable client RPC that sends 1 FString
- AActor with 1 replicated property only ( FString ) and calling ForceNetUpdate() on that actor?
wym overhead, packet size ? depends on alot of things there
what if the actor keeps coming in and out of netcull with the rep property etc.
also the reliable rpc, depending on whats going on in ur game if u got alot of reliables going on could cause big chungus blockage if its being spammed alot etc.
yea thats what I meant, trying to avoid this
overhead in that sense
whats wrong with replicated prop and no force update ?
also does it need to be an fstring ? any way u can map it to something smaller
it takes a while to replicate
ForceNetUpdate will replicate immediately
so it acts similar to rpc
in this case it has to be a string unfortunately
i mean theyre still very diff things though, rep properties are also used if u need to maintain the state of it in regards to net cull / late joins
is it a stateful thing or doesnt really mater ?
but what I'm saying is that we're usually told to avoid spamming reliable RPCs to avoid the issues you just mentioned, which is why I thought I could just use ForceNetUpdate() which will behave similar to RPC, but maybe it runs into the same issue I'm trying to avoid with RPCs? hence why I asked about overhead
its not, but since it can be spammed quite often, I made it a replicated property for now with no ForceNetUpdate()
just remembered now about ForceNetUpdate() to make it a bit faster
but just wondering about potential issues
Does anyone know how to call a Server event from a client
ServerRPC
@clear island my understanding of forcenetupdate downsides it your basically bypassing UEs optimized networking processing/load balancing whatever and can cause potential traffic spikes whcih depending on the amount of relevant actors can be lika an n^ issue, so should be used as sparingly as possible for like crucial game events
so it has the same issues as reliable rpcs
im not sure if its exactly the same, coz reliable rpcs have an issue where they can start queuing awkwardly if some are dropped or whatever
I guess I better leave it as is then, replicated property without using ForceNetUpdate
if its not an absolute crucial game event cant you just allow it to be abit delayed ? if the delay on it is noticable then is it an option to also look at increasing the bandwidth available by serv/client or server tickrate
yea
yea i think that would be best tbh
Yeah they are sublevels of the same persistent level
--
Is it not guaranteed that if I spawn a replicated Actor on the Server with a given Rotation, that the Rotation is the same on the Client?
Let me explain better what I would like to do
I am still in the learning how things works. Let's suppose there is a building with apartments in my game, and a player enters the building and he goes close to the door of one of the apartments in the building. The player can enter the apartment, but usually, the interior of the apartment is not directly part of the same building. Right? It looks like it's a separate part of the "map" as it's not really "inside" of the apartment or building. Is it what you describe with 'Streaming Level'?
Streaming Level is just a runtime loaded/unloaded level.
Without traveling.
In your example, the Streaming Level is in fact the Apartment, but the only thing that would happen is that either hidden in some "open door animation" or via a trigger zone that is in front of the door, you load the Streaming Level
Cause if the door is closed, no one needs that level to be loaded.
It's an optimization feature
is there some acharacter property thats replicated on both client and serv ? i know there's the network guid on the net driver but it seems abit sus to work with
trying to identify the same pawn from plugin context, i get it from the client world and using the dedi server world i need to match it somehow
i could easily just #if editor and replicate some property but surely there's something that exists no ?
Take GTA 5 as example, when you enter an apartment or 'your own apartment' it looks like it's in another map or it doesn't look it's in the building itself
Not sure that's a good example cause you are actually in that apartment
People can't see the inside but you can still see the oustide
That stuff is handled differently cause everyone can have the same apt
That is stuff one could handle via IsNetRelevantFor, but even then it's tricky with UE, cause the Server is handling collision and if you have multiple people in the same room, even if they aren't seeing each other locally, they still collide on the server.
I am not sure that you are actually in the building
In my game I want one of the teams to have an ability to pass through certain walls. What would be the cleanest way of achieving that?
I played the game
You are in the building. Players with Helicopters can fly infront of the Window :P
You just can't see the inside, but you can see the outside
So the building it's "all empty" except the apartment? lol
Pretty sure
Just give them a custom collision channel and make them not collide with it.
Nice nice
You can only have 18
Is it easier to do?
And you will not have all 18 for that
So you can only support a max of 18 people in the same apt
With 60+ players that GTA has, that won't work if everyone is in their own apt
You'd need to be able to tell UE to ignore collision between entities
But only in the apartment
Not per player. Have a single trace channel for the players. Make their response to taht channel nothing.
Sorted.
And people who are with you?
Your friends that visit your apt still have to collide
That's silly talk!
:D
Wonderful
I don't think this is easily possible in UE
The Server would need to be able to not only decide via IsNetRelevantFor who gets stuff replicated, but also decide which Actors should be considered for collision* based on that.
Idk if Choas has an easy way to plug a number on a collision entity and filter with that
Would be cool
I'm sure you could easily convert UE to use a lot more collision channels. It's just right now there's a hard limit because of hte enum?
Idk what the limit comes from
18 is a strange number
Even a uint8 would allow more
I think it's, "Who would need more than this?"
Maybe maybe.
Easy enough to make that a uint64 !
Does it makes sense?
But what if the players are unlimited? Every player get its own apartment + let's say it's customizable so it's not really "the same" apartment, but it is in the same position
Unlimited is not a thing with UEs server model
32-64 by default with optimization. 100 with ReplicationGraph and maybe Iris in the future.
Everything more needs custom stuff
are we supposed to update values on cmc using a server rpc?
Is it possible to host more than 100 players?
I just answered that or not?
Depends on what you want to do
For example?
just sprint really- so set the max walk speed up ?
mhm
You don't develop games with more than 100 players easily with UE
At that point you are in custom land that requires €€€€€
No, sprinting has to be properly implemented into the CMC in C++
Everything else will result in corrections
Pinned message with example code
im doing it in cmc with flags but it doesnt work on my client
i shall go through that aswell now thank you
You do not need any additional RPCs
Oh okay i see, i asked since changing my sprint pressed func to server made it work on client but it was jittery so i believe that was the wrong way to do so
You also don't use the flags anymore fwiw
I mean you can
And the Repo also does that iirc
But there are containers now that are used
@grand kestrel Why are we actually not using the Container to send the flags to the server in theCMC example?
Aren't the flags a bit outdated or is that used together?
alright
// Send move to server if this character is replicating movement
if (bSendServerMove)
{
SCOPE_CYCLE_COUNTER(STAT_CharacterMovementCallServerMove);
if (ShouldUsePackedMovementRPCs())
{
CallServerMovePacked(NewMove, ClientData->PendingMove.Get(), OldMove.Get());
}
else
{
CallServerMove(NewMove, OldMove.Get());
}
}
CallServerMove does this at the end
ServerMove(
NewMove->TimeStamp,
NewMove->Acceleration,
SendLocation,
NewMove->GetCompressedFlags(),
ClientRollBYTE,
ClientYawPitchINT,
ClientMovementBase,
ClientBaseBone,
NewMove->EndPackedMovementMode
);
Which uses NewMove->GetCompressedFlags()
So there you have the flags
CallServerMovePacked does this ServerMovePacked_ClientSend(PackedBits);
I'm sure they're still used unless I missed something
Ah that still uses the flag internally
I CAN'T TYPE FOR SHIT
void FCharacterNetworkMoveData::ClientFillNetworkMoveData(const FSavedMove_Character& ClientMove, FCharacterNetworkMoveData::ENetworkMoveType MoveType)
{
NetworkMoveType = MoveType;
TimeStamp = ClientMove.TimeStamp;
Acceleration = ClientMove.Acceleration;
ControlRotation = ClientMove.SavedControlRotation;
CompressedMoveFlags = ClientMove.GetCompressedFlags();
MovementMode = ClientMove.EndPackedMovementMode;
Yeah okay
I thought they just set a boolean or so in the container
But they also use the Move's Compressed Flags
So yeah I'm wrong there, disregard
You should use PackedMoveRPC either way though, but I think that's by now default set to true
At least in 5.0 it is
im using 4.27 and 4.26
Are you close to shipping? :D
If not, why are you from the stoneage exactly?
Idk if 4.27 and 4.26 have that and have it enabled.
So the GitRepo might be too new for you in some cases, depends on what changed n the CMC
um with one of my projects ive done a whole bunch already so im quite skeptical of migrating it and for the other reason i just weirdly like the stoneage😭
it sounds stupid but i just never moved ahead lmao
You should eventually. Man we released The Ascent on 4.26/27. That is like what, 3 years ago?
i have no cpp in my project at the very moment but theres still a lot in there, im just scared of something breaking
To be fair 4.26 still feels more stable than 5.x
Yeah I mean that's fair
yeah thats why im stilll using it
Having shipped on it, def not xD
That was a shit fest of cherry picked CLs
Man, I just hate that UE spawns Actors on different location/rotation on Server and Client
Server: X=-1451.613 Y=-657.024 Z=0.000
Client 1: X=-1452.000 Y=-657.000 Z=0.000
Freaking serialization
Fun
If it's gonna compress like that shouldn't the server compress and apply that instead of prior to compression
Guess you just gotta do it manually to the transform you use when spawning it which is silly
LogBlueprintUserMessages: Server: X=-1762.475 Y=-839.916 Z=0.000
LogBlueprintUserMessages: Server: P=0.000000 Y=12.656250 R=0.000000
LogBlueprintUserMessages: Client 1: X=-1762.500 Y=-839.900 Z=0.000
LogBlueprintUserMessages: Client 1: P=0.000000 Y=12.656250 R=0.000000
Rotation seems to be fine if I discable ReplicationMovement
but initial location repliation seems to still do this
So I will have to manually apply that compression I guess
I don't even know what the default compression for replicated actors is
Looks like 1 decimal
Would have to be or it would have done -839.916 -> -839.92 instead of -839.90
I'm not even using the Location though, but I assume because it's slightly off I get corrections anyway
It's weird
We have pre-placed launch pads
That are the same actor
And they work fine
But if I spawn them runtime they cause corrections
The code doesn't change, only the replicated location/rotation could be at fault. I shall spawn at 0,0,0 for testing
Nope, 0,0,0 still gives me corrections
What the f
Yeah okay, nvm rotation and location at 0,0,0 still cause corrections. What the f is the difference here
No chance a correction occurs before the transform replicates? Wouldn't think so but can't think of anything
It's 100% reproducable. Place the Jump Pad into the level, works. Spawn it runtime, doesn't work.
The actual code for jumping is a locally predicted GA with root motion source.
(on the character)
I can print and the same code calls
Working:
: [] Client 1: LAUNCH
: [GA_JumpPadLaunch_C_0] Client 1: P=0.000000 Y=0.000000 R=0.000000
: [GA_JumpPadLaunch_C_0] Client 1: 800.0
: [GA_JumpPadLaunch_C_0] Client 1: 600.0
: [GA_JumpPadLaunch_C_0] Client 1: 800.0
: [GA_JumpPadLaunch_C_0] Server: P=0.000000 Y=0.000000 R=0.000000
: [GA_JumpPadLaunch_C_0] Server: 800.0
: [GA_JumpPadLaunch_C_0] Server: 600.0
: [GA_JumpPadLaunch_C_0] Server: 800.0
Not working:
: [] Client 1: LAUNCH
: [GA_JumpPadLaunch_C_0] Client 1: P=0.000000 Y=45.000000 R=0.000000
: [GA_JumpPadLaunch_C_0] Client 1: 800.0
: [GA_JumpPadLaunch_C_0] Client 1: 600.0
: [GA_JumpPadLaunch_C_0] Client 1: 800.0
: [GA_JumpPadLaunch_C_0] Server: P=0.000000 Y=45.000000 R=0.000000
: [GA_JumpPadLaunch_C_0] Server: 800.0
: [GA_JumpPadLaunch_C_0] Server: 800.0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Who hurt this f*cker
: [GA_JumpPadLaunch_C_0] Server: 800.0
So I found the issue (cause the RMS requires values to be the same). Now just have to see why that value is wrong on the spawned one
And only on the server
What is the easiest method for distributing a game for testing remotely. Still steam or is there another way?
If you want to release on Steam anyway, then yeah
Otherwise, idk. Upload it to a Server you own?
Might need to get that setup asap then. I want to test between my PC and laptop
Steam is def the easiest way ify ou release on it anyway
Well, at least the "preferred" way
Takes a bit to setup properly
Especially if you don't want to do it manually all the time
The last I read steam took more of a cut from your game than Epic.. that was a couple of years ago.. Not looked into it since
ah.. the last I read, Epic took nothing until you made your first million
The 18% is generalized
What's the audience ratio though?
It's 12% I think even
Well you have to fight the people who are unable to install more than one program on their PC and have to cry online about needing a second launcher.
Then you have to fight the people who think Epic sells their data to China.
Then you have to fight the people who think EGS is bad so they don't buy there.
Then you have to fight the people who think Steam is the best thing in the world and nothing can replace it.
I always envisaged putting my crappy game on Epic and avoiding Steam. I think Steam want exclusivity rights for a while
Ah. I thought they wanted exclusivity
Ha, nope
ok nice.. I thought I had read that
Then all the little Steam Fangirls wouldn't be able to cry about Epic having exclusive deals with some games.
haha
Also, they probably still all buy on EGS.
Its a loud minority imo
But EGS doesn't have the same visibility anymore it had at the start, cause now there are a lot of games on there
So could be that your game is burried as much as it is on Steam
I don't listen to a lot of that. My life is too busy to listen to the noise
Good choice
but to get back to the original topic
For testing your Game, you can use Steam of course easily
You need 2 PCs and 2 Steam Accounts
But that's all
That's a whole topic on it's own.. How to get your game exposure
And the initial 100€/$
For your AppID
If you don't release on Steam then that's of course wasted
I already have made a dev steam account for testing
With your own ID?
hmm. nope but the last time I set this up it worked.. I paid nothing
Things HAVE changed a lot
You can't upload your game without that
Ah I wasn't uploading, merely connecting the clients
You can test with 480 AppID
But then you have to distribute it through other stuff
Yeah well you asked for distribution
Or not?
ah sorry. I don't know the specific ins and outs. I just meant in order to dev test it. I'll cross the distribution bridge in about 5 years when my game is complete
Right, then it doesn't matter what you use. You can also just connect directly via IP if the Port is open
You can use Steam's AppID 480. Or go through the (maybe?) pain of setting up EOS
Which I can't comment on cause I haven't done that yet
Ah I'll probably just check into doing that then. It's on the local network and I had that working from a template I was learning from
If it's just LAN, then you can just use SubsystemNULL
And Host/Join Sessions via that
oh nice
Steam only becomes interesting if it's outside the LAN
nice and simple (I hope)
Yeah SubsystemNULL just has to be enabled
Then you can use the Create/Find/Join Session nodes
I actually would like to test this very early prototype with some friends soon so I'll need to face beyond the LAN at some point
Fail fast is my motto
Yeah then you either use NULL + Direct IP connection
Requires Host to open Ports
Or Steam with 480 App ID
Which can sometimes be a bit tricky
Cause UE will get ALL 480 Games and filter them locally
So if you request 10 Sessions and those 10 are not matching your game, the game tells you "Couldn't find Session" :D
Is there a reason you've not tried setting up the EOS yet, or is it just time?
No time or need yet.
Internally we use Steam atm and don't dev a Multiplayer Game, cause we know how much work it would be.
Externally, barely any client uses it yet.
And the ones that did were handled by a co-worker
Mainly cause Epic only recently opened up for self publishing I guess
right.. I'm surprised (maybe only a little)
Sorry to change the subject. I posted a question earlier about allowing TeamA only to pass through certain walls. I have that working now with setting up a custom collision. Is it possible to have those walls use a different shader? I'd like the special walls to look normal for TeamB
Thanks for all the help here btw. I've logged this conversation to be properly digested later
You can but it's an annoying setup
You basically need to react, on the Wall Actor, when the Local Client gets their Character and their Team.
Idk where you save the team
If you have the team on the PlayerState then one way could be getting the PlayerState on the Wall and getting the Team, comparing to the Team variable you have on the Wall itself.
And then adjusting the Shader
I'm saving the team variables on the GameState :/
Only thing that will byte you is the Timing, cause PlayerState could not be replicated
How do you know if Player A is in Team B?
Ah the PlayerState holds that info
Actually. you can have particles on the owning client only right? Could it be done that way?
I can tell you that if I would need to set this up, I would do:
- Use C++ (hehe)
- Create a Team Variable on the PlayerState
- Have it OnRep and have a Delegate to broadcast when the OnRep calls
- Make my own PlayerController C++ Class
- Override "OnRep_PlayerState"
- Add a Delegate to broadcast when the OnRep calls (if ListenServer exists, then you need to also call this when the PlayerState is set/created, cause OnRep in C++ only calls on Clients)
- In the Wall Actor, GetPlayerController0 on BeginPlay
- Get the PlayerState,
- If it's valid, get the Team and check if the Team is "Invalid" (which would be a value it can have as an enum)
- If it is Invalid, bind to the Delegate to get notified when the Team changes and call the code to change the Material
- If it is valid, call your code to change the Material
- If it's invalid, bind to the Delegate that calls when the PlayerState OnRep calls on your PlayerController and then do the above code
That way you should not have any trouble with ping and replication.
cause you get notified when everything is there
And as usually I may add that doing this in BP only is not fun
Ok what you just described there is well beyond my capabilities. Here's the thing.. my plan is to put together this prototype in order to create a pitch for funding. I'd like the playable prototype to work as well as I can personally get it (not perfect) but with no bugs (as few bugs as possible) I will also be putting together a pitch deck with some x-images I'm going to create to show the Visual Target Art Style.
You can hack that together of course
But some thing won't change
You still need the Team on the PlayerState
But you can do some ugly Delay loops to get around the OnRep stuff
RE: this #multiplayer message - Would this be an easier hacky way of doing it?
It only has to have a visual indicator that TeamA can walk through the wall
BeginPlay -> 1.
- GetPlayerController0 -> GetPlayerState -> 2./3.
- Is PlayerState Invalid -> Delay 1 Second -> 1.
- Is PlayerState Valid -> GetTeam -> 4./5.
- Is Team Invalid -> Delay 1 Second -> 3.
- Is Team Valid -> UpdateMaterial -> End
Don't know hwo to easier visualize braching paths here
Ah, I was put off as soon as you mentioned C++ but if this can be hacked instead with Delays then maybe I'll give it a go
Yeah, just that Delays are not a production thing. If you just need a hacky prototype, sure
Thanks for the pointer man, it's really appreciated
Yeah I understand that well enough thanks
It's a right dirty hack but maybe I can build into it a limit or would that just continue until it definitely became valid?
I mean.. it WOULD have to become valid at some point right?
PlayerState yeah, theoretically it should be
Team, if we assume you have an Enum with a default "Invalid" entry, then that depends on you setting that variable at some point to the actual team
Maybe I'll build into it some kind of 'Please hold the line.. your call is very important to us'
So I know if it's silently failing
There is a high chance that walls aren't visible to the player when all of this calls anyway
This also won't handle team changes that happen afterwards
So from Team A to Team B
Only the initial one
Ah.. the teams aren't set from the beginning. It's an Asymmetrical balance switching gameplay, with the premise that if you die you switch teams and you are still included and participating until the end of the game.
Then you need a callback from the PlayerState
You won't get around that
Otherwise the Walls won't be able to react to a Player moving from Team A to Team B
Then you need to set the Team Variable in your PlayerState, in BPs, to Repnotify.
And add an EventDispatcher that you call when the OnRep calls.
Sure, I have a section of bp code for dealing with switching. I can insert this in there
There are a whole host of things that need to happen when the player switches team
And instead of doing this:
- Is PlayerState Valid -> GetTeam -> 4./5.
- Is Team Invalid -> Delay 1 Second -> 3.
- Is Team Valid -> UpdateMaterial -> End
You'd do this:
- Is PlayerState Valid -> BindTo "OnTeamChanged"
And the Event you bind to "OnTeamChanged" would then do "UpdateMaterial".
- and 2. stay the same
OnTeamChanged would then be the EventDispatcher in your PlayerState
Cheers Cedric. I've added a bunch of learning tasks to my Trello board. Lots to digest
Hii <@&608320500170620938> <@&213101288538374145> i wanted to test network emulation settings so I have opened default third person project.. and set the net mode to client and emulation settings to “everyone ” and preset to “Bad”.. in this case I have observed rubber banding on the player when we move and stop.. is there a way to fix it .. I haven’t changed anything everything on the character movement is default
Ahhh, buddy, you gotta read the #rules
You can't just ping Mods and UE Team for help with UE.
^
^
hello, i'm new to multiplayer, i'm trying to implement a simple Set Actor Location to my player`s pawn, Running it on server seems to replicate fine to other clients but it never happens locally, multicast seems to not solve it either, am I skiping a step i'm not aware of?
"locally" ?
i meant for the player who asked the event to happen on server
So the player will move to another location for the server and other players but not for the player who sent the server rpc?
yes
With a Character?
yes, and they does contain the Character movement component
the default way or the way that tuts tell u to replicate the lookAt angle is to just send it through an rpc to the server, the thing is this doesnt have interpolation and if u use this value in more important stuff than the character turn angle, like for example trying to use it in a spectator camera it feels kinda choppy, is there a way to replicate those kind of values "smoothly"?
i've been attempting a couple different methods, these are the last 2 attempts,
the one above (with the multicast) seems to at least attempt to move the client, but he gets corrected into the position he was before, the correction only happens to him, the server and other clients still get to see the event properly.
the other one seems to no even affect that client.
update: seems like the problem is only with the rotation portion of it
Can you print the result of GetActorRotation node before setting the rotation and rotation?
I usually use Timestamps
LastTimeXYZHappend = CurrentTimestamp
CurrentTimestmap can be GetTimeSeconds
And then you have a settings variable for the duration. e.g DelayBetweenXYZ
And then you can do if (LastTimeXYZHappend + DelayBetweenXYZ < CurrentTimestamp) -> DoXYZ and set LastTimeXYZHappened 0 CurrentTimestamp
first one is the rpc sender
what is state sync
is it sending inputs and correcting every now and then with state
or is it sending both at the same time
how would i loop thru all curent players and compare a value :/ ?
GameState->PlayerArray is an array of the player states of all connected players.
oh alirght
so how would i go about doing that x)
im in my game state now like the hows and the whats
ill try google first
hm in this tutorial were using player state instead of game state
any specific resons for htat?
Each player has a player state.
and each game only has one "game state" ?
obvi
so the score should be saved on each player and the game state would hold the "conditions" i suppose ?
Something like that.
and those state can the do server stuff or they only do server stuff i suppose ?
ok
The server-only thing is the game mode.
ok
ok so how would i go about showing
erhm
in this case i wanna show the top 3 players "score"
this is from a Widget do i do the logic in there or ?
I suppose.
ok how should i do it on a tic check wich one is highest or ?
What happens when you have replicated actor A and attach replicated actor B to it, but on one of the clients B gets replicated before A; does it just show up with a world space transform of its relative attachment transform?
It should teplicate correctly iirc
Components keep their own world transforms which may or may not be replicated.
Actors have FReplicatedAttachment struct as wel
Easy test, Set A Netpriority 1, B Netpriority 3, and spawn 100 pairs
In same tick
when the client drops a weapon, all connected clients dropped the same item too 😄
can anyone help me to fix it?
#Running on server called client multicast reliable function
TSubclassOf<APickupWeapon> WeaponPickup_TSC;
WeaponPickup_TSC = APickupWeapon::StaticClass();
if (AARMACharacterBase* MyCharacterRef = Cast<AARMACharacterBase>(GetPawn()))
{
FTransform SpawnTransformLocation = FTransform(FRotator(0), MyCharacterRef->GetActorLocation(), FVector(1);
APickupWeapon* NewWeaponPickup = GetWorld()->SpawnActorDeferred<APickupWeapon>(WeaponPickup_TSC, SpawnTransformLocation, nullptr, nullptr, ESpawnActorCollisionHandlingMethod::Undefined);
if (IsValid(NewWeaponPickup))
{
NewWeaponPickup->SN = SN;
NewWeaponPickup->ID = ID;
ItemWeaponRef = Cast<AItemWeapon>(Item);
if (ItemWeaponRef != nullptr)
{
NewWeaponPickup->Ammo = ItemWeaponRef->Ammo;
}
NewWeaponPickup->Quantity = 1;
NewWeaponPickup->FinishSpawning(SpawnTransformLocation);
Pickukp = NewWeaponPickup;
}
return Pickukp;
}
@latent heart something like this or :/ ?
the cast to player character bp fails tho
In multiplayer dedicated server game where is many players same time playing what is most performant way to check is there players close? I have ai turrets at swamp area and those are rotating but there is no point if no one are close. do "sphere overlap actors" every 20seconds or?
Something like that, yes, but it'll only work if you've actually set your player character and player state class vlaues in the game mode...
hmm,
im setting it in the player state why wouldent that work /:+0
hm right i suppose i get what your saying
trying to find where it special cases it if so.. lots just looks at attachparent and FRepAttachment AttachmentReplication.AttachParent not being null, which would normally be the case if the actors were replicated out of order, but there may be some place where it holds it back from being spawned until the attachparent exists?
Give the turrets a sphere collider and make it the size that you want to "detect" the player. When an actor overlaps, that can mean it is in range, so then you check the "other actor" to see if it is a player's actor (cast to your character class) and then do what you will with that value knowing that player is in range. As this is multiplayer, you may want to at that point add the player to an array on the turret so it can keep track of what enemies are in range. When there is an OnOverlapEnd event, that means something has left the sphere, so then you can check and see if again if it is a player's actor, and if so, remove them from the array that you are using to keep track of who is within range and if it was your current target player, attempt to get the next entity in the array index 0 - if there is none, then there's no others in range, if there is, make that the new target.