#multiplayer
1 messages · Page 175 of 1
PostNetInit I guess
beginplay would work as well as that can only fire after the initial bunch afaik
question: If your GameMode is designed for an Online Match (1 v 1) and you want to make a Local MP GameMode, would you make a Base GameMode and share functionality between them? Like for Local MP you'd need one UI overlay rather than every player creating it, and also Controllers would need to be created in the Lobby, rather than joining from another place.
I think if you use Beacons, you could effectively have one game mode while still being able to represent both a lobby and a local menu system for joining the game.
As far as within the game, that could probably be determined by setting a bool in the game instance that you're running local multiplayer only which you set if a second local player joins, and if true, check if the owner of your HUD class is == Get Player Controller 0 and if true, proceed with creating the HUD.
what is Beacons?
A lightweight replication point that you can use before fully connecting to the server
Allows you to rpc, without loading entire world
Hello
i am (finally) reworking my multiplayer setup from BP to c++.
in my game, the core stuff is relative to the time of the day
each 0.x secs, fake seconds are added.
for now, all was done on server and replicated to clients. Since there is never anything that changes the delay between added fake seconds (except when all players are in bed, then we pass time faster until morning), i thought that :
- on server and all clients, fake time is added over time (so UI and local stuff is always updated fast)
- only server will broadcast some specific events to other stuff (eg : this door is only open between 10:00 and 11:00) to unsure "security"
is this a good design ?
also, if this can help, this is running on a world subsystem
(eg : this door is only open between 10:00 and 11:00) to unsure "security" this wouldn't matter
If a client wants to modify their local game instance they can do that, doesn't matter what you replicate ultimately
What matters is whether the client is able to proceed with an action they shouldn't be able to
If a client gets into an area they aren't supposed to be in, the server would have to "handle" it so they can't do anything meaningful there
There's no security in replicating something vs not, essentially
so here, the door would have a boll CanOpen, set to false
- at 10:00, server (or client locally) would broadcast an event to the door so
CanOpenis set to true - when trying to use the door, on server the check is performed to see if this is usable
That's fine, but keep in mind, the client could teleport themselves behind the door or something
how ?
they just move their pawn locally
they can choose to ignore corrections from the server
well, eventually they will get corrected to a point where they are back facing the wall they previously went through illegally ?
if not, im not sure how to handle this
well i just learned the SS are locally only so there isnt a "server" part
so i guess i'll have some other classes like the game state having replication and broadcasting stuff to the subsystems
Yeah subsystems have no networking ability
im curious why
The only type that does is actors
oh yeah i forgot the actor channel part
but maybe there is a way ?
i found that you could do that to UObjects
Any object that replicates needs to go via an actor
UObjects can only do it when they belong to an actor for instance
but thats just curiosity i wont make it more complexe that its already
But my main point essentially was that replicating something to a client doesn't have any impoact on "security" from an anti-cheat perspective
but i could technically have a singleton actor that is empty and linked to world subsystems to be replicated
So replicating only the time of day and driving everything from that is just as "secure" as replicating bools about doors individually
okay, im just saying "security" for like, "its more safe than having it running on client" part, but i dont truly know the behind the scenes
truthfully it's not really
and you create more potential for bugs and issues by having multiple replicated states that essentialy denote the same information
If a client can derive the info it needs from a single property, that's far better design wise
well in BP it was on GS
- time of day (fake hours + fake minutes) changing on timer by event
and then, broadcast events. So stuff like the door "that is only unlocked at some periods", would subscribe to "OnHourChanged" and change its "IsUsable" bool depending on given params.
yeah that's fine, honestly I would avoid any state on the door if I could help it
checking a timestamp isn't gonna break the bank
so how would i dot that ?
tbh i dont see why its better ^^'
Just add an IsUsable function that checks the current TOD whenever you call it
but again
Because more cached state means more things to go wrong or go out of sync, this is just a general programming thing not MP related
its more "i dont see the differences", and i like the split up logical parts
okay
If some other system looks at the TOD and thinks "door should be openable", then looks at the door and sees it isn't interactable, it's because you have two conflicting states
like a missed broadcast event ?
Or that you queried in in between the broadcast event, or from an earlier callback in the event etc
Id probably store this info (if theres alot) in some data asset
In general the more stateless you can make something the more resilient it tends to be, I find anyway
so checking on server "is usable" would be more costy than checking locally on the WSS "is it the good time"
So even thirdparty (npc f.ex) checks the DA when figuring out if doors can be opened etc
One huge pitfall of OOP is how stateful it is
also, since im using GAS :
- should i run the check in some stuff relative to GAS or basique methods
I'm having a strange issue that makes it so comparing a user unique net ID (from playerstate) no longer matches when the game has been shut down and restarted? However, when I print the ID (to string) they are identical. What's going on here? Is the unique net ID struct containing more stuff than a string that changes each time you launch the game or something?
Here's an even weirder twist to the issue. When I play using a development build it IS always the same. But on a shipping build it's different each time the game is relaunched.
My mind absolutely does not comprehend what in the hell is going on
Does anyone know what kind of dark forces are at work here?
What backend service are you using?
And you're using FUniqueNetId::Compare to check?
Oh nvm, == calls Compare internally anyway
Should work fine AFAIK.
Unless for whatever reason it's not actually connecting to steam in one build
I just compare the Net Id Structs themselves
Because the "null" subsystem just generates random GUIDs each time.
I've made sure that the structs are only saved and compared after being validated
And I've printed them out and they are in fact valid
I've also checked the savegame data and it does contain the correct ID's
Guess you'd have to step through the code and see why the comparison fails
Yeah, gonna delve a bit deeper I guess
UniqueNetID's are wrappers around pointers so maybe it's failing because the pointer comparison fails
I'm willing to bet that blueprint == operator doesn't account for that
I'm gonna try and convert them to a string and compare the string to see if that works
Because whenever I convert them to a string, they always return correctly and identical
But it's like the struct has some other "things" that are different / invalid / null or dunno after a relaunch of the game
I guess the literal ID string is just one part of the struct
steams just stores your account CSteamID IIRC
There is no literal string, the data gets converted into a string
Hmmm
And could two different data sets convert to the same string?
or is that not possible?
theoretically yeah
I'm 99% sure the issue is because the FUniqueNetIdWrapper which Blueprint uses compares the actual internal pointer
So it's not smart to compare the structs?
the comparisson of the structs works fine as long as the game runs, between levels and all
Without actually debugging I really don't know
But when I relaunch the saved struct (read from savegame data) and the new net id struct no longer match
So my far fetched uneducated guess is that inside the struct data there's some kind of stamp that holds indeed a pointer to a gamesession or whatever else that is bound to a single running game session. And when the game relaunches, that part of the struct changes.
Gonna try and convert my comparrison system to compare the strings and see what that results into
If that works, I think we have our answer
What could also be the issue is that the unique net id struct can't be saved
But here's where the converted string will prob have no issues being saved
I think that fixed it
doing a final test
will report back
hey there! Could you provide a quick rundown of the database and matchmaking systems commonly used in competitive gaming nowadays? Thanks!
Do I understand correctly that when we server travel from one map to another, the only thing that travels with is the gamestate? Things like player controllers and such do not travel and just get spawned when the new level has loaded right?
Hmm gameinstance survives but not sure about gamestate
You can pack some stuff along for seamless afaik
GM and GS will transition as they are yeah
Controllers may also be kept
FSeamlessTravelHandler::Tick() is where you wanna look
This is exclusive to seamless tho right?
I've experienced this as well. FName in shipping/development builds are not reliably the same
IIRC: its usually something like in Editor GameMode/GameState are always GameMode_0, GameState_0 but maybe different in Shipping
GameMode specifically travels to the transition map and then gets overwritten with a new copy of itself
The docs on how GameMode "persists" is misleading because its "persistence" is more related to implementation details regarding seamless-travel then actually "persisting to the next actual level"
You can technically mark it as an actor to persist in "GetSeamlessTravelActorList" but this is ill advised you'll have to handle all the setup GameMode/GameState normally do for you
That's FName though, and that makes sense because FName is not case sensitive outside of editor
But yeah, names def won't be reliable
Trying to pass a USaveGame through to a server function but it is always NULL on the other side
Always will be
USaveGame is a local UObject on your machine, so you can't network references to it
how do i get the server to get the clients save game then
Guys, i Need your help to understand multiplayer. In my APlayerController child class, i got mouse input to rotate top-down character (child of ACharacter).
void AWTPlayerController::OnCursorInputHandle(const FInputActionValue& Value)
{
FHitResult CursorHit;
if (!OwnedPawn.IsValid() || !GetHitResultUnderCursorByChannel(UEngineTypes::ConvertToTraceType(ECC_Visibility), true, CursorHit)) return;
const FVector CharacterWorldLocation = OwnedPawn->GetActorLocation();
const FVector TargetPosition = FVector(CursorHit.Location.X, CursorHit.Location.Y, CharacterWorldLocation.Z);
const FRotator FinalRotator = FRotationMatrix::MakeFromX(TargetPosition - CharacterWorldLocation).Rotator();
OwnedPawn->SetActorRotation(FinalRotator);
}
When i start listen server mode with 3 viewports:
- Server-player is rotating correctly in all viewport
2 and 3 - clients, rotating only on their own viewports
If player controller owned by server, why rotations of this instances of characters is not replicated?
You're not sending an object when you send the RPC, your sending a reference to it
Upload it to the Server somehow, get the Server to load it
unfortunately i don't know the 'somehow'
Clients sending local files to servers sounds like a recipe for disaster ofc
I know you're really supposed to save data server side but I don't know how to go about that and you need some cloud storage right that i'm not paying for rn
That only happens locally
You never tell the server anything about the cursor hit location or the rotation that comes out of it
So, should I create method in controller or pawn, for example, which will be get const FVector3D& as rotation, and inside this method rotate pawn? Also mark this method UFUNCTION(Server, unreliable, WithValidation) ?
You need to send the server something
whether that's the cursor hit point or resultant rotation or whatever is up to you
Does anyone know how to build shipping with crash logs/debug symbols?
Clients are crashing in a shipping build when seamless travelling though not sure why
I don't know why that's here
instead of like #packaging
but there's a packaging option
but really, I wouldn't think of giving debug symbols to your players
I'm just internally testing steam-integration
def wouldn't give debugs symbols/debug build to actual players
it's useful to have the symbols in the staged output though so you can copy them to the symbol server/the third party crash service you use after the build, but exclude them from steam (insert other platforms here) upload
well do you know for sure without seeing the callstack?
Well the client is crashing after the server tries to seamless travel
also on past projects, we would upload to steam twice. we'd have internal builds that did have the PDBs included but anything external wouldn't have it
The server itself makes it to the next level fine but all the clients hard-crash on a segfault
idk which
depending on project budget, it might be good to use some third party service to handle crashes for you. at my old studio we used Bugsplat
Do debug builds (if uploaded to steam) still work with multiplayer?
That probs is the easiest if that works
well you can get debug symbols for shipping anyway, it's just a little harder because it's optimised code
you could do debug for someone internal to the studio to investigate
What do you mean someone internal to the studio to investigate?
you wouldn't give debug builds to the public
well yeah I'm debugging it myself of course hahah
multiplayer works regardless of the build type, it'd be pretty useless if it didn't
the only thing about doing a full-on debug build is that the perf will be shit
Ari actually recently did a video about a lot of debugging tips, even in shipping builds. Can't find it right now though. And at work, so can't spend to much time looking.
You could make a custom save game, like a text file. The server can keep records of each player (ID etc.), and instead of using a database you can store the files on your machine as the "server admin".
If you want to use a database later you can of course.
so the best option is to have all clients locally having their time ?
they will have no "delays" because ping isnt involve but im still scared of having clients not synced between each other
because, the event that will "make start the time of the day" will be called by server, so if a client start after another they will be out of sync
Is there a frequency limit of sorts for animation notifies that can be triggered on a server? I am using a listen server setup and sometimes the server is unable to hear sounds or see vfx from notifies placed in an animation montage that I can see other players play. It has also happened with a simple notify that triggers a debug print.
You need to change the notify rules iirc
To be branchingpoint or whatever its called
hi everyone. in a local multiplayer game i wish to have some UI elements which are across the whole screen, not seperated by each player viewport. is such a thing possible ?
Notifies are a system for setting up and receiving events in Animation Sequences to perform external actions.
Near the bottom
Addition settings
Thanks but I have already tried branching point, 0 weight threshold, trigger on server is checked, etc
AddToViewport vs AddToPlayerScreen
AddToViewport -> entire screen
PlayerScreen ->local split screen
Listen server doesn't tick animation poses the same way clients do
Listen server's only tick the character pose when it receives an update
thank you very much !
@gilded vapor so given that i want both for different UI elements, i would effectively have a widget for player screen and a second for viewport ?
Yes you would need 2 different widgets~~
Hm, I see, that would certainly explain this, thanks. I'll see if I can change this behavior easily or find an alternative, it's kind of annoying though
If its game-related behavior I usually do something like Notify -> communicates to client Component -> RPCs to the server
I don't suppose it would be as simple as changing this
If true TickPose() will not be called from the Component's TickComponent function.
There's a bunch of edge cases if you are using root-motion
Because the server will tick the animation on the server AND when it recieves updates
so the animation on the server will play faster than the client
Having to do an RPC for an animation that is already playing on the server just seems wasteful though
You can tick the character pose on the server, and call 'CharacterOwner->GetMesh()->ConditionallyDispatchQueuedAnimEvents();' from the CMC
to fire off anim-notifies
Can anyone help a little... If I use this function, it's replicated and all clients call OnDestroy. If I hit anything that's not the player, I spawn a Legacy Emitter at the hit location and I play the sound succesfully on all clients and server. If I use this Niagara System however, it only plays on the server. I made a NetMulticast RPC reliable to play the niagara system and even that doesn't play the Niagara system.
void AProjectile::Destroyed()
{
Super::Destroyed();
if (!ImpactParticles.IsEmpty() && !bHitPlayer)
{
const int32 RandomIndex = FMath::RandRange(0, ImpactParticles.Num() - 1);
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactParticles[RandomIndex], GetActorTransform());
}
if (!PlayerImpactNiagara.IsEmpty() && bHitPlayer)
{
const int32 RandomIndex = FMath::RandRange(0, PlayerImpactNiagara.Num() - 1);
FFXSystemSpawnParameters Params;
Params.Location = GetActorLocation();
Params.Rotation = GetActorRotation();
Params.Scale = FVector(1);
Params.bAutoActivate = true;
Params.LocationType = EAttachLocation::KeepWorldPosition;
Params.WorldContextObject = this;
Params.SystemTemplate = PlayerImpactNiagara[RandomIndex];
Params.bAutoDestroy = true;
UNiagaraFunctionLibrary::SpawnSystemAtLocationWithParams(Params);
}
if (ImpactSound)
{
UGameplayStatics::PlaySoundAtLocation(this, ImpactSound, GetActorLocation(), 0.25f, FMath::FRandRange(0.f, 10.f));
}
}
TickCharacterPose(delta * root_motion_tick_character_pose_scalar);
CharacterOwner->GetMesh()->ConditionallyDispatchQueuedAnimEvents();
@unique kelp
Will do some testing with this, thanks for the help 👍
im ngl its a can of worms
I batch all of the frame data into saved moves for the CMC. (IE so each saved move has the current-time and play-rate of the montage
And when the server playsback the saved-move it sets the animation to the received time. So that player-movements and player-animations are always in-sync when sending from client -> server
And the server always ticks the pose as well, but at a SLOWER rate then the actual play-rate. (~.8f) and then it will jump to the proper position when it recieves in update
Interesting, I'll see what I can get away with for our use case, thanks!
Given me a lot to consider
if statements are wrong
!bHitPlayer && bHitPlayer
Has anyone got the mover 2.0 stuff working in 5.4? When i add the mover plugin and restart I get the error: ?GetPrivateStaticClass@UPlayMontageCallbackProxy...could not be located in unrealeditor-movereditor.dll
no that bHitPlayer returns true
I have all valid pointers and values and locations are proper and everything comes out expected values
Just the clients never play it
It gets all the way to play
if (!ImpactParticles.IsEmpty() && !bHitPlayer)
if (!PlayerImpactNiagara.IsEmpty() && bHitPlayer)
Are these intended to basically be the same checks
Yes those work as expected
No
One checks if I hit the wall or ground
the other checks if I hit a player
ohh
I have 2 different arrays of particles
one for the ground one for the player
This function works perfectly on every client and server for the legacy emitters
This same function calls the spawn niagara with all valid data and it doesn't spawn on clients
So you're destroying it on the server?
A short clip
is bHitPlayer replicated?
because you might be destroying your particle server side before it collides client side
i didn't think about that
let me check please
You're a damn legend bro
Immediately solved the issue
Hero
thank you
welcome hahaha
Now I have to go back and undo all this extra trash code I wrote trying to be so verbose
I bet this function works just fine in the basic syntax
^^I always have to go back and delete a billion print statements
Well going back to undo my code because I thought it would work more simple broke it again
Looks like I did need to do all that verbose shit
That's so bad bro if it works don't fix it right
Bro there's no way I can't figure out how to fix this back I just had it working are you kidding
I'm dead
Wow I thought it was just so simple as I didn't replicate a damn boolean
nah nah
and now here I am what 30 minutes later and all I did was break it
I have it in a replicated function already that's called on all clients
It plays the sound and the emitter if I miss the player
The issue is when I hit the player
not trying to argue
If you have a RPC reading a replicated variable, it's likely that by the time the variable is replicated (end of the frame), the RPC will have already been executed
I'm trying the rpc now
^^yeah that's what I meant
I'm overriding the Destroyed() function inside the actor. In the source code it's replicated already if I call Destroy() on the actor explicitly
It auto replicates to fire on all clients
That's how I got away with the sound and the other emitter for just hitting the ground
None of that is replicated
now I need this boolean replicated properly
It probably would be easier (and better) to actually send the RPC from the hit-actor opposed to the projectile.
Why should I have to send an RPC tho
I should be able just to spawn a system on the locally controlled player
Destroy() calls a net multicast essentially already that I override
Well I guess it doesn't really matter with how you set it up
I'm pretty sure you need an RPC to replicate that you hit the player
You could also just do the collision checks client side and locally predict the vfx~~
I'm pissed because it was working all I did was have to call getlifetimereplicated props and add one DOREPLIFETIME and it worked
I had it figured out
I didn't have the RPCs and stuff
It's not replicating the boolean
it's so easy bro I just what am I missing
I tried the OnRep_bHitPlayer
It's not getting there true or false
This is crazy I labeled my boolean UPROPERTY(Replicated) and I have GetLifeTimeReplicatedProps override, calling super first, then DOREPLIFETIME(AProjectile, bHitPlayer);
For starts, I would consider EndPlay over destroyed. Or at least consider doing this stuff before running the super. Second it's better to use something more like a gameplay cue style setup for things like this. Less respawning of particles and whatnot.
This is a guided series for this project I'm trying to not refactor along the way until I'm done. This particular excercise was how to add new particles that only appear when you hit the player instead of the wall
I'm sure this is exactly what the test is covering, I need a new variable and replicating it myself is proving to be difficult for me to understand
it's gotta be something easy I missed
I literally had it working the moment this guy says did you replicate that boolean
and now I don't remember what I did obviously that I went back and erased
Not sure I'd trust replication that close to destruction.
Well is EndPlay called on all clients automatically if Destroy() is called on the server
No I can't see that it is
does replicatedusing mean I dont also need to have the specifier replicated? Is it a 2 in one?
EndPlay is called before the Destroyed call. It's just done earlier.
Correct
Right but I'm thinking of avoiding using another NetMulticast RPC
I can just use Destroyed() to play cosmetic effects until I change to GAS and use gameplay cues
IMO if you want to continue this route I would maybe consider setting a 0.3s lifespan instead of calling Destroy. Kill actor collisions and visibility, then set your replicated thing that it's hit something
Not ideal, but probably more safe for the visuals
Other than these two items, what else do I need to do simply to replicate a variable? ```cpp
void AProjectile::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AProjectile, bHitPlayer);
}
//////
UPROPERTY(ReplicatedUsing=OnRep_bHitPlayer)
bool bHitPlayer = false;
The actor needs to be replicated.
It is already ```cpp
AProjectile::AProjectile()
{
PrimaryActorTick.bCanEverTick = true;
bReplicates = true;
CollisionBox = CreateDefaultSubobject<UBoxComponent>("CollisionBox");
SetRootComponent(CollisionBox);
CollisionBox->SetCollisionObjectType(ECC_WorldDynamic);
CollisionBox->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
CollisionBox->SetCollisionResponseToAllChannels(ECR_Ignore);
CollisionBox->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
CollisionBox->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
CollisionBox->SetCollisionResponseToChannel(ECC_SkeletalMesh, ECR_Block);
ParticleAttachPoint = CreateDefaultSubobject<USceneComponent>("ParticleSpawnPoint");
ParticleAttachPoint->SetupAttachment(GetRootComponent());
ProjectileMovementComp = CreateDefaultSubobject<UProjectileMovementComponent>("ProjectileMovement");
ProjectileMovementComp->bRotationFollowsVelocity = true;
}
Relevancy is all that's left then. And not killing it before it has a chance to replicate.
If the projectile is too fast, and spawns dies within a frame or three, it might not actually replicate to the client.
It doesn't it travels for half a second
Way more than a few frames it's a gun bullet
Not hitscan
projectile
🤷♂️ Maybe try an AlwaysRelevant=true
can you explain this one to me COND_SkipOwner what is the owner? say I spawned an actor on the server and made my character the owner (on the server obv because I cant spawn it on a client an replicate it) Does this mean my client is the owner who is skipped if I set that character as the owner but from the server?
Also still recommend a small lifetime set instead of direct destroy.
Owner is the net owner of the actor.
Use case for that might be a local authority thing like the player's mouse movements that you want to replicate to others, but not get replication calls on the owning client.
So you make the client do aServerRPC for their mouse movements, set it on server, and it replicates to all but the one who set it basically.
thanks
There, mostly corrected. 😄
This makes 0 sense the variable isn't replicating
It's just not replicating
It never calls OnRep
Even tho that's what's labeled and defined
I put a breakpoint it gets to the line where it sets the value of the boolean
it just keeps on going never get to OnRep
Why
And the worst part is literally now an hour ago that this broke I had it working
It worked an hour ago
It is a different value on the client right?
Yes it's always false even tho in the Projectile.h I init the variable with true
I declare it bool bHitplayer = true; and the client returns false
And there is nowhere else in my code that I set it to anything other than 1 place I set it to true
I'm confused, how is it ever false?
You tell me
It plays the hit ground emitters if I hit the player on the client
That only happens if bHitPlayer is set to false
void AProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,
FVector NormalImpulse, const FHitResult& Hit)
{
if (ABlasterCharacter* Character = Cast<ABlasterCharacter>(OtherActor))
{
Character->MulticastHit();
bHitPlayer = true;
PlayerImpactNiagara.Empty();
for (UNiagaraSystem* System : Character->GetHitNiagara())
{
PlayerImpactNiagara.Add(System);
}
}
Destroy();
}
How are you testing that it is false on the client?
I can't see it in any of my breakpoints because it reads the server version and it's true on the server
But the emitter is in an if check for !bHitPlayer
It shouldn't be initialized to true, the client will initialize it to that too and if it's already true then the onrep won't run. The projectile doesn't start hitting the player so it should be false by default.
And you set it to false and restarted the editor?
Yeah
but hang on I just realized
I have a multicast Hit event as well on the player I'm calling
I put all the niagara on the player
Lemme see about calling it from the player
Damn bro the problem is if I play it on the bullet it shows the niagara where it hits on the body properly
if I just spawn it from the character idk where I got hit
could play blood off the legs on a headshot
I made more replicated variables just for fun it's not replicating anything it seems
I broke something big somewhere
I deleted everything to do with replication and I have LNKR errors for overriding GetLifetimeReplicatedProps. I'm doing the delete binaries and other temp folders
with the idea of having each WSS having their time for each client makes that they always have a "start" delay, so for one player its XX:50 and some other its XX:58
well a big fyi for world subsystems is that they don't support replication
yes
if that's important, but I'm not reading the lore
like any SS ?
before thinking to change to WSS there was still an issue of delayed replication, the server was updating the clients from GS
well if any was going to be replicatable, the world subsystem would've been it, but there isn't support
pretty sure you can use push model or good ol' ForceNetUpdate
to update the clients from server GS ?
well I've not looked in a minute, but the game state probably has a low net update frequency
its 10
like the player state
though you can sort of replicate world subsystems, by spawning an actor to proxy the data for you
i thought about that with Jambax
maybe to much complexity for just that i should rework the system in the GS on server side and just incresse the net update frequency
maybe make a "time" component and attach it to GS
I have this linker error of unresolved symbol in a generated file. I have deleted this function off of this class and it won't let me compile until I put GetLifetimeReplicatdProps() back onto my header file. Why must I have that function on this class in order to compile now from some stupid generated file?
LNK2001: unresolved external symbol "public: virtual void __cdecl AProjectile::GetLifetimeReplicatedProps(class TArray<class FLifetimeProperty,class TSizedDefaultAllocator<32> > &)const " (?GetLifetimeReplicatedProps@AProjectile@@UEBAXAEAV?$TArray@VFLifetimeProperty@@V?$TSizedDefaultAllocator@$0CA@@@@@@Z)
because your class contains a replicated property
Thank you I left 1 variable with the replicated specifier
is there any extra latency if passing through a component ?
Latency no. There's a slight extra size cost from what people say. Probably needs the actor and the component ref instead of just the actor. But it's mostly negligible for most cases.
I have read all the documentation I can find about replication it makes no sense. This boolean isn't being replicated ever. I put a breakpoint on the first line in my OnRep function and it never triggers. On the server the value returns as expected but I am literally at a loss for words
I have all the files just like epic documentation says to have them
Unreal insights network profiling kills a lot of worries or assumptions about things, It really made me able to see the whole networking picture and how expensive stuff really is (spoiler, it's a lot cheaper than I had originally thought it would be and the headers are tiny, like 14bits or so and replicated variables have like 16bits for header/footer packets.). I'd suggest profiling with it.
Empty RPCs are around 24bits
I did some testing a while ago because I was worried but at least now I have a clearer perspective.
Hey Y'all, been trying to render the Replication Net cull distance of my objects for debug and testing purposes to see what actual range might be best for my objects, nothing fancy here. I just can't figure out what box to check in order to do so.. Plenty of tutorials online that explains what Net cull distance is, but no one seems to tell me how can I see the range in game or in editor visualy, am I missing something here?
If i want to save my casted pawn object in player controller, what the best place to do this? OnPossessed is calling on server site only, but i need to save it in both sites
Double check your actor is set to replicate
How often are you accessing your possessed pawn where saving off a casted pawn is even worth it
Not sure if there's a built in debug command for that, but you could just render debug spheres on tick functions for actors
for example, i want to call any method inside this pawn by input action from controller
Well there's a delegate but not at my PC, but doubtful that will be even a worthwhile optimisation
Oh... that makes sense, so like, shere trace component with my actor on reference that uses the Net cull distance as radius if I get what you say?
@wet mica Do you plan on doing dedicated servers?
no, its listen server
There's a debug command to render spheres you can use. Not sure what it is offhand
Just do GetPawn<AMyPawn>() or w/e
I did the following things, and as of right now it works 3 players all clients and server. I replicated the entire array of possible niagara effects, and I added a multicast RPC that plays niagara as well. It works and honestly I just don't want it to break so I'm gonna leave it alone now
THank you everyone for whatever you helped with
Gotcha, I'll go take a look at the doc, thanks for the assist, I really appreciate it!
ULocalPlayer (or maybe ULocalPlayerSubsystem) has a delegate for when the player controller changes
Not sure how net mode has any bearing on that lol
It does for that part
I asked before I read the rest of the stuff 😅
Yeah but you also have a delegate like that on the controller too
Because ULocalPlayer won't exist on a dedicated server
Overall, I don't think this is a worthwhile endeavor
It's like OnPawnChanged and it's on authority and client
Yeah, but I can't remember the name of the delegate 😅
But yeah not really worth it just avoid a pretty trivial cast
I am trying to provide inputs to control top-down character from controller with enhanced input system.
So, i created 2 methods for it:
{
if (!OwnedPawn.IsValid()) return;
const FVector2d MovementVector = Value.Get<FVector2d>();
const FRotator YawRotation(0.0f, GetControlRotation().Yaw, 0.0f);
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
OwnedPawn->AddMovementInput(ForwardDirection, MovementVector.Y);
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
OwnedPawn->AddMovementInput(RightDirection, MovementVector.X);
}```
and
void AWTPlayerController::OnCursorInputHandle(const FInputActionValue& Value)
{
FHitResult CursorHit;
if (!OwnedPawn.IsValid() || !GetHitResultUnderCursorByChannel(UEngineTypes::ConvertToTraceType(ECC_Visibility), true, CursorHit)) return;
const FVector CharacterWorldLocation = OwnedPawn->GetActorLocation();
const FVector TargetPosition = FVector(CursorHit.Location.X, CursorHit.Location.Y, CharacterWorldLocation.Z);
const FRotator FinalRotator = FRotationMatrix::MakeFromX(TargetPosition - CharacterWorldLocation).Rotator();
OwnedPawn->SetActorRotation(FinalRotator);
}
And first method, for movement, is work correctly on each client and listen server viewports. But second one is working only for listen server instance. Each client can see only own pawn rotating. I still cant undestand, why. Character setup is default
Well that's not really going to be fixed with caching a pointer, GetPawn works fine
You need to send that information to the server for it to do anything
Input isn't networked
Yeah, just do an unreliable server rpc and send 'er up
The server won't have any information about the client's viewport or camera matrix or anything as well
So the target location is what you would typically send
Pretty much just send up the information you need to either recreate it, or what the client ends up with.
I aslo trying to replace last line with this method
UFUNCTION(Server, Unreliable)
void Server_SetPawnRotation(const FRotator& InRotator);
cpp:
void AWTPlayerController::Server_SetPawnRotation_Implementation(const FRotator& InRotator)
{
if(OwnedPawn.IsValid())
{
OwnedPawn->SetActorRotation(InRotator);
}
}
but nothing changed. Pointer check is valid, if i put log inside
And does the client actually own the pawn, is its movement replicated?
Though if it's something the player controller is possessing, you would typically also do it on the client too
yes, it is
And the rest of it?
How to correcylt check first one?)
If i can see rotating only on client site, guess it is
Well if it's a character, I assume it's the one the client is actually possessing?
Still not sure why GetPawn<T> isn't being used
yes, 100%
Then you have to "predict" it on the client too
ill replcae to getpawn in a sec
Quick question for anyone who might know. I have a "bounce pad" BP that is placed into a map. It runs logic on overlap that launches a character using their movement safe logic in a custom CMC. I'm still getting corrections on the client. The client sees you run over it slightly while the server is instantly bounced. I assume this is due to the client not predicting the launch since the launcher BP is performing its logic from the map (server owned). What's the best way to reconcile this? I'd like to avoid logic on the character itself checking for overlaps and doing prediction logic instead of the BP launcher itself handling it.
Also you should always just use the debugger. It hitting SetActorRotation here means it hits server side, but you didn't modify the rotation on the client
now its looking like this, but nothing changed:
void AWTPlayerController::OnCursorInputHandle(const FInputActionValue& Value)
{
FHitResult CursorHit;
auto* CurrPawn = GetPawn<AWTDwarf>();
if (!CurrPawn || !GetHitResultUnderCursorByChannel(UEngineTypes::ConvertToTraceType(ECC_Visibility), true, CursorHit)) return;
const FVector CharacterWorldLocation = CurrPawn->GetActorLocation();
const FVector TargetPosition = FVector(CursorHit.Location.X, CursorHit.Location.Y, CharacterWorldLocation.Z);
const FRotator FinalRotator = FRotationMatrix::MakeFromX(TargetPosition - CharacterWorldLocation).Rotator();
//OwnedPawn->SetActorRotation(FinalRotator);
Server_SetPawnRotation_Implementation(FinalRotator);
}
void AWTPlayerController::Server_SetPawnRotation_Implementation(const FRotator& InRotator)
{
if(auto* CurrPawn = GetPawn<AWTDwarf>())
{
CurrPawn->SetActorRotation(InRotator);
}
}
Yes because you commented out the local SetActorRotation call
yes, but it works on Current client, which takes inputs, and others client has no rotating to this pawn (controlled by input client)
looks like, that i didnt call to server about rotating?
You're in listen mode I'm guessing?
yes
Yeah so, it likely works on your client1 since he's the server but client2 fails because you're not calling your RPC properly. as client you need to let both your client and your server know that you're moving to this point to avoid desync. I'm guessing the Server call fails because of an authority problem coming from client2
void AWTPlayerController::OnCursorInputHandle(const FInputActionValue& Value)
{
FHitResult CursorHit;
auto* CastedPawn = GetPawn<AWTDwarf>();
if (!CastedPawn || !GetHitResultUnderCursorByChannel(UEngineTypes::ConvertToTraceType(ECC_Visibility), true, CursorHit)) return;
const FVector CharacterWorldLocation = CastedPawn->GetActorLocation();
const FVector TargetPosition = FVector(CursorHit.Location.X, CursorHit.Location.Y, CharacterWorldLocation.Z);
const FRotator FinalRotator = FRotationMatrix::MakeFromX(TargetPosition - CharacterWorldLocation).Rotator();
CastedPawn->SetActorRotation(FinalRotator);
Server_SetPawnRotation_Implementation(FinalRotator);
}
void AWTPlayerController::Server_SetPawnRotation_Implementation(const FRotator& InRotator)
{
if(auto* CastedPawn = GetPawn<AWTDwarf>())
{
CastedPawn->SetActorRotation(InRotator);
}
}
second function is server RPC. In first method, last 2 lines: i call it to local PC and to server one, No?
hey im using a texture for minimap rendering, since its multiplayer i need to create a new texture for each player right ?
To be more clear, you need one texture, locally created and managed, per machine.
Okay unless there's something I dont get from your code, pretty sure I understand your problem;
Instantiating your CastedPawn in the server function everytime is what causes your issue.
There's a delay between client and server when instantiating on the server, causing it to be null a few ticks.
Since you reassign is everytime in your if statement, you're consistently calling your Cast, but it nevers complete on that tick so it never apply the setActorRotation on the server
thats why you dont get this issue on your client1, since he is the server, he doesn't get that delay to instantiate, so its always true for that client
i changed cached pointer to cast like 5 mins ago)
before it, it was cached pointer, that i setup in void AWTPlayerController::AcknowledgePossession(APawn* P) method.
But nothing changed)
ill repeat problem:
client 1 (server) - Rotating correctly in own vieport and in others clients vieport
client 2 - Rotating correctrly ONLY in his viewport. Server didnt see rotating of this pawn too
client 3- same as client 2, but in his veiwport
Yep, thats the behavior of the issue im describing
because you're recreating the same problem but with different functions.
few things I would do, start by checking with a UE_LOG if your client2 actually ever calls it, you'll see it probably never does
Now, try to hardcode a delay into that function of like, 2 seconds, just to see if that fixes the issue ONLY, using delays in RPC is a big no-no but can be tolerated for debugging
if that solves your issue, Init a timer that will check every ticks that your CastedPawn isn't null, once its properly registered, then call your function dans delete your timer
But movement method is work correctly. Problem only in rotating input binding method
its ok:
void AWTPlayerController::OnMovementInputHandle(const FInputActionValue& Value)
{
auto* CastedPawn = GetPawn<AWTDwarf>();
if (!CastedPawn) return;
const FVector2d MovementVector = Value.Get<FVector2d>();
const FRotator YawRotation(0.0f, GetControlRotation().Yaw, 0.0f);
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
CastedPawn->AddMovementInput(ForwardDirection, MovementVector.Y);
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
CastedPawn->AddMovementInput(RightDirection, MovementVector.X);
}
Why is the movement handling in the controller anyway.. just move it to the pawn
yes, i know, that i cant replace it to pawn, but it should work in controller too)
It's too late to give up xD
I would assume your movement works because your PositionVector variable is replicated on server or your pawn is set to replicated movement. So even if your call fails when you call it on server, UE5 takes care of it anyway
you probably will get desync though once your project is deployed live
Anyway, best way to be sure, do a quick Log and check if the server ever calls your SetRotation for client2 or client3, I'd be willing to bet it stops at your if statement because its null everytime
You should move it though, it’s definitely not too late. Cutting corners really adds up, also I don’t think Casted is a word
Added method to log here
void AWTPlayerController::Server_SetPawnRotation_Implementation(const FRotator& InRotator)
{
if(auto* CastedPawn = GetPawn<AWTDwarf>())
{
LogHereMethod();
CastedPawn->SetActorRotation(InRotator);
}
}
For each veiwport, log is:
client 0(Server) : Server: Hello
client 1 : Client1 : Hello
client 2: Client2: Hello
Looks right?
that not even vaguely correct because why would a server RPC get called on other clients
also print debugging
Do something more like this;
{
UE_LOG(LogTemp, Warning, TEXT("Calls Function"));
if(auto* CastedPawn = GetPawn<AWTDwarf>())
{
UE_LOG(LogTemp, Warning, TEXT("Casted Pawn is not null"));
LogHereMethod();
CastedPawn->SetActorRotation(InRotator);
UE_LOG(LogTemp, Warning, TEXT("Called SetActorRotation"));
}
}```
or just use the debugger
Baby steps sswires, baby steps 😛
idk
UFUNCTION(Server, Unreliable)
void Server_SetPawnRotation(const FRotator& InRotator);
Shoul only call on server xD
the _Implementation function should only get called on the server, yeah. but I don't find print debugging particularly useful since when you hit the breakpoint you can check out everything in more detail anyway
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Server: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Client 0: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Client 0: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Client 0: Hello
LogTemp: Warning: Called SetActorRotation
LogTemp: Warning: Calls Function
LogTemp: Warning: Casted Pawn is not null
LogBlueprintUserMessages: [BP_PlayerController_C_0] Client 0: Hello
every log is triggered in each client
yes, but how i can check client with debugger in Rider/vs?
add a watch for UnrealEditor-Engine!GPlayInEditorContextString
and/or {,,UnrealEditor-Core}::GPlayInEditorID
Shouldn't there be a Client 1 or Client 2 somewhere?
Not for printing Hello. PlayerControllers only exist on the owning client and the server. Any other clients don't have a copy of it.
(Unless of course you're calling this on those particular clients)
idk, i always got client0. For example, i created empty BP child class of Character. Added PrintString to begin play. Started listen server with 3 PIEs, all of them mark as "CLient0". Have no idea, why
this example
can I see SetActorRotation function again
here
revert to this
I did, but i dont see your SetActorRotation function definition anywhere, essentially since it's being called properly, I'm guessing the issue is coming from there somewhere. the variable you're modifying is properly marked as replicated I suppose?
its a AActor method. I didnt overrided it
Also, i didnt provide any variable to save rotator values
Ah ha!
I packaged the game. Opened up 3 standalone packaged games
One host (player 1), one join as client (player 2), another join as client (player 3)
All joined in fine and can see each other. However, the moment player 3 moves, it disappears from player 2's screen. Besides that everything else works perfect. Player 1 sees 2 and 3. Player 2 only sees 1. Player 3 sees 1 and 2. All can interact with the world. Very weird.
This is Add BPC with IsServer check in Event Graph
However, if I switch to using Construction Script instead and remove the IsServer, then everything works and the issue is fixed.
Therefore I hereby decree that we should not dynamically add BPCs with IsServer in Event Graph anymore, move it to Construction Script
Running into a pretty damn weird issue with replication right now..
BP: https://blueprintue.com/blueprint/xjugbei4/
The SpawnShip customEvent is set up to Run On Server on the player controller. The function for now is called on Beginplay for the player controller.
We can ignore the save loading part here, it works as intended.
The problem begins where the SpawnActor for the BP_Ship_C is done. For some reason, these actors are only spawned on the server, and not replicated to the clients at all. Doing it with a multicast does not seem to make a difference.
The Load Ship Parts function also spawns a ton of actors, all of which are replicated to all clients.
Are you certain you have the BP_Ship blueprint marked as replicated?
You wouldn't multicast as multicasting wouldn't work on begin play as multicasts are only received on clients that have the actor already so the PlayerController wouldn't exist on the owning client, and, as it is a player controller, it would only ever exist on the server and the owning client anyway, not other clients. Further, if multicasting did work, then you're spawning individual copies of the actor on each instance, not one that would be connected through replication.
it was not on, god I need to sleep more
good to know about Multicast though!
Also, is BP_Ship a pawn that the player controller will possess?
No, it is however something that is used by the player pawn though
Its a bit odd to explain, but the player and [space]ship are 2 different things
Ok that's fine then.
It's just not great to refer to things using the indexes in multiplayer. A player controller normally has a reference to its possessed pawn directly through the function "Get Controlled Pawn", however, if this is run on a player controller's begin play, that might be before they've actually possessed their pawn which would break the "Get Player Pawn by Index" you're using as well as "Get Controlled Pawn".
This logic seems like it should potentially be within the "Possessed" event within the pawn as then you're guaranteed to have a player controller that has a pawn, and can use their references directly, though you could still store some references and settings back to the controller to ensure that the ship is only spawned once per player controller for example.
In the long run the function wont be called on Beginplay, its mostly done there rn to debug part loading.
In the final implementation it will be called once the game actually begins
hi have an actor that i want the player to not see but others to see. I spawn the actor and set an owner but this leads to the server owning all the actors and being ale to see it. How do i fix this? I set the OwnerNoSee on.
What's the context, what is this actor doing?
is every player meant to have one of these or is it literally 1 actor that's visible to everyone but that one player?
its a little light that i want others to see
everyone has one
but the owner shouldnt see it
yeah so owner no see is probably the ticket
or on begin play, check ownership, turn off if owner = local player or however you want to do it
or turn on if owner is not the local player
ohh i got it to work with the is locally controlled boolean. thanks !! :DD
I need help with a variable in my character blueprint not working properly for a client in a session. It works perfectly fine for the server host player, but for any other clients, the variable State is resetting to CharacterStates.Base.Idle every frame. At the start of Event Tick which leads to the Base Movement exec line prints the current state, and at the end of the exec lines from the Set States is a macro that prints the new state. The new state seems to work fine when called, but the "current" state at the start of every tick is always Base.Idle.
I disconnected the Set node for Idle, and it made it work fine. This has me really confused - I have no issues with this in server host character, only in joined clients. Is it a latency error of some sort? How can I fix this?
What does your Check Move Input macro look like?
Can't get a screenshot right now, but it gets a Vector 2D of my movement input action and uses a bunch of Compare Floats that check if both axes are 0.0 for Idle, Y is above .7 for Forward, and anything else for Moving
Do we agree that in GAS, we need only 1 AbilitySystemComponent and 1 AbilitySet right ?
Again, it works fine for the server host, which makes me wonder if it's a latency issue for the client. Or its getting the input from the host controller instead of the client controller, if that's possible..?
Well that's what is important. Input Values are not replicated automatically to the server, and replication only happens from server to clients, so setting those values on a client won't give them to the server.
So if your Check Move Input macro is attempting to get the input action values on the server for other clients, it would always return as idle.
Oh, okay. In that case, can I just set it with the input action event, or does it need to be more complicated?
Replication only happens from server to clients, and input events are local only, so setting the value on the client would only set it for that one particular client. If it's set on the server and this is on your character class, then it could replicate out to everyone for the server's character, but only because they're the server so they can replicate to everyone.
A smarter way would possibly be to have the states determined on the clients themselves based on the movement data received rather than relying on the server to enforce the state.
I think I understand. Does that mean every character blueprint is essentially being processed on the server, not on the clients' side?
Because this is the kinda system I'd rather have, I want clients to have as little latency from input to movement as possible
If you're using the "Character" class then it has the Character Movement Component which has some client-side prediction build into it.
Basically, Client Input > Add Movement Input > Client begins to move the character predictively > Sends Move data to Server > Server validates if movement is ok > Server sends out data to everyone else > Other clients see the character moving
If the server doesn't like the movement, it'll send a correction to the client attempting to make the move and prevent the movement from going out to anyone else.
Alright. How should I do this in the character blueprint? Are there specific nodes or variable settings I should have?
The only node that controls adding movement input is "Add Movement Input".
How the CMC handles all the rest is done in C++ land, and unless you're constructing custom moves, then you shouldn't need to touch any C++.
There may be other nodes that the CMC can utilize like add force or add impulse, but, I'm not great with them yet.
Messing around with Iris, looks like its replication system will not update internal object location automatically (using built-in Spatial filter), anyone know how this works?
So nodes like Set Actor Location and Launch Character wouldn't work?
SetLocation is a no unless you are doing it from server and I am pretty sure launch works fine since it adds to the accumulated impulse before it runs its PhysWalk function.
Set Actor Location can move the actor, but it wouldn't go through the CMC. So if you set the actor location on a client, the moment you use a CMC move, the server would send a correction and move the character back to the original location as that's where the server thought you were.
And yea, if you did it on the server, then the server would do it and replicate it to you and other clients.
Okay, I think I understand, I can only use nodes that run on CMC tick. As for the move input though, I changed it to a variable that gets set on the move action event, and compare that to change states because maybe that'd work as I wanted, but it does the same thing as just using Get Move. How do I get the local input?
Input Actions are local only, so setting that variable on a move input would only set it on the game instance that is pressing the input (which could be only on a client and therefore no one else would know that state). The server wouldn't know about clients pressing their inputs.
Clients and the server should be able to deduce the state of your currently simple system from the current Movement Mode of the CMC & the current velocity & acceleration of the CMC. In the Third Person Template project, the animation blueprints update their state on the Animation Blueprint Update which does exactly this - it reads in the current speed, and what the movement mode is, and then uses that in its graphs uses those values to display the character at different speeds and if they are falling/jumping.
Oh, alright. I guess I misunderstood it before. So, does this mean the server is the only thing that actually changes the state? Am I unable to use Input Action values in the tick event?
Server is the only thing that can replicate values to others. Setting a replicated value on a client only changes it on that one client, no one else receives the change.
You can read an Input Action value on tick, but again, they would only have a value for the game instance in which they are being actioned, so if it's on a client's instance, only that client would have a value.
Event Tick happens to fire on both client and the server, but when trying to read an input action on the server on an instance of a character that is owned by a client (ie. only the client would be pressing the input) the server would always return 0 value for the action value where the client would have the actual input value.
Lets say the client miss predicted something and now its value of, lets say a float is different, if I want it to be corrected but also not change it from the server, whats my best bet,
ForceNetUpdate on server or a specific Client_CorrectBlahValue rpc? Will forcenetupdate send things it thinks is already the same?
Is it actually a force update or has some other meaning like its really ForceEvaluationThisFrame where it still only sends things that it knows have changed from the servers perspective?
Typically a correction will be sent by the Server when the Server notices the Client is out of sync.
If the Client changes something on its side, without the Server knowing, the Server has no way of understanding it needs to force the Client to correct.
Depends on your type of game. If it's just a multiplayer co-op or something and you fully trust your clients to do whatever they want and the server will blindly accept what clients can do, you can do an rpc to tell the server that the server should change it's value to something and than that corrected value will get replicated back down to the client.
But if it's a game where you don't want cheaters/hackers, your server should always be right and it's more of a client is out of sync, so you should try and tell the client to update with the server's values.
If it's to do with movement however make sure you use the movement component for all movement logic for prediction and stuff.
Yeah its suppose to be a correction for a bad prediction but I wasn't fully sure of how a ForceNetUpdate worked, like if it was just to force evaluate the changes this frame in order to try replicate sooner or if it would send all the replicated values again to ensure its all in sync
ForceNetUpdate will only send what the Server knows has changed, if the Client changes its value locally, the Server has no idea and therefore cannot correct for that unless the Client explicitly tells the Server it happened.
Yeah I know generally how the replication stuff worked and would only replicate changes it knew, but I wasn't sure if force would do as it implied and force all the values to be resent, it appears it does not, I will need a correction rpc it seems. Thanks
No, its not a "force all values to be resent" its a "force my view of the network state to update on clients"
Hence its name, ForceNetUpdate
Yeah okay, I was about 50/50 of which one it was as the last sentence said #multiplayer message
Thank you for confirming.
If you do some research on how the CMC does prediction, you will notice it has a clear pattern which requires the Server to explicitly send an RPC to the Client when a correction is needed..
@opal pulsar You may also want to take a look at the Engines usage of INetworkPredictionInterface
It may help you understand further.
I think its pretty much only used on the CMC, but its been a while since I looked.
Will do 👍
i have a problem with splines
for some reason, client cant walk on mesh created with spline. Both listen server and client sees the same road, server can easly walk on it but client is being pushed back, like there is some collision on server side (but isnt becasue server walked there). Anyone had a problem like that with splines?
why are people so ignore me list type here?
Is my English that bad or is what you said just doesn't make sense?
never trust a hamster
where do you see a hamster?
your icon
Good Sir, that is not a hamster
I'm trying to understand what you are saying.
Ask a friend to test the game, it would be a real challange to find a random from discord to spend their time on your game. Just my 2 cent.
I for one, refused to download anything.
It's a public channel. Don't complain when the public talks back.
Especially when you're literally asking the public for help lol
Some people have no awareness
Block 😅
hey question
now im using linetracing to fire weapons on mp
but im missing the feel of a bullet "trace line"
but acctualy spawning the bullets
would be way more costly right ?
im only doing that for granades / missiles
Of course.
u found me out?
y i mean if it was singelplayer that would make sence
not on MP
advince on how to do a bullet trace ?
with linetracing ?
no i mean liek the visuals
i have all that
just want some more bullet "tracing" like trail
ah i see
well post a video and this community may help you
May as in they are snobs
Line trace would imply instant hit detection anyway. Which is probably okay for realistic games with a very fast projectile in CQB.
In this case, do you need the trail? Could just handle the sfx as a smoke and flash and call it a day, imo.
For something that move over time, like Halo's game projectile, I don't think line trace is the solution. You will need a projectile component.
yeah well i dont need the trail but it would be more implying where the bullets are comming from
do whatever they wish to do
Then you can just spawn the trail, take a look at Rainbow Six Siege
see how the trail looks like.
If you have some examples from marketplace, you can try to figure out how they do it, I suppose.
can't help you here as i've done little to no SFX
hm alright
is it just me or does mover 2.0 use quite a bit more bandwidth?
The answer is interpolation!
Hello does the client own data that should be only on the server for ex if i want to make a connexion to database only on server, does the client have those informations too once it's compiled?
huh?
and the client only knows about stuff that is explicitly replicated
but directly connecting to a database server is also its own can of worms
maybe the question is more towards if stuff get compiled into the binary (which it would if not using macros for server only code etc), but im just guessing, otherwise it makes no sense
well yeah if secrets are stored in default INI files, people could datamine that
unless this is saving progress in a local SQLite database or something, there are very few reasons why you'd want to directly connect to a database server
yes i have my variables dynamic for security and also to scales servers
but the code compiled (gamemode) , is it present in my client?
this is why you'd use the with_server_code macros for example
what does this even mean
it's to avoid to leak infos/gamelogic to hackers or cheaters
the game mode class isn't instantiated on the client when connected to a server, but it's knows of the game mode class
@cursive steeple : https://forums.unrealengine.com/t/dedicated-server-code-split-from-client-code/7446
with_server_code when i compile to avoid leak server code to client right ?
what are you talking about?
directly connecting to a database server is already a no-go, but what exactly are you trying to protect?
the client won't know of any data on the server unless it's been replicated
It's a shortcut sample 🙂 my friend
Just to clarify, what sswires is telling you is about runtime info, i.e replicated stuff, my link is for removing code from being compiled into the binary for specific targets
WITH_SERVER_CODE is 1 on the Game target
it's only 0 on the Client target
UE_SERVER is used for dedicated server targets
thanks for the correction, this is true
thx a lot, it's clear now
Hi everyone, I'm having an architecture pickle here and wondering if someone has a nice tutorial/doc for database connection best practices for multiplayer online.
I started by wrapping my SQLDatabase class in a ActorComponent since I feel like it should be store at 2 different places because theres 2 purposes to it, manipulating player information and manipulating "public" information (public storage for example). Having the owning client directly call the DB feels like a terrible idea and I feel like it should be handled by the server so I was thinking about putting it into player state for player information related, like, upon connection load that player character info based on his ID. But everything else, I'm not sure if it should be handled by GameInstance, GameState or am I even on right track here?
if it's a global database then it's probably better to just have a REST API so neither the client or server are connecting directly to a DB
That's something I didnt even consider and I work with REST APIs on a daily basis lmao. Heum, but how would you go about handling the credentials from your game? I mean, the server or client will need to use creds in order to call the API and validate they have authorization to do so, there's technically a connection happening somewhere, even though it isn't the DB directly
I'm interested in best/most secure practices for this too.
no idea if i can get help here, but when I try to sort out my AWS gamelift SDK, I get errors saying Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARY) (found version "3.3.0") despite me having OPENSSL_ROOT_DIR inside the system environment. anyone know what can cause this?
i've followed every form of documentation, youtube tutorial, forums, to no result
Depends how you authenticate users really. If users are required to register with the service before being allowed to log in, then you have a login server that authenticates via Username/password/2fa/etc and the login server hands the client a token that is used to access the other game REST services.
As you know you can't store secure credentials in a packaged client so this is the only option.
Yeah sorry, was a little unclear in my last question, so yeah going the API route i would probably go a oauth2 authentication route and yes, what you described is essentially the game plan, register first through website, and login with U/P/2FA. What Im more wondering is the initial question. Because all we do here is replace SQL Database class with a API class. But that API class, where would be the best place to put it in the game so that I can access it whenever I might need it. I guess at this point since the token generated is valid to the player that restricts what he can do with the API but he still needs to be able to save and load his inventory for instance, so giving access to the owning client the API class is still a bad idea. So where would I put it so that the server makes the call and validation
ok well I'm not really sure for the architecture you're describing, for our game the user auths with the server and the server replicated all the information they need, there's no 3rd party (keeping those in sync is asking for lots of extra complications I'm sure).
personally I'd start with using the GameMode to authenticate the player (player connects, override GameModeBase::PreLogin to accept/reject, etc).
once player is successfully connected use your custom PlayerController class, or Pawn class depending on how you want it to work, to replicate inventory etc from server to client.
Choice of PlayerController or Pawn for storing inventory is down to the lifetime of the inventory. Is it tied to a specific character, or can the player switch characters, etc.
sorry I have to go out now but hopefully that will get you started
yeah good starting point, thanks for the assist i appreciate it a lot
using this method (everything through the server) you can store secure credentials in your official server package since you never release that to the public. this way the server can auth with the rest api using built in secrets, or secrets from the machine anyway
Hello there, fellow devs !
Do you know how optimized is replication ?
I mean : Can I have a data updated several times per second set to replicated ?
If I want to have players up-to-date when reconnecting or joining mid-game, nothing does it more efficiently than replicated variables I suppose.
But for variables frequently updating, I tend to – whenever possible – use Multicast to initiate the value going up/down for every player and another Multicast to update every player when the value changes direction or reach min/max value.
This however doesn’t suit player joining mid-game very well.
Unless maybe in the BeginPlay of many of my Actors I fetch for Server data manually ?
What are you thoughts on the matter ?
Thank you very much for your attention ! 👍
The trick is to NOT update things that fast. You're not doing yourself any favours by brute forcing reliable multicasts instead
If it's an unreliable multicast, then it goes through the same system as property replication anyway so is pointless
Also, multicasting is usually a bad idea, unless every single client needs to know what is happening with that specific data, which more often then not, you realise that only the server needs to know
Thanks @undone needle !
I agree !
Thanks for the answer @chrome bay !
You mean, no data should be updated that frequently and replicated, right ?
If high update frequency is for the smoothness of a visual, obviously it's gonna be played independently on each client and not replicated.
But if it is a data such as a battery energy level you recommend me to refresh the value a lot less frequently, such as once or twice per second ?
I suppose the client can interpolate between those values for a smooth visual representation.
its a case by case basis but the idea is there yes, unless its player movement, and even then i dont necessarily agree with unreal that it needs to update 100times per seconds if you do something else than a FPS. But for your battery level, how quickly does the battery energy drops? If the score drops every 5 seconds, updating it once every 2 seconds is fine depending on what the battery is used for.
For instance; battery for a player cell phone, it doesn't matter if he gets to use it 1-2 seconds more than what the server actually said he could.
but battery that powers a generator that prevents player from going through a wall, that one should be updated several times per second so that all players that tries to go through said wall can all do so once the energy level hits 0
Thans again @undone needle for the insight !
It now seems obvious I should reduce the frequency and replicate it !
Have a nice day, both of you !
You won't get a steady stream of updates in the "real world" anyway, so relying on it is not a good idea. You must design things to be resilient to data loss.
I make these words my motto !
Design a code resilient to data loss
Thanks ! 👍
Something like: Client clicks widget button, button calls event inside pawn with a server RPC. Server RPC calls a RepNotify function which sets the skeletal mesh.
Let's say I want to do p2p with server validation, like how some games treat the server as a third player with final authority, while the connection between two players is peer to peer for lower latency. Would I just use a bunch of RPCs or something? I have the infrastructure to serialize inputs, game state, and rollback if needed Also, is putting server code on a gamemode class the way to go? Any good resources resources to learn more about how server builds work and how the details of how built in replication works?
hey yall, what startegies do you do to make client side hit detection feel more responsive?
hello guys! excuse me if this is not the place to put this question
i have this section of bp in a power up that one of two players can pick up in mid game, the idea is that while is getting picked up, it does a small animation (the one in the timeline), the animations plays correctly on one client, but not in the other player client.
the bp is replicated, as his components and timeline, along with the movement.
what i am doing wrong? how can i fix it so the timeline plays on both clients?
I may be wrong but my guess is you need to create two custom events, one that is multicasted and preforms the event and then second that run on server and calls that event
that's 100% what's going on. When calling from client, a multicast RPC gets dropped, it needs to be called from server
so, if i have an event for pressing and another one for releasing, that would total 4 custom events that i need to make?
yes, you need to create four events altogether
my advice would be to remove the word server from the two you already have
-Then you make a new event and name it "serverPicking up"
-set the new event to run on server
-then with the new event call the old event
-then on E run the new event
Repeat same process for the release event
How can I hide the emitter from the instigating player?
How should I deal with server and client misaligns in sandbox games. E.g. player on the client breaks an Item, but there is a lag and on the server Item is not actually destroyed. Now, server should have full authority, so, the client's chunk should be reversed if misalign occurs. But, sending whole chunk is obviously a very bad idea. I also can't just sore item's location as its ID, as this isn't minecraft's type of building system, items can be placed freely
I'm losing my mind. I can't seem to understand RPC implementation. Can someone hold my hand and walk me through how to get the opponents name that is saved in their Game Instance?
🤚
GameInstance is itself not replicated, and exists only on Server, so its variables won’t be replicated either. Your best place for something you’d want replicated from GameInstance would be GameState or PlayerState, which is replicated
If you want to store your player's data/state, like e.g. their name, health, score, inventory etc.
Use Player's State
As, as the @fierce egret mentioned, Game Instance is not replicated
Just to be 100% I get this right, the reason why a player inventory should be in player's state is...?
I mean, it's not like someone else needs to know what's in another player's inventory (aside from some games like mobas) or am I missing something important here?
Its because its replicated, can be transferred between servers and is not destroyed along with the pawn/character
It doesn't have to be, but let's say at some point you want to be able to trade between players and they can see into eachother's inventories. You could store it on PlayerController, but then that data would never be available to anyone other than the owner of the player controller.
You don't need to replicate it to other players. You need to replicate it from the server to yourself
That's the part I was missing, makes a lot more sense, thank you both
Now in terms of getting a player's name from the game instance to the playerstate....
You'd need to send an RPC on an actor that is owned by that player (like their player controller or player state) and pass the name as saved in the game instance as an input on that RPC.
Within that RPC call, you'd set that value into a replicated variable on the PlayerState. Once this value is set on the server other clients will receive it.
Updating your UI is either event driven by using an OnRep and pushing the value into your UI or triggering an event dispatcher on the playerstate that your UI would bind to, or otherwise using a bind within the UI to constantly read the value from the particular playerstate.
Ok i have the playerstate holding the custom player name
Why is it still in the game instance?
This isn't correct.
Begin Play of the playerstate will fire on the server and all clients. This effectively would be setting the name of all playerstates present on any instance of the game to the name in the game instance of the game running this code.
Cut Game Instance completely out of this equation
You don't want to use it in this situation
ok
Also, remember to set player's name server side via RPC, just like Datura described
exactly
And CustomPlayerName must be set to replicated
Don't use bindings in widget unless you absolutely have no other alternatives, they are super expensive to run
I had it set to repnotify but I changed it to be "replicated"
repnotify is fine, if you need to check when its replicated
If you have to check it, then change it back
i'll do repnotify because the players wont be joining at the exact same time and will need to update the name.
Not really sure what I am missing, but running SetActorLocation on the server against a replicated actor makes it 'slide' from X to Y from the client's perspective - it's not instantaneous as it is from the (listen) server's perspective. Any clues? (Note1: it's not a APawn with CMC or whatsoever)
Isn't there situation where having Game Instance holding player name would make sense thought?
Example: Login in, assign player name to game instance, join matchmaking-> join game -> load level. This would destroy every items aside from game instance here, or am I wrong?
And what are you gonna do with player name in the game instance
You won't pass it to server or client from there
It won't destroy anything, as its not replicated. Game Instance is existing separately on the client and the server, and they don't know about each other
When player joins, game instance from new client have no effect on the game instance on the server
Yes, I know this, but in terms of someone having trouble just understanding replication, using a bind to get something working is better than having to try and explain how to push values into UI or use event dispatchers 😛
I kept my player name in a save game object. Player join, send server it's save data.
I seen epic using game instance to store avatar and player name but that's like, meh
And you keep save games on the client?
Very old tutorial
Yea I am a pleb, no data base for my case
It means that client has authority, and can manipulate data of the save
Player may cheat, I can't really stop them at my current level
Did you store anything else in this save game object?
I will store everything, it will be kinda baldurs gate
Player r free to cheat, it's their lost
If its by the game design, its ok
👍
Isn't it the purpose of Game Instance to hold game data that must persists between levels?
I can't store it somewhere because player may join other people game with the same gears and data
I have the Custom Player Name set in the PlayerState. I Created a custom Event that executes on the servers instead of on begin play. And i have the Custom Player Name variable set to Repnotify.
Unless I do some auth with cloud saving etc, but as newbie I rather focus on simple mp game first
Its not the only thing that can persist between levels. E.g. You can transfer player's state between levels
Oh. Will have to test that out, I always been under the impresison that everything but GI got destroyed upon level load
Afaik you can even keep actors alive on server travel
HALT. I might have make a mistake
For the most part that is generally true. Persisting other actors requires more set up.
Hard travel destroy most things tho
Because I have somewhat bad memory, I misinterpreted my thought
You can send data between levels via OpenLevel
I'm not sure about player's state tho, how was it done
But it wasn't out of the box for sure
Hmm there's a function that have old player state output. Not sure if that's for reconnecting player or for server travel
how can i call onrep on server ?
Its called naturally in blueprints, in C++ its a little more complicated
so you cant even force it ?
You can
U don't need to tho?
the listen server can update itself
You are already the server
UI update is in the OnRep method
Can make the change right away
@obtuse field Sounds good, I'll go double check that myself 😉 Anyway Gtg, see ya!
Doing it blueprint way is actually redundant and feel very wrong imo
thats why im switching to cpp
I'm saying about the repnotify part
now i wonder how to call it on server to call the onrep function
For server, make the change right away. For client on rep notify
so i need to make another function
@lament flax You can try to dig into UNetConnection https://docs.unrealengine.com/4.26/en-US/API/Runtime/Engine/Engine/UNetConnection/
But I won't promise anything. Show results if you do find anything interesting tho
i guess this is the way
Just call the function?
will this even work ?
Why not, but depend on what you are doing I guess.
seems weird to call a OnRep_ method
That's not what I'm implying tho
Wrap what you want to do in a function
For client on rep notify, call that function
For sever. In the code where you want to call it. Just call the function. Use switch has authority to make sure the code only run on server
I think you should break down what data should be send over and how client handles it.
Knowing what data goes around in what machine and how each machine handle them simplify the thought process imo.
thats what i thought
I'm going to start with the binding method because I need to keep it simple for now. Does this look right?
Close but not quite.
This would only return the value stored in the very first playerstate in the array. You'd want to create a widget for each playerstate, feeding in a reference to that playerstate, then you can bind to read the name from the playerstate associated to that widget.
@undone needle
Yup ^
If I want to do p2p with server validation, like how some games treat the server as a third player with final authority, while the connection between two players is peer to peer for lower latency, how should I go about it? Would I just use a bunch of RPCs or something? I have the infrastructure to serialize inputs, game state, and rollback if needed Also, is putting server code on a gamemode class the way to go? Any good resources resources to learn more about how server builds work and how the details of how built in replication works?
lol I can't believe how hard this is for me to understand.
Try your best, we believe in you
There is no P2P in Unreal. Everything is client->server, including listen servers (where one player acts as the host of the game), which means there will always be an authority that is in control of the game. You wouldn't necessarily gain any better latency between clients unless they happen to be closer to each other and on higher speed networks than the server itself - eg. if you had two LAN computers playing, then you could make an argument that they could potentially have better latency between them then the server.
Thanks! I'll keep pushing.
He can always use TCP connection
Yes, but then that's not Unreal's networking system.
Its not RPC, but still supported by unreal
That's what I was thinking, actually have that working already with GGPO, but I was wondering if anyone had ideas how I'd do that alongside an unreal server that is allowed to lag behind players but do stuff if serialized game states after rollbacks differ too much.
would I just have to code a custom server entirely separate from unreal?
Effectively, yes. Sorry I responded a bit quickly before fully reading the question... Not necessarily, but you wouldn't use most of Unreal's built in systems for handling replication for anything relating to your players or actions they take, but you could use Unreal to simulate what is happening based on the data received and then attempt to manipulate what is happening in the P2P system. You'd have to program how Unreal should be responding to certain events within the P2P system, and have the server simulate it and correct anything based on what it thinks should've happened. What I mean by effectively yes, is that you would be creating something separate from Unreal's own replication system to handle what is happening in the P2P system.
Ok so I am a little lost with this. I can create and join sessions and all that with a little server browser thing, now I am trying to just get the direct invite/join through Steam matchmaking setup.
Loading the packaged game I can go start a game and invite through steam friends and it pops up on Steam but how do I access that invite? I can see that there is the 'OnSessionInviteReceivedDelegates' which passes the InviteResult but it does not seem to fire ever.
Ah, that makes sense. How would I run certain code on the server asynchronously from the clients? is it possible to use async on RPCs?
Online multiplayer is already async. Your copy of the game won't be running exactly as it is on the server, and the server doesn't have to replicate all actors. So for example, you could have actors on the server that represent the client's characters and then have the clients have their own representation of those characters and there doesn't have to be a network pointer between them but then you wouldn't reference them over the network in the standard way. The clients can playback their own version of those actors based on the information in the P2P system and then receive instructions from the server to then set those actors to what the server wants (though the clients could technically ignore it). This is what I mean though - you're basically having to reconstruct how Unreal networking would work to facilitate such a system.
Under normal Unreal networking, the server is normally considered ahead of the clients as it is the authority and most actions that clients performs requires the clients to ask the server to do it, so then the clients are behind until the server replicates the results back to them - so by the time the clients get the data the server would already be however many milliseconds ahead in its own processing. It's when you do client prediction that the clients would be considered ahead of the server, but still they communicate to the server what they are doing and then the server is then "catching up" to them, and correcting if it doesn't like what they are doing.
I'm not sure I understand what you mean by async RPCs.
it was a misunderstanding of Unreal's system. I thought that the clients waited for the server to respond before proceeding, and didn't do much by way of prediction
I wanted the server to simply lag behind the clients, validating the packets they sent to each other with the same code the clients currently use for simulating "ticks" (not unreal ticks, our own update function)
it wouldn't be hard to send the serialized data, but I'm new to this type of networking specifically
Unreal kind of doesn't have a lot in terms of client prediction. The character movement component included with the character class has some predicted movement built in, and if you look into the Gameplay Ability System it opens up actions that players can take that are client predicted.
only thing I've done before was outside the context of unreal and was just serialization and deserialization
so if I ran the function to process an update as a server rpc, would it allow the clients to continue their execution until receiving a response from the server to force a rollback or disconnect if deemed necessary?
thank you so much for your time btw
Hello, What's the common approach to implementing typical MMO targeting in a multiplayer game? Is client authority with server target validation sufficient? Thanks!
or would be better use GAS TargetActors?
Additionally, if you could provide some learning resources regarding this topic, it would be greatly appreciated!
The clients can do whatever they want to do locally and then report things to the server using a replicated actor they own.
You can have the server tell them to do things after the fact if necessary but that doesn't mean that the client has to do it either.
What is important is that the server is the authority, so at the end of the day, it's the server's copy of the game that should be considered the "real" version of the game being played, so if one client continually reports things incorrectly, it would constantly be getting corrected, especially if it didn't do something you told it to do.
I think the hard part here is the reconciliation as you can't use Unreal's own built in systems for movement and prediction for those characters.
server code goes in gamemode, right?
That sounds about right. Handle managing the targets client side, upon activation of an ability pass along the target to the server, server validates if it is a valid target.
GAS' target actors can be much more complex and can handle a variety of scenarios.
we don't plan on using unreal's movement system, we have that done. it already works with GGPO, but we'd like to add a level of validation to prevent cheating
It can technically go anywhere as you're able to differentiate whether you're running on the server or client. Game Mode is something that will only exist on the server, and can be excluded from client builds if your intention is to run dedicated server builds exclusively it can make sense to put it there if you wanted to ensure code specific to the server isn't distributed to clients.
Check the pins for the network compendium. Start there.
How might I go about replicating a timer?
- Server actor (bp_forge) does a thing and the server starts a 60s looping timer
Goal: Player opens bp_forge widget and can see a progress bar of that server's timer for that actor
I've tried replicating the Timer Handle, but client is still not able to read it. My thoughts are to instead replicate a "time elapsed" variable, and update it using another timer or tick. Is there a better way to do this?
I figure I'll have maybe 10-30 of these timers going within player cull, and ideally 300+ server-wide.
Just replicate the start time, and the local client can visually show the timer ticking down using its own clock.
Then when event finishes, server can RPC or multicast result (depending on what happens)
And then read pins on how to network sync clocks better.
How would I go about creating a variable for that start time, is that just a "now"?
Basically. Or you could replicate the time it is due to end instead, and the client knows to countdown to that. Same idea really.
Offset by ping but works pretty well
The client timer is ofcourse just a 'prediction', server shows up with the final say
I tend to think what client see is a mere illusion
Yepp
Aww heckin', she's working! Thanks friends ♥️
All me baby
That is awesome, your UI is so clean. with your drag and drop how did you get the icon to go under the cursor?
what 🤔
If I remember right... when you create a drag and drop operation there is a way to specify a visual as well as an offset if its needed.
So I have an issue I need to fix basically the cursor is over the icon in my game which blocks the icon from being dropped directly to the next slot over. Its super weird to explain without showing
@lusty sky
if it makes sense for some reason I think the cursor dictates the drop event and not the image
You can setup a drag visual from the drag & drop operation:
Thank you
And allignment/anchor
Can someone give this a pin? I've found this to be a great learning resource for starters with Mover:
https://github.com/daftsoftware/FGMovement
yo just want to ask. Do the ue5.4 dedicated servers work on the release or do we have to wait a little?
can you run a server for 5.4 game?
yea they work
Ight
Oh really good to know actually, thanks!
Question regarding Player States, since they are replicated to ALL clients, I should absolutely avoid to store any unnescessary data as much as possible right? Example; Let's say a character's gun, I should NOT store the whole gun reference because the mesh is already loaded in the game locally for everyone, instead just the gunId with properties like ammos should be stored on the player state and have the logic to spawn the mesh handled locally by the clients, is my reasoning correct here?
Why would you store the player's gun on the player state at all? Surely it's on their pawn.
Unless it's some sort of persistent inventory?
Was just a random example to illustrate the point is all
I'm actually curious how it replicates class references now.
However you're right. Replicating as little as possible to maintain the game state is generally best.
Just avoid multicasts for anything related to state.
I try to avoid multicast period ^^
But thanks for the confirmation
They have a place, tbh. Like a global chat could probably just be multicasts? I guess?
Depends on the chat, you don't want to multicast to all player if a player doesnt have access to a certain channel in my opinion
Mutlicasts don't get sent to things which aren't relevant.
So manage your relevancy.
That includes standard distance relevancy if you're doing it on world objects.
But, yeah, it migth just be easier to send single-rpcs to each player than create that whole system.
Forgot about that for multicasts, but then I feel like a chat is a very bad use of multicasting. Imagine you have a world chat in your chat box but two players are too far away from each others to be relevant, they wouldn't see the other's message then
Oh, player state only relevant based on net relevancy, game state always relevant
gotcha
wait, player state is always relevant too?
Yes
Why?
Men everytime I feel like I start to understand RPCs I get thrown a curved ball
I mean, If a player state purpose is to store a player's data and replicate it to everybody all the time, then what's the point here?
I get it for small FPS matchmaking stuff. But like, Imagine you got a huge map. Who cares of what happens to Player X when he's not even close to where you're at?
That's why player states and player pawns are different things...
I get that, partly. When I look a UE doc, they state that player state is the perfect place for example a player's health. But what do I care about the health of someone who's not even in my range?
A UE doc? Which one?
It also might just be out of date and not relevant to game design in the last 10 years.
Or it's dependent on the type of game you're making.
And maybe player health is relevant to you on the other side of the map if you're in a party together.
Etc.
Yeah, they're not rules, and it will depend what's most suited for your game. As long as you understand the implications of where you store your information, it's all good.
Well, I mean, it's obvious that I want my player's health in a player's state for server replication. What I don't want is that to be relevant across the whole network. I thought that was the job of Game State
Then put it on your player's pawn.
So the pawn becomes a natural choice.
And your party example makes sense, but I would assume that the net relevancy changes for people that are in the same party with you
Okay so, as long as I never destroy the pawn it will be fine?
You can have the health on the player state and not replicate it.
And then set it on each new pawn as you make them.
Well, I need to replicate it so that the server knows where his health is at
What
Replication only happens server to client.
And you definitely don't want the client having authority of something as important as health.
Oh okay, I see what you mean
You could destroy it, but if there's data you don't want to lose, keep it elsewhere.
so, the player state could hold server side only the player's health and not replicate it, and have that player's health on the pawn that takes care of replication and since the pawn is relevant only within range, then only the people close enough would get to know that player's health is what I understand?
Basically the system I'm suggesting is that the server has health in 2 places - Once on the player state for its own purposes and once on the pawn which is replicated to relevant clients. When you spawn a new pawn, jsut copy the value across. When the health changes on the pawn also back that value up onto the player state.
Yeah okay got it
Of course you'd do this by wrapping the health in a setter function so it always gets set on the PS.
I'll try that, thanks a lot for letting me know that PS is always relevant, that would have been a problem
Or you could simply transfer the health from one pawn to the next.
Or, well, if a pawn is destroyed, isn't the health 0 anyway?
Yeah obviously
Unless you switch between pawns.
Nah the pawn remains at 0 health cause i want his inventory lootable if another player decides to loot him only
respawn after a short timer
So why does the player state even need health?
Surely if the player respawns and their corpse is there already, you'd need 2 health values in your original plan?
(2 on the player state)
Nah the original pawn is destroyed upon respawn, so it could technically always be the same, or I could delete the first one on respawn and create a new one on respawn point
both ways could work
So the body is only lootable for a short time? Teh time it takes to respawn?
yeah exactly
For health you don't really need to transfer anything, just a default value on the pawn will do?
As long as health changes are verified server-side.
Idk, seems more simple to me than having it in two places, if not always relevant.
Unless it's a mechanic to change pawns and retain the same health or something.
Yeah thats what I'm realizing, I dont have much informations for my game that requires to always be relevant, most of it happens based upon range
Kewl beans
Aight, thanks a lot to you both, you saved me from a lot of refactoring
My Blueprint tabs keep rearranging. Is there a reason for it/ method to prevent it?
when opening my server (using -log), it opens then closes instantly
Post logs
Hi, i need a bit guidance with one problem i have in setting up a multiplayer game. I need (and want to) keep some input on the Player Controller, and currently I'm a bit lost. What is the idiomatic way to register input with Enhanced Input Component in MP scenario like this. Latest i got in debugging is that Input Component doesnt exist on any PC (when using Play as Client option), with Play as Listen server just one player has a properly working input. is there any tutorial that i can reference to?
yeah, there are none in logs folder
ok it's cuz i did shipping not development
You may be receiving that error because you're attempting to access the input component on an event that fires on both the client and server and the server's copy of the player controller won't have the input component where the client side would. In blueprints, the below example works just fine for setting up an input component on a player controller.
In C++ I believe it would be set up something like this if you defined IA pointers on your player controller.h
void AYourPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
auto* EnhancedInput{ Cast<UEnhancedInputComponent>(InputComponent) };
if (IsValid(EnhancedInput))
{
EnhancedInput->BindAction(OpenMenuAction, ETriggerEvent::Triggered, this, &ThisClass::Input_OnOpenMenu);
}
}
what's with the meme of the list initializer syntax when an equals sign is perfectly readable
I was doing it exactly like that, Server never had Input Component. I managed to force it and now delegates dont trigger
Just copied code from somewhere 😛
I really like this guy's information/explanations, https://cedric-neukirchen.net/docs/session-management/online-subsystems/
Anyone have anyone/anything similar I could check out?
The Online Subsystem and its Interfaces exist to provide a clear abstraction to common online functionality across the available set of platforms in a given environment.
some cpp tutorials teaching people to use {} lul
I've been seeing it quite a bit recently
Using lul... lul. 😦
I have an event node on the BeginPlay GameState that I want to trigger on both server and client. But for some reason it doesn't trigger on the client unless I put a 3 second delay at the beginning of the node. Why could this be?
??? None of that should be triggered on a client anyhow. It's a server RPC
Ah sorry I should have explained, the last node leads to an actor with a Server-Multicast RPC
as I said it works great if I put a delay node but not without it
That would be your issue then. It likely hasn't replicated to the client yet. This is also state. State is exceptionally rarely multicast. You should prefer replication. Instead of putting that value on the GameMode. Put it on the GameState with a setter and a delegate and make your objects bind to that and pull from it.
Alright, I'll read up on delegate and do this. Thank you! ☺️
i have created a server using a virtual machine and created a 7777 port. used the "open level" node and pasted in the public IPv4 address, however my player does not get connected to the server/change map. no idea what the issue is
Did you port forward that port?
I am wanting to stitch together a series of dedicated servers. I've read the documentation and it looks like I can do this using non-seamless travel.
I'd like to work on this feature without having to package and fully deploy two servers each time I test it.
I've found a command line that looks like it spins up a local server and I'm able to connect to this server in PIE using the Open Level (by Name) node and 127.0.0.1:7777 as the "Level Name".
So, I can hit that command line a second time, it appears to launch a second server process; cool. But how can I get the IP of that second process - and ideally, how can I configure the IP of that second process?
Here's the command line used to start the local dedicated:
"C:\UnrealEngine\Engine\Binaries\Win64\UnrealEditor.exe" "C:\Homestead\Homestead.uproject" GoblinForest -server -log -nosteam
The goal here is to jump between Server A and Server B during a single client session.
The IP is the same
The port is +1
So 7778
Amazing, thank you!
yeah
nvm i just checked a port checker website apparently it is closed
even though i set it to open on virtual machine
oh weird, actor's position and rotation spawned by a server are slightly off on a client.. i wonder if they get compressed or something
Follow-up question: I'm wanting to send a payload of data along with the player (attributes, inventory, etc.). I could use a detached web service and pull in that payload after level transfer, I could look at ways to sync the server-side .sav files, but I think it would be easier to use the game instance.
How bad of an idea would it be to store the data on the game instance during the transfer. I'm concerned that an enterprising player might figure out how to inject data during level load.
an enterprising player will figure out how to inject data one way or another if he's really motivated regardless
is there any issue replicating a GameplayTag ?
no
If you need the game/project to not have cheaters, or at least to most likely not have cheaters, then that's a terrible idea
If you need data between 2+ DedicatedServers and Clients shouldn't be able to cheat, you need to both host the Servers and some Database away from them
If the servers are all being ran on the same machine like a cluster, you can just have the server save the data to a file locally before the transfer. Then have the player transfer, and have the second server load it.
My AWS is weak, but I'll research this. Thanks both ♥️
One other question I have. I get using Projectile Motion for something replicated like a ball.
What kind of physics would I want to have per stage?
Assume this is an Online Multiplayer Mobile Tennis game. We're planning different courts / types of bounce etc.
My current project is a golf/adventure game and my golf balls use projectile movement component which has stuff in there for altering bounce and all that.
Although I didn't understand exactly what you were asking with the current wording sorry aha.
I created a VM on Azure, then run my dedicated server on that machine but when I am trying to connect it via public IP I couldnt do it. Everything works pretty well on my local machine with 0.0.0.0 but not with public IP
Should I do anything else than copy my dedicated server exe to machine and run it?
Its okay xD
I'm asking about the stages themselves
Like different materials give a different bounce
So, would I want a court to be just a physics material?
only if you don't define the tag on both the server and client
don't if def specifically on clients ect or the tag list will mistmatch on client and server
Quick question:
Should I learn networking in general in c++ first, or straight to ue5 multiplayer?
Yes
Learn how replication works before trying to do a multiplayer game.
Just simply try getting a Door to open and close via Player interaction on multiple Clients.
ok thx
Keep in mind that Just the door is very little but is a good starting point. What you need to understand is that there is a lot to know and it can get extremely confusing, and frustrating at times. Good news is, plenty of good documentation and tutorials out there, sink your teeth into that, learn the information and try to apply it in a test project until you have a good grasp on things before starting implementing it in your project.
If anybody knows a solution to the 9999ms server ping bug while using steam subsystem please let me know (@ me).
Seems like the bug was set to "Wont Fix" in 2018 for somereason.
https://issues.unrealengine.com/issue/UE-27444
tbh displaying ping is an important part of making a game that uses server lists, its the thing that everyone looks at when picking a server to join. I have no clue why a bug like this is not high priority to fix? Again if you know any alternatives please let me know, I did see elliotek post on the forums about it (https://forums.unrealengine.com/t/steam-session-ping-9999/327245/78) , but he edits read only files which the engine doesn't even compile any of my new changes in for somereason.
Its crazy that this bug has not been fixed ever since 2016.
Similar thing is with the in game active player count being always set to one. Thankfully I managed to update the sessions player count manually using the update session function given by the session interface so thats at least solved. but this one I have no clue on how to solve
Hey, can anybody here help me debug my item drop system for MP? I can get pickups working, but havve no clue how to sync up item spawning
Are you using any kind of online subsystem? Steam, for example, requires you to port forward.
You might also need to add that port rule to the firewall inside the VM.
@civic turtle thats bc u use steam test id..?
I know this isn't really a solution, but I want to mention it works with dedicated servers 😅
If you post some of your code someone should be able to help, but the flow would sort of be something like:
Client Initiates Drop request in some manner (ie. OnDrop of a Widget on to the main canvas) > RPC to Server on client owned actor/component with reference to the item object and/or inventory you're trying to manipulate with any kind of index of the item (never just a refernece to the Item ID) > Server validates object exists in the inventory in question > Server removes object from inventory if player is allowed to remove it > Server spawns replicated actor to represent the dropped item.
it could be, but are you 100% sure about that? Im waiting for the steam page to finish reviewing so I can have access to my own app id and use it. But it seems like people in the forums were also getting this error while using their own app id. I guess I will know soon anyways, but from what I read it might be deeper than that
yea im pretty sure this is only a listen server issue, thanks for letting me know anyways though
Hm ive only heard it from others tbh never tried it myself so not sure tbh
An alternative would be to look into Online Beacons.
I never heard of online beacons, I will look into them. Thanks
Gotcha yeah! Thats very helpful
I figured out a bit here and there, but I also have a follow-up
So, I have an item dropping item system on an item that simulates physics
Obvious syncing it between clients sucks donkey dick, and I'd rather have the item not simulate it so it doesn't have to sync
However, when I drop the item, I still want to play a small impulse animation, but I can't do that without simulate phyiscs
Is there a possible workaround?
@civic turtle also do you know in guessing your games uses listen server, is it same ports needed to open on your router ad before ? (After release)
If I open two multiplayer windows in standalone mode. How do I know which one is server and client?
@somber tundra if you just want to yeet the item a bit, put a ProjectileMovementComp on it
Or make a second actor just for this that then when it lands spawns the correct item
From inside the editor? With PlayAs(Listen)Server selected?
Hm, not sure if the window title would state anything
it doesn't
Probably best to just put some debug UI on the screen
You can get the owning player of the widget and check if it had authority
And then change some text based on it
Any console command to check that
Don't think so
ok thanks
Thank you a lot, that solved my problem last night :D. Thanks anyway it works 🙂
@thin stratus ayo exi :)
can we pin snaps mover stuff? been using it myself as a learning resource and... i think its pretty valuable https://github.com/daftsoftware/FGMovement
Hello everyone,
I am curious what is the best way to replicate an array between clients while I don't care about the order of elements inside it? I basically have a general counter for some accomplished feats that is shared between players (for quests) and I want to properly replicate that so each player's quest log can display the proper numbers
would that be a FastTArray?
if you want to do some operations in the client after replication, such as adding something in your UI, Fast array has some very convenient callbacks per member
I think I read about them once, they don't guarentee member order yeah? But as it's just counters, I don't really care about that
disregarding performance, fast arrays offer you a very neat amount of QOL features
so if you dont care of the order and your data struct has some members that you will use for your quest system, its a good option
I see, thank you I think I'll have a look 🙂
now in terms of performance... tarray v fast array - depends on the use case (one might be faster than the other), you can read here in the message history some posts from Jambax explaining how they work more in detail and when to use each
It definitely isn't going to be a big array so I don't think that matters to my use case
it's more the QOL like you say to properly interact with edits
the name is a bit missleading hahaha, it doesnt mean that the fast array will be always faster 🤣
ah I see 😂
but ye take a look, might suit ur purposes
PostReplicatedChange Does a change include Add/Remove aswell?
No
Change relates to an existing element having its members values changed
I see, ty 🙂