Rotating a component of an actor

Hey guys,

I’m trying to rotate a widget component which is a child object of an actor.

The widget should act like a billboard which always faces the camera.
I’m failing at the math for the rotation of the object.

How would I calculate the Rotator to rotate the widget accordingly ?

Thanks in advance.

Cheers Edregol

Hello Edregol,

First question, what type of camera you have ? first, third person ?..

Second question, where do you calculate you camera? is it a cameraActor? cameraComponent?, calcCamera on pawn? on PlayerController? a custom PlayerCameraManager?

With these infos, i’ll be able to help you

gamer08

Hello Edregol, thanks for these infos.

If you are using the third person template and you didn’t change anything related to the camera, the camera rotation follow your controller rotation. So when you move the mouse that change the controller rotation and so the camera one.

What you can do, is to use getControllerRotation() to get what you need and update your component / object rotation with that.

Do you follow me?

I could make an example for you if you want (could you give more details of what you want exactly).

If you need anything just tell me, always glad to help.

gamer08

Hey there, thanks for your fast response.

I am using a third person camera on a camera boom which are both components of my character. So I am using a UCameraComponent.

The camera and character setups are right out of the third person example so as far as I know the camera is handled on the PlayerController.

Thanks for the advice,
I’ve accomplished what I wanted to do. However its kinda hacky. I have to clamp the pitch and roll values manually otherwise the rotation is all over the place. Any ideas why?
This code gets called within the object which contains the widget component. It maintains a pointer to the camera object from the character.

FVector directionVector = ActorToWorld().GetLocation() - Cam->ComponentToWorld.GetLocation();

FRotator PlayerRot = FRotationMatrix::MakeFromZ(directionVector).Rotator();
PlayerRot.Pitch = 0;
PlayerRot.Roll = 90;
NameplateWidget->SetWorldRotation(PlayerRot);

Hello again,

First off, from what you said, you made a rotation from z, so it only take into account one axis instead on 3.

Also just a reminder in case of in Unreal Engine system the rotation follow these rules

Yaw is the rotation around Z (UP/Down)

Pitch is the rotation around Y (Right /Left)

Roll is the rotation around X (Front/Back)

Also in your case, you could use the controller rotation and use the Yaw and/or Pitch if you want your object to face the camera.

May I ask, why you use this FRotationMatrix::MakeFromZ to calculate your player rot ? it seems not usefull for me.

If you want your object always facing the camera and the by default (0,0,0) the object start facing the camera you just need to apply Camera Yaw /Pitch to your object.

To answer your other question, you need to manually clamp the Pitch and Roll because you construct a matrix rotation from the Z axis of your direction, After that you extract a rotation. It’s why it gives you strange result.

If you need help, more infos or an example, don’t hesitate.

gamer08

Hi there,

actually I have no idea what I am doing. xD I am searching for solutions to my problem and take what seams to fit.

However, I did not take the controller rotation since I may want to change the camera perspective later on. Therefore I can not rely on the controller rotation.

In addition, I figured It is enough to rotate the widget around the Z axis for now.

How could the code above be optimized to actually work as a billboard? Taking into account that a camera object and the object itself is given to calculate stuff?

Hello Edregol, if I was you, I would keep simple as posible.

Your goal is to make your board always facing the camera right?

Ok so let’s do it :slight_smile:

First off, we will assume that your object start facing the camera at the beginning of the game (start with camera rotation (Yaw, Pitch, Roll).

Also, I will assume your object is always in camera view. (Your camera can always see your board).

Finally, I’ll suppose your object is at a relative position from the player or it’s in a menu ?

Just tell if I’m wrong with something.

Now that’s the tricky part, because it will depend ont the camera behavior you want ( Classical third person, shoulder camera, custom view etc…).

You also need to decide, if you want your board to always be at same distance from camera and/or player.

In my example, I will take a classical third person view the object follow the player at a relative position.

//Character Position
characterPosition = character->GetActorLocation();

//New object's rotation.
FRotator newRotation (CameraRotation.Pitch, CameraRotation.Yaw, 0.f)

//Construct a matrix rotation for calculate new object's position
FRotationMatrix cameraRotation(newRotation);

//realtivePosition is the board position relative to the player.
FVector finalPosition = characterPosition + cameraRotation.TransformPosition(relativePosition);

ObjectRotation = newRotation; 
ObjectPosition = finalPosition;

Is that help you?

If not you can give more details about the behavior you want and I’ll adapt my example.

Also, if you have any questions/problems, I’m here.

gamer08

Hi there,

thank you again, for your help.

I don’t need to transform the position of the widget since its location is set by the actor to which it is bound to.

So I just need to get the rotation right.

What I did now is the following:

FRotator PlayerRot(0.f, Cam->GetComponentRotation().Yaw + 90.f, Cam->GetComponentRotation().Roll + 90.f);

I’m only interested in controlling the yaw and roll of the object. the pitch should stay as it is.

However I need to add 90 degrees to both of them in order to get the rotation right.

Well, the 90 degrees which have to be added to the roll can be explained since the widget has been rotated by 90 degrees on the x to stand upright.

However, I don’t get why I have to add 90 degrees to the yaw.

54021-pickupwidget.png

The camera pitch value seems the be off as well. If I do the following the widget is completely off.

FRotator PlayerRot(Cam->GetComponentRotation().Pitch, Cam->GetComponentRotation().Yaw + 90.f, Cam->GetComponentRotation().Roll + 90.f);

I did not touch the camera at all. Can anyone explain why the camera rotation values are off?

Well the initial rotation on the x axis (roll) is 90. That explains that. However the rest is set to 0.

54023-widgettransforms.png

FRotator PlayerRot(Cam->GetComponentRotation().Roll, Cam->GetComponentRotation().Yaw+90, Cam->GetComponentRotation().Pitch+90);

I guess the Rotator or the setRelativRotation Method of the WidgetComponent is broken if I swap the Pitch an Roll values everything works as expected, odd.

I’ll have a look at my camera configuration.

Hello again and thanks for these precisions !

What your object default rotation at start ? and What it looks on screen at start? I mean because it seem you always need to add 90 deg so.

Test it without moving the camera at start.

I mean you take the camera rotation, so that should do it for what you need.

Maybe your object’s initial rotation need to be adjust.

gamer08

And if you test at the beginning of the game without moving the camera, what’s the result on screen ?

Technically by default, you do not control the camera Roll with the mouse. You only control Yaw and pitch. So, I suppose you change something in the controls and functions to update the roll. Did you change the rest accordingly ?

Also check your camera default’s rotation at start if everything is allright.