How does Quaternion.LookRotation() works - unity3d

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.

Related

Rotation does not match when converting vector and quaternion on Unity

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

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 change the Y position of moving forward spaceship in Unity 3D

i have start a project in unity 3d.I want to make a spaceship that moving forward,but when i pressed the ArrowUp then i want to change its y postion to
( currentpos+ 1.5 ) but i want this smoothly.
this is my code
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey (KeyCode.UpArrow))
transform.position = new Vector3 (transform.position.x, 5f,
transform.position.z);
through the above code the Y position of object can b changed but it work so fast and i want to make it smooth.
so please help me.
I think the best solution to your problem is to use Mathf.SmoothDamp.
Example:
private float targetY = 0f;
private float verticalVelocity = 0f;
private const float smoothTime = 1f;
private void Update()
{
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey(KeyCode.UpArrow))
{
targetY = 5f;
}
float y = Mathf.SmoothDamp(transform.position.y, targetY, ref verticalVelocity, smoothTime);
transform.position = new Vector3 (transform.position.x, y, transform.position.z);
}
This example will smoothly change the y coordinate to 5 over the course of 1 second (you can change the smoothTime constant for a different time).
Based in your own code the easiest way for you to work it out could be something like this
//this sets the X position
transform.position += transform.forward * Time.deltaTime * 10f;
//if the button is pressed then modify Y
if (Input.GetKey (KeyCode.UpArrow))
transform.position += new Vector3 (0, 5f * Time.deltaTime * y_speed,0);
y_speed could be a public float y_speed = 1.0f in your script so you could modify it from the inspector to get the effect you want to achieve.
Hope it helps!
Assuming your spaceship is a rigidbody, you should take a look at Rigidbody.AddForce
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
By working with forces, you can get a smooth movement in all directions very easily, and tweak it within the Rigidbody's parameters (like mass) without fiddling in the script again. It's part of the Unity physics model.
If you only want to move in y-direction, input a vector like (0,1,0) but you can also input the Transform.forward vector of your spaceship's Gameobject. That way, it will always move the direction it is facing in.

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().