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



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.

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


 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:


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:


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.

This is a diamond mate. Worked like a charm! For quaternionic logic, Epic says

It seems almost the same for this purpose, but thanks for the knowledge.

Oops forgot to mention which logic I used.



    FRotator temp = AIOwner->GetPawn()->GetActorRotation();

    const FRotator resultRotation = FMath::RInterpTo( temp, temp + FRotator(0, 10, 0), DeltaTime, 2.0 );
    AIOwner->GetPawn()->SetActorRotation(resultRotation);


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)



((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:


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:


APlayerController PC = //some code to get the player controller
PC->PlayerCameraManager->SetViewTarget(SpinningPawn, FViewTargetTransitionParams());

FViewTargetTransitionParamsis 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::CalcCamerawhich 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.

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!

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



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.

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/API/Runtime/Engine/Components/FTimeline/index.html

No, it is independent and define as (in .h)



    /** First person camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* FirstPersonCameraComponent;


and initialized as (in .cpp)



    // Create a CameraComponent
    FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
    FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent());//SK_Mannequin, FName("head"));
    FirstPersonCameraComponent->bUsePawnControlRotation = true;


Yes, by AAIController.

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!

Sounds interesting, I’ll definitely try that.