I have a moving object (the ship) with several child objects (its turrets). The turrets are to rotate towards the player object regardless of the direction the ship is facing. The problem is, unless the ship is rotated straight up, the turrets just spin around wildly.
The code to rotate the turrets is as follows:
//Rotate towards player
dir = PlayerScript.GlobalVariables.playerPosition - myPosition;
angleToTarget = Vector2.Angle(dir, transform.up);
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90;
transform.localRotation = Quaternion.RotateTowards(transform.rotation, Quaternion.AngleAxis(angle, Vector3.forward), turnSpeed);
The ship is instantiated with this code. Changing rotation changes the intitial rotation. At rotation = 180 it is rotated vertically up:
newEnemyShip = Object.Instantiate(enemyShip2, new Vector3(mousePosition.x, mousePosition.y, 0), Quaternion.Euler(210, 0, rotation));
The ship has an initial rotation which never changes. It's movement code is:
//moves in straight line at constant speed
transform.Translate(Vector3.up * currentSpeed * Time.deltaTime, Space.Self);
It also has this to lock it onto the 2d plane:
//Lock rotation on 2d plane
Quaternion q = transform.rotation;
q.eulerAngles = new Vector3(0, 0, q.eulerAngles.z);
transform.rotation = q;
Any help would be great appreciated!
I figured it out! I'm not sure what the problem was with the original code, but the following code for the turret worked:
//Rotate towards player
dir = PlayerScript.GlobalVariables.playerPosition - myPosition;
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90;
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.AngleAxis(angle, Vector3.forward), turnSpeed);
Bijan, thanks for taking the time to look and respond
Why you just don't use transform.LookAt(playerPosition) ?
Related
So I tried to use a script from tutorial that Makes a 3d object rotates smoothly to the direction the object is moving towards and when I tried to use it to my 2d sprite it started to rotate really weird 3D rotating, I am really new to unity so please expect any stupid mistakes and here is the script I used:
float horizontalInput = Input.GetAxisRaw("Horizontal");
float verticalInput = Input.GetAxisRaw("Vertical");
Vector3 movementDirection = new Vector3(horizontalInput, 0, verticalInput).normalized;
if (movementDirection != Vector3.zero)
{
Quaternion toRotation = Quaternion.FromToRotation(movementDirection, Vector3.forward);
transform.rotation = Quaternion.RotateTowards(transform.rotation, toRotation,
rotationSpeed * Time.deltaTime);
}
I tried to replace it with Vector3.right but still the same issue, I also tried to replace it with Vector3.up but this weird 3D rotation still exist.
I've got a problem with my script, I want the enemy of mine, follow and rotate towards the player. while he's moving around.
It seem to work nice, but when my player turning rotating 180 on y, my enemy seems to go back a lot(his position), and only when my player returning to his normal rotation , the enemy seem to come back.
What did I do wrong?
public class EnemyTesting : MonoBehaviour
{
public GameObject player;
public float speed = 1.5f;
public float turnRate;
private void Update()
{
Vector3 toTarget = player.transform.position - transform.position;
float angleToTarget = Vector3.Angle(transform.forward, toTarget);
Vector3 turnAxis = Vector3.Cross(transform.forward, toTarget);
transform.RotateAround(transform.position, turnAxis, Time.deltaTime * turnRate * angleToTarget);
transform.Translate(toTarget * speed * Time.deltaTime);
}
By "goes back" I understand rotation, not position.
I think that your problem is with Vector3.Angle. Check in the docs that the function returns the smaller of the two possible angles between the two vectors. In the case the angle is bigger than 180 you need to handle that in the code to make your enemy rotate accordingly.
Edit: I think that is produced by the rotation space of the translate function.
Set Space.World in the transform.Translate arguments
Try this:
private void Update() {
Vector3 toTarget = player.transform.position - transform.position;
transform.LookAt(player.transform.position);
transform.Translate(toTarget * speed * Time.deltaTime, Space.World);
}
You could use Quaternion.RotateTowards to slowly rotate the direction of the enemy towards the player.
This behavior also makes the enemy walk towards its forward vector, instead of directly at the player.
var towardsPlayer = player.transform.position - transform.position;
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
Quaternion.LookRotation(towardsPlayer),
Time.deltaTime * turnRate
);
transform.position += transform.forward * speed * Time.deltaTime;
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;
I am currently making a flight simulator. Right now, I am trying to get the plane to fly on its own, but I am having some problems with trying to rotate the plane such that it is parallel to the ground.
This is my code:
heightDetect = new Ray (transform.position, Vector3.down);
if (Physics.Raycast (heightDetect, out hit, Mathf.Infinity)) {
Debug.Log (hit.distance);
transform.rotation = Quaternion.FromToRotation(transform.up, hit.normal) * transform.rotation;
Debug.DrawRay (heightDetect.origin, heightDetect.direction*1000);
}
The code works and all, but the problem is it is way too bumpy. The camera on the plane keeps jerking about on my screen, and is completely unplayable. Is there a way to smoothen this process? Thank you!
Presumably you are doing this in your Update function, and therefore changing the rotation of your plane many times per second. Instead of directly setting the rotation, you could use spherical linear interpolation:
public float speed = 0.1f;
void Update() {
...
var targetRotation = Quaternion.FromToRotation(transform.up, hit.normal) * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * speed);
}
This effectively smoothes the rotation over time. It works by taking the current rotation and the eventual desired rotation, but only returning a rotation somewhere in between (controlled by speed).
If I understand correctly, you're looking for the Quaternion.Lerp to smooth your rotation for Quaternions, or Mathf.LerpAngle for Vector3 rotation.
Usage example:
Vector3 currentRotation = transform.rotation;
Vector3 newRotation = Quaternion.FromToRotation(transform.up, hit.normal) * transform.rotation;
newRotation = new Vector3(
Mathf.LerpAngle(currentRotation.x, newRotation.x, Time.deltaTime),
Mathf.LerpAngle(currentRotation.y, newRotation.y, Time.deltaTime),
Mathf.LerpAngle(currentRotation.z, newRotation.z, Time.deltaTime));
transform.rotation = newRotation;
Multiply Time.deltaTime by any value to change lerp's "speed".
IHi I've been working on a camera rotation method.
I'm trying to rotate a camera using the mouse inputs.
I need the horizontal rotation to be parallel to a x,y plane(my board) and the vertical rotation to be limited to certain angle(something like 40 degree to -40).
I use quaternions to rotate the camera.
Here my code so far
float angle = (mouseX_Current - mouseX_ActionStart) * 0.25f;
Quaternion horizontalRotationQuat = Quaternion.AngleAxis(angle, Vector3.up);
angle = (mouseY_Current - mouseY_ActionStart) * 0.25f;
Quaternion verticalRotationQuat = Quaternion.AngleAxis(angle, Vector3.right);
Camera.main.transform.rotation *= (horizontalRotationQuat * verticalRotationQuat);
My problem is that by adding those mouse related rotations to my current camera orientation quaternion the camera is no more parallel to the plane(x,y) which it s looking at.
I' ve been trying to create a correction quaternion to add to the camera quaternion after adding those mouse related rotations but I can't seem to find the right one.
Quaternion currentOrientationQuat = Camera.main.transform.rotation;
Quaternion corretionQuat = new Quaternion(0.0f, 0.0f, - currentOrientationQuat.z, currentOrientationQuat.w);
Camera.main.transform.rotation *= corretionQuat;
If someone could help me out on this I would be very grateful.
Thanks.
Sorry for the English, not my primary language.
Solved this using another method
float angle = (mouseX_Current - mouseX_ActionStart) * 0.25f;
Camera.main.transform.Rotate(0.0f, 0.0f, angle, Space.World);
angle = (mouseY_Current - mouseY_ActionStart) * 0.25f;
Camera.main.transform.Rotate(angle, 0.0f, 0.0f, Space.Self);
Feeling dumb after seeing how easy it was to do it.
Did'nt even needed the quaternions for this one.