Unity point game object to another only on the Local Y Axis - c#

I would like to have a Gameobject point to another only on the Local Y-axis.
void FixedUpdate()
{
if(started){
Quaternion lookRot = Quaternion.LookRotation(target.position - transform.position);
transform.rotation = Quaternion.Lerp(transform.rotation,Quaternion.Euler(transform.eulerAngles.x, lookRot.eulerAngles.y, transform.eulerAngles.z),1);
}
}

If I understand you correctly what you want to achieve is make this object "point at" the target but only allow it to rotate around its local Y axis.
What I would do for this is map the targets actual position onto a mathematical Plane that goes throw this object's position and uses the local Y axis as normal.
Then make your object face towards this mapped position additionally also passing in the local Y axis as the target UP vector which means it rotates only around its local Y axis.
something like e.g.
void FixedUpdate()
{
if(started)
{
var targetPosition = target.position;
var plane = new Plane(transform.up, transform.position);
var mappedTargetPosition = plane.ClosestPointOnPlane(targetPosition);
Quaternion lookRot = Quaternion.LookRotation(mappedTargetPosition - transform.position, transform.up);
}
}

Related

unity3d - how to clamp x axis from gameobject transform forward perspective?

i moved object according mouse position with ray cast
,i would like to know how i can clamp in any given position and rotation the object x axis that relative to transform forward of the object?
, not generally relative to the world any ideas? , thanks in advance.
the code below shows the basic how i implement object movement according the mouse position
now i want to clamp it
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
plane = new Plane(Vector3.up, transform.position);
float enter;
if(plane.Raycast(ray,out enter))
{
hitPoint = ray.GetPoint(enter);
transform.position = hitPoint;
}
If I understand you correctly what you are trying to achieve is to move your object only on its local x-axis.
And do something like this (behold my amazing paint skills)
You can use Vector3.Project to achieve that like e.g.
var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
var plane = new Plane(Vector3.up, transform.position);
if(plane.Raycast(ray, out var enter))
{
var hitPoint = ray.GetPoint(enter);
var actualPositionDelta = hitPoint - transform.position;
var mappedPositionDelta = Vector3.Project(actualPositionDelta, transform.right);
transform.position += mappedPositionDelta;
}

Unity LookAt, but instead rotate entire body towards direction in 3d space

Wasted many hours trying to figure out the rotations and many hours looking for answers, but wasn't able to find anything that fits my problem. I need to rotate an entire gameObject to a specific direction rather than rotating in y axis:
1) How the object is currently rotated while given a direction inside Quaternion.LookRotation or by Atan2.
2,3) Examples of how it should rotate. The red ot simbolizes the pivot point from which the rotation happens
Not much code to show as there is not much to it besides gameObject transformations which are rotated and a direction in which to rotate gameObject.
As requested
[System.Serializable]
public class ToRotate
{
//Object which will be rotated by the angle
public GameObject gameObject;
//Object last known position of this object. The object is rotated towards it's last global position
private Vector3 lastPosition;
//Initializes starting world position values to avoid a strange jump at the start.
public void Init()
{
if (gameObject == null)
return;
lastPosition = gameObject.transform.position;
}
//Method which updates the rotation
public void UpdateRotation()
{
//In order to avoid errors when object given is null.
if (gameObject == null)
return;
//If the objects didn't move last frame, no point in recalculating and having a direction of 0,0,0
if (lastPosition == gameObject.transform.position)
return;
//direction the rotation must face
Vector3 direction = (lastPosition - gameObject.transform.position).normalized;
/* Code that modifies the rotation angle is written here */
//y angle
float angle = Mathf.Rad2Deg * Mathf.Atan2(direction.x, direction.z);
Quaternion rotation = Quaternion.Euler(0, angle, 0);
gameObject.transform.rotation = rotation;
lastPosition = gameObject.transform.position;
}
}
Since you want the object's local down to point in a calculated direction, while keeping the object's local right unchanged as possible, I would use Vector3.Cross to find the cross product of that down and right to determine the direction the object's local forward should face, then use Quaternion.LookRotation to get the corresponding rotation:
//Method which updates the rotation
public void UpdateRotation()
{
//In order to avoid errors when object given is null.
if (gameObject == null)
return;
//If the objects didn't move last frame, no point in recalculating and having a direction of 0,0,0
if (lastPosition == transform.position)
return;
//direction object's local down should face
Vector3 downDir = (lastPosition - transform.position).normalized;
// direction object's local right should face
Vector3 rightDir = transform.right;
// direction object's local forward should face
Vector3 forwardDir = Vector3.Cross(downDir, rightDir);
transform.rotation = Quaternion.LookRotation(forwardDir, -downDir);
lastPosition = transform.position;
}

Player rotation and camera rotation

