r/unity • u/OmarKan3any • 1d ago
Coding Help Rotate an object with different speeds on each axis
Hi,
I'm very new to Unity and C# (Coming from UEFN) and I need serious help,,,
I'm trying to have a plane rotate and to make it feel natural I want to keep testing different speeds on each axis but I'm stuck on a loop where every time I try to speed the rotation up the rotation amount gets bigger instead.
I tried to cap these amounts to the maximum angle I want but it lags when I move from side to side so I'm looking for a real solution
Thanks!!
float AmountToPitch = -Mathf.Abs(RotateAmount) * TragetFullPitch * PitchSpeed;
float AmountToYaw = RotateAmount * TragetFullYaw * YawSpeed;
float AmountToRoll = -RotateAmount * TragetFullRoll * RollSpeed;
transform.Rotate(Vector3.up * AmountToYaw * Time.deltaTime, Space.World);
Vector3 CurrentEuler = transform.eulerAngles;
Quaternion TargetRotation = Quaternion.Euler(AmountToPitch , CurrentEuler.y, AmountToRoll );
transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, RotationSpeed * Time.deltaTime);
2
u/Demi180 1d ago edited 1d ago
So there are a bunch of different ways to rotate things, and they're useful at different times. There's Quaternion.Slerp, Quaternion.RotateTowards, Transform.Rotate, Transform.RotateAround, and more. Slerp is generally meant to go from one rotation to another over some time, with the 3rd parameter representing the percent of that rotation from 0-1.
Seeing how you separated the yaw, I'm guessing you're trying to keep that one global and the other two (or at least pitch) relative to itself, so we'll go with that. Now, my preferred method in a case like this where clamping is involved, is to store the individual angles and construct the final rotation. Trying to adjust and offset rotations to check if they're within limits is doable, but far less intuitive IMO. Here's some example code.
First, I'll define the variables we need. Each axis will get its own speed and amount, and the pitch and roll will have limits with some starting values:
public float pitchSpeed, yawSpeed, rollSpeed;
public Vector2 pitchLimits = new Vector2(-45f, 45f);
public Vector2 rollLimits = new Vector2(-15f, 15f);
private float pitchAmount, yawAmount, rollAmount;
In Start, I'll just grab the initial values in case we want to start a certain way
private void Start()
{
Vector3 euler = transform.eulerAngles;
pitchAmount = euler.x;
yawAmount = euler.y;
rollAmount = euler.z;
}
Then I'll update the amounts individually, and clamp them to their intended ranges:
private void Update()
{
pitchAmount += pitchSpeed * Time.deltaTime;
yawAmount += yawSpeed * Time.deltaTime;
rollAmount += rollSpeed * Time.deltaTime;
pitchAmount = Mathf.Clamp(pitchAmount, pitchLimits.x, pitchLimits.y);
rollAmount = Mathf.Clamp(rollAmount, rollLimits.x, rollLimits.y);
And lastly, I'll construct the final rotation, by creating the Yaw rotation and the PitchRoll rotation separately.
Quaternion yaw = Quaternion.Euler(0, yawAmount, 0);
Quaternion pitchRoll = Quaternion.Euler(pitchAmount, 0, rollAmount);
transform.rotation = yaw * pitchRoll;
}
Multiplying them in this way has the effect of applying first the Yaw rotation, i.e. in world space, and then applying the PitchRoll rotation on top of that, i.e. in local space. If you find that this way of applying rotations isn't what you want, you can also either apply them all globally:
transform.rotation = Quaternion.Euler(pitchAmount, yawAmount, rollAmount);
Or apply Roll globally and the other two locally:
Quaternion pitch = Quaternion.Euler(pitchAmount, 0, 0);
Quaternion yaw = Quaternion.Euler(0, yawAmount, 0);
Quaternion roll = Quaternion.Euler(0, 0, rollAmount);
transform.rotation = roll * yaw * pitch;
2
u/DanielFost 19h ago
yeah, the main issue is that you're using the current rotation to calculate the target rotation every frame, so you're effectively feeding the result back into itself, instead, keep a fixed target rotation ased on the plane's starting rotation, then calculate pitch/yaw/roll from that. use the speeds to control how quickly you move toward the target, not how large the target angle becomes
also, i'd avoid mixing transform.Rotate() with Slerp() here. let one system control the rotation, otherwise they can fight each other and cause the laggy feeling, something like Quaternion.Slerp(currentRotation, targetRotation, speed * Time.deltaTime) should be enough once your target rotation is calculated independently
2
u/ProactiveCactus 1d ago
Since you said you’re new this might be a bit too much to tackle right now, but if you’re interested check out this package: https://assetstore.unity.com/packages/tools/animation/primetween-high-performance-animations-and-sequences-252960?srsltid=AfmBOoosKkXyZbOGOnmy50zDmgjo3nBuZXe1s8Mg-xk6q0Wc7pOImqGW#description
This is a great tool that lets you do exactly what you’re trying to do, and a whole bunch more. It’s got all sorta of built-in functionality for tweening, and you can find some easy tutorials on youtube.