- Home /
Change transform.forward while slerping rotations around the transform.forward axis
Pretty new to Unity and 3d game development, so I am probably not asking the question correctly, but here goes...
I am working on a space RTS game which uses UnitySteer (https://github.com/ricardojmendez/UnitySteer) to move units. In general it works pretty well and gives some really cool looking behavior. However, there is a deal breaking issue I am running into. Units, somewhat randomly, rotate around their forward axis/vector (not sure I am getting the terminology correct). That is to say the units are heading in the right direction in world space, and their engines and cockpits have the correct orientation, but they are spinning like a top around the axis that runs from engine to cockpit.
I have been digging through the source code and found this snippet that sets a unit's forward vector:
/// <summary>
/// Turns the vehicle towards his velocity vector. Previously called
/// LookTowardsVelocity.
/// </summary>
protected void AdjustOrientation(float deltaTime)
{
/*
* Avoid adjusting if we aren't applying any velocity. We also
* disregard very small velocities, to avoid jittery movement on
* rounding errors.
*/
if (DesiredSpeed > MinSpeedForTurning && Velocity != Vector3.zero)
{
var newForward = OrientationVelocity;
if (IsPlanar)
{
newForward.y = 0;
}
if (TurnTime > 0)
{
newForward = Vector3.Slerp(Transform.forward, newForward, deltaTime / TurnTime);
}
Transform.forward = newForward;
}
}
While I suspect there might be an issue with how the OrientationVelocity is set in code further upstream, I thought I would focus on the AdjustOrientation method for now.
What I would like to accomplish is to still get the units to correctly orient themselves, but drastically reduce the speed at which they rotate around their local forward vector. Ideally I would love an auto-level algorithm but that is probably outside the scope of this question.
I have taken a couple stabs at reducing the rotation speed, but it always affected their overall movement and not just the rotation along that one vector.
Answer by robertbu · Mar 23, 2014 at 08:36 PM
In context (i.e. playing with the app so you can see what what effect your changes are making), these problems usually can be figured out fairly quickly. Out of context with just a snipped of the code that may or may not be the real problem, getting to a solution is problematic. Note I don't believe the code 'as is' will not compile because it uses 'Transform' with an upper case 'T' rather than 'transform'.
As a shot in the dark, here is something for you to try. The 'Vector3.up' is the LookRotation() can be change for your situation. For example, you may want 'transform.up' instead.
protected void AdjustOrientation(float deltaTime)
{
/*
* Avoid adjusting if we aren't applying any velocity. We also
* disregard very small velocities, to avoid jittery movement on
* rounding errors.
*/
if (DesiredSpeed > MinSpeedForTurning && Velocity != Vector3.zero)
{
var newForward = OrientationVelocity;
if (IsPlanar)
{
newForward.y = 0;
}
Quaternion q = Quaternion.LookRotation (newForward, Vector3.up);
if (TurnTime > 0)
{
transform.rotation = Quaternion.Slerp(transform.rotation, q, deltaTime / TurnTime);
}
else {
transform.rotation = q;
}
}
}
}
Sadly this code does compile. I kind of wish it didn't. The class uses "Transform" to hold it's own transform. The commit comment says it was for performance, but I am not sure how it adds anything performance wise.
Anyway, your solution solved the problem. I was curious as to why though. Shouldn't using an up vector from the world space (if that is what is being done) always prevent the units from rotating around their forward vector? After adding your changes, they mostly stay aligned with the world space, but sometimes they will rotate a little bit around the forward vector.
The use of a variable named 'Transform' is a confusing practice. Using a variable to store the 'transform' and using that variable ins$$anonymous$$d of 'transform' is a good practice. When I do something like this:
Vector3 pos = transform.position;
...what's happening under the hood is:
Vector3 pos = GetComponent<Transform>().position;
By getting and storing the 'transform' in Start(), I avoid all the GetComponent() calls when I access the transform.
As for LookRotation(), it will attempt to use the provided 'up' as the axis of rotation, but it will use other rotations if it cannot get the job done using the provided 'up' vector. Note if you only want to rotate around the 'y' axis, the code above has the 'IsPlanar' variable for that purpose.
Your answer
Follow this Question
Related Questions
Make Gameobject Stand On Surface Facing Certain Direction 0 Answers
Car Front Tires rotation clamped between 270° - 90° 0 Answers
Rotate an object based on vectors. 1 Answer
Rotating wrong 0 Answers
Help with hold x,y,z rotation 1 Answer