In my game, Im always rotating a gameobject (Cube) with Quaternion.Lerp. And I need which face of this cube is looking up. So I think I can use current rotation of object to get this (if there is a better way please say it).
Firstly this gameobject's rotation (0,0,0). when I rotate it forward it becomes (90,0,0). There is no problem. But after that, when I rotate it second time it doesnt become (180,0,0). it is (0,180,180). How can I prevent unity to do this.
Try using euler angles instead of quaternions, they are much simpler, here is an example:
transform.eulerAngles = new Vector3(180, 0, 0);
There are multiple ways of representing a rotation with Euler angles. When you convert the rotation of your GameObject (stored internally as a quaternion) to Euler angles (using either transform.eulerAngles or transform.rotation.eulerAngles) you may not get the result you're expecting.
You could get around this by storing a Vector3 (let's call it currentRotation) containing the rotation of your object in Euler angles, and construct Quaternions from it using Quaternion.Euler(currentRotation). You can do your interpolation by calculating your target rotation (targetRotation) as a Vector3, then constructing a Quaternion for it before doing Quaternion.Lerp:
var targetRotationQuaternion = Quaternion.Euler(targetRotation);
var currentRotationQuaternion = Quaternion.Euler(currentRotation);
transform.rotation = Quaternion.Lerp(currentRotationQuaternion, targetRotationQuaternion, *your t*);
Incidentally, this answer is very similar to a comment on http://answers.unity3d.com/questions/667037/transformrotationeulerangles-not-accuarate.html but it's worth reproducing here in case that ever gets taken down.
Related
is there a way to apply a rotation for any arbitrarily orientation (Object A's rotation relative to Object B's local orientation)
I know I can simply get desired result if i do setParent thing, but i want to get without it
In my situation, my character holds water bottle and moves around the room holding it so I set its rotation like this
transform.rotation = mainCamera.transform.rotation;
but As bottle top pointing to the sky seems more natural, I want it to rotate 90 degree by its own X-axis
I tried below codes but it dosent work as i intended
`originalRotation = transform.rotation;
Quaternion rotationDelta = Quaternion.FromToRotation(Vector3.forward, mainCamera.transform.forward);
transform.rotation = rotationDelta * originalRotation;`
Yes, Like i said above if i make my character parent to the bottle will solve the issue, but i want to
do it without it.
Thank you
Try this one:
transform.forward = mainCamera.transform.up;
I'm trying to make a pick up objects mechanic like the one in Amnesia. It's easy to calculate needed rigidbody's velocity, so that the held object stays in front of camera, but my problem is that the object doesn't rotate at all when I hold it. And I would rather have it always be rotated towards the camera. This could easily be achieved with simply parenting the object to player's camera, but...
The behaviour I'm after is as follows: if the bottle I picked up was standing on a table, with neck of the bottle facing ceiling, I would like to see this bottle always with its neck facing ceiling while I hold it. But if this bottle collides with something, it should behave like it actually bumped onto something, so it should rotate some small amount, but it should always try to return to its "original" rotation (in this case, neck facing ceiling).
I think that I need to calculate angular velocity for that and probably have some lerp to return to original rotation, but I'm at a loss on how to do that properly.
I think that the first thing I would need to do is to store the initial direction the moment player picks object up:
Vector3 targetDirection = playerCamera.transform.position - transform.position;
Script is on the held object, so "transform" refers to it. In FixedUpdate() I probably need to have some interpolation, so that angular velocity always tries to rotate the object to original rotation:
rigidbody.angularVelocity = Vector3.Lerp(rigidbody.angularVelocity, targetAngularVelocity, lerpSpeed * Time.fixedDeltaTime);
I don't know how to calculate targetAngularVelocity, because after all I would like the held object to return to original rotation smoothly. I'm not even sure if that's the right way to do this thing and perhaps I should do something else than to calculate angular velocity needed to rotate object properly. I tried just interpolating localRotation to original local rotation, but that did not allow the held object to bump on stuff (the movement then was very jittery). Any ideas?
You need a stabilizer. A script which will add torque/angular velocity to the object, whose angle is different from the target one. Say, you have two variables: targetDirection and currentDirection aka transform.forward. Then you write something like this in fixed update:
var rotation = Quaternion.FromToRotation(currentDirection, targetDirection).eulerAngles * sensitivity;
rigidbody.angularVelocity = rotation;
I recommend to set sensitivity about 0.05 and then increase it if the object stabilizes too slow.
Probably I confused the order, so you should put minus somewhere, but the approach itself is applicable.
Goal:
Calculate a rotation, that can be used, to correct the Transform of the bones, so they get rotated as expected when manually rotated.
In Detial:
Character's bone Transform is not imported to Unity correctily, ie. the left hand's Z axis does not looks towards the top of the hand, but backwards, while the right hand's Z axis looks forward.
The bones default rotation is not the same as you would expect if you have seen the rig in another application before.
I had the idea to create a class, that puts the character in T-Pose, then maps the bones rotation.
(I would assume that Unity does something similiar under the hood, that's how I got the idea.)
So the class would be used with an API like this:
/// This should return the rotation, where the bone pointing forward rotated by rotation.
/// Ie. when rotation = Quaternion.Identity the left hand should look forward.
Quaternion CorrectRotation(HumanBodyBones bone, Quaternion rotation)
{
return Quaternion.Inverse(tPoseRotations[bone]) * rotation;
}
The problem is, that I can't seem to find a good way to map theese rotations.
My last attempt was this:
Vector3 boneDirection = (boneTransform.position - parentTransform.position).normalized;
Quaternion mappedRotation = Quaternion.LookRotation(boneDirection, parentTransform.up);
As you can see in this image, with this method the hands look in the same direction, forward, but still not rotated correctly, they have an offset from the desired result. (The correct rotation is shown by the purple hands.)
When given other rotations, the hands follow with the same offset, so other then this unwanted offset they work correctly.
So basically, I would appriciate any help to fix my problem, either this way, or with a different solution, that works with different rigs.
The chest bone of my player can be rotated while aiming.
Now I wanted to evaluate how much (minimum and maximum rotation) I should let the chest be rotatable.
To do that, I allowed all degrees of rotation and took a look at the Inspector.
For example, the minimum value that the chest should be rotatable to the left should be Y=-15.
At Y=-15 (seen in the Inspector), it still looked natural.
Now I wanted to code this.
To my surprise, chest.localRotation.Y was a completely different value than what the Inspector is showing.
I have then taken a look at the chest variable and extended the view.
I just can't see the rotation value that the Inspector is showing.
How should I go on in this case, please?
I'm using this to rotate the bone:
Chest.LookAt(ChestLookTarget.position);
Chest.rotation = Chest.rotation * Quaternion.Euler(Offset);
Thank you!
The reason why it doesn't work:
Quaternion is not a human readable value.
One Quaternion is allways unique but can have multiple (infinite?) different representations in Euler space! The other way round one Euler represents allways exactly one Quaternion value.
If you look at the docs it explicitly says
Don't modify this directly unless you know quaternions inside out.
Than as said what you see in the inspector is the localRotation in relation to the parent Transform.
Better said it is one of the many possible Euler inputs that result in the Quaternion. What you see in the debug at localEulerAngles is another possible Euler representation. Unity usually in localEulerAngles also gives you only values > 0.
It seems that the chest anyway will only rotate around the Y axis, right?
If this is the case you can simply get the Angle between the chest's original forward vector and the target. It is way easier to handle Vector3 values than Quaternions ;)
It seems to be the same use case as in this post
// get the target direction
Vector3 targetDir = ChestLookTarget.position - Chest.position;
// Reset any difference in the Y axis
// since it would change the angle as well if there was a difference I the height
// between the two objects
targetDir.y = 0;
// however you currently rotate
// instead rotate only the Vector3 variable without applying it to the transform yet
Vector3 newDir = Vector3.RotateTowards(Chest.forward, targetDir, RotationSpeed * Time.deltaTime, 0.0f);
// Compare the target direction to the parents forward vector
float newAngle = Vector3.Angle(Chest.parent.transform.forward, newDir);
if (newAngle > MaxRotationAngle)
{
// What should happen if angle gets bigger?
return;
}
// If angle still okey set the new direction
Chest.rotation = Quaternion.LookRotation(newDir);
I am working with Unity 5 and making the logic of some NPC characters that will walk through a plane randomly and with animations. When the characters reaches the destination, a new target is generated after 3 seconds. The animator works fine and so does the pathfinding. Now I want the model to face forward the correct direction.
I am having a weird issue were the model does not seem to follow any conventional relation. First, it works almost fine, since the rotation is almost the one expected. The second path is deviated and after the third one is almost backwards. Is like if somehow the model were calculating the rotation related to something I have no clue.
This is part of the code I am using:
Vector3 look = targetPosition - transform.position;
Quaternion targetRotation = Quaternion.LookRotation(look.normalized,Vector3.up);
Quaternion newRotation = Quaternion.Lerp(transform.rotation, targetRotation, turnSmoothing * Time.deltaTime);
rb.MoveRotation(newRotation);
I have also tried setting the transform Euler angles, and this code:
float turnAngle = Mathf.Atan2( look.z, look.x ) * Mathf.Rad2Deg;
float smoothAngle = Mathf.LerpAngle( transform.eulerAngles.y, -turnAngle, rb.velocity.magnitude * Time.deltaTime );
rb.MoveRotation( Quaternion.Euler( 0, smoothAngle, transform.eulerAngles.z ));
Always the same result. Am I missing something? I have read about the root motion in the animator but I have disabled animations and the patter persists. Also, the model seems to have the correct Z direction set. Its driving me nuts!!
Any input is appreciated.
First of all, i want to say that you should be using Quaternion.Slerp for rotation interpolations. Lerp is a more linear interpolation wheras Slerp will make rotations seem more natural. Although i do not believe this to be the issue here.
I don't ever really use Quaternion functions, so to me your code looks fine. I can however suggest to maybe try an approach using Vector3.RotateTowards or even transform.Rotate, they should be able to get you what you are trying to accomplish here.
EDIT: I just noticed you are using rigidBody.MoveRotation after your custom Lerp interpolation. Unity API states:
Use Rigidbody.MoveRotation to rotate a Rigidbody, complying with the
Rigidbody's interpolation setting.
So, RigidBody already has its own interpolation it will try to do against your custom interpolation. The issue may lie there, because you are not setting the rotation explicitly. Try just inserting your target direction into MoveRotation and rigidbody will try and get you there. It is not an immediate rotation.
Check that your look vector is not near zero length. If you feel a root animation overwrites your rotation use simple cubes instead of NPC characters. To debug your look direction use targetRotation instead of newRotation. You can render debug lines to visualize the line NPC to target. Good luck.
I have not enough reputation points to write this as comment.