Announcement

Collapse
No announcement yet.

Smooth way to spin pawn

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Smooth way to spin pawn

    I was wondering if there is a smooth way to spin a pawn (yaw for z axis). Right now I am using
    Code:
    AIOwner->GetPawn()->SetActorRotation(FRotator(0, deg++ * DeltaTime ,0));
    in the Tick function. The resulting spinning is ghostly and too zombie like (with lot of flickering and shaking). That for me is not so desirable.
    https://ravimohan.net/
    https://github.com/ravimohan1991

    #2
    Several ways to go about this. Sometimes I may want rotation to be interpolated with an ease in and ease out. For that I would use

    Code:
     const FRotator resultRotation = FMath::RInterpTo( CurrentRotation, TargetRotation, DeltaTime, RotSpeed );
     AIOwner->GetPawn()->SetActorRotation(resultRotation);
    There is a version that interpolates rotation at a constant speed, didn't test it yet but it would look very similar:
    Code:
    const FRotator resultRotation = FMath::RInterpConstantTo( CurrentRotation, TargetRotation, DeltaTime, RotSpeed );
    AIOwner->GetPawn()->SetActorRotation(resultRotation);
    In both these functions, CurrentRotation is as the name implies... your current rotation. TargetRotation is the final rotation you want to reach (Not the increment). DeltaTime would be passed from your Tick function. And RotSpeed is a scalar that multiplies the incremental rotation the function does.

    I havn't used this myself, but perhaps a more elegant solution to spinning an actor is by using the RotatingMovementComponent
    Simply add this component to your pawn and it should spin it automatically based on the speed and offset you provide.

    Also, can you try this and let me know if it does anything:

    Code:
    APawn* pawn = AIOwner->GetPawn();
    FQuat quat(pawn->GetActorUpVector(), FMath::DegreesToRadians(deg));
    pawn->AddActorLocalRotation(quat)
    I might be getting my quaternion logic wrong here, but the idea is to create a quaternion that rotates about an axis ( I chose the up vector of the actor to spin it about its yaw) with a given amount in radians. Add to your pawn's rotation every tick and see if that works.
    Last edited by herob4u; 07-08-2019, 09:22 AM.

    Comment


      #3
      This is a diamond mate. Worked like a charm! For quaternionic logic, Epic says
      // FRotator version. This could be a simple wrapper to the FQuat version, but in the case of no significant change in location or rotation (as FRotator),
      // we avoid passing through to the FQuat version because conversion can generate a false negative for the rotation equality comparison done using a strict tolerance.
      It seems almost the same for this purpose, but thanks for the knowledge.

      Oops forgot to mention which logic I used.
      Code:
          FRotator temp = AIOwner->GetPawn()->GetActorRotation();
      
          const FRotator resultRotation = FMath::RInterpTo( temp, temp + FRotator(0, 10, 0), DeltaTime, 2.0 );
          AIOwner->GetPawn()->SetActorRotation(resultRotation);
      Last edited by The-Cowboy; 07-08-2019, 07:06 PM.
      https://ravimohan.net/
      https://github.com/ravimohan1991

      Comment


        #4
        Ok another related question on the same note. What is the right way to spin the Controller along with the pawn such that even the viewpoint rotates (i.e if my Controller is possessing the pawn, I should see the world rotating). So far, I have tried (in the Tick)
        Code:
        ((AMAIController*) AIOwner)->FindDummy()->GetController()->SetControlRotation(resultRotation);
        where APawn Dummy is possessed by my Controller in the BeginPlay() event (I UnPossess() the default APawn and Possess() the Dummy during the event).
        Last edited by The-Cowboy; 07-08-2019, 09:13 PM.
        https://ravimohan.net/
        https://github.com/ravimohan1991

        Comment


          #5
          Originally posted by The-Cowboy View Post
          Ok another related question on the same note. What is the right way to spin the Controller along with the pawn such that even the viewpoint rotates (i.e if my Controller is possessing the pawn, I should see the world rotating). So far, I have tried (in the Tick)
          Code:
          ((AMAIController*) AIOwner)->FindDummy()->GetController()->SetControlRotation(resultRotation);
          where APawn Dummy is possessed by my Controller in the BeginPlay() event (I UnPossess() the default APawn and Possess() the Dummy during the event).
          From what I understand, that is exactly the job of the PlayerCameraManager. The way I do changes in perspectives is by changing the ViewTarget of the PlayerCameraManager. The ViewTarget is like the actor you are viewing the world through. So in reality, you do not even need to possess or unposses anything (unless that is intended).

          Since the camera is tied to the player, you would want to use your PlayerController. Once you have a reference to that, you can call either of the following:
          Code:
          APlayerController PC = // some code to get the player controller
          PC->SetViewTarget(SpinningPawn, FViewTargetTransitionParams())
          Which internally would call it through the associated PlayerCameraManager. Doing it manually would look like:

          Code:
          APlayerController PC = //some code to get the player controller
          PC->PlayerCameraManager->SetViewTarget(SpinningPawn, FViewTargetTransitionParams());
          FViewTargetTransitionParams is a very handy structure that allows you to specify settings on how the camera transition is performed - mainly the blend type and duration.

          Another cool tip to camera management is to understand how the camera picks its location based on the ViewTarget you set. It depends on the implemention of AActor::CalcCamera which you can override. Be default, it would try to look for a CameraComponent in the actor and use its position and properties for your camera manager. If no CameraComponent exists, then it will simply use the actor's location and rotation in the world. This means you can conveniently control where the camera will end up on that pawn in your blueprint editor by adding and repositioning a CameraComponent.

          Comment


            #6
            You are right, there is no need to possess the pawn atm. Just a reference to playercontroller's camera manager is enough. Actually I wanted playercontroller's control to override the default spinning (generated by AI logic) that is why I wanted to possess the pawn. But possessing the pawn stops its spinning (I will figure it out later).
            Thanks!
            https://ravimohan.net/
            https://github.com/ravimohan1991

            Comment


              #7
              Ok, I have been trying this but can't figure out the reason. When I spin the pawn now with yaw and pitch, the code
              Code:
              PC->SetViewTarget(SpinningPawn, FViewTargetTransitionParams())
              enables the camera to rotate the viewpoint only along yaw and not the pitch. I logged the rotations of the SpinningPawn which show the rotations along both yaw and pitch (so it wobbles) but camera viewpoint is not wobbling.
              https://ravimohan.net/
              https://github.com/ravimohan1991

              Comment


                #8
                Originally posted by The-Cowboy View Post
                Ok, I have been trying this but can't figure out the reason. When I spin the pawn now with yaw and pitch, the code
                Code:
                PC->SetViewTarget(SpinningPawn, FViewTargetTransitionParams())
                enables the camera to rotate the viewpoint only along yaw and not the pitch. I logged the rotations of the SpinningPawn which show the rotations along both yaw and pitch (so it wobbles) but camera viewpoint is not wobbling.
                Does the SpinningPawn use a SpringArmComponent to contain the CameraComponent? Is the pawn possessed?

                You could check to ensure the SpringArmComponent inherits pitch by setting that bool.
                Also check if there are any MaxViewPitch limit enforced in the PlayerCameraManager.
                Also check the pawn's inheritance flag, bUseControllerRotationPitch. If the pawn should drive the camera/controller view, then this should probably be disabled.

                Comment


                  #9
                  You could also use a Timeline. Set a callback which rotates the actor, and then in your Tick, call the timeline's TickTimeline method, which then fires your callback with what the current value should be. For something simple, just InterpTo works fine, but if you have complex curves or want things to happen at specific times along the animation, a Timeline would be a great tool to have access to.

                  https://docs.unrealengine.com/en-US/...ine/index.html

                  Comment


                    #10
                    Originally posted by herob4u View Post

                    Does the SpinningPawn use a SpringArmComponent to contain the CameraComponent?
                    No, it is independent and define as (in .h)
                    Code:
                        /** First person camera */
                        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
                        class UCameraComponent* FirstPersonCameraComponent;
                    and initialized as (in .cpp)
                    Code:
                        // Create a CameraComponent
                        FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
                        FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent());//SK_Mannequin, FName("head"));
                        FirstPersonCameraComponent->bUsePawnControlRotation = true;
                    Originally posted by herob4u View Post
                    Is the pawn possessed?
                    Yes, by AAIController.

                    Originally posted by herob4u View Post
                    Also check the pawn's inheritance flag, bUseControllerRotationPitch. If the pawn should drive the camera/controller view, then this should probably be disabled.
                    That is it. I thought I checked all the flags but this was set to false. Setting it to true did the trick. It looks little funny thought that the pawn is now having pitch (imagine a pole turning 90 degrees, along the axis perpendicular to its length direction) but that is expected since camera's targetview is pawn.

                    I tried setting target view as controller (which might be more desirable), bu I get some wired rendering on the camera screen.

                    Thanks!
                    https://ravimohan.net/
                    https://github.com/ravimohan1991

                    Comment


                      #11
                      Originally posted by nilamo View Post
                      You could also use a Timeline. Set a callback which rotates the actor, and then in your Tick, call the timeline's TickTimeline method, which then fires your callback with what the current value should be. For something simple, just InterpTo works fine, but if you have complex curves or want things to happen at specific times along the animation, a Timeline would be a great tool to have access to.

                      https://docs.unrealengine.com/en-US/...ine/index.html
                      Sounds interesting, I'll definitely try that.
                      https://ravimohan.net/
                      https://github.com/ravimohan1991

                      Comment

                      Working...
                      X