#multiplayer
1 messages ยท Page 689 of 1
If it does, you'll need to ping an RPC back and forth without sending anything after the first OnRep IMO, when the client gets the RPC back that array would likely be filled
You could also check !bHasBegunPlay to use RPC method assuming it's false during first OnRep (which would imply it should be populated in BeginPlay, which may not be the case)
I can just update the array on the client and server in the characters beginplay and endplay
I had a bigger issue though, my character wasn't relevant. So had to flip always relevant on
PostNetReceive is called only on the initial bunch ?
looks like it's called in PostReceivedBunch so i guess i have my answer.
hello, everybody. If I simulate two clients in the editor, their movement appears perfectly smooth. If I spawn a spectator class that can move around freely, everything looks great, as well. If I set a view target so one client may spectate anotherโs camera, there is terrible jitter for the spectator that doesnโt exist for the client thatโs actually playing. thereโs no jitter to the camera, just the animations. any ideas on where to start looking to troubleshoot this? thanks in advance ๐
I think of it as a global OnRep lol
so it's called each time a property is replicated or at each initial bunch ? ๐ค
Former
Example use case from my plugin
void AMICharacter::PreNetReceive()
{
Super::PreNetReceive();
if (GetLocalRole() == ROLE_SimulatedProxy)
{
bWasSimulatingPivot = bSimulatedPivot;
}
SavedRagdollActorLocation = RagdollActorLocation;
}
void AMICharacter::PostNetReceive()
{
Super::PostNetReceive();
// Received ragdoll update
if (SavedRagdollActorLocation != RagdollActorLocation)
{
UpdateRagdoll();
}
}
I've seen Epic use it FWIW @twin juniper
In UT, ages ago, it's where I learned about it
might take a look then, thx !
hey! how would you guys implement mutators? Right now we have two ways:
- We simply have a replicated gameplay tag container in our GameState and our game code checks it, it's the simplest but also IMO not the greatest in term of encapsulation etc
- Use seperate objects (like abilities) that modify the game state
๐ค
i would use an actor component (let's say UMutatorListComponent) with mutators array of AInfo
and have the GameplayTagContainer on the AInfo (AMutator)
and a boolean to say whether the mutator is active or not
oh I see yeah
yeah I think i'm going to do this, I don't think I should bother with seperate objects even if it looks more elegant it feels more complicated for just simple mutators
Is it possible to determine when a structure is fully done replicating? Or some sort of config or override that prevents OnRep methods from firing until the structure is fully done replicating?
I'm running into issues with a structure triggering an OnRep method multiple times as it's fields are being populated. Types like booleans seem to be coming through instantly but references to actors sometimes are coming through as null.
Check if itโs begun play?
Though Iโm curious as to why thatโs an issue
Also you should expect some delay in actor references since itโll require the actor itโs referring to to be fully replicated if itโs a hard reference
If my dedicated server's game mode spawns a pawn and tells a player controller to possess it, is there any reason that 'event possessed' should run twice? is that an editor error or is something wrong there? (4.26 running in editor as client with a dedicated server, 1 client) LogBlueprintUserMessages: [MotionControllerPawn_C_0] Server: Possessed LogBlueprintUserMessages: [MotionControllerPawn_C_0] Server: Possessed Same pawn both prints coming from the server itself. The default pawn for the gamemode is none.
I notice that if i set the default pawn to motioncontrollerpawn and just let the player automatically create one and possess it, the server possessed runs only once.
What's likely happening is you're spawning 2 pawns and possessing them both. The game mode already spawns a default pawn, as per what you set in the game mode's setting for it.
which is under RestartPlayer iirc
Gamemode is set to 'none' for default pawn.
and when I check the world outline there is only a single pawn.
do you have spectator specifically set to false?
Start players as spectators is set to false.
and the spectator class is the just the base engine class, I don't use that.
The motioncontrollerpawn is reporting possess twice, same pawn, same controller as well if I print that out.
LogBlueprintUserMessages: [MotionControllerPawn_C_0] Possessed by: PC_UserController_VR_C_0
LogBlueprintUserMessages: [MotionControllerPawn_C_0] Server: Possessed by: PC_UserController_VR_C_0
LogBlueprintUserMessages: [MotionControllerPawn_C_0] Server: Possessed by: PC_UserController_VR_C_0```
there are also no pre-existing copies of the pawn in the world. It's pawn free.
Interestingly this happens both in multiplayer and in standalone singleplayer. So whatever is causing that isn't related to multiplayer.
On possess only gets called once on the controller
LogBlueprintUserMessages: [PC_UserController_VR_C_0] Server: Controller Possessed
LogBlueprintUserMessages: [MotionControllerPawn_C_0] Server: Possessed by: PC_UserController_VR_C_0```
hey, im trying to build either a dedicated server, or a listen server, so that i can test things outside just using the play button. but selecting the dedicated server doesnt seem to be an option like it normally is? additionally, when i build from Visual Studio, it says that server targets arent supported?
has anyone seen this sort of thing before?
even from project launcher it says that my ue5 ea doesnt support server targets, which is weird because its fully up to date? and as far as i can tell, eu5 ea actually does?
not supported from binary distribution
though I'm not sure why you're doing anything serious with the EA build
which is getting close to a year old now
oooooooh that would make sense
ill try to get the github version i suppose? or would that be the same thing
no, you can compile the server target there
it's still pretty experimental but the 5.0 branch there will be way more up to date
and you may want to pull from that branch frequently since it's still under active development
maybe thats where im seeing tutorials pull from
because it seems like their unreal 5 is different from mine in some ways. im guessing because mine is the EA. but there isnt a full build somewhere is it?
aside from git
huh? no
5.0 isn't in preview yet but since you're on the EA build I'd figure that you like living on the edge anyway
that makes sense
Hello guys.I am trying to make a simple voice proximity voice chat using dedicated server model.Can anyone tell mw how to do it??
Can I safely call RPC events on BeginPlay? Is there any possibility that my client is not yet initialized to run the RPC?
BeginPlay on client or server?
give a delay and run.You will be fine
Can anyone know how to implement voice chat in unreal engine
on dedicated server model
delay is always the wrong answer xD
why??
because you can never be sure that the delay is long enough to cover all the cases
resolving race conditions with delays is terrible idea
And thus it's better to actually know when smth is ready. And its in fact not that difficult. The actor has two functions, I don't remember the names, would need to search my code, that notify the server that an actor is now being started replication on another client (next frame you should be able to send RPCs to the client) and on the client you also get notified that this actor now gets replicated so the next frame also should be ready for RPCs.
And I don't know but I would assume that after BeginPlay was called, we can be sure replication was already setup successfully. On the client only, for the server that must not be the case as you can have joined after BeginPlay was called.
Delay is by far the worst way to "solve" any MP bug/race condition. It's just a clear demonstration you don't understand the issue.
Don't mean to pile-in but I see this in "tutorials" now and it drives me crazy.
our game will typically bounce over a 100 RPCs before BeginPlay is called, which is typically 15 seconds after level is loaded
but i agree on the delays, we spawn an entire procedural level separately on client and server, set everything up, and then we call BeginPlay
we don't have one delay involved
and it would not be possible to time it right with them anyways
delays are just.. insidious, when you have 1-2 timing issues, sure, you can make it work with delays
but as the game grows in complexity, there is no way you can keep 50 delays or 500 delays timed right
my approach is - everything needs to be ready before BeginPlay is called, BeginPlay just does some minor stuff, it doesn't set any game critical systems/data up
and definitely doesn't do anything that depends on timing, as there is no guaranteed order in which actors call BeginPlay
Can you create another PIE session while running in editor, to simulate a client joining the server? I need to test a save system
Yeah I guess so๐๐.
Anyone know how to do voice chat in dedicated server multiplayer unreal engine
This is one of the best discoveries I had about UE4. I'm immediately going to try it. I've always travelled PIE clients to an empty map and then OpenLevel with localhost to simulate players joining to the server..
My question was more about on server to call run on client RPC. But asking it like that makes me wonder if there is any difference between two cases?
Well yes, there is: #multiplayer message
Oh sorry I thought it was answer to another message
The functions I was talking about are:
Server side: AActor::OnSerializeNewActor
and on client: AActor::OnActorChannelOpen
you will btw fail if you calln an RPC IN OnSerializeNewActor, next frame seems to be fine
I don't believe those exposed on blueprint readily?
Don't think so^^ I do everything network related in code, sorry ^^'
So even reliable run on client events don't assure they'll be called in client if I call them from server BeginPlay? What about variables that have onrepnotify functions? If I set a replicated variable on server BeginPlay, it should be replicated to the client whenever it's ready, right?
There's no reason you need to delay a client RPC. The gameplay framework calls Client RPC's on player controllers the instant they are spawned. So long as you have the owner set at that time, it shouldn't be an issue.
Same is true to properties, they are all sent in the initial bunch and onreps will be called before begin play
Note that there's a very good chance the RPC will be called before begin play also (client side)
It becomes an issue if the Object you want to call an RPC on is not owned by the client and the client joins later, then BeginPlay may be called before you even connected
Oh I see
I guess that's the difference between your and Jambax's answer right?
Yeah I see what you mean, if the client isn't around, no client RPC will be sent to them - but similarly if there's no client present, a client RPC can't be called anyway.
well I assume. For me I take any object into account. If we just think about playercontroller Jambax might be right
<@&213101288538374145>
But I for example had the issues with some RPCs and thus I used the Actor functions to be sure replication has started ^^'
I don't think it should be a problem on my case since I'm working on my Pawn then, I don't need the logic to be run on simulated proxies
I forgot what the setting's called here. Do you remember? There's the one config setting to delay RPCs until all params of the RPC have been fully replicated. Been forever since I've last seen that in the wild
So it's fine that my character that spawns on a late joiner doesn't run the beginPlay logic for me
Nothing I can recall. RPC's that are received in the same frame as replicated properties are called after properties have been set, IIRC.
In fact it already won't replicated to proxies since it's run on client
I guess Frigerius' point is more about multicast events
My point actually is that I wanted to sync stuff earlies possible and I ran into issues with trying to send RPCs too early xD
Because if the replicated actor is owned by a client on spawn, the client should have already joined to the game, thus can't join late
Aight ๐ Thought you might know. I think of it every now and then ๐
Yep, I think that should work. I mean you can test it, just add some package loss and delay in the debug settings^^
Alright cool, thanks for confirmations
Ah google's the friend net.AllowAsyncLoading & net.DelayUnmappedRPCs
@marble gazelle
hm interesting
Basically delays the RPC until its params have been fully replicated
on the receiving client end
Cool, will have a look on this, thx ๐
That's disabled by default and probably for good reason IMO
Yeah I bet^^ I'll just check what it does in source and then I'll decide ๐
Calling RPC's that rely on it's params having already replicated sounds like a messy race condition waiting to happen
Yup , which is why it's been forever since I played with that, but it exists
Basically also means you're fine designing your game logic to have a bunch of load dependencies
well I have a working solution \o/
Which is not a fun idea ๐
that doesn't sound right
delaying them until NetGUID for the Actor whose channel is used is acknowledged by the client makes more sense
guys, the Visible property of a SceneComponent is not network replicated
how can I safely change it across the network
is there some kind of multiplayer event system I can use?
Does SceneComponent not have setHiddenInGame? I think that replicates by default.
/** Whether to hide the primitive in game, if the primitive is Visible. */
UPROPERTY(Interp, EditAnywhere, BlueprintReadOnly, Category=Rendering, meta=(SequencerTrackClass = "MovieSceneVisibilityTrack"))
uint8 bHiddenInGame:1;
Are you maybe on an old version of UE4?
Ah nevermind.
Afaik it is, but let me check something
is there a way to make a property replicate
other than putting Replicated in the macro?
From my own notes:
// Visibility, collision, and tick-state are all replicated be UE, for replicated actors.
// Therefore we should only edit these actor properties for unreplicated actors, or the server.
Now this is for actors: I'm sorry if I'm being unhelpful in relation to scene components.
Yes. Semantics. ๐ I would assume that's how it works, given the naming of the thing
hm but this is the visibility of a component on an actor
but is there another system i can use
to propagate it to clients
other than to make it replicate?
i don't think so
Well I would defer to you then, in this case.
You can of course make some system on top of it, if needed (although I still question whether it's required)
as long as its net addressable, there are a ton of ways to making it replicate stuff to clients without it being replicated
but there's no Unreal system for multiplayer events?
I would ask my own question: What would prevent me from creating a blueprint-exposed delegate, in my UGameInstanceSubsystem?
Unrecognized type 'FOnMyEventSignature' - type must be a UCLASS, USTRUCT or UENUM
Trying to add UPROPERTY(BlueprintAssignable)
that is not a USTRUCT, yes?
Ah, true, and UObject isn't on that list
Ah ok so it's just about as simple as the error message tells me.
So following up on yesterday, where I was using GameState to replicate an FName, what is the best way to provide a delegate/notification when the FName changes?
you'll have to be way more specific
i can't if i don't know what i'm looking for xd
try with what are you trying to do then
best way, replicate FGameplayTag instead of FName, OnRep with a delegate broadcast on Set and OnRep
I guess I should do something like GetMyGameInstance->GetMyReplicationComponent->BindToEvent...
My current system is storing the source-of-truth inside of the GIS, and just using the replication component with a UFUNCTION(NetMulticast, Reliable) to propagate the value to all clients.
Weird... I have the same issue when I move the delegate into the UCLASS UActorComponent
You use RepNotify variables and the OnRep function for that
Your GameInstance should not have Gameplay Code
And it also can't really replicate things
This is a custom UGameInstanceSubsystem
I know it can't replicate things
Hence the replicated UActorComponent attached to the GameState.
But it sounds like my way of doing the replication was bad
So I was storing the FName on the custom GIS, and then updating that on all clients by running a UFUNCTION(NetMulticast, Reliable) function on the replicating component.
It sounds like I should replace that by storing the FName on the replicated component, and switch it to being RepNotified.
My only annoyance/confusion is that I want to pipe all "interaction" with the system through the game instance subsystem. i.e., I want MyGameInstanceSubSystem->OnFNameChanged....
Hm well the GI and its Subsystems aren't really meant for this
You already have the GameState and hte Component
That should be enough
True, but it doesn't have persistance across seemless travel.
The GIS exists for two reasons:
- convenient, single point of contact with this information
- re-hydration of the data, after a seemless travel (gameState gets destroyed)
Well, I feel like a failure 
Ever since I moved my stuff from a DynamicMulticast into a the component as an OnRep variable, my client is always wrong
Cedric I'm reading through your PDF Compendium right now. Really good stuff!
Slight update: Replicated works, ReplicatedUsing doesn't :/
Part of working with something new is finding out the pitfalls and learning from them
No need to feel like a failure, this is the natural circle of things
Thanks for the kind words ๐
I'm also feeling a lot better cause I got most of my stuff working. It's amazing how useful a little mentorship goes.
It sure is ๐
Especially with Unreal a lot of it is just knowing how to do the thing right, because there are so many options
sometimes small mistakes pile up, leaving an insurmountable task, and a few offhand clarifications can clear everything up.
What doesn't work?
Doesn't it compile or doesn't get replicated?
In the end I solved it.
I guess I would write a few of my misconceptions, in case it helps anyone:
- BlueprintAssignable must be DYNAMIC_MULTICAST
- ReplicatedUsing doesn't need to set again the variable (just confused about the flow)
Those were the latest in a long list
How do I go about making a UDP socket request ? Is there any built in UE libraries for it or do I have to rely on sendto/recvfrom?
How do I get rid of the jittery movement of Clients from the Listen Server's perspective? I also want to keep using networked root motion, if that's relevant for a workaround. This jitter ofc only occurs when emulating a certain degree of latency, not when ping is below 50ms etc.
If somebody has an answer, please ping me, thx
@grand kestrel I think u mentioned having looked into this issue in depth in the past?
Has anyone here used VR Expansion for multiplayer? I'm wondering what the recommended Movement Replication Type is for Grip Components
I'm starting to refactor my VR Character such that their actions are replicated
You mean the <12 hours ago we were just discussing it? ๐
This issue was specific to root motion on Z axis and the listen server's character from the client's perspective, but the issue is the same in both cases, and neither have a solution on either UDN or elsewhere
It's listen server, it's in the entire foundation and hasn't been fixed since 2014 when it was released 
Neither Paragon or Fortnite use listen server, Epic do not care about it
As there's no solution literally anywhere, it stands to reason that listen server as a whole is inadequate and they're not going to remake something they've ignored for nearly 8 years which they have no use for themselves
What's wrong with listen servers?
Why would simulated proxy predict anything?
Or do I have autonomous and simulated proxy backwards
We have a mechanic to push enemies back via projectiles, but when latency is severe and projectiles are frequent is causes very ugly situations
For example clients shoot enemy AIs and they get pushed back way too later
That's expected and how it's have to be, but just looking for possible workarounds
You have it correct, my desire is kinda absurd ๐
Idk, the whole prediction ecosystem in stock ue4 is a bit of a mess. You got CMC, Network prediction plugin, and GAS but no domain agnostic framework.
I'm fine with diving into some low-level things with CMC or anything else, but just the idea itself seem to be doesn't making sense. I wanted to get some opinions about would 'predicting' something as simulated proxy would make sense at all
I thought there might be some workaround available. I've seen a suggestion to set bOnlyAllowAutonomousTickPose to false and skip calling TickCharacterPose in CharacterMovementComponent. Although this might have repercussions for root motion. So I just wondered if that's a feasible solution at all
It's not a solution
Selectively skipping the TickCharacterPose in SimulatedTick can help, but not solve it
There were loads of ideas on UDN such as disabling combining moves (ew), limiting listen server fps, and so forth but none of them solved it, some made it a bit better, some made it worse, none made it acceptable
But what do all the UE4 games with listen servers do then? Have jittery animations? UKaos said something about clamping listen server tick to 30fps? uve also mentioned a fix for client rotation on listen servers in a thread I saw today, does that still apply?
I don't have jittery animations in every situation
I don't use forums much at all so definitely don't remember that, but the best settings I've found to eliminate mesh rotation jitter for my turn in place system was ENetworkSmoothingMode::Linear and NetworkSimulatedSmoothRotationTime = 0.01f (and ListenServerNetworkSimulatedSmoothRotationTime)
That goes for dedicated too though, not just listen
I see, for me, a regular jogging state machine already jitters badly on the listen server when using the Average network emulation profile
I donโt know if itโs been posted here or elsewhere but listen server couldnโt rotate another playerโs character mesh and I found out why. Linear fixes all my issues and just works so much better on both dedicated and listen server. It turns out, Epic has decided youโre not allowed to use linear on listen server, even though this breaks heaps of...
That was the thread where u wrote about it a year ago or so
Since 4 years? Try 8
๐
Oh, right, I remember that
It literally forces your network smoothing mode to exponential regardless of your setting lmao
else if (NetMode == NM_ListenServer)
{
// Linear smoothing works on listen servers
// but makes a lot less sense under the typical high update rate.
if (NetworkSmoothingMode == ENetworkSmoothingMode::Linear)
{
NetworkSmoothingMode = ENetworkSmoothingMode::Exponential;
}
}
You definitely should use that fix if you want linear on listen, because it makes a lot less sense to have your mesh jitter -_-
...Which reminds me, I wouldn't have been able to test linear with listen, I should check if it helps, I didn't have my own fix in my tests
I love how it doesn't even tell you it's overriding your setting
Dunno
Gonna check now
For this particular issue, or at least my issue, it makes 0 difference
Because I just tried that fix I mentioned earlier and it still doesn't look completely smooth when running
Not sure if it's the animation or the position update that's badly interpolated
This is a better fix though because it wont overwrite after you change to exponential just FYI
void UCMC::OnRegister()
{
const ENetworkSmoothingMode SavedNetworkSmoothingMode = NetworkSmoothingMode;
Super::OnRegister();
// UE4 forces this back to exponential which
// BREAKS turn in place and any mesh rotation!
const bool bIsReplay = (GetWorld() && GetWorld()->IsPlayingReplay());
if (!bIsReplay && GetNetMode() == NM_ListenServer)
{
NetworkSmoothingMode = SavedNetworkSmoothingMode;
}
}
It'll probably look even worse if you reduce fps with t.maxfps
I see, weird thing is that the tooltip for this setting says it's only for simulated proxies, not for authorities
Makes sense since they overwrite it anyway for these I guess
So to sum it up, if I want to make a fast paced arena game with a listen server, there's no way for me to get a good experience movement/ animation wise?
I'm sure there is, but you'll have to be comfortable enough with the character system and animation system that you wouldn't have to ask this question.
You can always roll your own character and not use ACharacter
@cosmic epoch did you notice Epic marked it as "wont fix" https://issues.unrealengine.com/issue/UE-32005
That's a great way to realize there isn't a lot in CMC/character that is unnecessary, it's only fault is how deeply it's tied to the concept of a character which the prediction framework aims to resolve
But sure, there's certainly nothing wrong with doing that yourself, and you get a great example to work from, and it's nice to narrow it down to only the functionality you specifically require
Thx guys, I'll have a more thorough look at this then. @grand kestrel yeah I saw the issue being marked as won't fix, just hoped there was a feasible workaround. Maybe the new network prediction plugin will fix this?
Well, it wont on it's own, not unless Epic recreate, or create a new character using it
And no guarantee they'll bother with listen server much if at all
Does anyone have any thoughts on how I would implement an "Initial Only" replicated variable within a Struct?
Guess one can only hope, I really don't get how they can ignore listen servers so badly, they're really popular for small games
As in the only time i want it to be sent to Clients is when they first receive it.
Alternatively, is there a way to determine within NetSerialize if its the first time sending to that Client?
I'm curious what the best way to handle this race condition is. I record stats during gameplay, kills/deaths, attacks, and hits (attacks that hit a target player). There is a bool which is toggled to determine if stats should be recorded, true during InProgress, false during prematch and post match. The final kill (which ends the game and sets the bool to false) sometimes doesn't record my final attack stat because the the bool is now false. This can result in possibly more hits than attacks which shouldn't ever happen. I'm guessing the same is probably true for my kill/death stats which are more important. Quick "solution" would be to make sure no actions can happen on match end (attacks, players shooting, deaths, etc) and then just put a small delay before i stop recording stats. Does this seem reasonable? I guess i just introduce the chance that stats that shouldn't be recorded after a game is over are actually recorded. Things like projectiles in flight causing hits, deaths that happen after the match, etc.
not sure if there's a nice way to do it, I feel like struct replication is abit weird - I'd probably end up using a multicast with some serverside bool to see if it's been sent out or not for staggered session joiners @fossil spoke sounds like a terrible solution though now I write it out
@soft dawn is the bool a replicated var managed by the server ? Just set it after you do your end match logic
That's one of the most ridicilous things in the engine lol
I'm not familiar with CMC deeply but still couldn't find a reasonable purpose for that thing ๐
You record stats on server only right?
Its not replicated, stats are set on server only
How do you have a race condition then? On final kill it should go
- Final Hit (counted)
- Final Kill (counted)
- Stop Recording Stats
Nothing after this is recorded
most of the time i get both a hit and an attack recorded correctly, but like 1 in 10 times I get a hit and no attack recorded. This is in blueprints too so maybe that is causing it
Server needs to manage all stats and the bool, then it can handle it no problem without there being any race condition
Blueprints won't be the issue
It's probably your logic. Make sure the stat is recorded before the bool is decided
You might be going Hit, Kill, Set bool, TryUpdateStats
@cosmic epoch I can't find the thread and not at my PC rn, but if you remind me tomorrow I can find it. Basically some absolute gigachad found out how to fix it - you essentially need to inherit the movement component and use that and do some overrides. Fixed the listen server jittery interp perfectly for me
I can't remember the specifics though need pc
Thx, ping me if u found it. I already override several functions in the CMC for my custom character class, but some jitter still remains
// Smooth on listen server for local view of remote clients. We may receive updates at a rate different than our own tick rate.
if (CharacterMovementCVars::NetEnableListenServerSmoothing && !bNetworkSmoothingComplete && IsNetMode(NM_ListenServer))
{
SmoothClientPosition(DeltaTime);
}
We may receive updates at a rate different than our own tick rate.
this could be the reason for that 'won't fix' thing
@ember vine I would love to see this thread, too!
Okay I will get out of bed see if I can find
@ember vine thank you! but itโs nbd to wait until tomorrow if youโre in bed!
@ember vine @dark edge thanks, looking at it further, something is resulting in multiple hits on some of the shots, seems to happen when i'm firing a lot
np
I'm using easy ballistics, i wonder if the penetration is causing two impacts on the player ๐ค
and i cant find this thread, all i've manage to do is find an old notepad file with the code in
MoveAutonomous(float ClientTimeStamp, float DeltaTime, uint8 CompressedFlags, const FVector& NewAccel)
{
if (!HasValidData())
{
return;
}
UpdateFromCompressedFlags(CompressedFlags);
CharacterOwner->CheckJumpInput(DeltaTime);
Acceleration = ConstrainInputAcceleration(NewAccel);
Acceleration = Acceleration.GetClampedToMaxSize(GetMaxAcceleration());
AnalogInputModifier = ComputeAnalogInputModifier();
const FVector OldLocation = UpdatedComponent->GetComponentLocation();
const FQuat OldRotation = UpdatedComponent->GetComponentQuat();
const bool bWasPlayingRootMotion = CharacterOwner->IsPlayingRootMotion();
PerformMovement(DeltaTime);
// Check if data is valid as PerformMovement can mark character for pending kill
if (!HasValidData())
{
return;
}
// If not playing root motion, tick animations after physics. We do this here to keep events, notifies, states and transitions in sync with client updates.
if (CharacterOwner && !CharacterOwner->bClientUpdating && !CharacterOwner->IsPlayingRootMotion() && CharacterOwner->
GetMesh())
{
//// We disable this as it causes listen servers to see clients in an extremely jittery manner
//if (!bWasPlayingRootMotion)
// // If we were playing root motion before PerformMovement but aren't anymore, we're on the last frame of anim root motion and have already ticked character
//{
//
// //TickCharacterPose(DeltaTime);
//}
// Trigger Events right away, as we could be receiving multiple ServerMoves per frame.
CharacterOwner->GetMesh()->ConditionallyDispatchQueuedAnimEvents();
}
if (CharacterOwner && UpdatedComponent)
{
static const auto CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("p.NetEnableListenServerSmoothing"));
int32 EnableSmoothing = CVar->GetInt();
if (EnableSmoothing &&
CharacterOwner->GetRemoteRole() == ROLE_AutonomousProxy &&
IsNetMode(NM_ListenServer))
{
SmoothCorrection(OldLocation, OldRotation, UpdatedComponent->GetComponentLocation(),
UpdatedComponent->GetComponentQuat());
}
}``` looking at this now i have no idea how this works honestly im honestly quite sussed out by it
but i know we deffo had a solution for it, i cant really test it rn though
there may have been some other settings or something as well that needed applying, but not sure
That was very kind of you to look that up for us. Thank you, @ember vine !
will definitely take a look
Thats not really a sufficient solution.
Thx, I already implemented this earlier but will check again if it has something extra in it that I lack
Im figuring that the Struct could hold an internal list of connections that its already had NetSerialize called for it.
Then any subsequent calls can ignore serializing specific properties into the archive if its connection exists in the list already.
So I have my VR pawn set up to replicate hand position based on the local motion controller position. For some reason this causes a crash on my dedicated server, yet worked fine in a listen server environment. It's a very simple setup. The local pawn checks the position of the hands, then makes an RPC to the server. The server multicasts to all clients, branches on not locally controlled, then sets the position of the hands. The dedicated server logs are fairly useless, and I'm a bit confused as to why this works fine in a listen server but not a dedicated server.
To clarify multicasting and then filter by not locally controlled means that it should set the hand position on all the other clients which aren't the client doing the actual moving, correct?
@ember vine @grand kestrel so I ended up trying 3 things to alleviate the Listen Server jitter, of which 2 & 3 helped me reduce the issue by about 90% (almost as smooth as a simulated proxie in a client game)
-
Modifying the [/Script/Engine.GameNetworkManager] inside DefaultGame.ini according to a suggested change by UKaosSpectrum (no difference for my issue sadly)
-
Override CharacterMovementComponent::MoveAutonomous to comment out TickCharacterPose(DeltaTime);
- override ACharacter::PossessedBy to comment out Mesh->bOnlyAllowAutonomousTickPose = true;
This fixed the jittery animations as suggested, not sure about the drawbacks it might have for root motion anims/tasks
- Override CharacterMovementComponent::OnRegister to do the opposite of what it usually does at the last if statement (force Linear Network Smoothing Mode for the Listen Server when itยดs set to Exponential) as suggested by @grand kestrel . I left the Network Smoothing Mode of my Character at Exponential in my blueprint settings.
This improved the jittery movement interpolation on the Listen Server a lot, but itยดs still not 100% as smooth as having a Simulated Proxie with Exponential smoothing on a client
To summarize, I think the last riddle that needs to be solved is the difference between Linear and Exponential Network Smoothing Modes for the Listen Server, why Exponential causes jittery interpolation on the LS, and then to make Exponential behave the same as it would on a simulated proxie, which is buttery smooth
Hm I removed TickCharacterPose from SimulatedTick (conditionally), will try removing from MoveAutonomous too
iยดd love to test with both changes too, are u using a special skip condition for SimulatedTick?
if (CharacterOwner->IsLocallyControlled() && CharacterOwner->HasAuthority()) { TickCharacterPose(DeltaSeconds); }
@cosmic epoch MoveAutonomous only calls TickCharacterPose "If we were playing root motion before PerformMovement but aren't anymore"
The bOnlyAllowAutonomousTickPose change didn't help me, but could just be because my issue is a bit different (but related)
Are you testing with reduced FPS (~60)?
As it stands this is the only thing that has made a difference for me. Removing it from MoveAutonomous did nothing
yeah, my CPU struggles to get over 40-50 fps for the 2 viewports
though what I donยดt really get is that Simulated Tick is supposed to be only used for Simulated proxies, which isnยดt the case here, unless the docs are only telling half the truth as always
the Listen Server has Authority for the client actor after all, or does that somehow still qualify as a simulated proxy because it gets the input from the autonomous proxy on the client?
yeah this makes it perfectly smooth for me, but it kills rotation sync xD my client char can now face in a different direction on the listen server than he does on the owning client
Weird that this doesnยดt make a difference for u, it basically makes the anims of the client on the listen server run at native fps instead of being ping dependant (typically 10 fps or so)
Not too weird, it seems to be an issue with similar origins but it's very specific so I guess those "fixes" wont solve everything
@grand kestrel ok, I figured that out at least, the rotation desync comes from combining ur method with the NetworkSmoothMode override
seems that forcing Linear smooth mode skips some rotation sync code, which combined with ur TickPose skip results in rotation of the char mesh not being synced at all anymore
btw, thatยดs not how it works, it calls TickCharacterPose whenever we are not doing Root Motion and are also not on the last frame of root motion, so TickCharacterPose not being called is the exception, not the norm
Mm I didn't think to add some logging there, just took the comment at face value (oops)
itยดs ok, u probably oversaw the ! in if (!bWasPlayingRootMotion)
I really wonder if this "Smooth local view of remote clients on listen servers" stuff even helps in any way?
apparently it neither helps with the terrible animation fps nor with the position interpolation in a meaningful way, despite being enabled by default, so maybe itยดs broken?
CharacterMovementComponent::UnpackNetworkMovementMode returns OutMovementMode EMovementMode::MOVE_None instead of EMovementMode::MOVE_Walk, when passed ACharacter.GetReplicatedMovementMode(). I am not doing any packing on server side. Is it not supposed to auto-work or am I doing something else wrong.
@grand kestrel ok I think I finally fixed it for good, and the solution was easier than I thought. I applied the OnPossessed and the MoveAutonomous animation fps fix and then also set the listen server position and rotation smooth intervals to the same ones used for simulated proxies in the CMC blueprint.
Now I can't tell the difference anymore between a non owned character on client or on listen server, and root motion seems to be fine too
Are u doing MyChar.GetReplicatedMovementMode() or MyChar->GetReplicatedMovementMode()
is there a way to spawn a non-replicated object (in this case a client-predicted projectile) on the client, rpc a pointer to that object to the server, have the server spawn a real object (the real projectile), set a var in the real object using the pointer from the client (that points to nothing on the server), and then have that pointer replicate back to the owning client to identify the fake projectile associated with the new real projectile? I'm trying to figure out a good way for projectiles to know which fake client projectile they are replacing when replicated back to the owning client without setting up some kind of global projectile manager system
Pointers to actors are rpced via GUID and that only works if they are replicated or pre existing props
would it be really really dumb to somehow convert the pointer to a string before rpcing it, then convert it back to a memory address after replication?
im just not sure how to easily set this up. if i use generic IDs it'll work just fine except I need to store a map of all fake projectiles and their IDs somewhere that that the real projectile can query
U could generate it on the fly with a seed
A seed that's synced between server and client
yeah but what i mean is after the real projectile replicates, it knows it needs to replace fake projectile #1579, how does it find that projectile? it needs to query something, or use GetAllActorsOfClass, which i probably dont want to do
Well u can simply store all fake projectiles in an array
yeah but where do u put the array? on the player? on the game state? on a projectile manager class?
Anywhere I guess, maybe on the projectile owner or in the game instance or game state
i just feel icky tying projectile logic to the player class itself lol, i guess anything will work just doesnt feel particularly clean
i could do a projectile manager that's just a component of the gamestate i guess
I think u can even make ur own singleton
alright, thanks for the discussion, i'll probably go with a manager class for now unless i find some reason not to
I heard unreal tournament has some nice code for predictive projectiles
still wild to me there's no built-in anything for this, and i know everyone has different implementations but it just feels like one of those things that every single FPS has to code at some point, even just a basic implementation built into unreal would be neat
Yeah, although the Gameplay Ability System has some nice predictive targeting actors
It doesn't. It's incomplete and they only did the easy parts. It's a trap, you wont realize until you're knee deep
I learned from it a long time ago and I fully completed what they aimed for
Don't recommend anyone uses their method other than the prediction, it's a mess
I'd just use GAS though for forward prediction now, no need to reinvent the wheel
The major part is rewinding hitboxes for projectiles (the actual projectile code is incomplete too though)
This changed the nature of the issue but it's still there for me - I think I'm going to create a far more isolated testing environment to eliminate any possibly interfering factors
What kind of a game are you working on?
That I'm testing the listen server issue for? None, just a plugin
I'm in the bag with curiosity and the cat, because those are some extensive changes and testing, that got me curious ๐
I had a dream where Epic did those instead ๐
I had those too. They all died a horrible death when I looked at the source code ๐
Cruel reality huh
I'm adding a replicated component to an actor in BeginPlay of my server. Is the replication of the component to the client done by flagging the component itself as replicated or the actor that owns it?
Good to know, never bothered with dummy projectiles myself tbh
Is this per variable or per RPC or per packet?
Per replicating component
Should be per packet
That's why they moved the character movement RPC's into the character actor and out of the movement component.
Cheaper but even tighter coupling
Interesting, wouldn't have thought that 5 bytes per packet makes such a difference to them
100 players should make difference
Especially considering that it will try to squeeze as many rpcs into one packet as possible
Fortnite numbers though init. Economy of scale plays a big role
Guess they wanted it to be extremely accessible, even with low bandwidth connections
its also server costs
running through props and comps == more game time on the server
@kindred widget I should move the discussion to this channel. What about things like Possess/Unpossess, AttachToActor? How can you tell about them?
I know this was a long time ago, but did it work for you what Zlo suggested, or you stuck with SetViewTarget?
Cause I'm having the same jitter you are talking about ๐ฆ
Both of the things you just mentioned are automatically replicated. You only have to do these things on the server.
If you were to make Server Accept Client Authoritative Position true, then wouldn't it stop using the server prediction to teleport the player to the "server's predicted position". I'm trying to achieve a simple death ragdoll, it doesn't seem like its accepting my client authoritative position changes and continues to move the ragdoll camera and capsule component to where the server thinks the body landed.
Hi, I can't seem to be able to SetViewTarget to a client spawned camera. Any body got any advice?
@undone plinth When are you calling this?
After PostLogin
On the player controller
It spawns it and its there in the worldoutliner but just doesn't set the view target
That is way too early.
Several things call SetViewTarget. Off the top of my head, CameraManager's PostInitComponents, and PawnRestart at least set it, there are a couple of other initializing functions that call that.
If you want to call it that early, I'd recommend overriding the PlayerCameraManager's SetViewTarget, and do your own thing, if fail, call Super.
Ah okay! Yeah thinking about it. It would probably be overridden at somepoint! Thanks I'll come up with something else.
in terms of best practice, If you bind a function up to some UI ie a button dynamic multicast delegate, and have the player cause the UI to broadcast to a bound function, how do you then make sure the server calls it / or have the client tell the server you want to call the function
i'd never reference the UI from game code
unless its the HUD that just spawns and places widgets around
UI can and has to reference the game code though
so its ok for a button to directly access and call a function
basically, getting the game to production level usually includes scrapping some 4-6 iterations of the UI
and you really don't want to end up fixing the game code because of that, game code should not care if there is even any UI
if you have any c++ involved, its painfully easy to reliably access the PC, and with it, other classes that can send and receive RPCs from any widget
I agree with Zlo - I typically only have the PC add/remove widgets on an as needed basis. The widgets rely on event dispatchers to update themselves.
You also need to change the mode to client authorative movement, just setting the server to accept it isn't enough
The only time I've ever done this was for the entire project somewhere. This goes into DefaultGame.ini
ClientAuthorativePosition=true
MAXPOSITIONERRORSQUARED=9000
One is to set the mode to use your client authorative position, the large value on the error is to make sure a codepath doesn't ignore the client auth movement anyway
You can use those as a starter point to look into making changes that work for your particular use case. There's only one place incode that uses the max position error. Not sure about the client auth check, but happy hunting! ๐
I will give it a try, thanks man ๐
I didn't even know you were able to do this. Seems quite risky.
Keep in mind this is inside the ini file and will affect the entire game, please don't just copy paste. I've given those as a reference for you to look into, it should help finding what you need. Don't just apply blindly, just like with everything else in UE
Yea, gonna test it out first and see what happens
There's a lot of things you can do in UE except seamless travel in PIE, because reasons .... ๐คฆ ๐คฃ
It's not like the one thing you actually want to have to develop a multiplayer game ๐
I thought UE just hard-required server authoritative.
I'm currently looking to the shooter game epic games provide in the market place. I just saw that and was wondering what's the point of it. I'm not sure I get it. It seems like the replication is paused when something is inside the player bounding box. BuildPauseReplicationCheckPoints just created an array with different points all on the edge of the player bounding box
I haven't looked at it in a good while but I believe it was still jittery using the view target method
Does anyone know a good resource for explaining good practices with respect to order of operations when initialising widgets?
I'm finding that often my widgets need to bind to eg the character or player state, but those objects haven't yet been replicated from the server
so they're null when I try to bind
I assume I should be waiting for all necessary replication to happen, THEN initialise my HUD (for example)
Try to bind until you succeed
but not sure if there's a standard architecture for this
really???
You can do either.
seems scary to me just delay looping until things are ready but if that's how people do it....
you shouldn't have to use delays or bind
binding, last time I checked, kills your performance
Binding is fine for a quick and dirty UI. I wouldn't try make EvE online with it but it's fine for a small operation
binding to a delegate is fine
ah
binding your UI elements to a function is terrible
oh yeah I hate that anyway
yeah, avoid it like the plague my friend
Even just binding to a property is fine if you don't have a thousand of them.
I was expecting that there would be engine delegates I could bind to in BP
like OnRep_CharacterPossessed or whatever
I see one for player state which is good
what are you specifically trying to do? in almost all cases you can get away with an event-based system where one event triggers the next without having to delay / poll for something
yeah that's what I want
are you running into some sort of race condition where something isn't ready?
yeah
on Event Construct
in a bunch of widgets
the widget is trying to bind to a given actor's delegates (eg character)
but it doesn't exist yet
how does the widget get created / added to the screen?
ohh the good old HUD class
tbh I've never used it lol
I usually create my widgets on my controller or pawn, depending on the widget
it has an Event Initialise method that kicks everything off
I don't use that HUD class at all - you're referring to the one you can specify in the game mode?
yeah
Im converting a game from single player into multiplayer
(not my idea ๐ )
it uses this HUD class
rip lol
ya
depending on how deep its tentacles are, you might be able to move the setup from the HUD to a simple Create Widget -> Add to Viewport on the character, which means the character is 100% alive and existing when the construct on the widget runs
what's the class calling on the event Initialize? is it just creating other widgets?
yep
oh, you can probably just call that same logic on the begin play of the character then
Don't call that method till everything is there
oh yeah good idea, I guess there's no reason to use the hud class necessarily
I like the hud class because it's a good place to put all your UI instead of crowding the player controller.
yeah could just avoid the engine lifecycle stuff
makes sense
will try that, thanks ๐
I believe the HUD class is old school - other vets in here can correct me if I'm wrong.. I've only been using the engine for ~3 years
just an FYI, make sure you check to see if the player is locally controlled
just remembered you said you're going from single to multiplayer
avoid creating the widget if the character / controller isn't local, otherwise you'll get all kinds of weird behavior (stacked widgets, null references, etc.)
ah yeah don't want widgets on the server, good call
also don't want widgets from other clients
That's another reason I like using the HUD. Only one exists in a world (besides splitscreen) and only for the local player.
Hey, I have a actor that has a mesh comp with bReplicates and bReplicateMovement enabled. I'm only moving it on the server so its smooth on the listen server. I thought it would Lerp the transforms for me? But the client sees it stuttering.
Any advice?
bReplicateMovement replicates the movement for you but is most likely what's giving you that stutter
if you're going to handle the movement yourself, you need to set bReplicateMovement to false
good luck ๐
Turned it off and its still the exact same behaviour
right since the server is setting the position on tick, not the clients
you'll have to look into movement interpolation
like what data is required for your clients to simulate an actor moving from point A to point B
that data needs to be sent to your clients and your clients will set the actor location in their instance of the game
your server will also be doing it, but the idea is that everyone is doing the same thing collectively using data provided from your server
what's APerson inherit from? are you using your own custom character vs. ACharacter?
Yeah inheriting from AActor only. So I need to roll client side prediction.
?
I feel like though I've rolled replicated AActors before and it seemed to lerp between positions/move normally in examples I've had before. I'm gonna load one up and see if its an issue
Why you no use Character class?
Its already have movement prediction.
You can keep bReplicateMovement
Store the client position on OnRep_ReplicatedMovement (or something similar to this) and interpolate it to server location in tick
GetActorLocation() on simulated proxies is server's location
The values you stored in OnRep is previous update's location
You lerp to GetActorLocation() in tick
If it's player controlled pawn forget about it, its too complex. Just to CMC instead
Also pls don't abuse Epic coding conventions ๐ฅฒ
There are several question marks there though
-> Why dont you use ACharacter instead?
-> If you dont want ACharacter, why not APawn instead of AActor?
So I know Reliable RPCs are guaranteed order on the same replicated Actor.
However, does anyone know if this is true for the Destroy() method? In otherwords, if I call a Reliable RPC on an actor, and then destroy it immediately after, is the order guaranteed?
I assume thats an server RPC, if server destroyed the actor, why would it matter?
I've got a Multicast that calls an event on a non-replicated actor. But I also want to call that Multicast immediately before it gets destroyed.
So clients receive the multicast, call the event on the non-replicated actor, but then very soon after the replicated actor with the Multicast needs to get destroyed on everyone.
Just wondering if I should expect that to be out of order during packet loss
Example:
MulticastDoThing(FVector Location)
{
//.. do stuff
if(GetLocalRole() == ROLE_Authority)
{
Destroy();
}
}
I don't think Multicast will work on Non Replicated Actor.
it's replicated
i guess that was worded wrong
Ignore the non replicated actor
If that Destroy() somehow gets received on the client first, then that Multicast wont run, that's what I'm trying to wonder. It seems to work but I'm not sure if this is a potential race condition under packet loss
There is also OnDestroy or OnPendingDestroy iirc.
What you trying to do before destroy?
It needs that Location vector to pass it into another actor (which isnt replicated)
Like this
MulticastDoThing(FVector Location)
{
OtherActor->SetActorLocation(Location);
if(GetLocalRole() == ROLE_Authority)
{
Destroy();
}
}
Oh, then you don't even need Multicast,
Look up AActor virtual functions, cuz I am sure the clients get a function call from server to request client to destroy their actor.
How am I supposed to send the location then? It's an arbitrary value
I think I'm going to have to test this rapidly under heavy simulated lag to see if I can break it. Digging through the NetDriver to see how Destroy() actually works is kinda crazy haha
Oh lol,
Yea probably add a timer or something
yeah that's the other solution
can just hide it and then destroy later
worst case
This some sort of treasure hunt mechanic?
Hah no I'm over simplifying the code, it's an ability that throws a flag in Capture the Flag. We get odd desyncs here and there and I'm trying to figure out what the hell is causing it, it's extremely rare
The ability gets destroyed after it throws the flag, but we're not going to be doing that anymore anyway.
So if I have a character bp and a component and add all my server rpc in component then add that component to my character . All should work as it would placing them in the character bp.
Oh ok
Found out the reason.
In Character.cpp there is following line 1544(UE 4.25.4) in GetLifetimeReplicatedProps.
DOREPLIFETIME_CONDITION( ACharacter, ReplicatedMovementMode, COND_SimulatedOnly );
Is there a way to change this in the derived class. I don't want to change the engine code.
yes
Override GetLifetimeReplicatedProps, call Super, and then there are some other macros you can use to replace DOREPLIFETIME... will find it in a sec
RESET_REPLIFETIME_CONDITION(ACharacter, ReplicatedMovementMode, COND_SomethingElse)
Grateful
I get this error. I have no replicated member in my custom Character.
error C2509: 'GetLifetimeReplicatedProps': member function not declared in 'AGSCharacterBase'.
Declare it in your class, then.
it's just a normal function - the fact that the declaration gets generated for you when you have replicated members is just a nicety.
Ok.
he doesn't need to, UnrealNetwork.h already does
so he most likely forgot to include it
GetLifetimeReplicatedProps, not the REPLIFETIME macros.
yes
UnrealNetwork.h cannot declare a function for a class it doesn't know about...
it's declared in the parent class then
i never declared GetLifetimeReplicatedProps in any of my headers
Yes, because UHT auto-declares it for you when you have replicated properties.
Declaring in a parent class does not declare it for child classes to override. You still have to declare that you're overriding it.
it should for him too then
Not if he doesn't add any replicated properties...
Which is precisely what he said. So again, he needs to declare it himself.
This is one of those dumb niceties that UHT shouldn't do because it hides normal C++ features and confuses people who aren't intimately familiar with the engine.
agreed ๐
my bad then
Same with UHT auto-declaring _Implementation functions...
At least in the early days it seems like UHT's design was to generate as much for you as possible... which just makes things confusing. It feels like they've gone back on that a bit at least, they haven't removed that codegen but it at least lets you declare things yourself if you want (iirc it originally didn't).
Character Movement does not replicate...
- Owning Actor is replicating
- Character Movement Component, Component Replicates is CHECKED
- Checked on the other client/server, the Max Walk Speed is still 600
I guess you have to Multicast? But then what's the purpose of the "Component Replicates" in Character Movement Component if it doesn't even work?
CMC replicates just fine without you changing anything.
That specific property is not marked to replicate.
Notice the lack of the "replicates" icon (the two spheres) on the set node.
- Checked on the other client/server, the Max Walk Speed is still 600
cause you are setting the walk speed on... the client
anyway, ^ too. I don't remember if CMC replicates that data manually or not but it's definitely not going to work from the client.
no ๐
you just set it on the server
and it will replicated to clients
depending on the rep condition
and if you do that in cpp you can even do better and override the GetMaxSpeed function
so you can have let's say MaxRunSpeed, MaxSprintSpeed implemented in the component itself
I tested it out like this:
Basically, if I press "5" on the client then walk on Client:
- On Server: everything looks fine, walking slow
- On Client: looks differently here, the animation is walking as if the speed is 600, but the actual distance covered is as if you're speed 10
This has a "stuttering" effect
It has the stuttering effect as that particular variable isn't replicated, so even though you set it on the server, the client has a different value.
I see, it's like how siliex mentioned, there's no two spheres in Set Max Walk Speed
So even though the Character Movement Component is replicating, that variable is not replicated
Is that right?
a class or component can be replicated but its variables can be set not to replicate
And you can usually tell if the variable is replicated by these little bubble icons.
Gotcha, okay
So the solution is simple, Multicast
set it on the client then call the rpc
other clients will see the speed set by the server
the owning client will see the speed set on himself + the server
the owning client's speed will match what the server has so you won't get that crazy correction stutter
I see, gotcha
Thanks you guys
Only temporarily. The stutter comes from the server letting you walk at the new speed before your client has seen the speed change. You need to do max speed changes AS a move.
@pure mango CMC does not replicate anything, it hands it to the character which handles replication then passes it back. This is because components have an extra byte with each RPC to identify the component on the actor that called it, so it's an optimization
It's pretty messy to follow code-wise but I guess they're penny pinching due to characters usually being the most significant bandwidth hog
Hey all, is there a race condition here in the picture, considering two clients asking to verify their killing shot on the server which calls this function? I don't want to add any more kills to the scoreboard if the final kill is taken. Is this bool check enough considering both RPC calls should run sequentially on the server after they're received? (if this knowledge is correct of course)
I'm always intrigued about how does event graph and events work sequentially. Especially for the RPC cases. If two clients call an RPC that calls the same event on GameMode, will the second execution wait for the first to finish? Will they work on the same execution line if first takes long time without delays? What if there is delay node? If I can get a little insight or a pointer to where I can get more information about these, I would be grateful as well.
- There's no guarantee for ordering of RPCs from separate clients - there can't be.
- RPC execution happens on the game thread so one cannot interrupt or run at the exact same time as another.
- Delays and other latent nodes work the exact same way as they do with other blueprint events. A delay in one event will not affect another - delays (and other latent actions) do not block anything from executing, they just cause nodes hooked to the right side to execute on a future frame.
There's only a race condition here if the server isn't authoritative (ie clients can decide their own score).
By order I meant the order according to their arrival on server. I don't care which kill reaches to the server first. I just don't want to increase the kill score over the limit. So according to your answer and second explanation this should be fine since I store the scores in GameState as replicated variables. Thanks very much!
That's correct
However one thing to be very aware of when doing things like this is to:
(1) Verify someone else hasn't completed the action ( easy with your current example )
(2) Make sure the params are still valid. The client could be referencing in actor that's already been killed on the server, or the game's state could've been changed in a way that makes the params no longer relevant. Something to be mindful of
Hello peeps!
I am having a problem with possesing a pawn through gamemode. I have a UI on each client where you can either select team A or team B. So the UI calls the event "On Team Selected" on the GM which has two inputs(playercontroller and team). The event spawns a character and joins the relevant team, but only if it is the server host. I am guessing this is because the gamemode only replicates server stuff.
Any solution to this? I have thought about using gamestate or simply just having this logic in the playercontroller instead.
GameMode usualy doesn't replicate at all
not sure for peer to peer, but with a dedicated server you don't even have a game mode on a client
GameMode only exists and runs on the server. So you want that ClientToServer RPC somewhere else. There are a variety of different ways this can be implemented. The RPC ( Event ) just needs to live on a client owned actor
Thanks guys, i figured it had something to do with the gamemode only existing on the server yes. I'll look more into client rpcs, kind of a newbie ๐
How much does it cost to make your make game online multiplayer like fortnite, apex etc
Explain "cost"? That severely depends on the scenario
If you have a complete singleplayer game that you now want to throw money at to magically make multiplayer capabale, or if you have a game idea/funding and want to plan to make a game but don't know how much effort it is to make it MP, or if you need to decide whether or not you want to add MP to your game, etc....
There are a ton of potential scenarios that you can find yourself in, and there's not one magical "cost" formula for everything
Context is King
- Cost of developing multiplayer code (5x singleplayer)
- Cost of developing anticheat, report system, replay system
- Cost of running dedicated servers + infrastructure
- Cost of producing recurring content to bring players back and avoid "ded gaem" reviews
These games are the most expensive to run
Like how much do you have to spend (as in money) for multiplayer?
If you have to ask....
As I said, there is no magical formula for this. It depends -entirely- on the scenario that you find yourself in, so if you want better information on that you're going to need to give more details
hello! Can someone pls confirm me, that one of the following events (GM) is being called when client joins server map?
I mean - I've situation, where the player is in sort of single player map, and if he clicks the UI join button server map is loaded. So my question, if those events are fired again, or not.
Have you tried just breakpointing them?
cant simulate the server client travel so easily
so was curious if someone has this knowledge already
this is run when I start the game, just I'm not sure I can rely on this when client travels to server map
If you can't test it in 5 seconds then get that working first.
Server seamless travel isn't support in PIE, so "just testing it in 5 seconds" is not a thing
Launch with a bat file
Again, that's not a 5 second test
It is on my machine lol
thanks guys, even I've playfab involved and need to test on oculus - therefore this complicated things a bit with server deployment etc
to be more informative - I think I found the answer
it's not relevant for Adriel, as he knows the answer with his knowledge about how to test this in 5sec
There is another one, which is commonly used for letting player in the game or reject them.
AGameMode::PreLoggin()
Its not available in BP tho.
Hello, I'm looking for some advice related to the character movement component in a multiplayer scenario. I'm working on a top down style game, and my current movement strategy is to use a client side navigation mesh to create acceleration based movement to the local character movement component, additionally, I have orient rotation to movement set, as the camera is fixed to be centered on the character. This seems to be working great! The wrinkle is that I'd like to add the ability to "turn and face" a direction when a character uses an ability (I'm using GAS but I think that's able to stay out of scope here). I think I'm out of my depth on this, but I couldn't find a way to introduce a rotation only "move" to the CMC, in fact it appears it wouldn't view that as an "ImportantMove".
I've hacked something together using a combination of cancelling any outstanding navigation, and using AActor::SetActorRotation on all of the AutonomousProxy, Authority, and SimluatedProxy scenarios. This actually works relatively well, but sometimes the AutonomousProxy can end up with the wrong orientation. I think this is a result of the AutonomousProxy fully applying the local AActor::SetActorRotations before a ClientAdjustPosition happens from one last small move from the previous navigation. I can only reproduce when there is some amount of "momentum" from a previous move request. I guess I could build something to "wait" for outstanding moves to be fully processed, but my goal was to get this rotation functioning as smoothly as the rest of the client side navigation, even if the AutonomousProxy has latency to the Authority. Ideally I would accomplish this without using any movement. I considered forcing the character to move a small amount in the direction I want them to face, but I'm not sure I can guarantee a "full" rotation, without introducing a non trivial amount of "forward" movement.
I'm quite confident I'm doing this wrong and fighting the CMC, but I'm not sure where to go from here.
Maybe I can subclass and add a new packed flag, like crouching, to ensure a rotation only move would be replicated?
Ahh fighting the CMC, a tale as old as time
how many units will the player control in this game?
and are you worried about cheating?
I've had really good results with entirely client-driven movement using Pawns and SmoothSync (the plugin)
Also, in some setups I'm pretty sure this could work
like on a timeline or something
I'd have to take a look at that plugin. Players control a single pawn. I don't think the control rotation suggestion can work without moving away from the client side nav mesh strategy as I'm using orient to movement and ignoring all control inputs (maybe I'm misunderstanding your suggestion)
I'm pretty new to all of unreal, was the scenario I layed out completely crazy, or is my understanding of my situation fairly accurate
I mean, you're pretty deep in a pretty common problem
so you're not dumb
I use smoothsync because I trust my players not to cheat
if you're making League of Legends....you need proper server oversight
now that we discuss it I'm pretty sure I've had this problem before........was remaking Age of Empires 2 and I had to tell me guys to move a little forward whenever they turned to face a different direction
Hey Guys, I have an actor with an event that should run on server. My character right clicks and then that event on that actor gets called, but it isnt triggering, caz afaik actors need to be owned by the client, but idk how to do that, any help regarding this?
I am trying to do a simple building system where right clicking sets the actors materials and some other infos through an event. Is there a better way to do that?
Do the RPC through the players pawn or character controller
I didnt get you, actually i am new to multiplayer
That's fine
i have to do all of them in the character bp?
Where are you doing it right now?
Everything in Unreal is bad joojoobs for sending messages to teh server except for the character and the controller.
But once you get onto the server, you can trigger an event externally
so can a multicast event call this actor function
i will run an event on the server from character bp
which triggers a multicast => then actor
Nothing to do with multicast
So if you want to detonate a nuclear bomb, you start on your character.
RUNONSERVER ---->>> SendDetonationAttempt
Then the server version of your character can tell the server's version of the bomb to run it's DETONATE event.
no i want all players to see the material change
and for people to see it, dont i need a multicast?
Multicast isn't great because it'll only work for players who are near the object when the change occurs. What you want is a variable on the object with ONREPNOTIFY replication, so everyone can run an event in response to the change of the variable.
Have replicated variables on the actor
oh
And set them for Onrep
Onrep MyMaterial -> apply changes etc
should this work?
built block is the actor i was talking about
and this is the character bp
The actual flow would be like
In pawn or controller
Input -> run on server event -> set variables in building actor
In building actor
Onrep MyVariable -> apply changes (change material, do whatever)
Basically the SERVER version of the pawn or controller is what's doing the thing
So if I want to change the color of a banana for all players, the flow would be like this.
My character sends a message to the Server version of my character.
The server's character send a message to the banana to change his BananaColor Variable (which is replicated with onrepnotify).
Each client's banana receives the change in BananaColor and runs the onrep event.
I'm hoping to avoid this. I had something that did this a while back and it was ok, but I needed to make the move somewhat large to ensure that there was enough time spent moving to get up to a 180 degree rotation
Yup
ok lemme try what u guys told me, thanks a lot!
Yeah I'
Onrep is the best. Then if someone late joins they see the banana as the correct color where they wouldn't have been around for the multicast
m sorry I couldn't help more, maybe fiddle with turning control rotation on and off
I'm going to try subclassing the CMC/FSavedMove_Character to override IsImportantMove and see if I can get a rotation only move replicating using a new flag for the "look at" operations.
I think the right goal is to get this rotation move into the CMC saved move machinery, but it's probably going to be hair pulling work. I'll at least learn something along the way ๐
Oh, maybe I can hack this in with a movement mode change! Then I won't need to subclass FSavedMove_Character and deal with all of that fallout
Is there a convention people use for multiplayer projectiles? I can't find any actually useful information to make this work properly.
@dull chasm could you just not have the CMC care about rotation at all?
I do want my characters oriented to where they are moving at all times. What would you suggest manages the rotation other than the CMC?
I didn't really work with CMC before but there should be nothing preventing you from calling some code right after CMC does its work to orient the player based on the current velocity
(although I'm pretty sure that CMC should be capable of doing that itself)
It's absolutely capable, it just conflicts with my desire to every once in a while set an explicit rotation while stationary :)
@dull chasm AI controllers with FocalPoints makes that much easier with the pawn's CMC set to smoothly rotate to it's control rotation. Otherwise you're looking at creating your own logic somewhere like the Pawn. Make a local space vector or something and always set rotation towards it if it is not 0,0,0
I'll look into that thanks! My players don't have any direct input (it's click to move) to the character anyways so that may work very well
Does anyone know if there's an online multiplayer game that users don't need to sign up (or make an additional account externally or separate from the store account), but can also do cross-platform play? Btw, just searching for a good example (to avoid double sign ups...)
I don't know of a game, but EOS? You only need the epic account
If it's click to move why are you worried about prediction?
Destiny 2?
I know from Steam, there was no account sign-up process.... Not entirely sure it's cross-platform.
I'll look into it!
I have this variable in an actor component class
UPROPERTY(ReplicateUsing = OnRep_MyArray)
TArray<UObjectChild*> MyArray;```
`OnRep_MyArray` is called however if I iterate over the array of pointers
for (auto Single : MyArray)
{
// Use "Single"
}
`Single` is NULL, is there a way to fix this?
don't know if this is the solution, I'll try it tomorrow https://forums.unrealengine.com/t/can-uobjects-be-replicated/41720
okay so i'm trying to do projectile prediction, my current approach is to have the client spawn a fake projectile, assign it an ID, send the server the spawn params and ID. Then the server validates whether to spawn the projectile, if so it will spawn the authoritative version, which has an OnRep for owning player that will replace the client's fake projectile. The tricky part is how to catch the server up to the client's fake projectile. I can use Predict Projectile Path with the client's ping, but I'm not sure what to do in the case that the server actually hits something within that prediction. Do I just immediately notify the client to destroy his projectile and perform hit effects on the server, or do I only register hits if the client thinks he hits something?
the other case is if the client's fake projectile hits something before the server rep replaces it
You just call the projectile actor's tick and pass the prediction time as deltatime
None of that accounts for player rewind though, it's not easy to achieve with projectiles, forward prediction is only the easy half of that puzzle, players will still complain the hitreg is bad (and it will be)
Also spawning projectiles is asking for trouble if you have guns instead of say, magic spells with low rate of fire, spawning them costs a lot, need to pool them instead
Where are you filling the array? Have the actors replicated to the client prior to being added to the array? Otherwise it will receive the array replication before it receives the spawned actor replication and thus be null
Luckily i am using spells for the most part. I didn't know you could manually call tick with a custom deltatime that's way smarter than whatever nonsense i was doing
Does anyone know if the CharacterMotionComponent in the new prediction plugin will also remove the need to the Character class?
ok i am back
so i did this rep notify
with an extra variable "Was actor placed"
so now everything calls perfectly
but even if i set the independent vasriable to true (it also prints true in servers and clients) but actually remains false
for example i have this repnotify on character bp, which just makes the mesh itself visible
same thing is happening, altho new visibility is set to true
it isnt making it visible
this is a different bp btw
I'm not asking what causes it, I'm asking why you think it is false, because it isn't...
oh, if i press f8 and get out of the game
i can see that its not independent as theres no check mark on the actor's variable
and for this, its obvs because i can see the character not becoming visible
f8 detaches the pawn
yeah ok
ok so I want you to take a picture of the PRINT STRING result when you get it
and post it
why don't you jump in my private server and stream your setup in greater depth so we can really get to the root of this
Minecraft old school
Hey guys having a hard time trying to debug a timeout issue, the logs dont say anything much just that a timeout has ocurred, how do i debug this?
goddamit replication will fry my brain.. if one player moves his head and i want to tell all clients, hey THIS player moved his head, is a SELF reference in the "move head" function right or wrong? for the other clients the self reference would be THEIR headrotion and not the headrotation from the client who turned his head.. atleast the player moves his head for a second and immidiately goes back to default..
Don't replicate "Dude1 moved his head", replicate "Dude1 is looking in this direction"
Also skip owner.
so i would write two functions, one for the client who does something and one for simply setting the value so others can see the result
IF you're using ControlRotation as the view rotation of the pawn, there should be another rotator that can be used on non-owning clients, sec
ya this one
IIRC it's automagically synced up to ControlRotation, but also exists for remote clients while ControlRotation doesn't
Only need one function for setting the head rotation. Call that locally on the owning client and then RPC to server the direction. Have server version set that value to be replicated, skip owner. OnRep call the head rotation function.
BaseAimRotation is for Pawns mostly. It uses replicated Pitch, but assumes Yaw from the pawn rotation.
oooh yeah now i get it, thank you i will try that
IDK why the hell they didn't just make control rotation available everywhere but if it lives in the Controller it makes sense
Yeah. Rotators replicate very small. Not really a huge issue to replicate one.
Specially with roll being ignored most times, and they compress into shorts and bytes anyhow, most rotators are between 3-4.7 bytes.
@tawny windIf your end goal is that everyone sees everyone looking in the correct direction, then replicate some rotator (Call it AimDirection or whatever) OR leverage BaseAimRotation if that works for your setup. Do not directly replicate things that can be derived from that.
I mean to be fair, this is framework from like dial-up days. ๐ So I get the stingy sentiment with networking to that degree, but still. Not so true anymore.
For most shooter type games 2 rotations is enough, that is, body facing rotation and aim rotation.
Yeah thats exactly what i'm trying to do, thank you both!
Self is in reference to the instance of the blueprint the code is being run on. If you had some RPCs on a character from input of a character > server > multicast with a reference to self on the multicast, it's still referencing only the instance of the blueprint the code was originally started from, so that particular character that started the RPC chain.
Thank you very much Datura, thats exactly what i wanted to be sure about, i guess the symptoms have another cause then
okay so i finally got it to work, its probably dirty and i will rewrite it later but i will see, i simply send the rotater with a custom event(multicast) and set the aimrotation with it and the animbp reads it with a cast so the animation can use it, i'm a bit confused about the idea of setting a value to "replicated" since you need to cast to the clients anyways, right now its working fine without setting the rotater to replicated
do i mix something up right now?
i guess with the current method i send way to much data for such little functionality but this is my first multiplayer project so i cant really tell
Gooood afternoon!
I'm attempting to use a NetMultiCast to toggle visibility on an object.
Functions like SetActorLocation do work, and I've checked on the client-side that the right object is being called and the client has authority over it, but ToggleVisibility and SetVisibility do not seem to have any effect on the rendering of the item, though the visibility flag of the mesh component does toggle correctly.
Is there something else that must be done to support toggling visibility over a network?
// using static mesh actors
for (TActorIterator<AStaticMeshActor> ActorItr(GetWorld()); ActorItr; ++ActorItr)
{
const auto before = ActorItr->GetStaticMeshComponent()->GetVisibleFlag();
ActorItr->GetStaticMeshComponent()->ToggleVisibility();
const auto message = FString::Printf(TEXT("%s Authory %d Visibility (Before %d, After %d)"), *ActorItr->GetName(),
ActorItr->HasAuthority(), before, ActorItr->GetStaticMeshComponent()->GetVisibleFlag());
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, *message);
// prints that the flag has changed on both the client and the server but only server visibility changes
}
// using a function in a subclass of actor
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
class UStaticMeshComponent* MeshComponent;
UFUNCTION(BlueprintCallable, NetMultiCast, Reliable)
void ToggleVisibility()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Toggling"));
MeshComponent->ToggleVisibility();
}
@daring portalWhy not just set hidden in game on server?
you shouldnt need to multicast anything
I would like the object to be hidden on all connected machines and setting hidden on server does not seem to replicate either
In terms of debugging - you're not actually printing the state before and after toggling, just when creating hte RPC
So you're only checking what the state switch is on the server, not on the client, where you're actually experiencing the issue
The debug does print when I click the button though.
The message on the client machine's screen would be client side, no?
Let's say I did this over from scratch ๐
What would be the best way to do it?
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Toggling"));
MeshComponent->ToggleVisibility();
}```
This is your multicast fucntion
that executes on both server&client, but it's the least information you get in terms of debugging
all your debugging is at the server-side where the RPC is created, so you know what the visibility state is on the server when you do it
like with any debugging, trying to zoom in on where the issue might be is a crucial skill
So you want to narrow down the possibilities of where the problem may lie. Adding more information in the relevant places is a good way to start
Uhm. So.
On the left side, the server, those items did disappear. On the right side, the flag is false but the items are still visible. Another command, such as moving the items up or down (for nonstatic) replicates as expected.
Presumably // using static mesh actors is being called from both client and server, instead of just server, but that wasn't the point I was trying to make
Ah, I see you were talking about the multicast function on the object one, let me isolate that and add more debug ๐
You'll probably see that it runs twice and hides it then makes it visible again on the client
Assuming the RPC is being created on both client&server, instead of you having that piece of code only run on the server
So I've put the call to iterate for all visibilitytoggleable actors and to call toggle visibility on them outside of an RPC call- it runs only on the server, then the individual objects should have their RPC's run correctly, as I understand it.
The drape in front of the camera becomes hidden on the server but not on the client, though the client also sends the message that the drape's visibility flag has been set to false.
It seems like the message that is coming from the server is also displaying on the client. ๐ค
I see, it is actually the RPC that isn't working as expected- not the visibility toggle. Odd, all my other RPCs work. I'll figure out what I bungled!
Fyi I have no idea whether or not that's networked. I only ever use UE_LOG
I'll switch back to using UE_LOG. Is it possible to look at only the client instance's logs?
If your RPC doesn't work and you've setup everything properly, you might be trying to call the RPC before the actor has replicated to the client from server
AddOnScreenDebugMessage isn't networked, it's just because you're in PIE that it appears everywhere.
If you were running separate processes it'd only appear on the instance that called the function.
Yeah that was a little confusing ๐
Is there any setup I should do for actors that are static in the scene that I would want to network? For my other actors, it seems to be working as expected.
Oh bloody hell I'm an idiot
Of course UStaticMeshActor has replicates false by default
So... just a random thought here
And bear with me
The thing with networking is, you always want to do as little as you can get away with
your line of thought would be, if you can do it on a local per client basis, you should
Here you are now thinking of replicating all of your static mesh actors to toggle their visibility, making one RPC call for each actor in the world every time you want to do this
Instead you could have a single RPC call that says "ToggleVisibilityOnSMs"
and in the executing logic, it iterates over all your meshes and toggles the visibility locally
So instead of doing 100x RPC -> 1 per mesh, you do 1x RPC -> For all 100 meshes
So that's what I had in the game mode, and I thought that's what the TActorItr would accomplish
But for some reason it wasn't
I had...
UFUNCTION(Exec)
void Toggle();
UFUNCTION(BlueprintCallable, NetMultiCast, Reliable)
void ServerToggle();
void AScenarioGameMode::Toggle()
{
ServerToggle();
}
void AScenarioGameMode::ServerToggle_Implementation()
{
for (TActorIterator<AStaticMeshActor> ActorItr(GetWorld()); ActorItr; ++ActorItr)
{
const auto before = ActorItr->GetStaticMeshComponent()->GetVisibleFlag();
ActorItr->GetStaticMeshComponent()->ToggleVisibility();
const auto message = FString::Printf(TEXT("%s Authory %d Visibility (Before %d, After %d)"), *ActorItr->GetName(),
ActorItr->HasAuthority(), before, ActorItr->GetStaticMeshComponent()->GetVisibleFlag());
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, *message);
}
}
}
My understanding is that the reliable multicast would run on the server and all clients, but it seems I have done something wrong.
You're only calling ServerToggleSurgicalDrape not ServerToggle ?
In the code snippet above ToggleVisibility should not be an RPC
because otherwise, again, it gets called twice
assuming everything is setup properly
Fixed the name of the function in the sample. Calling Toggle() with a console command which should call ServerToggle.
Rather, which I would like to call ServerToggle that will run the implementation on all connected machines.
Maybe rather than showing what I have, I can describe what I would like, which seems like it should be simple. I would like a console command any connected machine can run that will call its associated function on every other connected machine.
You're also missing the _Implementation function declaration in the header
That isn't necessary. If it was, it wouldn't compile.
It doesn't get created by the generator? Looks like if I add it to the header it still compiles.
Including _Implementation declarations is optional (though I personally prefer to include it since it makes code generation less "magical").
Makes the code base more explicit rather than implicit, and that's always a good thing
I agree, it's just not a problem here.
That's interesting it compiles either way. There must be some macro magic to ensure that it doesn't create multiple declarations.
Or more likely the header tool just checks if it already exists and doesn't add it.
UHT generates declarations for these functions if you don't write them yourself.
Yep.
Right so if I wanted a command any machine could call such that a function runs equally on all machines, how would I do that? Not how I did it above, obviously ๐
okay
so
you have an RPC inside of gamemode
gamemode only exists on the server
( this is why it's important to show all the code )
Which means it cant run on any of the clients, which is why your code isnt working
Ah yup, that'll do it. So move all this to a manager class and I'm golden?
How do console commands work on the clients if they have no game mode instanced?
As long as the class is an actor that's replicated and has properly replciated to all clients you're golden
๐คท I don't use console commands
Probably for the best ๐
Childhood trauma from the vast majority of games not allowing me to use the console due to it falling on a dead key on my keyboard, and it not being remappable
Anyone had issues with an Array of structs not replicating?
Noop, should work fine
Presuming the struct is a USTRUCT() with it's own UPROPERTY members
Yeah they are
Is there some specific criteria I must meet when modifying values at struct index or individual struct members values?
not at all
I must have mangled something somewhere then
(moving everything to a manager class solved things, thanks @hollow eagle @verbal tendon )
whatever you changed, the engine will compare the next time it checks the actor for replication
and determine what to send
Hello what's the best practice to pick up items in a multiplayer ue4 game ? Because obviously if you create an RPC from an actor that is not owned by the RPC instigator ( and instigator is not the server), the RPC will be rejected so you cannot do things directly like this, so do I list all the items on the ground in the world and give a reference in my RPC from an other owned actor to retrieve the item ? what's best practice ?
Send RPC through an actor (or component) you do own with a ref to what you want to pickup/interact with
Meh ^^' I guess that's the way, I have to change where all the methods are ahem
Generally you design the system so you can use it for a variety of things of course
are there apis to get all actors in the world ?
how do I use that ref ?
how do I get it
This is the way.
๐
Shoot a ray out to see what it hits etc, lots of ways to do it
I'm already doing this, my question is
I can't send a *actor in a RPC
you can
It doesn't matter, the engine handles that internally
So long as the actor is either a) stably named or b) spawned on server and replicated, you can reference it over the network
Thank you I'll try
Or wait, can't I set the owner live ? when you interact on the object on the ground you become its owner and you can RPC afterward, but then you'll tell me, for it to work, I'd need an RPC to make the client owner, and then it comes back to the same issue ahem ?
You can set the owner but that has other problems
A) you can't have more than one owner, so how do you handle two players
B) Owner is replicated property and inherently latent, so there are responsiveness issues
yeah it comes back to the same, I can't change the owner from the item itself, if the interaction instigator is an unowning client
So in a MP environment the way you'd mitigate the latency
is by playing a pickup animation instantly locally on the client
Instead of waiting for the item to change ownership, or whatever you're doing you can already kickstart the visual process on the instigating client's end
But yeah generally, you have a general-purpose interaction system on either the controller/pawn, and that handles the networking and interaction
Items might have a component or interface that forms the "interactable" behaviour
I had this but this isn't multiplayer compatible to have an interact implementation on Items
So Now I'm just putting it on the controller, and having test instance and casting for the interactables I'm hitting
<@&213101288538374145>
whuw that was fast
or can we somehow do it ? not sure
with the ref ?
I am so ready to fight my array, I wonder if its because I have an array inside an array thats causing it not to replicate properly, hmm
I create an interact function on Items needing a controller ref, to find the pawn and inventories to interact with ?
Maybe, Unreal doesn't support collections of collections
Use a Struct instead I would assume
Array of structs with array of structs in
Was just an easy way to sort some stuff thats modular, but I can change it
Ahem actually I'm not sure this is not supported you should ask a pro ๐
Seems to be mangled, but I am pretty sure I have heard something similar before
As long as everything is defined and replicated properly that shouldn't be a problem
You cant expect the parent class to take care of it, each of your container element class needs to handle replication properly separately
Maybe one of your structs is not a UStruct and stuff
All the structs are marked properly, ustruct, body, uprops etc
and the top level array is marked for replication with doreplifetime, and the super is not missing either
Sure it is
Struct props don't need to be marked as replicated (they can't, in fact)
You cant add replicated in to struct props
sure ?
yep
Very sure
Its prob just an issue due to the depth of the arrays and such
I am just gonna create a better solution, its overdue anyway
omgg
I didnt know TMaps cant replicate
Gonna scream tonight ๐
Hence why I mentioned classes, not structs. Structs aren't made for that ๐
But also if you're going for that kind of nested replication, you gotta think that you maybe shouldn't ๐
Part of that is branching responsibilities out to appropriate manager classes, rather than packing everything into one place into nested data structures
Well I am actually just doing some digging right now out of curiosity
I made a TArray of structs with just a Int in
to see if it will replicate
oh fuck
I forgot to set the component to replicate
omfg
xD
lol
can UObjects even be replicated?
Yes
okay then maybe that's the reason, I'll try waiting for them to be replicated
Is fast array replication more efficient when replicating a large tarray once? Or do the benefits only come into play when changing values within the array and re-replicating?
So if I have the pointers as part of an array, how do I know when the pointers of the array are valid on the client ๐ค
I create the objects on the server, and I all replicate is the array of pointers
and I don't quite understand how to send those objects to the client
Check out this article by James, https://jambax.co.uk/replicating-uobjects/
If the server created an Actor that is not replicated, and server send RPC(Actor*) to client, client is gonna get null, iirc
@harsh lintel If you spawn actor (or object) and add it to a replicated array, it will replicate before the actor is spawned on client so it will be nullptr in the OnRep
You could use the OnRep to set a pending bool that is evaluated on the next PostNetReceive, just means it's behind by one rep cycle
Haven't had to deal with it myself so not sure if there's an easier/better way that's skipping my mind, actors could add themselves to the array
Hey, I need a second set of eyes on this, I feel like I'm taking crazy pills.
I have an Actor AI that is set to replicate. This actor has an Actor Component that is also set to replicate. Inside this Actor Component is a variable that is set to replicate. I call a run as server function inside the player controller to update the variable inside the AI Actor Component. The server sees this change, the client has no idea it happened. Does this sound like I'm doing something obviously incorrect?
I have also tried to update the variable as a multicast from the player controller, also does not seem to update the client. The actor itself seems to be replicating just fine, it's just this Actor Component that does not want to update across the network
How are you checking to see what the value is that the client sees?
@sinful tree The client was throwing a Null error so I added a repeating function in the AI that just prints the variable to console every two seconds. Both server and client print the variable, only the client always prints Null
What type of variable is it that you're setting?
It's a reference to a player controller
Are you hoping to see that player controller reference on a client other than the one that set it?
ie. Client 1 sets the value, Client 2 needs to see it?
Yea, I need a list of any controller that is interacting with this AI. So anyone who interacts with it gets added to an array. Only the array does not replicate across
So that won't work. Player Controllers only exist on the local client and on the server. Clients cannot get reference to other client's player controllers.
Best you can do is possibly playerstate or their controlled character.
Ahhh
It sounds like you're setting it correctly otherwise.
Okay, so if I were going to tackle this issue: Basically I'm syncing a widget state. It's a dialogue, so there's one leader, and the rest of the players are subscribers to the conversation. The leader sends his decisions to the subscriber controllers and their UI updates accordingly. Since I cannot use references to the player controller, what do you think the best way to tackle this would be?
If it needs to persist across characters (changing possessed characters or character destroyed etc) then playerstate, if it never needs to exist across characters then it can go on either, personally for something that has very little to do with the actual character's actions or movement I would put it on the playerstate even if you can use either, unless the dialogue changes between the actual character, note that AI don't get a playerstate by default (need to enable bWantsPlayerState for AI if you want them to have one)
@pseudo schooner Is this for stuff like SW:TOR dialog type stuff?
@grand kestrel I do lock the characters during conversation, and I have to move their camera around occasionally but I have an event system to handle most of that. I'll look to see if I can pop them in the player state, I'll have to look into getting AI access to it, thanks for the heads up.
Yes @kindred widget. It's very similar where one person leads the conversation and the others are along for the ride. But I'm adding something like Divinity where players can jump into an ongoing conversation
Btw, thank you @sinful tree
You don't have to put it in the playerstate, if it makes just a tiny bit more sense to go in the character then just put it there
@grand kestrel I was actually just thinking...would it be "wrong" to have a component in the AI that tracks the current dialogue and sends all the subscribed controllers updates? AI is on the server so it should have access to all controllers, and the conversations are disposable data. I can have the widget just send a message to the AI Component any time a selection is made instead of watching other players states for changes or jumping through multiple systems just to send a message
If I was going to write that into Unreal, I would personally do it through Playerstate. When a Dialog starts, spawn an actor server side and let it replicate. Set an array of "Users" as player's Playerstates. OnRep, if player is supposed to be in said dialog, then play the whole thing locally through a sequencer using a faked character(to avoid CMC issues, it'd be easier to clone characters and not full depossess current pawns). So the only thing that really needs replicated is that the player should start the dialogue, and each "Scene" that needs to be played, and then player's decisions if they're allowed to input them.
Hey very new to multiplayer and networking, and wondered if anyone could point me to some great resources on how to implement a secondary client-to-client co-op gamemode in a single player game, or if it would even be worth attempting that
You mean you made a single player game and you're trying to add co op?
yeah later down the line, it would be nice to add a fun little multiplayer mode to my game, and I was just wondering what resources would be good/what issues I may come across in trying to implement it as a peer to peer system through steam, cause I have no idea where to start
Well what I can tell you now is if you want your game to be co op you need to program it to be co op from start up to the very end. Do you have any multiplayer experience?
I do not
but the multiplayer portion would be using a completely different set of levels and actors, so I shouldn't have to replicate anything else surely?
It's less like a single player game where someone can join you, and more of a different mode, that is separated from the base game
If Im not mistaking Playing together means being in the same level. That's how it works in ue4 (I could be wrong)
Server and client can't be on two different maps
It does, but think of it like this
Single player has level 1, 2 and 3 and character 1
Multi player has level 4, 5, 6 and character 2
They would be on the same map just the single player content is separated form the multiplayer content
@kindred widget I'm a bit less advanced than you it seems but I will do some reading on this and see if I can implement it. Thanks for the suggestion! Also thanks @grand kestrel
That would work fine in theory. You just need to properly replicate what's going on in the playerstate of the character, and the gamemode
The server needs to know what's going on between both clients
ah I see the documentation only mentions client-server not client-client
is what im looking for not possible?
would I have to have at least 1 dedicated server
It's really just client server client
You can use dedicated or listen server
All you need to do is just tell the server for example important information like. "Client has finished level 1"
So that way the other player can know about it.
does the mean I could use the lobby host as the listen server for the other players
When launching a multiplayer game, there are two methods in which the game can be hosted. The first, is by using a Listen Server (default setting) which means that the machine that has the authority is also running a client and can play the game normally while hosting for other players.
This seems like what I'm looking for
Yeah that's fine you can use a listen server... you're still gonna have to do what I said. What are you expecting the difference to be exactly between listen server and dedicated server?
A dedicated server means I'm either going to have to show the player how to set one up, or I'm going to have to rent server space, whihc I don't want, a listen server, not entirely sure, but it appears it can just use the players game as the server host
thats what it seems like
now I could be totally wrong
but im also not sure if there would be any security issues of having the player be the host, aside from the ease of cheating
which im not worried about, but if a dedicated server system would be easier, I suppose server space for my game wouldnt be that expensive to rent
A listen server is when the player is also the server. Basically their computer is the server. Dedicated server is when there is no player, just a server and no client
yeah thought so
