I have a mouse look script which allows the player to look up and down in a 3D first person game. It works perfectly in the Unity Editor. Once I build the game, I can only move the mouse on x-axis. I have tried using the old and new input system, but the same result happens. I have tried setting the window mode in the player settings to fullscreen and windowed already as well as setting the input system to both.
Here is a video clip of this happening: https://www.youtube.com/watch?v=_AxX2OmkU_Y
public class MouseLook : MonoBehaviour
{
Transform playerTransform;
PlayerController playerController;
InputMaster input;
Vector2 lookDir;
public float sens = 500f;
private float xRotation;
// Start is called before the first frame update
void Start()
{
// Hide cursor
Cursor.lockState = CursorLockMode.Locked;
playerTransform = transform.parent;
playerController = playerTransform.GetComponent<PlayerController>();
input = playerController.Input;
}
// Update is called once per frame
void Update()
{
lookDir = input.Player.Look.ReadValue<Vector2>();
// Gets mouse inputs
float moveX = lookDir.x * sens * Time.deltaTime;
float moveY = lookDir.y * sens * Time.deltaTime;
// Clamps rotation
xRotation -= moveY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerTransform.Rotate(Vector3.up * moveX);
}
}
I would use Input.GetAxis("MouseX") and Input.GetAxis("MouseY")
Make sure not to use Input.GetAxisRaw because it won't work as intended with mouse inputs :)
Documentation Link
Here is a example from the above link for mouse looking:
using UnityEngine;
using System.Collections;
// Performs a mouse look.
public class ExampleClass : MonoBehaviour
{
float horizontalSpeed = 2.0f;
float verticalSpeed = 2.0f;
void Update()
{
// Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float v = verticalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(v, h, 0);
}
}
Related
I am new to programming and currently working on a little shooter game in unity. I just implemented recoil but my "PlayerCam" script (Line 31: transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);) interrupts my "Recoil" script, the Euler function to be exact. Without this line recoil works, but I cant move obviously. With it the screen just shakes a bit (reset every frame and not continuing the recoil). What do i need to change?
PlayerCam.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCam : MonoBehaviour
{
public float sensX;
public float sensY;
public Transform orientation;
float xRotation;
float yRotation;
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void Update()
{
float mouseX = Input.GetAxis("Mouse X") * sensX;
float mouseY = Input.GetAxis("Mouse Y") * sensY;
yRotation += mouseX;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);
orientation.rotation = Quaternion.Euler(0, yRotation, 0);
}
}
Recoil.cs
using UnityEngine;
public class Recoil : MonoBehaviour
{
private Vector3 currentRotation;
private Vector3 targetRotation;
[SerializeField] private float recoilX;
[SerializeField] private float recoilY;
[SerializeField] private float recoilZ;
[SerializeField] private float snappiness;
[SerializeField] private float returnSpeed;
void Start()
{
}
void Update()
{
targetRotation = Vector3.Lerp(targetRotation, Vector3.zero, returnSpeed * Time.deltaTime);
currentRotation = Vector3.Slerp(currentRotation, targetRotation, snappiness * Time.fixedDeltaTime);
transform.localRotation = Quaternion.Euler(currentRotation);
}
public void RecoilFire()
{
targetRotation += new Vector3(recoilX, Random.Range(-recoilY, recoilY), Random.Range(-recoilZ, recoilZ));
}
}
Thank you for your help :)
I'm not sure where your Recoil class comes in as far as modifying your PlayerCam's orientation, but it sounds like your camera is being hard-reset to the value of the player's turn angles every frame, rather than combining them with the current recoil (sometimes called "punch") values.
To do a recoil/viewpunch setup correctly, you'll need to give your camera class access to an orientation that represents the current amount of rotation caused by the recoil, and combine that with the camera's current player angle setup.
Something like:
// get your current recoil offset here
Quaternion viewPunch = MyRecoil.transform.rotation;
// update the "base" rotation, aka where the player is looking
// (your existing code)
float mouseX = Input.GetAxis("Mouse X") * sensX;
float mouseY = Input.GetAxis("Mouse Y") * sensY;
yRotation += mouseX;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
// final camera rotation = viewPunch * player angles.
// to rotate an orientation, we always do rotation * current,
// not the other way around.
// if the strength of the recoil has gone back to 0 or hasn't
// happened yet, we'll end up with the normal player angles,
// as expected.
// if your camera object is a child of another object, you may need to set localRotation instead
transform.rotation = viewPunch * Quaternion.Euler(xRotation, yRotation, 0);
Somewhat new to Unity and C#, trying to let the camera move around for the user to see the room. It's kind of like a visual novel so I only want a specific part of the room to be visible.
This is what I have so far. It works perfectly but it starts at the minimum angle, and I want it to start at coordinates that I have set in the inspector.
I tried creating a method that will start it in the exact values, but that didn't work
public class CameraMovement : MonoBehaviour
{
// Start is called before the first frame update
public float mouseSensitivity = 70f;
public float yawMax = 90f;
public float yawMin = -90f;
public float pitchMax = 90f;
public float pitchMin = -90f;
private float yaw = 0.0f;
private float pitch = 0.0f;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
SetCameraStartingPosition();
}
// Update is called once per frame
void Update()
{
HandleMouseMovement();
}
void SetCameraStartingPosition() {
transform.eulerAngles = new Vector3(0.02f, 0.292f, -0.323f);
}
void HandleMouseMovement() {
yaw += mouseSensitivity * Input.GetAxis("Mouse X") * Time.deltaTime;
pitch -= mouseSensitivity * Input.GetAxis("Mouse Y") * Time.deltaTime;
yaw = Mathf.Clamp(yaw, yawMin, yawMax);
pitch = Mathf.Clamp(pitch, pitchMin, pitchMax);
transform.eulerAngles = new Vector3(pitch, yaw, 0.0f);
}
}
Right after you call that SetCameraStartingPosition method, the Update method will be called and it uses the cursor position to change the Camera rotation (or the transform that Camera attached to). But you used CursorLockMode.Locked right before that and the current cursor position is at the center of the window. So, before the first frame is even started to be shown your camera would go to the center of the window.
How can I stop the character turning and tilting with the camera in the y-axis? I mean I want to be able to look up and down without changing the player position. It's ok to have it turning around on the x-axis (left and right).
Here is the code:
using UnityEngine;
using System.Collections;
public class Actions : MonoBehaviour
{
public float speedH = 2.0f;
public float speedV = 2.0f;
private float yaw = 0.0f;
private float pitch = 2.0f;
private void Update()
{
yaw += speedH * Input.GetAxis("Mouse X");
pitch = Input.GetAxis("Mouse Y");
pitch = Mathf.Clamp(pitch, -30f, 45f);
transform.eulerAngles = new Vector3(pitch, yaw, 0.0f);
}
private void Start()
{
}
}
I would create an empty game object and parent the camera to it. Then I would use a script to move the obj to the player's position and then rotate the obj based on the mouse input axis.
This is what I have so far.
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
CharacterController control;
[SerializeField]
float moveSpeed = 5.0f;
[SerializeField]
float jumpSpeed = 20.0f;
[SerializeField]
float gravity = 1.0f;
float yVelocity = 0.0f;
// Use this for initialization
void Start () {
control = GetComponent<CharacterController> ();
}
// Update is called once per frame
void Update ()
{
Vector3 direction = new Vector3 (Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical"));
Vector3 velocity = direction * moveSpeed;
if (control.isGrounded) {
if (Input.GetButtonDown ("Jump")) {
yVelocity += jumpSpeed;
}
} else {
yVelocity -= gravity;
}
velocity.y = yVelocity;
control.Move (velocity*Time.deltaTime);
}
}
I'm following a tutorial, and it looks like everything is the same, but the player is not moving.
If it is all same with tutorial, your problem must be about your input settings. Check your "Horizontal", "Vertical", "Jump" from Edit -> Project Settings -> Input
Then on inspector look at variables under Axis list to check them if they assigned true, maybe there is no Horizontal or Vertical variable.
I am creating a game involving a turret and it needs to "point" (that is, rotate) to the mouse. It's in 3-D environment, but at a bird's eye view. So for my purposes we are in a 2-D environment.
Here is my code:
using UnityEngine;
using System.Collections;
public class Turret : MonoBehaviour {
// Use this for initialization
void Start () {
}
int speed; float friction; float lerpSpeed ; private float xDeg ;
private float yDeg; private Quaternion fromRotation; private Quaternion toRotation;
void Update () {
xDeg -= Input.GetAxis ("Mouse X"); yDeg += Input.GetAxis ("Mouse Y");
fromRotation = transform.rotation;
toRotation = Quaternion.Euler(yDeg,xDeg,0);
transform.rotation = Quaternion.Lerp(fromRotation,toRotation,Time.deltaTime * lerpSpeed);
}
}
If you could tell me what I'm doing wrong or give me the correct code that would be great! Please note that I am using a C# script.
Input and rotation calculations are not right.
xDeg -= Input.GetAxis ("Mouse X"); yDeg += Input.GetAxis ("Mouse Y");
toRotation = Quaternion.Euler(yDeg,xDeg,0);
You are making a top down game. So I assume that you are trying to aim at where mouse points on a 2D plane, which is ground. You should get your input not based on mouse axes but taking account where your mouse cursor is.
That being said, you can use this method to achieve your goal:
public class CharacterInput : MonoBehaviour
{
public Transform CharacterTransform;
void Update()
{
var groundPlane = new Plane(Vector3.up, -CharacterTransform.position.y);
var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitDistance;
if (groundPlane.Raycast(mouseRay, out hitDistance))
{
var lookAtPosition = mouseRay.GetPoint(hitDistance);
CharacterTransform.LookAt(lookAtPosition, Vector3.up);
}
}
}
And to rotate it smoothly:
public class CharacterInput : MonoBehaviour
{
public Transform CharacterTransform;
public float RotationSmoothingCoef = 0.1f;
void Update()
{
var groundPlane = new Plane(Vector3.up, -CharacterTransform.position.y);
var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitDistance;
if (groundPlane.Raycast(mouseRay, out hitDistance))
{
var lookAtPosition = mouseRay.GetPoint(hitDistance);
var targetRotation = Quaternion.LookRotation(lookAtPosition - CharacterTransform.position, Vector3.up);
var rotation = Quaternion.Lerp(CharacterTransform.rotation, targetRotation, RotationSmoothingCoef);
CharacterTransform.rotation = rotation;
}
}
}
Better calculate smoothing in FixedUpdate to make it independent of frames per second. So it rotates at the same speed on every computer configuration:
public class CharacterInput : MonoBehaviour
{
public Transform CharacterTransform;
public float RotationSmoothingCoef = 0.01f;
private Quaternion targetRotation;
void Update()
{
var groundPlane = new Plane(Vector3.up, -CharacterTransform.position.y);
var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitDistance;
if (groundPlane.Raycast(mouseRay, out hitDistance))
{
var lookAtPosition = mouseRay.GetPoint(hitDistance);
targetRotation = Quaternion.LookRotation(lookAtPosition - CharacterTransform.position, Vector3.up);
}
}
void FixedUpdate()
{
var rotation = Quaternion.Lerp(CharacterTransform.rotation, targetRotation, RotationSmoothingCoef);
CharacterTransform.rotation = rotation;
}
}
I think this is a common mistake for a Unity beginner (as I had it wrong the first time as well).
As you probably know by now, the Update() method is called every new frame.
So, every new frame (in your code) you calculate where the mouse is, how to rotate and call Lerp.
What you probably miss is how Lerp works and that is interpolating the motion by making one step every frame , i.e every time Lerp is called it rotates (in your case) by some interval. Your interval is Time.deltaTime * lerpSpeed which changes every frame since Time.deltaTime is the time between 2 consecutive frames.
So to make Lerp work properly (== smooth interpolation) you must call it with the same start and end position and complete the interpolation between them (call Lerp from 0 to 1 with as many intervals as you wish).
What I suggest you do is move this code:
xDeg -= Input.GetAxis ("Mouse X"); yDeg += Input.GetAxis ("Mouse Y");
fromRotation = transform.rotation;
toRotation = Quaternion.Euler(yDeg,xDeg,0);
to a different place (one which Update has access to these variables) and:
Set toRotation everytime it should move (xDeg can be computed along side)
Remove fromRotation and instead call Lerp like this:
Lerp(transform.rotation, toRotation,Time.deltaTime * lerpSpeed)