Rotation does not match when converting vector and quaternion on Unity - unity3d

Please tell me the reason why the rotations of A and B do not match in the following code.
// Initial pose
transform.forward = (new Vector3(0f, 0f, 1f)).normalized;
// Rotate
transform.forward = (new Vector3(1f, 1f, 0f)).normalized; // A
// convert quaternion
Vector3 fwd = transform.forward;
Quaternion rot = Quaternion.FromToRotation(new Vector3(0f, 0f, 1f), fwd);
transform.rotation = rot; // B
And how do match A/B rotations?

Offical documentation for FromToRotation states
Usually you use this to rotate a transform so that one of its axes eg. the y-axis - follows a target direction toDirection in world space.
And here
transform.forward = (new Vector3(1f, 1f, 0f)).normalized;
we just assign the forward axis of transform to look diagnolly in X and Y.
Now
Quaternion rot = Quaternion.FromToRotation(new Vector3(0f, 0f, 1f), fwd);
This line will just create a rotation based on whatever side of Transform faces worlds forward and align it to the fwd. Well I know its parameters says FromDirection ToDirection but it is a bit ambiguous. It should have stated FromAxis ToDirection
Hence A not equals B

Related

How to convert from direction and rotation around y-axis to Quaternion in Unity

How to convert from direction and rotation around y-axis to Quaternion in Unity.
I want to rotate the object that is up-wards.
The object rotate certain direction and then rotate around an axis (object's local up-wards).
I implemented it as follows, and pressed the A button and the B button.
However, obj (button B) sometimes becomes a different quaternion (button A).
Why is this? Is there a solution?
if (Input.GetKeyUp(KeyCode.A)){
obj.transform.rotation = Quaternion.EulerAngles((float)Random.Range(0,359), (float)Random.Range(0,359), (float)Random.Range(0,359));
}
if (Input.GetKeyUp(KeyCode.B)){
// decomposition of vector and rotation around axis
Vector3 up_axis = new Vector3(0f, 1f, 0f);
Vector3 fwd = obj.transform.rotation * up_axis;
Quaternion q = obj.transform.rotation;
// create quaternion
Quaternion objective_rot_wo_w = Quaternion.FromToRotation(up_axis, fwd);
Quaternion diff = objective_rot_wo_w * Quaternion.Inverse(q);
diff.ToAngleAxis(out float _tmpAngle, out Vector3 _tmpAxis);
float around_y_angle = _tmpAngle;
// set
Quaternion rot = objective_rot_wo_w;
Quaternion rot_z = Quaternion.AngleAxis(around_y_angle, up_axis);
obj.transform.rotation = rot * rot_z;
}
Thank you for your cooperation.

Point game object to another only on the Local X Axis

I would like to have a Gameobject point to another only on the Local X-axis.
void FixedUpdate()
{
if(started){
Vector3 targetPosition = target.position;
Vector3 direction = Vector3.ProjectOnPlane(targetPosition - transform.position, transform.right);
Quaternion lookRot = Quaternion.LookRotation(direction, transform.right);
transform.rotation = Quaternion.RotateTowards(transform.rotation, lookRot, Time.fixedDeltaTime * 45);
}
On the y-axis it worked with transform.up instead of transform.right, but on the x-axis the Gameobject only rotates permanently around the z-axis.
You could do something like this:
Vector3 beforeRot = transform.eulerAngles;
transform.LookAt(gameObjectToLookAt.transform);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, beforeRot.y, beforeRot.z);
This will take a record of the position before looking at the object.
Make it look at the object.
Reset rotation back to its original except the X rotation

How do I get my character to move correctly using New Input System & Rigid Body physics? Unity3D

I have been experimenting with trying to recreate a 3rd person character controller from a Brackeys tutorial, but using the new input system and rigid body physics.
The rotation works properly, but moving forward or back moves me forward compared to the camera, and moving left or right moves me backward.
The desired effect is changing the input should change my rotation to match the input direction relative to the camera and then move in the direction the player model is facing
Here is where I'm at:
private Vector3 GetMoveInput()
{
return new Vector3(_input.MoveInput.x, 0f, _input.MoveInput.y); //convert input Vector2 into a Vector3
}
private void PlayerMove()
{
if (_playerMoveInput.magnitude > 0.01f){ //only update rotation if player is moving
float targetAngle = Mathf.Atan2(_playerMoveInput.x, _playerMoveInput.z) * Mathf.Rad2Deg + _mainCamera.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
//down here is where the problem lies I believe
_playerMoveInput = new Vector3(_playerMoveInput.x * _movementMultiplier * _rigidBody.mass,
_playerMoveInput.y,
_playerMoveInput.z * _movementMultiplier * _rigidBody.mass);
_rigidBody.AddRelativeForce(_playerMoveInput, ForceMode.Force);
}
}
I have tried setting y and z to 0f, multiplying by transform.forward, setting _playerMoveInput to transform.forward, and Quaternion.Euler(0f, angle, 0f) * transform.forward but no positive results.

How does Quaternion.LookRotation() works

I'm trying to make a cube to look at the mouse i found the following code:
RaycastHit hit;
if(Physics.Raycast(ray, out hit))
{
Vector3 targetPosition = new Vector3(hit.point.x, transform.position.y, hit.point.z);
Quaternion rotation = Quaternion.LookRotation(targetPosition - transform.position);
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * 10.0f);
}
I don't get it why did he subtract targetPosition from transform.position ?
Documentation LookRotation(Vector3 forward, Vector3 upwards = Vector3.up)
LookRotation transforms a direction vector into a Quaternion. In this example, he wants the angle between the two points. By subtracting the two position vectors, you can get the distance between the points and transform that distance vector into a Quaternion.
upwards is simply used as a reference. You can set it to anything you like, but if you leave it blank (as it is in this case) it will default to Vector3.up.

Topdown camera focus with angle

I'm making a topdown game with the camera at 40 degree angle. What I want to do is when i click an gameobject, It will move the camera and position the object at the left side from the center of the camera view regardless of its rotation. So that I can place a menu at the right side. How do I get the offset of the angled camera so that the object is in the middle left side of the camera view?
Right now i use lerp but it overshoots the target because of the cameras angle. Sorry for the noob question I'm new to unity3d.
transform.position = Vector3.Lerp(transform.position, new Vector3(target.transform.position.x, transform.position.y, target.transform.position.z), 0.1f);
First of all you should start by finding point that your camera will move/lerp to.
In your case in can be simplified to 2D-Space:
It shouldnt be tough to find that one.
Use transform.forward of camera to get vector (Vector3 cameraDir) of direction your camera is looking at
Rotate by horizontal fov / 4 around y axis:
Vector3 cameraDirRotated = Quaternion.AngleAxis(hFov/4f, Vector3.up) * cameraDir;
-cameraDirRotated will be vector from Cube To point P you're looking for, u can also scale it:
Vector3 PtoMoveTo = cube.transform.position - cameraDirRotated.normalized * 5f;
Full:
Vector3 FindCameraTarget(Transform targetObj, float hFov)
{
Vector3 cameraDir = transform.forward;
Vector3 cameraDirRotated = Quaternion.AngleAxis(hFov / 4f, Vector3.up) * cameraDir;
Vector3 target = targetObj.transform.position - cameraDirRotated.normalized * 5f;
return target;
}
Then:
transform.position = Vector3.Lerp(transform.position, FindCameraTarget(target, 90f) , 2f * Time.deltaTime);
For performance u can save that target vector once if Cube is not moving. Search web how to precisely count horizontal fov. Multiply speed by Time.timeDelta if u lerp in Update().