Move to rotated direction [2D] [Unity] - c#

I have a sheep which is rotating to random direction. Question is how to make it move all the time in the direction it was rotated (rotation changes every 5 seconds).
Here is my code:
using UnityEngine;
public class Sheep : MonoBehaviour
{
private float SheepMovementSpeed = 30f;
void Start()
{
InvokeRepeating("SheepRandomRotate", Random.Range(3f, 4.9f), 5f);
}
void Update()
{
}
public void SheepRandomRotate ()
{
var dir = new Vector2(Random.Range(-10, 10), Random.Range(-10, 10));
var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle + 90, Vector3.forward);
}
}
Any ideas?

Use the same Vector3.forward you used in your rotation
transform.position += (Vector3.forward * Time.deltaTime * speed);

In Update
transform.up is up relative to the rotation. So if the camera is facinf forward that should work for your sprite.
transform.Translate(transform.up* Time.deltaTime * SheepMovementSpeed )

Related

Drone Controller in Unity: movement issues with the unity inputSystem

I'm trying to build a controller for a unity gameobject to move it similary to a normel quadrotor drone. So the drone should be able to ascend and descend by mobing the left stick up and down, turn around by moving the left stick sidewards and move horizontally by using the right stick.
I tried implementing it with the unity inputSystem, but unfortunately, it doesn't really work the way it is supposed to.
Movements are mostly not smooth and the rotation causes the horizonzal movement to move in wrong directions.
Here is my code:
public void OnMove(InputValue inputValue)
{
//horizontal movement
Debug.Log(inputValue.Get());
Vector3 move = new Vector3(inputValue.Get<Vector2>().x * 10 * Time.deltaTime, 0, inputValue.Get<Vector2>().y * 1 * Time.deltaTime);
move = Quaternion.Euler(0, rotation, 0) * move;
//playerDrone.transform.position += new Vector3(inputValue.Get<Vector2>().x * 10 * Time.deltaTime, 0, inputValue.Get<Vector2>().y * 10 * Time.deltaTime);
playerDrone.transform.Translate(move, Space.World);
}
public void OnClockwiseRotation()
{
//rotation of drone clockwise
playerCam.transform.Rotate(0, 0.5f, 0, Space.World);
rotation += 0.5f;
}
public void OnCounterclockwiseRotation()
{
//rotation of drone counterclockwise
Debug.Log("Rotation");
playerCam.transform.Rotate(0, -0.5f, 0, Space.World);
rotation += 0.5f;
}
public void OnAscend1()
{
//ascend drone
playerDrone.transform.position += new Vector3(0, 0.1f, 0);
Debug.Log("Ascend");
}
public void OnDescend()
{
//descend drone
Debug.Log("Descend");
playerDrone.transform.position += new Vector3(0, -0.1f, 0);
}
Does anyone know why the movement is so problematic with that implementation?
Thanks in advance
There are a few mistakes I'd say
Your rotation and your ascending are frame-rate dependent. Here you didn't use Time.deltaTime
In both OnClockwiseRotation and OnCounterclockwiseRotation you do
rotation += 0.5f;
You are using once playerDrone and another time playerCam .. you should probably stick to one as it sounds like you are only rotating a camera but not the drone.
In general I would not hardcode the values into your code but rather expose some class fields so you can adjust the velocities vis the Inspector without having to recompile
You probably would rather do something like
// Adjust these in the Inspector!
// in angle per second
public float rotationSpeed = 45;
// in meter per second
public float ascendingSpeed = 1;
public float forwardSpeed = 1;
public float sidewardsSpeed = 1;
public void OnMove(InputValue inputValue)
{
// In this case probably not a big deal but in general use getters only once
var input = inputValue.Get();
var move = new Vector3(input.x * sidewardsSpeed * Time.deltaTime, 0, input.y * forwardSpeed * Time.deltaTime);
move = Quaternion.Euler(0, rotation, 0) * move;
playerDrone.transform.Translate(move, Space.World);
}
public void OnClockwiseRotation()
{
var angle = rotationSpeed * Time.deltaTime;
playerDrone.transform.Rotate(0, angle, 0, Space.World);
rotation += angle;
}
public void OnCounterclockwiseRotation()
{
var angle = rotationSpeed * Time.deltaTime;
playerDrone.transform.Rotate(0, -angle, 0, Space.World);
rotation -= angle;
}
public void OnAscend1()
{
playerDrone.transform.position += Vector3.up * ascendingSpeed * Time.deltaTime;
}

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);
}