i want the player to look into the direction, the camera is looking.
The camera follows the player (3rd person game style).
I've tried it with
transform.localRotation = new Quaternion(transform.localRotation.x,
cameraMain.transform.localRotation.y,
transform.localRotation.z,
transform.localRotation.w);
but it doesn't work.
Sometimes the player starts rotating the other direction.
the following code will make the object (specified in the parameter) face in the direction of where the main camera is looking:
public void lookInDirectionOfCamera(Transform object) {
RayCastHit hit;
if (Physics.raycast(cameraMain.transform.position, cameraMain.transform.forward, out hit)) {
object.forward = hit.point - object.position;
}else { //if the raycast didnt hit anything, make the object face 100 units in front of the camera
Vector3 point = Camera.main.transform.position + Camera.main.transform.forward * 100;
object.forward = point - object.position;
}
}
This will make the player face the point that is forward to the camera. If you just want them to have the same rotation in the y-axis don't use Quaternions!
Instead, you can just do it with Euler angles:
transform.eulerAngles = new Vector3(transform.eulerAngles.x,
cameraMain.transform.eulerAngles.y,
transform.eulerAngles.y);
The reason not to use transform.localRotation is because that is a Quaternion. The y component in a Quaternion is not the same as the y-axis in a Euler angle (what you are used to seeing), Quaternions are very confusing so you should almost never set individual values in them. If you want to edit them only use the built-in methods.
Get the direction the camera is looking with cameraMain.transform.forward, make a copy with a y value of zero, then use Quaternion.SetLookRotation to look in that direction with the global up direction.:
Vector3 cameraDirection = cameraMain.transform.forward;
Vector3 characterLookDirection = new Vector3(cameraDirection.x,
0f,
cameraDirection.z);
Quaternion newRotation = new Quaternion();
newRotation.SetLookRotation(characterLookDirection, Vector3.up);
transform.rotation = newRotation;

unity fix orientation in an axis

I have a first person rigidbody capsule that rotates so that he will always be upright against the gravity direction. I want to rotate my player to the side so that the player camera will not rotate vertically.
My code is,
void Update() {
FixOrientation();
}
void FixOrientation()
{
if (trans.up != -GetGravityDirection())
{
Quaternion targetRotation = Quaternion.FromToRotation(trans.up, -GetGravityDirection()) * trans.localRotation;
trans.localRotation = Quaternion.RotateTowards(trans.localRotation, targetRotation, 5f);
}
}
The result is,
In the image above, I changed the gravity direction to point to the ceiling.
This code only rotates the player at the global x-axis no matter where he is facing which means when i'm facing global forward or backward, the player will rotate vertically the camera. What I want is for it to rotate on the side(local z axis).
Unity already has a method for exactly that: Transform.Rotate has an overload taking an angle and a rotation axis.
It might look like
// rotation speed in degrees per second
public float RotationSpeed;
void Update()
{
FixOrientation();
}
void FixOrientation()
{
if (transform.up != -GetGravityDirection())
{
// Get the current angle between the up axis and your negative gravity vector
var difference = Vector3.Angle(transform.up, -GetGravityDirection());
// This simply assures you don't overshoot and rotate more than required
// to avoid a back-forward loop
// also use Time.deltaTime for a frame-independent rotation speed
var maxStep = Mathf.Min(difference, RotationSpeed * Time.deltaTime);
// you only want ot rotate around local Z axis
// Space.Self makes sure you use the local axis
transform.Rotate(0, 0, maxStep, Space.Self);
}
}
A Sidenote:
Just in general be careful with the direct comparison of two Vectors
trans.up != -GetGravityDirection()
uses an approximation of 0.00001. In your case that should be fine anyway but for comparing you should rather use
Vector3.Angle(vector1, vector2) > threshold
to define a wider or stronger threshold

How to make a plane to rotate only on one axis?

How to make a plane to "look" at the camera by rotating on only on one axis?
For example, I have a plane with a texture of smoke coming from the pipe. If I walk around the pipe the plane should always be facing the camera, rotating along the y axis. But the direction of the smoke should not change, therefore, along with the x and z axes, the plane should not rotate.
Here is a code example which helps to rotate the plane on all axes:
void Update()
{
transform.LookAt(Camera.main.transform.position, -Vector3.up);
}
How to make it rotate only on one axis?
One approach to this is to store the object's original rotation in a Vector3 using transform.eulerAngles. You can then create another Vector3 to store the object's rotation after the LookAt function has completed. You can then set the object's rotation to a new Vector3 using only the y value from the second variable and using the original x and y values. It would look something like this:
void Update()
{
Vector3 originalRotation = transform.eulerAngles;
transform.LookAt(Camera.main.transform.position, -Vector3.up);
Vector3 newRotation = transform.eulerAngles;
transform.eulerAngles = new Vector3(originalRotation.x, newRotation.y, originalRotation.z);
}

Categories