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
Related
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
I have been trying this for two days with no success. I cant figure out where I'm missing the point. All the missiles are moving towards the position of the target but not following it. The position remains fixed and all the newly created missiles come to this point instead of following the target.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HomingMissile : MonoBehaviour
{
private GameObject target; //changed to private
private Rigidbody rb;
public float rotationSpeed;
public float speed;
Quaternion rotateToTarget;
Vector3 direction;
private void Start()
{
target = GameObject.FindGameObjectWithTag("Player"); //uncommented this
rb = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
//made some modifications
Vector3 direction = (target.transform.position - transform.position).normalized;
float angle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;//interchanged x and z
Quaternion rotateToTarget = Quaternion.Euler(0, angle, 0);
transform.rotation = Quaternion.Slerp(transform.rotation, rotateToTarget, Time.deltaTime * rotationSpeed);
Vector3 deltaPosition = speed * direction * Time.deltaTime;
rb.MovePosition(transform.position + deltaPosition);
}
}
I selected the target(transform) using the inspector.
I'm using Unity and C# obviously you know that.
What Im trying to achieve is that the missile should follow the position of the target in real time. And i can add the destroy code for the missile myself.
Note :
Please don't tag this as a duplicate. It is not.
The game is 2D where Y is always constant. Vertical axis is X and Horizontal axis is X. The objects are 3D. That's why I can't use rigidbody2D.
EDIT:
Code edited. The missile follows the target and also points to the direction of motion. How to make the missile make a circular rotation when it needs to rotate?
Firstly, consider:
Not modifying a rigidbody.velocity directly, as it will result in unrealistic behaviour
Using FixedUpdate() instead of Update() when controlling rigidbodies
Use rigidbody.movePosition() and rigidbody.moveRotation() instead. Here's an example:
Vector3 dir = (target.transform.position - transform.position).normalized;
Vector3 deltaPosition = speed * dir * Time.deltaTime;
rb.MovePosition(transform.position + deltaPosition);
Try out rigidbody.MoveRotation() yourself for practice.
Finally, understand that there are many ways to implement homing for missiles. Here's one that is commonly used in real life.
Edit: I will not recommend using rb.addForce() because if u try it out u will realise it is too indeterministic.
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].
I am working on a third person shooter. And I have found this code. But I cant make no sense with it. First it is multiplying Quaternion with "Vector3.forward" and compiler is showing nothing. And also can you make me clear about the main logic of this code. I know memorizing the code is not a good habit. So can you explain me the code. And what does that Quaternion.euler does, is that for changing euler to quaternion.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour {
[SerializeField]
Transform target;
[SerializeField]
float distance;
[SerializeField]
float targetheight;
private float x = 0;
private float y = 0;
void LateUpdate()
{
y = target.eulerAngles.y;
Quaternion rotation = Quaternion.Euler(x, y, 0);
Debug.Log(rotation);
transform.rotation = rotation;
var postion = target.position - (rotation *Vector3.forward* distance + new Vector3(0, -targetheight, 0));
transform.position = postion;
}
}
Let's break it down:
y = target.eulerAngles.y;
This is Transform.eulerAngles() and gives you the current rotation of the target as Quaternion.
Then that rotation is reapplied to the target, but with the rotation around the Z-axis removed.
Quaternion rotation = Quaternion.Euler(x, y, 0);
Debug.Log(rotation);
transform.rotation = rotation;
This is Quaternion.Euler(x,y,z) and gives you a rotation from three degree values.
Last is the following calculation:
var postion = target.position - (rotation *Vector3.forward* distance + new Vector3(0, -targetheight, 0));
transform.position = postion;
Multiplying a Vector3 by a Quaternion means to apply the rotation to the vector. So in this case you'd rotate the forward vector based on the rotation of the target (without the Z-axis rotation, since we set that to 0 earlier). Then that resulting forward vector is multiplied by a certain distance to give us a point somewhere in front of the target's current facing direction and lowered according to the targetheight variable.
Lastly that calculation is subtracted from our own current position, basically performing a point reflection with the target being the point. The result is that we actually end up with a position that has a positive height (originally we were using a negative targetheight) and are behind the target's facing direction.
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.