How to stop body from rotating around wrong axis in unity - c#

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.

Related

How do I change my direction towards rotation angle at all times?

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;

Camera behaviour weird when rotating around player

I am going for a RuneScape-style camera that rotates around the player using WASD. Rotating horizontally works fine but when I mix the two (as in pitching up or down) the camera rotates around the player really awkwardly, the camera might invert or will sort of gimbal I guess.
Here's my code:
public float pitch;
public float zoomSpeed = 4f;
public float minZoom = 5f;
public float maxZoom = 15f;
public Transform target;
public Vector3 offset;
public float yawSpeed = 100f;
private float currentZoom = 10f;
private float currentYaw = 0f;
private float currentPitch = 0f;
void Update()
{
currentZoom -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);
currentYaw -= Input.GetAxis("Horizontal") * yawSpeed * Time.deltaTime;
currentPitch -= Input.GetAxis("Vertical") * yawSpeed * Time.deltaTime;
Debug.Log("Yaw: " + currentYaw + " Pitch: " + currentPitch);
}
void LateUpdate()
{
transform.position = target.position - offset * currentZoom;
transform.LookAt(target.position + Vector3.up * pitch);
transform.RotateAround(target.position, Vector3.up, currentYaw);
transform.RotateAround(target.position, Vector3.forward, currentPitch);
}
Any help would be gladly appreciated!
It looks to me that you are using currentPitch, but rotating it around the forward axis? Which would create roll on the world foward axis?
If your up vector is always world up, then the yaw you have will work. But what you want to do is recalculate the right vector from your current location to your target after you apply the yaw.
void LateUpdate() {
transform.position = target.position - offset * currentZoom;
transform.LookAt(target.position + Vector3.up * pitch);
transform.RotateAround(target.position, Vector3.up, currentYaw);
transform.RotateAround(target.position, Vector3.Cross((target.position - transform.position).normalized, Vector3.up), currentPitch);
}

Limit Player Rotation Up and Down

