Unity 3D instantly rotate in the direction of movement - c#

I have a somewhat similar question to this one, I'm trying to rotate in the direction of movement but the issue is that I want to maintain my position and just instantly rotate because I have a procedural maze and there's not enough space to gradually swing around in the direction of movement in a wide turn. I'll post code attempts at the bottom, attempt two gives the error: viewing vector is zero.
If you look at all four of these screenshots, when the y-axis is rotated, the x-axis and z-axis jump to a new position. When I'm moving this ends up looking like I'm teleporting around the maze. Anyone know how to rotate while remaining in the same position?
Here's right:
Here's forward:
Here's left:
Here's back:
here's code attempt 1:
public void playerMovement()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
Vector3 movementx = new Vector3(horizontalInput, 0f, 0f);
Vector3 movementy = new Vector3(0f, 0f, verticalInput);
movementy = transform.forward * verticalInput;
movementx = transform.right * horizontalInput;
if (horizontalInput > 0)
{
transform.eulerAngles = new Vector3(0f, 90f, 0f);
transform.Translate(-movementx.normalized * 0.1f, Space.Self);
}
if (horizontalInput < 0)
{
transform.eulerAngles = new Vector3(0f, 270f, 0f);
transform.Translate(-movementx.normalized * 0.1f, Space.Self);
}
if (verticalInput < 0)
{
transform.eulerAngles = new Vector3(0f, 180f, 0f);
transform.Translate(movementy.normalized * 0.1f, Space.Self);
}
if (verticalInput > 0)
{
transform.eulerAngles = new Vector3(0f, 0f, 0f);
transform.Translate(movementy.normalized * 0.1f, Space.Self);
}
}
Here's code attempt 2:
public void playerMovement2()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
movement = transform.TransformDirection(movement);
transform.Translate(movement.normalized * 0.1f, Space.Self);
transform.rotation = Quaternion.LookRotation(movement);
}

I took your second attempt and modified it:
This way you will walk and look in the direction you
void Update()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
transform.Translate(movement.normalized * 0.1f, Space.World);
transform.rotation = Quaternion.LookRotation(movement, Vector3.up);
}
However then the character will always "flip" back to forward
-> you can solve that by only moving when new input is given
For example like this:
void Update()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
if (movement.magnitude > 0f)
{
transform.Translate(movement.normalized * 0.1f, Space.World);
transform.rotation = Quaternion.LookRotation(movement, Vector3.up);
}
}

Related

How do I keep raycast relative to the object its bound to?

I have a car game and I would like to use raycast to detect other obstacles and do stuff if the ray hits.
The problem is after the car does a 90 degree turn the raycast move in a way I did not intend them to, like this:
But when I rotate the car by 90 degrees it looks like this:
I'd like the rays to remain as they are in the first image regardless of the rotation of the car.
Here is the code to cast the rays and to draw them:
private void OnDrawGizmos()
{
sensorStartPosition1 = transform.position + new Vector3(1f, 0.6f, 0f);
sensorStartPosition2 = transform.position + new Vector3(-1f, 0.6f, 0f);
Gizmos.DrawRay(sensorStartPosition1, transform.TransformDirection(Vector3.right) * 3.5f);
Gizmos.DrawRay(sensorStartPosition2, transform.TransformDirection(Vector3.left) * 3.5f);
}
private void RunSensors()
{
RaycastHit hit1;
sensorStartPosition1 = transform.position + new Vector3(1f, 0.6f, 0);
//dTS = detect traffic signs
Ray dTS = new Ray(sensorStartPosition1, transform.TransformDirection(Vector3.right));
if(Physics.Raycast(dTS, out hit1, sensorLen ))
{
}
Debug.DrawRay(sensorStartPosition1, transform.TransformDirection(Vector3.right) * 3.5f);
RaycastHit hit2;
sensorStartPosition2 = transform.position + new Vector3(-1f, 0.6f, 0);
// dLIT1 = detect left incoming traffic
Ray dLIT1 = new Ray(sensorStartPosition2, transform.TransformDirection(Vector3.left));
if(Physics.Raycast(dLIT1, out hit2, sensorLen))
{
}
Debug.DrawRay(sensorStartPosition1, transform.TransformDirection(Vector3.left) * 3.5f);
}
what am I doing wrong?.. thanks in advance
You calculate the two start positions with an offset along the global world space X axis regardless of the rotation in
sensorStartPosition1 = transform.position + new Vector3(1f, 0.6f, 0f);
//...
sensorStartPosition2 = transform.position + new Vector3(-1f, 0.6f, 0f);
instead rather calculate them like
sensorStartPosition1 = transform.position + transform.right * 1f + transform.up * 0.6f;
//...
sensorStartPosition2 = transform.position + transform.right * -1f + transform.up * 0.6f;
Or simply
sensorStartPosition1 = transform.position + transform.rotation * new Vector3(1f, 0.6f, 0f);
//...
sensorStartPosition2 = transform.position + transform.rotation * new Vector3(-1f, 0.6f, 0f);
Btw instead of
transform.TransformDirection(Vector3.right)
transform.TransformDirection(Vector3.left)
you can also simply use
transform.right
-transform.right

Camera flies off when trying to set camera bounds