How can i rotate a spaceship back to it's original rotation to face the original position?

The spaceship start moving from point A. The spaceship is facing the moving direction.
Now when i click one on the L key i want that the spaceship will rotate and will face to the original position it was start moving from. But even if the spaceship is now rotated by axis Z or Y or X to rotate it first to the regular rotation values and to face to the start moving position.
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour
{
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private Vector3 originalPosition;
private Quaternion originalRotation;
// Use this for initialization
void Start()
{
originalPosition = transform.position;
originalRotation = transform.rotation;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey("p"))
{
isPKeyDown = Input.GetKey("p");
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
if (Input.GetKey("l"))
{
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0);
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
}
IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while (lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is where i click the L button but i tried some things but can't yet find how to do it.
The main goal is if i click once on L the spaceship should automatic rotate if needed and move back to the original position and then land on ground. L stand for landing that's the main goal.
Add a variable on top -
...
private Vector3 originalPosition;
private Quaternion originalRotation;
private bool landShip = false;
...
And use following code in update function -
if (Input.GetKey("l"))
{
landShip = true;
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
if(landShip){
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0.5f);
}
Once the spaceship lands, set the landShip value back to false.

Zoom in or zoom out Camera

I have a ball which is focusing by a camera at random height and distance. On mouse scroll I want to zoom in-out my camera towards the ball. I have tried this weird code and its behaving weird as I expected.
void ZoomInOut() {
if(Input.GetAxis("Mouse ScrollWheel") > 0){
Debug.Log("mouse scroll wheel greater");
distance += 20.0f;
Vector3 negDistance = new Vector3(targetFollow.transform.position.x, targetFollow.transform.position.y, -distance);
Vector3 pos = transform.rotation * negDistance + targetFollow.transform.position;
transform.position = pos;
}
if(Input.GetAxis("Mouse ScrollWheel") < 0){
Debug.Log("mouse scroll wheel less");
distance -= 20.0f;
Vector3 negDistance = new Vector3(targetFollow.transform.position.x, targetFollow.transform.position.y, -distance);
Vector3 pos = transform.rotation * negDistance + targetFollow.transform.position;
transform.position = pos;
}
}
If want to zoom directly forwards/backwards, can use this: ZoomWithMouse.cs
It just moves camera along transform.forward axis.
using UnityEngine;
// Zoom forward and backward with mousewheel, Attach this script to camera
public class ZoomWithMouse : MonoBehaviour
{
public float zoomSpeed = 300;
void Update()
{
var mouseScroll = Input.GetAxis("Mouse ScrollWheel");
if (mouseScroll!=0)
{
transform.Translate(transform.forward * mouseScroll * zoomSpeed * Time.deltaTime, Space.Self);
}
}
}
source:
https://github.com/UnityCommunity/UnityLibrary/blob/master/Scripts/Camera/ZoomWithMouse.cs
using UnityEngine;
using System.Collections;
public class Zoom : MonoBehaviour
{
private float _speed = 10;
private void Update()
{
float mouseScroll = Input.GetAxis("Mouse ScrollWheel");
if (mouseScroll!=0)
{
transform.Translate(Mathf.Sign(mouseScroll) * transform.forward * _speed * Time.deltaTime, Space.World);
}
}
}

move in deirection of the Camera but ignore Y-Axis

I'm using the following code to move the camera in whatever direction it is facing. It is working fine.
public class moveCam : MonoBehaviour {
public float walkSpeed = 0.9f;
void Start () {
}
void Update () {
//Walk In Direction Of Camera
transform.position += transform.forward * walkSpeed * Time.deltaTime;
}
}
The only problem I want to restrict my camera to ground level(i.e a constant position at Y), the work around for this is negate the calculate Y by resetting it, for which I am doing this
void Update () {
//Walk In Direction Of Camera
transform.position += transform.forward * walkSpeed * Time.deltaTime;
transform.position = new Vector3(transform.position.x,0.7f,transform.position.z);
}
what I want to know is, Is there a better way to achieve this.
Just reset the Y position after the change like the following
void Update(){
//Code to move in any particular direction
transform.position = new Vector3(transform.position.x,FIXED_Y_VALUE,transform.position.z);
}
or don't change Y direction at all -
void Update(){
Vector3 newCameraPosition = transform.position + transform.forward * walkSpeed * Time.deltaTime;
transform.position = new Vector3(newCameraPosition.x,transform.position.y,newCameraPosition.z);
}

Categories