I have the basic movement and rotation working however I can not work out a way to limit the rotation up and down. I want to make it so that you cant look more than 90° up and down.
Ive tried multiple ways such as using if statments and using clamp.
using UnityEngine;
public class FPSController : MonoBehaviour {
public float speed = 5f;
public float sensitivity = 2f;
public GameObject Camera;
CharacterController controller;
float moveFB;
float moveLR;
public float rotX;
public float rotY;
void Start()
{
controller = GetComponent<CharacterController>();
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void FixedUpdate ()
{
moveFB = Input.GetAxis("Vertical");
moveLR = Input.GetAxis("Horizontal");
rotX = Input.GetAxis("Mouse X") * sensitivity;
rotY = Input.GetAxis("Mouse Y") * sensitivity;
transform.Rotate(0, rotX, 0);
Vector3 movement = new Vector3(moveLR * speed * Time.deltaTime, 0, moveFB * speed * Time.deltaTime);
controller.Move(transform.rotation * movement);
Camera.transform.Rotate(-rotY, 0, 0);
}
}
With this code you will be able to rotate the camera beyond 90 degrees causing it to be upside down etc
"Camera" is a built-in unity class, I would recommend renaming it to "camera".
Try this to clamp the camera's rotation:
(with your other public floats)
public float minAngle = -90;
public float maxAngle = 90;
(at the end of FixedUpdate)
Vector3 temp = camera.transform.localEulerAngles;
camera.transform.localEulerAngles = new Vector3(Mathf.Clamp(Mathf.DeltaAngle(0, temp.x), minAngle, maxAngle), temp.y, temp.z);
Edit: changed eulerAngles to localEulerAngles
Edit 2: changed the order of the arguements of Mathf.DeltaAngle
I fixed it here. Not to sure on how it works but it works. Credit to video:https://www.youtube.com/watch?v=F5eE1YL1ZJY
using UnityEngine;
public class FPSController : MonoBehaviour {
public float speed = 5f;
public float sensitivity = 2f;
public GameObject Camera;
CharacterController controller;
float moveFB;
float moveLR;
public float rotX;
public float rotY;
public float minAngle = -90f;
public float maxAngle = 90f;
void Start()
{
controller = GetComponent<CharacterController>();
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void FixedUpdate ()
{
moveFB = Input.GetAxis("Vertical");
moveLR = Input.GetAxis("Horizontal");
rotX = Input.GetAxis("Mouse X") * sensitivity;
rotY -= Input.GetAxis("Mouse Y") * sensitivity;
rotY = Mathf.Clamp(rotY, minAngle, maxAngle);
transform.Rotate(0, rotX, 0);
Vector3 movement = new Vector3(moveLR * speed * Time.deltaTime, 0, moveFB * speed * Time.deltaTime);
controller.Move(transform.rotation * movement);
Camera.transform.localRotation = Quaternion.Euler(rotY, 0, 0);
}
}

Unity Player Controller - how to make it so it doesn't go upside down

This is my CamMouseLook script and I need it so when the player moves the mouse all the way up it doesnt turn upside down. I want him to be able to look up just not so much up that it turns the view upside down
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamMouseLook : MonoBehaviour {
Vector2 mouseLook;
Vector2 smoothV;
public float sensitivity = 5.0f;
public float smoothing = 2.0f;
GameObject character;
// Use this for initialization
void Start () {
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update () {
var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
mouseLook += smoothV;
transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
character.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, character.transform.up);
}
}
What you can do is to lock the rotation in a specific axis. For example to limit in the Y and X axis so the player can only rotate from [-60,60] degrees you can use:
using System;
using UnityEngine;
public class MouseLook : MonoBehaviour
{
public float mouseSensitivity = 70.0f;
public float clampAngle = 60.0f;
private float rotY = 0.0f; // rotation around the up/y axis
private float rotX = 0.0f; // rotation around the right/x axis
void Start ()
{
Vector3 rot = transform.localRotation.eulerAngles;
rotY = rot.y;
rotX = rot.x;
}
void Update ()
{
float mouseX = Input.GetAxis("Mouse X");
float mouseY = -Input.GetAxis("Mouse Y");
rotY += mouseX * mouseSensitivity * Time.deltaTime;
rotX += mouseY * mouseSensitivity * Time.deltaTime;
rotX = Mathf.Clamp(rotX, -clampAngle, clampAngle);
Quaternion localRotation = Quaternion.Euler(rotX, rotY, 0.0f);
transform.rotation = localRotation;
}
}
Now you can adapt this script to limit the rotation in the angle and the range you need

Unity fps rotation camera

In my game I have a camera and I want to have an FPS like rotation attached to this camera.
So if I move my cursor to the left, I want my cam to rotate to the left. If I move my cursor up, then the cam should look up, etc.
I currently have it partially working. I can look left and right, up, and down. The problem occurs when I look down and then move my cursor left and right. It then gives me a "Roll" effect.
See this video to see exactly what I mean:
http://www.screencast.com/t/Phedh8H0K13
Obviously when I look down I still want to have a "Yaw" effect instead of a "Roll" effect. Anyone any idea how to do that? This is what I have so far:
// Update is called once per frame
public override void update ()
{
this.camera.transform.rotation *=
Quaternion.AngleAxis( Time.deltaTime * sensitivityRoll * Input.GetAxis("Vertical"), Vector3.forward );
this.camera.transform.rotation *=
Quaternion.AngleAxis( Time.deltaTime * sensitivityYaw * Input.GetAxis("Mouse X"), Vector3.up );
this.camera.transform.rotation *=
Quaternion.AngleAxis( Time.deltaTime * sensitivityPitch * Input.GetAxis("Mouse Y"), Vector3.left );
}
I just found my answer in this topic:
http://forum.unity3d.com/threads/109250-Looking-with-the-Mouse?highlight=person+camera
The code from that topic:
C# Mono code:
using UnityEngine;
using System.Collections;
/// MouseLook rotates the transform based on the mouse delta.
/// Minimum and Maximum values can be used to constrain the possible rotation
/// To make an FPS style character:
/// - Create a capsule.
/// - Add the MouseLook script to the capsule.
/// -> Set the mouse look to use LookX. (You want to only turn character but not tilt it)
/// - Add FPSInputController script to the capsule
/// -> A CharacterMotor and a CharacterController component will be automatically added.
/// - Create a camera. Make the camera a child of the capsule. Reset it's transform.
/// - Add a MouseLook script to the camera.
/// -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.)
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationY = 0F;
void Update ()
{
if (axes == RotationAxes.MouseXAndY)
{
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
else if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
}
}
void Start ()
{
//if(!networkView.isMine)
//enabled = false;
// Make the rigid body not change rotation
//if (rigidbody)
//rigidbody.freezeRotation = true;
}
}
Simple Script, Not Sure it will work with you, might as well give it a try
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;
using System.Threading;
using UnityEngine;
public class mouse_lookat : MonoBehaviour
{
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerBody.Rotate(Vector3.up * mouseX);
}
}
using UnityEngine;
public class CameraRotator : MonoBehaviour
{
[SerializeField] private Transform _head;
[SerializeField] private float _sensitivity;
[SerializeField] private bool _invertVertical;
private void Update()
{
var deltaMouse = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y");
Vector2 deltaRotation = deltaMouse * _sensitivity;
deltaRotation.y *= _invertVertical ? 1.0f : -1.0f;
float pitchAngle = _head.localEulerAngles.x;
// turns 270 deg into -90, etc
if (pitchAngle > 180)
pitchAngle -= 360;
pitchAngle = Mathf.Clamp(pitchAngle + deltaRotation.y, -90.0f, 90.0f);
transform.Rotate(Vector3.up, deltaRotation.x);
_head.localRotation = Quaternion.Euler(pitchAngle, 0.0f, 0.0f);
}
}
i created 2 scripts for my FPS project that work flawlessly for my movement (currently havnt added jump mechanics) and it seems like youve overcomplicated alot of things that can be quite simple and straight forward.
im also new to coding so please correct me if im wrong heres my code
// this is in the player script which i put on an empty parent object of the camera and player sprite
public class player : MonoBehaviour
{
[Header("player Movement")]
[SerializeField] float moveSpeed = 5f;
[SerializeField] public float mouseSensitivity = 5f;
Rigidbody rigidBody;
// Use this for initialization
void Start()
{
}
void Update()
{
Move();
}
private void Move()
{
transform.Translate(Vector3.forward * Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime);
transform.Translate(Vector3.right * Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime);
transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * mouseSensitivity);
}
//this is the camera movement script which i put on the camera(will also use this script to add a function to change from 1st person to 3rd person for certain abilities)
{
player player;
// Use this for initialization
void Start()
{
player = FindObjectOfType<player>();
}
// Update is called once per frame
void Update()
{
MoveView();
}
private void MoveView()
{
transform.Rotate(Vector3.left * Input.GetAxis("Mouse Y") * player.mouseSensitivity);
}
}

Categories

Resources