x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Replicating Actor Rotation

I'm trying to replicate my actor rotation to all other clients which are connected in a multiplayer game. So far I've already achieved the implementation of a boolean called bIsAiming, following this awesome tutorial: https://wiki.unrealengine.com/Survival_Sample_Game:_Section_5#Making_the_player_sprint.

However I tried to get the replication of the rotation working in the same manner but keep stumbling across the problem that the rotation is only set on the calling client + the server. This means the server fails to tell all other clients to update the rotation of said actor accordingly. I'm a bit puzzled at the moment. I already tried to replicate an FRotator and SetActorRotation in the EveryTick method but this wasn't successful either.

Here is my code example, perhaps someone can point me in the right direction :-)

BaseCharacter.h

     // gets the rotation needed to aim at the crosshair
     FRotator getRotationToCrosshair();
 
     // rotates the actor
     void SetRotation(FRotator rot);
 
     UFUNCTION(Server, Reliable, WithValidation)
     void ServerSetRotation(FRotator rot);
 
     void ServerSetRotation_Implementation(FRotator rot);
 
     bool ServerSetRotation_Validate(FRotator rot);

BaseCharacter.cpp

 FRotator ABaseCharacter::getRotationToCrosshair()
 {
     //set Rotation towards crosshair
     FRotator camYawn = FRotator(0, FollowCamera->GetComponentRotation().Yaw, 0);
     FRotator charYawn = FRotator(0, GetControlRotation().Yaw, 0);
     FRotator charRotation = FMath::RInterpTo(camYawn, charYawn, 400, 0.1);
     return charRotation;
 }
 
 void ABaseCharacter::SetRotation(FRotator rot)
 {
     
     SetActorRotation(rot);
 
     if (Role < ROLE_Authority)
     {
         ServerSetRotation(rot);
     }
 }


 //////////////////////////////////////////////////////
 // REPLICATION
 /////////////////////////////////////////////////////
 
 void ABaseCharacter::ServerSetRotation_Implementation(FRotator rot)
 {
     SetRotation(rot);
 }
 
 bool ABaseCharacter::ServerSetRotation_Validate(FRotator rot)
 {
     return true;
 }
 
 void ABaseCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
 {
     Super::GetLifetimeReplicatedProps(OutLifetimeProps);
 
     // Value is already updated locally, skip in replication step
     DOREPLIFETIME_CONDITION(ABaseCharacter, bIsAiming, COND_SkipOwner);
     //DOREPLIFETIME_CONDITION(ABaseCharacter, rotation, COND_SkipOwner);



the setRotation method is called here in the .cpp

 void ABaseCharacter::Tick( float DeltaTime )
 {
     Super::Tick( DeltaTime );
 
     if (IsAiming())
     {
         ZoomIn();
     }
     else
     {
         ZoomOut();
     }
 }
 
 void ABaseCharacter::ZoomIn()
 {
     //to-do: toggle crosshair
 
     if (!bIsSprinting && GetCharacterMovement()->IsMovingOnGround())
     {
         if (!bIsZooming)
         {
             //switch to over the shoulder view
             FollowCamera->SetWorldLocation(ShoulderCameraPosition->GetComponentLocation(), true);
         }
 
         bIsZooming = true;
 
         SetRotation(getRotationToCrosshair());
     }
 }
 



Thanks in advance!

~Theo

P.S: Is it possible that the characterMovementComponent already handels the replication of the bIsCrouched and if a character is in the air? I didn't need to implement methods for jumping and crouching as they were perfectly working in a multiplayer setup.

Product Version: UE 4.8
Tags:
more ▼

asked Aug 20 '15 at 01:19 PM in C++ Programming

avatar image

Theololz
98 12 15 22

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

This should get you started. I typed this all off of the top of my head so it's likely a made a mistake somewhere. Let me know if you have any more problems/questions.

.h:

 UPROPERTY(ReplicatedUsing = OnRep_OwnerRotation)
 FRotator OwnerRotation;

 UFUNCTION()
 void OnRep_OwnerRotation();

 UFUNCTION(Server, Unreliable, WithValidation)
 void Server_ReportOwnerRotation(const FRotator& NewRotation);

.cpp:

 void ABaseCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
 {
     Super::GetLifetimeReplicatedProps(OutLifetimeProps);

     // Value is already updated locally, skip in replication step
     DOREPLIFETIME_CONDITION(ABaseCharacter, bIsAiming, COND_SkipOwner);
     DOREPLIFETIME_CONDITION(ABaseCharacter, OwnerRotation, COND_SkipOwner);    
 }

 void ABaseCharacter::SetRotation(FRotator rot)
 {
     OwnerRotation = rot;
     OnRep_OwnerRotation();

     if (!HasAuthority() && IsLocallyControlled())
     {
         Server_ReportClientRotation(rot);
     }
 }

 bool ABaseCharacter::Server_ReportClientRotationovement_Validate(const FRotator& NewRotation)
 {
     // reject implausible rotations by returning false
     return true;
 }
 void ABaseCharacter::Server_ReportClientRotation_Implementation(const FRotator& NewRotation)
 {
     // can also perform other validation here as well (e.g. prevent remote client from doing something obviously impossible), since this runs on server
     OwnerRotation = NewRotation;
     OnRep_OwnerRotation();
 }

 void ABaseCharacter::OnRep_OwnerRotation()
 {
     // if you want to interpolate/smoothly animate on remote clients, comment this out
     SetActorRotation(OwnerRotation);
 }

bonus points: non-owner instances of the game could interpolate to smooth out the animation (note that RInterpTo is not frame-rate independent. you would want to use a fixed time-step function plus interpolation or extrapolation to get perfect frame-rate independence, but this example should be good enough to get you started)

 void ABaseCharacter::Tick(float DeltaTime)
 {
     ...

     if (!IsLocallyControlled())
     {
         SetActorRotation(FMath::RInterpTo(GetActorRotation(), OwnerRotation, DeltaTime, 0.5f));
     }

     ...
 }
more ▼

answered Aug 20 '15 at 02:40 PM

avatar image

cancel
2.4k 101 72 124

avatar image Theololz Aug 21 '15 at 09:21 AM

Hey,

Thank you very much for answering! I still do have some questions and problems. First of all what exactly does

 UPROPERTY(ReplicatedUsing = OnRep_OwnerRotation)

I was just aware of using

 UPROPERTY(Transient, Replicated)

Do I understand the chain of events right, when I say that:

  1. Client calls “setRotation”.

  2. Client is not the server therefor tells the server to handle this problem

  3. The server executes the function: sets the rotation, and then tells every client to call “onRep_OwnerRotation()”?

Where does the server tell all the other clients that ClientXYZ is now looking in the direction A? Isn’t there the reference to this specific actor missing? Something like this: http://puu.sh/jJ7yg/5d87695742.jpg ?

My Problem is that this code obviously compiles but it’s not achieving the desired effect, unfortunately. It’s still the case that, when Client_1 rotates, he rotates locally (by calling “onRep_OwnerRotation()”), then tells the server about its change in rotation. The server does display the rotation movement of Client_1 correctly but Client_2 does not see any change in motion.

pic: http://puu.sh/jJ8gw/4ea097d432.jpg

Sorry for any inconvenience

~Theo

avatar image Theololz Aug 23 '15 at 11:19 AM

It’s still the case that, when Client_1 rotates, he rotates locally (by calling “onRep_OwnerRotation()”), then tells the server about its change in rotation. The server does display the rotation movement of Client_1 correctly but Client_2 does not see any change in motion.

I've just checked: The Client_2 has set the OwnerRotation to (0,0,0) which obviously means it doesn't get updated on this client.

Any further help? :)

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Update:

Okay I got it working and Cancel was absolutely right (marking your answer as the solution now).

There is just one slight adjustment which has to be made in order for it to work properly:

 void ABaseCharacter::SetRotation(FRotator rot)
 {
     OwnerRotation = rot;
 
     if (!HasAuthority() && IsLocallyControlled())
     {
         Server_ReportOwnerRotation(rot);
         OnRep_OwnerRotation();
     }
 }

Do not call OnRep_OwnerRotation() or SetActorLocation before this if statement. Otherwise it will f*** everything up :D

Thank you very much canel!

more ▼

answered Aug 23 '15 at 01:43 PM

avatar image

Theololz
98 12 15 22

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question