I'm using Unity 5 (latest version), and I'm trying to make a conveyor belt type of thing. To do so I want to have cylinders rotate on the z-axis, and only the z-axis. How would I do that?
You can use the transform.Rotate method to rotate an object around a fixed axis.
The method has various constructors but a simple way to achieve what you want would be using the following depending on the axis you actually want to rotate the object around.
using UnityEngine;
using System.Collections;
public class RotateCylinder : MonoBehaviour
{
// rotation speed in degrees per second.
private float rotationSpeed = 1f;
void Update()
{
// Use one of the following depending on the axis you want to rotate the object, this will depend on how your object is transformed.
// Rotate around X Axis
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
// Rotate around Y Axis
transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
// Rotate around Z Axis
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
}
}
Well, it was rather hard to rotate GameObject ONLY in one axis, nothing worked correctly, adding values to another axis, even RotateAround or Rotate, but...
Vector3 v = transform.localRotation.eulerAngles;
transform.localRotation = Quaternion.Euler(v.x + dx, v.y + dy, v.z + dz);
dx, dy, dz - how much you want to change value in degrees.
Related
This question already has an answer here:
How do I rotate a Quaternion with 2nd Quaternion on its local or world axes without using transform.Rotate?
(1 answer)
Closed 1 year ago.
Regardless of the rotation of the cube, by pressing the button, the cube should rotate to the face.
Example:
My code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
public class CubeDoTweenController : MonoBehaviour
{
private Quaternion targetRotation;
private void Awake()
{
targetRotation = transform.rotation;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
targetRotation *= Quaternion.FromToRotation(Vector3.up, Vector3.right);
transform.DORotateQuaternion(targetRotation, 1f);
}
else if (Input.GetKeyDown(KeyCode.W))
{
targetRotation *= Quaternion.FromToRotation(Vector3.up, Vector3.forward);
transform.DORotateQuaternion(targetRotation, 1f);
}
}
}
After a couple of turns, the old cube starts to rotate. Thanks in advance for any help
Ok I have the solution to your problem... Instead of using Vectro3 axis, try to use your transform axis like so:
transform.rotation *= Quaternion.FromToRotation(transform.up, transform.forward);
The thing is that what does Quaternion.FromToRotation(Vector3 from, Vector3 to) is calculating the angle between from and to. Then you apply this rotation on your transform which is local.
For exemple
Quaternion.FromToRotation(Vector3.up, Vector3.right);
generate a rotation of 90 degrees around z axis.
Applied two times on your game object, x axis equals -x axis
Quaternion.FromToRotation(Vector3.up, Vector3.forward);
generate a rotation of 90 degrees around x axis.
But now, as your x axis equals -x axis, it is like the rotation around x has been inverted but if you follow the rotation of your cube, everything is fine.
Using local axis will then follow the rotation of your cube and do as your cube rotates in world space
I tried this code but it doesn't work correctly.
Edit: LookAt makes the GameObject invisible
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyPoint : MonoBehaviour {
public float offset;
public Transform target;
private void Update()
{
Vector2 difference = target.position - transform.position;
float rotZ = Mathf.Atan(difference.y) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotZ + offset);
}
}
You can use LookAt.
Rotates the transform so the forward vector points at target's current position.
transform.LookAt(target);
Simply place this on your objectA and in the target field drag&drop any other objectB → objectA's forward vector will always point towards objectB.
An alternative overwrite also takes a world position as Vector3 instead so you can also use
transform.LookAt(target.position);
which will basically do exactly the same thing.
If you need another axis pointing towards the target you can still use LookAt and afterwards Rotate. E.g. in order to not make the forward but rather the up Vector of the object point towards the target you can use
transform.LookAt(target);
transform.Rotate(Vector3.right * 90);
this thread is pretty old, but nonetheless i thought i might just pitch in. In line 13 you're using the wrong trig function. Using Mathf.Atan2(y, x) yields the arctangent y/x in the range of -π to +π, instead, you're using Mathf.Atan(y) which just does calculations based on y only and doesn't take into account the x value as well.
float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg //Get arctangential of x and y and turn it into degrees with 180/π
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
So I'm writing a script that's able to rotate an object using mouse movements.
The scene I have set up is a camera with an object in front of it. Moving the mouse left results in the object rotating left, moving the mouse up results in the object rotating up, etc. Now I have a little problem. When I rotate the object 90 degrees left or right and then rotate it up or down it rotates around the Z axis instead of the X axis like I want it to. This happens because the Z and X axis ofcourse rotate with the Y axis I manipulated earlier when rotating it left or right.
I made two gifs showcasing the problem:
What I want to always happen: https://media.giphy.com/media/wsUxoi9LyXXbB24PNg/giphy.gif
What's actually happening: https://media.giphy.com/media/1jl3MNtMuXW9AAUQOZ/giphy.gif
Here's the code I'm currently using:
public float object_rotSens = 100.0f;
float object_rotY = 0.0f;
float object_rotX = 0.0f;
void Update()
{
object_rotX += Input.GetAxis("Mouse X") * object_rotSens * Time.deltaTime;
object_rotY += Input.GetAxis("Mouse Y") * object_rotSens * Time.deltaTime;
objectImRotating.transform.localEulerAngles = new Vector3(object_rotY, -object_rotX, 0);
}
I hope that someone can help me change the code so I have the preferred rotation even when the object is rotated any amount around the Y axis. Thanks in advance!
Update:
Chris H helped me fix the problem. For anyone who has the same problem here's what helped me fix the problem:
object_rotX = Input.GetAxis("Mouse X") * object_rotSens * Time.deltaTime;
object_rotY = Input.GetAxis("Mouse Y") * object_rotSens * Time.deltaTime;
objectImRotating.transform.RotateAround(objectImRotating.transform.position, new Vector3(object_rotY, -object_rotX, 0), 100 * Time.deltaTime);
Try using Transform.RotateAround instead localEulerAngles.
I am currently implementing a radio in Unity for Oculus. Player can twist the knob to change volume. However, either eulerangle or rotation cannot return a unique value while turning in 360 degrees.
And below code has the same problem with eulerangle.
void Start ()
{
oldRight = Vector3.right;
angle = 0.0f;
}
void Update ()
{
Vector3 right = transform.right;
float tempAngle = Vector3.SignedAngle(oldRight,right,transform.forward);
if (right.y < oldRight.y)
{
angle += tempAngle;
}
else
{
angle -= tempAngle;
}
oldRight = right;
}
transform.rotation
If you want XYZ angles (and not a quaternion),
transform.rotation.eulerAngles
First of all, we don't know what's the relation between the radio game object and the knob game object, and that matters.
I'll make an example in order to show how you can get the rotation of the knob regardless of that relation.
In the image below, the radio is the cube, with its transform reset all to 0.
This is the cylinder which acts as the knob:
The important part here is that I rotated and placed the cylinder such that the X axis of the transform is parallel to the X axis of the cube.
And here is the script that rotates the cylinder and reports the angle of such rotation:
using UnityEngine;
public class RotateKnob : MonoBehaviour {
public float m_Speed;
void Update() {
if (Input.GetKey(KeyCode.RightArrow)) {
transform.Rotate(Vector3.up, Time.deltaTime * m_Speed, Space.Self);
}
if (Input.GetKey(KeyCode.LeftArrow)) {
transform.Rotate(Vector3.down, Time.deltaTime * m_Speed, Space.Self);
}
var angle = Vector3.SignedAngle(transform.right, transform.parent.right, transform.up);
Debug.Log(angle);
}
}
Notice how the rotation is done relative to the Y axis and Space.Self.
The angle is taken relative to the Y axis of the cylinder (which is the axis around which we rotate the cylinder), thus transform.up as the SignedAngle third parameter, and ofc we measure the angle between the transform.right and the transform.parent.right (the transform.right of the cube that childs the cylinders).
With this code you don't have to worry about the transform of the cube in the world, the result will always be relative to the cube when rotating the cylinder.
Please do remember that the angle will be reported in the range [-180,180] and not [0,360].