I have this script below and I want my player to always move towards the rotation angle, which doesn't happen. It only changes direction when I click.
My purpose is for the player to move at all times and towards the rotation which should be controlled by mouse position/mouse x axis (kind of like auto-run, but always change rotation based on mouse, not just move right or left).
I've tried about 10 different methods, nothing worked so far...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementController : MonoBehaviour
{
public float speed = 4;
public float rot = 0f;
public float rotSpeed = 80;
public float gravity = 8;
private Camera cam;
Vector3 moveDir = Vector3.zero;
CharacterController controller;
Animator anim;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController> ();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontalSpeed = 8.0f;
//Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float z = horizontalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(0, h, 0);
//Move Input
if(controller.isGrounded){
if(Input.GetMouseButtonUp(1))
{
anim.SetInteger ("condition", 1);
moveDir = new Vector3 (0,0,1) * speed;
// moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if(Input.GetMouseButtonDown(1))
{
anim.SetInteger("condition", 0);
moveDir = Vector3.zero;
}
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
}
Transform.LookAt
Just get a cursor position and that's it
Vector3 direction = target.position - player.transform.position;
Quaternion finalPlayerRotation = Quaternion.LookRotation(direction);
player.transform.rotation = finalPlayerRotation;
This also works in some cases:
Vector3 direction = target.position - player.transform.position;
player.transform.right /*You may need to change the Right to upper, -upper, -Right depend on the player rotation and the target position*/ = direction;
Related
I recently started on unity and I wanted to make simple movement which can be seen below.
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
//Variables
float speed = 5.0f;
public float turnSpeed = 4.0f;
public float moveSpeed = 2.0f;
public float minTurnAngle = -90.0f;
public float maxTurnAngle = 90.0f;
private float rotX;
//Other
Vector3 Char_velocity;
Rigidbody Physics;
void Start()
{
Physics = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
//Get axis on which we want to move
if (Input.GetButton("Vertical"))
{
//Creating vector which velocity is calculated based on vect3, speed and gets FPS compensation via fixed
//delta time
Char_velocity = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
Physics.MovePosition(transform.position + Char_velocity * speed * Time.fixedDeltaTime);
}
if (Input.GetButton("Horizontal"))
{
Char_velocity = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
Physics.MovePosition(transform.position + Char_velocity * speed * Time.deltaTime);
}
float y = Input.GetAxis("Mouse X") * turnSpeed;
rotX += Input.GetAxis("Mouse Y") * turnSpeed;
rotX = Mathf.Clamp(rotX, minTurnAngle, maxTurnAngle);
transform.eulerAngles = new Vector2(-rotX, transform.eulerAngles.y + y);
}
}
Mouse movement has been the problem for me. I got it to somewhat work but I have 2 issues. The camera should move the whole body while rotating from side to side but instead rotates the body when moving along the Y axis.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
CharacterController characterController;
[SerializeField] private float speed = 5.0f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
private Vector3 moveDirection = Vector3.zero;
private void Start()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
var horizontal = Input.GetAxis("Horizontal");
var vertical = Input.GetAxis("Vertical");
transform.Translate(new Vector3(horizontal, 0, vertical) * (speed * Time.deltaTime));
if (characterController.isGrounded)
{
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("vertical"));
moveDirection *= speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * Time.deltaTime);
}
}
I was new in game development when I am making an game but I got the problem that the character is not able to jump and when I try to move the character it keeps floating on the air.
This code here works for me
if (Input.GetButtonDown("Jump"))
{
rb.velocity = new Vector3(rb.velocity.x, jumpHeight, 0);
//jumpheight is set at 14, and my gravity scale is at 4
}
you will have to reference your 'rb' like:
public Rigidbody2D rb;
then drag your players rigidbody into the new Rb that shows up on the script.
rb.velocity adds a velocity of the original x velocity and sets the y velocity to 14, and z velocity = 0.
Hope this answers your question
Unity2D
How to make game object to face opposite from the position of another game object?
I have a fish that is going always forward and randomly rotating to make semi random movement,
and i want that in range of player(shark) the fish change direction opposite to shark and start moving faster(trying to escape). I have speed increase already but i doknt know how to make the opposite direction.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FishMove : MonoBehaviour
{
Rigidbody2D rb;
int rotZ = 0;
[SerializeField]
Transform target;
float speed;
bool move=true;
bool rotace = true;
[SerializeField]
int smerRotace;
[SerializeField]
float casRotace;
float nula;
[SerializeField]
Transform shark;
float fearRange=4;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
if (rotace)
{
rotace = false;
smerRotace = Random.Range(-1, 2);
if (smerRotace == 0) nula = 0.2f;
Invoke("Rotace", Random.Range(3.0f*nula, 9.0f*nula));
nula = 1;
}
rotZ += 2 * smerRotace;
float distance = Vector2.Distance(transform.position, shark.position);
if (distance < fearRange)
{
speed = 0.1f;
}
else
{
transform.rotation = Quaternion.Euler(0, 0, rotZ);
}
transform.position = Vector2.MoveTowards(transform.position, target.position, speed);
speed = 0.05f;
}
void Rotace()
{
rotace = true;
}
}
Notice: at the part when I am saying to add/subtract 90 (you’ll know when you get there), try adding 90, if that doesn’t work, try subtracting 90 to get the right result.
To make it move fully the opposite direction, you should do a few things. First, I will tell you about Mathf.Atan2(float y, float x). Atan2 is arctangent. Arctangent takes a position, and finds the amount of rotations to rotate at that object, in radians. Then, you would want to multiply by Mathf.Rad2Deg, or radians to degrees. It converts radians to degrees, which unity uses. Then, you would add some degrees to face the opposite direction.
Here is a way to make an object look away from the the mouse:
using UnityEngine;
using System;
using System.Collections.Generic;
public class LookAtMouse : MonoBehaviour
{
public GameObject obj;
Vector3 offset;
Vector3 mousePosition;
float rotation;
void Update()
{
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
offset = mousePosition - obj.transform.position;
rotation = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg - 90f;
obj.transform.rotation = Quaternion.Euler(0f, 0f, rotation);
}
}
Basically, the script gets the mouse position, and stores it in mousePosition. Then, it gets the offset of the mouse relative to obj. The rotation is the product of the arctangent of the offset and the amount of degrees in a radian (unity uses degrees, not radians), minus 90. Arctangent is 90 degrees off of the target, so people usually add 90 to get it to look at the target. We are looking away from the target, so we subtract 90 to be 180 degrees away, or half way.
We would do the same thing for your script; here it is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FishMove : MonoBehaviour
{
Rigidbody2D rb;
int rotZ = 0;
[SerializeField] Transform target;
float speed;
bool move=true;
bool rotace = true;
[SerializeField] int smerRotace;
[SerializeField] float casRotace;
float nula;
[SerializeField] Transform shark;
float fearRange=4;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
Vector3 offset;
float rotation;
void FixedUpdate()
{
if (rotace)
{
rotace = false;
smerRotace = Random.Range(-1, 2);
if (smerRotace == 0) nula = 0.2f;
Invoke("Rotace", Random.Range(3.0f*nula, 9.0f*nula));
nula = 1;
}
rotZ += 2 * smerRotace;
float distance = Vector2.Distance(transform.position, shark.position);
if (distance < fearRange)
{
speed = 0.1f;
offset = transform.position - shark.transform.position;
rotation = Mathf.Atan2(offset.y, offset.x) * Mathf.Rad2Deg - 90f;
transform.rotation = Quaternion.Euler(0f, 0f, rotation);
}
else
{
transform.rotation = Quaternion.Euler(0, 0, rotZ);
}
transform.position = Vector2.MoveTowards(transform.position, target.position, speed);
speed = 0.05f;
}
void Rotace()
{
rotace = true;
}
}
Tell me in the comments if it works or if it doesn't work.
Hi I am very new to Unity and only got basic knowledge. I created a player who can move and also a camera which follows the player and according to the mouseX and mouseY acis the camera rotates.
Now I want the camera rotation angle to be the forward position.
If the player press w he moves along x acis but if the camera angle change and the player press w it should move into this direction.
player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoublePlayer : MonoBehaviour
{
private CharacterController _controller;
public float _jumpHeight = 3f;
[SerializeField]
private float _moveSpeed = 5f;
[SerializeField]
private float _gravity = 9.81f;
private float _directionY;
void Start()
{
_controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
Vector3 direction = new Vector3(horizontalInput, 0, verticalInput);
// set gravity
_directionY -= _gravity * Time.deltaTime;
direction.y = _directionY;
_controller.Move(direction * _moveSpeed * Time.deltaTime);
}
}
camera.cs
public class CameraController : MonoBehaviour
{
public float RotationSpeed = 1;
public Transform Target, Player;
float mouseX, mouseY;
void Start()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void LateUpdate()
{
CamControl();
}
void CamControl()
{
mouseX += Input.GetAxis("Mouse X") * RotationSpeed;
mouseY += Input.GetAxis("Mouse Y") * RotationSpeed;
mouseY = Mathf.Clamp(mouseY, -35, 60);
transform.LookAt(Target);
Target.rotation = Quaternion.Euler(mouseY, mouseX, 0);
Player.rotation = Quaternion.Euler(0, mouseX, 0);
}
}
For Target and Player variable I selected the player object.
Do someone has a simple solution I can understand?
You could simply take the direction and rotate it along with the object that component is attached to using Quaternion * Vector3 operator
var rotatedDirection = transform.rotation * direction;
Or if you rather need the orientation of the other script attached to a different object then do e.g.
// link your camera or whatever shall be used for the orientation via the Inspector
[SerializeField] private Transform directionProvider;
and then
var rotatedDirection = directionProvider.rotation * direction;
Since you're getting the rotation directly from a Transform, you could use Transform.TransformDirection:
Vector3 rotatedDirection = transform.TransformDirection(direction);
I am working on an RTS game and would like to support the camera to rotate around the current center of the screen on mouse button pressed, just like in any RTS, strategy game.
I tried the MouseOrbitImproved script as shown on the unity wiki (copied below), but it needs a target object used by the camera to rotate around. My problem is that my target is always the current center of the screen.
Any idea how to achieve this, but only while the middle mouse button is pressed?
using UnityEngine;
using System.Collections;
[AddComponentMenu("Camera-Control/Mouse Orbit with zoom")]
public class MouseOrbitImproved : MonoBehaviour {
public Transform target;
public float distance = 5.0f;
public float xSpeed = 120.0f;
public float ySpeed = 120.0f;
public float yMinLimit = -20f;
public float yMaxLimit = 80f;
public float distanceMin = .5f;
public float distanceMax = 15f;
private Rigidbody rigidbody;
float x = 0.0f;
float y = 0.0f;
// Use this for initialization
void Start ()
{
Vector3 angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
rigidbody = GetComponent<Rigidbody>();
// Make the rigid body not change rotation
if (rigidbody != null)
{
rigidbody.freezeRotation = true;
}
}
void LateUpdate ()
{
if (target)
{
x += Input.GetAxis("Mouse X") * xSpeed * distance * 0.02f;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
y = ClampAngle(y, yMinLimit, yMaxLimit);
Quaternion rotation = Quaternion.Euler(y, x, 0);
distance = Mathf.Clamp(distance - Input.GetAxis("Mouse ScrollWheel")*5, distanceMin, distanceMax);
RaycastHit hit;
if (Physics.Linecast (target.position, transform.position, out hit))
{
distance -= hit.distance;
}
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + target.position;
transform.rotation = rotation;
transform.position = position;
}
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
}
In your orbit function, where you determine the object to orbit around, raycast a ray from the center of the screen and orbit around the collision:
public LayerMask groundLayerMask; // mask to choose orbitable layers
...
Ray screenRay = Camera.main.ScreenPointToRay(new Vector3(Screen.width/2f, Screen.height/2f, 0f));`
RaycastHit hitInfo;
Physics.Raycast(screenRay, out hitInfo, Mathf.Infinity, groundLayerMask.value);
Vector3 orbitPosition = hitInfo.point;
You can check if the middle mouse button is pressed with Input.GetMouseButton(2). Before orbiting, check it and only detect mouse input changes if its held down.
In the MouseOrbitImproved code it might look like this in the LateUpdate method:
void LateUpdate ()
{
// Skip mouse input here if middle mouse button is not pressed
if (Input.GetMouseButton(2))
{
x += Input.GetAxis("Mouse X") * xSpeed * distance * 0.02f;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
y = ClampAngle(y, yMinLimit, yMaxLimit);
}
Quaternion rotation = Quaternion.Euler(y, x, 0);
distance = Mathf.Clamp(distance - Input.GetAxis("Mouse ScrollWheel")*5, distanceMin, distanceMax);
Ray screenRay = Camera.main.ScreenPointToRay(new Vector3(Screen.width/2f, Screen.height/2f, 0f));`
RaycastHit hitInfo;
Physics.Raycast(screenRay, out hitInfo, Mathf.Infinity, groundLayerMask.value);
Vector3 orbitPosition = hitInfo.point;
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + orbitPosition ;
transform.rotation = rotation;
transform.position = position;
}
In the class fields, get rid of public Transform target; and add public LayerMask groundLayerMask; and set it in the inspector to only collide with whatever layer your ground is.