The player controls the camera movement to look around the level and I am trying to set boundaries so the camera cannot go too far. However, when I have the boundary code added, the camera flies off whenever I press a button to move.
if (Input.GetKey("d"))
{
transform.Translate(new Vector2(camSpeed * Time.deltaTime, 0));
transform.position = new Vector2(Mathf.Clamp(transform.position.x, minX, maxX), 0);
}
if (Input.GetKey("a"))
{
transform.Translate(new Vector2(-camSpeed * Time.deltaTime, 0));
transform.position = new Vector2(Mathf.Clamp(transform.position.x, minX, maxX), 0);
}
if (Input.GetKey("w"))
{
transform.Translate(new Vector2(0, camSpeed * Time.deltaTime));
transform.position = new Vector2(0, Mathf.Clamp(transform.position.y, minY, maxY));
}
if (Input.GetKey("s"))
{
transform.Translate(new Vector2(0, -camSpeed * Time.deltaTime));
transform.position = new Vector2(0, Mathf.Clamp(transform.position.y, minY, maxY));
}
I have set values min and max values to higher than needed levels and the camera still flies off, no matter what the values are set to.
To explain my comment; instead of setting x to 0 every time you move with W or S you should move the clamping to the end, and clamp both x and y (and probably keep Z value?):
if (Input.GetKey("d"))
{
transform.Translate(new Vector2(camSpeed * Time.deltaTime, 0));
}
if (Input.GetKey("a"))
{
transform.Translate(new Vector2(-camSpeed * Time.deltaTime, 0));
}
if (Input.GetKey("w"))
{
transform.Translate(new Vector2(0, camSpeed * Time.deltaTime));
}
if (Input.GetKey("s"))
{
transform.Translate(new Vector2(0, -camSpeed * Time.deltaTime));
}
transform.position = new Vector3(
Mathf.Clamp(transform.position.x, minX, maxX),
Mathf.Clamp(transform.position.y, minY, maxY),
transform.position.z
);

Slowly rotate an object in the z-axis

How to slowly rotate an object in the z-axis?
I have an object at an angle z=0 and I want it to move to z=100.
How do I do it so it slowly rotates in like 5 seconds?
public Vector3 rotationDirection;
public float durationTime;
private float smooth;
void Update()
{
smooth = Time.deltaTime * durationTime;
transform.Rotate(rotationDirection * smooth);
}
rotationDirection should be from (0,0,0) to (0,0,20) however the rotation does not stop after reaching the angle. How do I stop it when it reaches (0,0,20)?
Using Quaternion.RotateTowards did the work.
void Update()
{
Vector3 direction = new Vector3(0, 0, 20);
Quaternion targetRotation = Quaternion.Euler(direction);
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, Time.deltaTime * 20f);
}

Unity 3d, point object towards mouse (3d space)

I searched around for a while but I couldn't figure out how to solve this nasty bug. I am using a top down view (pointing towards -z), basically 2d with 3d objects and camera in perspective mode.
I need to orient an object towards the mouse , ignoring the z aspect, as everything moves on the same plane.
I am using the following code:
Vector3 mouseToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition + new Vector3(0, 0, 1f));
mouseToWorld.z = 0f;
Vector3 difference = mouseToWorld - transform.position;
difference.Normalize();
float angle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, angle - 90);
Unfortunately it only works when the object is still, and breaks as soon as the velocity is > 0;
Any hint would be appreciated :)
p.s. I am adding 1 to the z and then resetting it, because otherwise the mouseToWorld is constantly 0 wherever I move the pointer.
Perhaps it breaks because the velocity vector and the mouse direction aren't the same.
the following script will make an arrow follow the mouse, It's basically the same as yours except it updates the position as well:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowMouse : MonoBehaviour {
public float moveSpeed = 0.01f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
transform.position = Vector2.Lerp(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition), moveSpeed);
Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
difference.Normalize();
float rotation_z = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotation_z);
}
}
Thanks for the answer! I figured out you need to subtract the distance between the player and the camera to the initial mouse position:
Vector3 mouseToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition - new Vector3(0, 0, Camera.main.transform.position.z));
Here the working script:
Vector3 mouseToWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition - new Vector3(0, 0, Camera.main.transform.position.z));
//Debug.DrawLine(transform.position, mouseToWorld);
mouseToWorld.z = 0f;
Vector3 difference = mouseToWorld - transform.position;
difference.Normalize();
float angle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, angle - 90);

Unity3D C# direction change while running don't work

I'm currently working on a 2D game in Unity as a beginner in Unity and C#.
My character should walk left and right with axis horizontal, this works perfectly. But now I want, that my character runs, when I press additionally "Fire1". This works partly too, but when I change the direction while pressing "Fire1" the character stops. Without pressing "Fire1" the direction change works. It seems the script don't get the horizontal change, because the debug.log says "0" when "Fire1" is pressed while direction change.
if (onPlatform) {
activeMoveSpeed = moveSpeed * onPlatformSpeedModifier;
} else if(Input.GetButton("Fire1")) {
activeMoveSpeed = moveSpeed * sprintSpeedModifier;
} else {
activeMoveSpeed = moveSpeed;
}
Debug.Log (Input.GetAxisRaw ("Horizontal"));
//Player go left and right
if (Input.GetAxisRaw ("Horizontal") > 0f) {
myRigidbody.velocity = new Vector3 (activeMoveSpeed, myRigidbody.velocity.y, 0f);
transform.localScale = new Vector3 (1f, 1f, 1f);
} else if (Input.GetAxisRaw ("Horizontal") < 0f) {
myRigidbody.velocity = new Vector3 (-activeMoveSpeed, myRigidbody.velocity.y, 0f);
transform.localScale = new Vector3 (-1f, 1f, 1f);
} else {
myRigidbody.velocity = new Vector3(0f, myRigidbody.velocity.y, 0f);
}
You could try to multiply each moveSpeed by Time.deltaTime. I had an issue that seems pretty similar to this one and it helped.

Categories