For our character’s animation, I’m trying to write a generic server function to pass in relevant replicated bools, and switch them to true or false to feed the state machine but VC returns the build error: “Replicated bool parameters cannot be passed by non-const reference”. Do I really have to write a separate function for each variable change or is there a way around this?
I’m not a pro in code, so correct me if I’m wrong.
This doesn’t mean that your variable in const; it’s a const reference. You can still change the variable itself.
Another thing: if your bool variable is replicated, why do you need to send it through a server function? Isn’t it already supposed to have the same value on server and on client?
As far as I know, you can only change what you pass in, whether that’s a reference or otherwise. In theory, I suppose you could pass in a const pointer and dereference but unreal doesn’t like that either.
Replicated variables should only be changed on the server side hence the server call.
Oh, okay. Actually, I’m right at the point where I have to do the same thing: make a bunch of replicated bools and set them on server by the client for movement and animation purposes.
If I have any progress with that, I’ll come back with details. If you do, please update the thread =)
Will do man! Seems there’s no way round it but feel free to get in touch if you run into any obstacles. I’ve been debugging my way through it for a few weeks and things finally working so feel free to shoot any questions my way! Cheers
Hey, I’ve been trying to figure it out, but not too much progress so far.
The issue is, my character’s movement set is non-standard, with dashes and wall jumps etc., which is controlled by a bunch of booleans and a few delay timers, so simply replicating the variables doesn’t do much. I tried calling on the server side the same functions that are executed on client, but it breaks the character movement anyway.
As a workaround I came up with this: make character not replicated, create another actor that will represent the character on the server and on other clients, and call a server function to set its location (and at the same time transfer some bools to control animation);
On one hand, the character class doesn’t have to perform functions on the server side, which are redundant, but on the other hand I have to send a server command to set another actor’s location on Tick(), and I’m not sure if it’s a viable solution, even if I mark it as Unreliable (AFAIC, by default the replicated character movement is Unreliable too).
Ok so from what I can understand, it seems like your workaround could be overkill; you’ll end up duplicating a pretty massive object across your whole game, while essentially sending the same amount of packets between servers and clients. In essence, the logic is that you have to send a replicated variable to the server to be changed AND change it locally too. I think you could probably just do this using a if (HasAuthority()) {//change bool}; //local change bool; but we ended up just writing a small server function for each replicated bool and float that feeds into the anim state machine. All tested and working on server and client.
I’ll share one of our replicated movements that involve floats and bools in the hope it might help.
.cpp
void AMyCharacter::Server_SetHasStartedJump_Implementation(bool bValue)
{
bHasStartedJump = bValue;
}
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Set fall time
if (GetCharacterMovement()->IsFalling())
{
FallTime += DeltaTime;
}
else if (FallTime > 0)
{
// Reset fall time and reset jump attack bool after a delay
FallTime = 0;
if (bIsJumpAttack)
{
FTimerDelegate FlipBools;
FlipBools.BindLambda([this]()
{
Server_SetIsJumpAttack(false);
bIsJumpAttack = false;
GetWorldTimerManager().ClearTimer(Timer_JumpAttack);
});
GetWorld()->GetTimerManager().SetTimer(Timer_JumpAttack, FlipBools, 1.7f, false);
}
}
void AMyCharacter::OnPressedAttack()
{
if (!bIsAttacking && !bIsJumpAttack && !bBowEquipped)
{
if (GetMovementComponent()->IsFalling() && (b1hSwordEquipped || b2hSwordEquipped))
{
// can jump attack after falling for >= 0.5 secs
if (FallTime >= 0.5)
{
Server_SetIsJumpAttack(true);
bIsJumpAttack = true;
}
}
Note that with poor connection or low frames, this will invariably cause juttery movement for the client as the server has the final word on what the character is doing, but that’s a later problem.
Thanks, I’ll look into it!
As for my workaround: from what I could find in the documentation, the default frequency of character replication is 100 times a second, and I get that it would be lower with lower framerates.
As for
you’ll end up duplicating a pretty massive object across your whole game
I disable the main character replication completely, and what I send through a Server Function is one FVector and three or four Bools, which then replicate to all other clients. I can’t see how that’s heavier then using built-in character replication, which replicates the location 100 times a second plus a bunch of other stuff, I suppose. Correct me if I’m wrong.
And a simple example of non-standard movement set in my case. Let’s take Dash, for instance. When the character dashes, I need to calculate dash location, disable gravity, disable axis inputs, manually change MovementMode to Falling, decrease BrakingDecelerationFalling, and a bunch of other things, and run a timer that will change all those things back to normal when dashing is over. If I want to do all that with default character replication, I have to call the same function on the server side, because otherwise client and server movement are in conflict. And even when I tried calling all these functions on the server side, the client movement was jerky nonetheless.
So ultimately what I’m curious about is: wouldn’t it take less networking to replicate a simple actor than a character?
Options A: Character location is being replicated 100 times a second, and you also replicate all your custom bools and other variables, and call a bunch of server functions;
Option B: You only replicate location and a bunch of bools, without calling any functions and with no other stuff that’s going on in the Character class.
Re the object duplication, I wasn’t referring to the netwrok demands but the local demands. In the traditional case, you have one local character object that is duplicated to the server. In your case (again if I’ve understood correctly), you have two on the client side and one duplicate on the server. The additional object will be doubling calculations that your GPU and CPU will be performing and, depending on how complex your object is and how many instances exist in your world, will add a significant performance burden.
As for your character, I can only imagine the complexity comes from trying to get your dashes to look smooth. I can sympathise with that, and agree that it may increase the bandwidth excessively. The movement update is as frequent as it is for a reason; it minimises movement lag, which is necessary given how big a geographical distance (and thus ping difference) can exist between players so I’d be hesitatnt in changing that. Another thing to bear in mind is that anything important to gameplay (and fairness) runs from the server in order to avoid cheating. In your current state, hacking would be much easier as everything is executed on the client side and passed to the server so a player could easily transport himself across the map by manipulting clinet-side code. With all this in mind, I’d personally opt for sending your changes directly to the server as they mostly seem like tiny bool and float objects and so the extra bandwidth is a small price to pay to avoid the above issues.
Thank you! My project is pretty simple and the replicated actor will be quite simple too, and cheating is not someone will do there. I’ll try it out and see how mush lag will it cause, if any.
Thank you for your help!