Unity 3d movement not working with Camera direction - c#

I have two scripts one is the MouseHandler and the other is the SimpleMovement. rotating the camera works and moving works however when the camera turns the movement doesn't go in that direction. E.G i turn the camera 90 degrees to the right but the forward doesn't change. The forward doesn't go to where the camera is facing. Sorry if i'm just being stupid. Any help would be appreciated
MouseHandler script:
public class MouseHandler : MonoBehaviour
{
// horizontal rotation speed
public float horizontalSpeed = 1f;
// vertical rotation speed
public float verticalSpeed = 1f;
private float xRotation = 0.0f;
private float yRotation = 0.0f;
private Camera cam;
void Start()
{
cam = Camera.main;
}
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * horizontalSpeed;
float mouseY = Input.GetAxis("Mouse Y") * verticalSpeed;
yRotation += mouseX;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90, 90);
cam.transform.eulerAngles = new Vector3(xRotation, yRotation, 0.0f);
}
}
SimpleMovement Script:
public class SimpleMovement : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private void Start()
{
characterController = GetComponent<CharacterController>();
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
characterController.Move((Vector3.right * horizontal + Vector3.forward * vertical) * Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
}
}

First, get a reference to the main cmaera and cache it, because you're going to be referencing it frequently, and simply using Camera.main is a bit expensive:
private Camera mainCam;
...
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
Then, use mainCam.transform.right and mainCam.transform.forward but with the y set to 0 and normalized instead of Vector3.right and Vector3.forward. This will make the movement be based on the rotation of the camera:
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0f,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0f,
mainCam.transform.forward.z).normalized;
characterController.Move(
(camRightFlat * horizontal + camForwardFlat * vertical) * Time.deltaTime);
Altogether:
public class SimpleMovement : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0f,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0f,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
}
}

Related

How to make the player walk in the direction it is pointing?

I made a simple movement system in Unity 3D, but I don't know how to make it so that I move in the direction my player is pointing in.
using UnityEngine;
public class PlayerControler : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1f;
public float Gravity = 9.8f;
private float velocity = 0f;
void Start()
{
characterController = GetComponent<CharacterController>();
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
characterController.Move((Vector3.right * horizontal + Vector3.forward * vertical) * Time.deltaTime);
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
}
}
This is the player controller.
using UnityEngine;
public class MouseControl : MonoBehaviour
{
public float horizontalSpeed = 1f;
public float verticalSpeed = 1f;
private float xRotation = 0.0f;
private float yRotation = 0.0f;
private Camera cam;
void Start()
{
cam = Camera.main;
}
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * horizontalSpeed;
float mouseY = Input.GetAxis("Mouse Y") * verticalSpeed;
yRotation += mouseX;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
cam.transform.eulerAngles = new Vector3(xRotation, yRotation, 0.0f);
}
}
This is the code that makes my character face where my cursor is.
Edit: This is a First-Person 3D game. The player has a CharacterControler component on it, and the Main Camera is a child of the player. The second piece of code changes the direction that the camera is facing when the cursor is moved. The first script is the movement script, and utilises the CharacterController component of the player to move. I want to make to that instead of going in four static directions every time I press a movement key, I want the player to move in proportion to the direction that the camera is facing (on the X axis). E.g: If I am facing West and I press “W” to go forwards, I want the character to go West instead of North.
Instead of the global vectors Vector3.forward and Vector3.right in
characterController.Move((Vector3.right * horizontal + Vector3.forward * vertical) * Time.deltaTime);
rather use your local direction vectors Transform.forward and Transform.right
characterController.Move((transform.right * horizontal + transform.forward * vertical) * Time.deltaTime);
#derHugo was right, but I forgot to update the angles in the player movement script, so it always thought that I was rotated 0,0,0.
using UnityEngine;
public class PlayerControler : MonoBehaviour
{
Vector3 angles;
CharacterController characterController;
MouseControl mouseControl;
public float MovementSpeed = 1f;
public float Gravity = 9.8f;
private float velocity = 0f;
void Start()
{
characterController = GetComponent<CharacterController>();
mouseControl = GetComponent<MouseControl>();
}
void Update()
{
angles = new Vector3(mouseControl.xRotation, mouseControl.yRotation, 0f);
transform.eulerAngles = angles;
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
characterController.Move((transform.right * horizontal + transform.forward * vertical) * Time.deltaTime);
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
}
}
Updated code
Note: I had to made the X and Y rotation variables public.
[HideInInspector]public float xRotation = 0.0f;
[HideInInspector]public float yRotation = 0.0f;

How to let camera's vertical rotation move the camera up and down?

I have a player in the game, which I can move using the keyboard and rotate only on the horizontal axis using the mouse. That means, I can aim only horizontally and I can not aim it up and down.
I have the Main Camera and another VM Camera from Cinemachine. The current state of the game is like this:
On the horizontal axis, I rotate the player, but on the vertical axis I only want the player's camera/FOV to be moved up and down.
My movement script attached to the player is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController characterController;
public float speed = 35f;
public Animator animator;
// camera and rotation
public Transform cameraHolder;
public float mouseSensitivity = 2f;
public float upLimit = 50;
public float downLimit = -50;
// gravity
private float gravity = 9.87f;
private float verticalSpeed = 0;
void Update()
{
Move();
Rotate();
}
public void Rotate()
{
float horizontalRotation = Input.GetAxis("Mouse X");
float verticalRotation = Input.GetAxis("Mouse Y");
transform.Rotate(0, horizontalRotation * mouseSensitivity, 0);
cameraHolder.Rotate(-verticalRotation * mouseSensitivity, 0, 0);
Vector3 currentRotation = cameraHolder.localEulerAngles;
if (currentRotation.x > 180) currentRotation.x -= 360;
currentRotation.x = Mathf.Clamp(currentRotation.x, upLimit, downLimit);
cameraHolder.localRotation = Quaternion.Euler(currentRotation);
}
private void Move()
{
float horizontalMove = Input.GetAxis("Horizontal");
float verticalMove = Input.GetAxis("Vertical");
if (characterController.isGrounded) verticalSpeed = 0;
else verticalSpeed -= gravity * Time.deltaTime;
Vector3 gravityMove = new Vector3(0, verticalSpeed, 0);
Vector3 move = transform.forward * verticalMove + transform.right * horizontalMove;
characterController.Move(speed * Time.deltaTime * move + gravityMove * Time.deltaTime);
}
}
This is the code i use, it works for me, it's super easy to implement, and stops moving the camera when you aren't focusing the game, is the script from one of Brackey's tutorials modified for this purpose:
using UnityEngine;
public class CameraController : MonoBehaviour
{
public PlayerController player;
public float sensitivity = 150f;
public float clampAngle = 85f;
public bool look = true;
private float verticalRotation;
private float horizontalRotation;
private void Start()
{
verticalRotation = transform.localEulerAngles.x;
horizontalRotation = player.transform.eulerAngles.y;
// Defines the state of the cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void Update()
{
// Looks around if the user is in the window
if (look)
{
Look();
}
Debug.DrawRay(transform.position, transform.forward * 2, Color.red);
// If the player presses ESC while in the game, it unlocks the cursor
if (look && Input.GetKeyDown(KeyCode.Escape))
{
look = false;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else if (Input.GetMouseButtonDown(0) && !look)
{
look = true;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
private void Look()
{
float _mouseVertical = -Input.GetAxis("Mouse Y");
float _mouseHorizontal = Input.GetAxis("Mouse X");
verticalRotation += _mouseVertical * sensitivity * Time.deltaTime;
horizontalRotation += _mouseHorizontal * sensitivity * Time.deltaTime;
verticalRotation = Mathf.Clamp(verticalRotation, -clampAngle, clampAngle);
transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);
player.transform.rotation = Quaternion.Euler(0f, horizontalRotation, 0f);
}
}

Rotating Rigidbody controller

There is my script Rigidbody controller -
public float Speed = 5f;
public float JumpHeight = 2f;
public float GroundDistance = 0.2f;
public float DashDistance = 5f;
public LayerMask Ground;
private Rigidbody _body;
private Vector3 _inputs = Vector3.zero;
private bool _isGrounded = true;
private Transform _groundChecker;
void Start()
{
_body = GetComponent<Rigidbody>();
_groundChecker = transform.GetChild(0);
}
void Update()
{
_isGrounded = Physics.CheckSphere(_groundChecker.position, GroundDistance, Ground, QueryTriggerInteraction.Ignore);
_inputs = Vector3.zero;
_inputs.x = Input.GetAxis("Horizontal");
_inputs.z = Input.GetAxis("Vertical");
if (_inputs != Vector3.zero)
transform.forward = _inputs;
if (Input.GetButtonDown("Jump") && _isGrounded)
{
_body.AddForce(Vector3.up * Mathf.Sqrt(JumpHeight * -2f * Physics.gravity.y), ForceMode.VelocityChange);
}
if (Input.GetButtonDown("Sprint"))
{
Vector3 dashVelocity = Vector3.Scale(transform.forward, DashDistance * new Vector3((Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime), 0, (Mathf.Log(1f / (Time.deltaTime * _body.drag + 1)) / -Time.deltaTime)));
_body.AddForce(dashVelocity, ForceMode.VelocityChange);
}
}
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
}
What the best way to make a turn on y in the direction of the camera ? That is,the player turns to the side where the mouse is turned? Is it in fixedUpdate or update?
This is the camera script:
public float Smoothness = 0.3F;
public Vector2 Sensitivity = new Vector2(4, 4);
public Vector2 LimitX = new Vector2(-70, 80);
private Vector2 NewCoord;
public Vector2 CurrentCoord;
private Vector2 vel;
public GameManager GameMangerS;
public Transform Target;
public float TransformSpeed;
public Animator CameraAnimator;
void Update()
{
NewCoord.x = Mathf.Clamp(NewCoord.x, LimitX.x, LimitX.y);
NewCoord.x -= Input.GetAxis("Mouse Y") * Sensitivity.x;
NewCoord.y += Input.GetAxis("Mouse X") * Sensitivity.y;
CurrentCoord.x = Mathf.SmoothDamp(CurrentCoord.x, NewCoord.x, ref vel.x, Smoothness / 2);
CurrentCoord.y = Mathf.SmoothDamp(CurrentCoord.y, NewCoord.y, ref vel.y, Smoothness / 2);
transform.rotation = Quaternion.Euler(CurrentCoord.x, CurrentCoord.y, 0);
}
And added this line to the controller script -
void FixedUpdate()
{
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Euler(0, MainCamera.CurrentCoord.y, 0);
}
When I'm standing the player normally rotates, but when I start to move, all rotations are reset and the player is not moving.
Update
Simple Rotation can be achieved using transform.Rotate().
Example:
this.transform.Rotate(Vector3.up, 30);
This example is gonna rotate the transform by 30° around the Vector that points upwards.
LookAtMouse:
To make your object turn towards the mouse, you need the ScreenToWorldSpace() method from your camera. In order to convert the ScreenCoordinates into your WorldCoordinates.
Example:
Please note:
You have to set the camera instance! If you don't add that, you'll get a NullReferenceException.
This Snippets shall only show the steps needed to achieve the behavior you wish.
You will have to find out yourself how to integrate that lines of code into your code to make it work. Consider what Programmer told you in the comment when integrating that.
Vector3 mousePosition = Input.mousePosition; //get the screenSpaceMousePosition
Vector3 worldPosition = this.camera.ScreenToWorldPoint(mousePosition); //convert it into worldSpacePosition
Vector3 calculatedDirection = worldPosition - transform.position; //calucate the looking direction
calculatedDirection.y = 0;
Quaternion rotation = Quaternion.LookRotation(calculatedDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);

Unity 5 fpscontroller weird error

I made this script for my Player object. It has to child, 1 camera and 1 model.
They problem is whenever i move my mouse the player moves down. and the cam goes up.
Script:
public GameObject cam;
public float sensitivity = 2f;
public float walk_speed = 2f;
public float run_speed = 2f;
CharacterController player_CC;
float speed;
float moveFB;
float moveLR;
float rotX;
float rotY;
bool canMove;
void Start () {
canMove = true;
player_CC = GetComponent<CharacterController>();
speed = walk_speed;
}
void Update () {
if (canMove)
{
moveFB = Input.GetAxis("Vertical") * speed;
moveLR = Input.GetAxis("Horizontal") * speed;
rotX = Input.GetAxis("Mouse X") * sensitivity;
rotY = Input.GetAxis("Mouse Y") * sensitivity;
Vector3 movement = new Vector3(moveLR, 0, moveFB);
transform.Rotate(0, rotX, 0);
cam.transform.Rotate(rotY, 0, 0);
movement = transform.rotation * movement;
player_CC.Move(movement * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftShift))
{
speed = run_speed;
} else
{
speed = walk_speed;
}
}
movement = transform.rotation * movement;
You're multiplying your transforms rotation by your movement vector. Separate the logic.
I know what caused it. But i dont know why it did it. But i used a charachtercontroller and a rigidbody on the same object. Sorry for wasting your time :/

Rotate Camera when touch unity 3d

Here it is. I have a human anatomy, and I would like to rotate the camera when I touch anywhere. but looking at the human anatomy. how can I do that :(
[https://www.youtube.com/watch?v=EfYeL2FYyyA&t=148s] this is what exactly I really wanted to please help me !
`
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);
}}
You could use a trick instead of using too many "math" in this case.
There will be empty gameObjects in each of the element you want your camera to rotate around, lets call those "anchors"
When the element is selected, you simply make the camera child of the anchor.
And then if you just rotate the anchor, your camera will rotate because it is the child.
This will get the effect you want.
Here is a simple example from youtube, for rotating the object.
Here is another one from Unity answers.
Hope this helps! Cheers!

Categories