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);
Related
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraSc : MonoBehaviour
{
public float sens;
public Transform body;
public Transform head;
float xRot = 0;
void Start()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
float x = Input.GetAxisRaw("Mouse X") * sens * Time.deltaTime;
float y = Input.GetAxisRaw("Mouse Y") * sens * Time.deltaTime;
xRot -= y;
xRot = Mathf.Clamp(xRot,-80f,80f);
transform.localRotation = Quaternion.Euler(xRot,0f,0f);
body.Rotate(Vector3.up, x);
transform.position = head.position;
//transform.rotation = head.rotation;
}
}
I have a body and I want my camera to follow my head. it follows of course but it vibrates, its like its not moving , its teleporting to head every second. I tried using FixedUpdate but it was worse. I tried Lerp too but lerp makes camera follow slow, when I move my mouse quick it takes a lot of time to follow.
If you don't need any acceleration or advanced movement for your camera, you can simply make your camera gameobject a child of your head gameobject in the scene hierarchy (or prefab). This will make your camera copy the position and rotation of the head gameobject without any coding.
If you wish to make it third person view, you can simply modify the child position which will always be local to the parent's one.
Hopefully this helps.
It's can be complex problem. Maybe one of these solutions can help.
Why you use Input.GetAxisRaw() - this function return value without smoothing filtering, try Input.GetAxis() as alternative.
"Vibration" effect can be if camera position updates later than your body position. Try setup position for you body object in LateUpdate().
Problem can be in rotation calculation, in your case euler angles will be enough. Try to use something like this:
public float sens = 100.0f;
public float minY = -45.0f;
public float maxY = 45.0f;
private float rotationY = 0.0f;
private float rotationX = 0.0f;
private void Update()
{
rotationX += Input.GetAxis("Mouse X") * sens * Time.deltaTime;
rotationY += Input.GetAxis("Mouse Y") * sens * Time.deltaTime;
rotationY = Mathf.Clamp(rotationY, minY, maxY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
**```
I am making a game in which you control a machine gun and attempt to kill enimies. There is no actual player, but only a camera. I needed a first person aspect to the game, so I added some simple script to level 1. If you lose, the level is reset. But, whenever you run it, the cameras rotation gets set off, even though its set to 0,0,0. After you die and respawn, for some reason, the camera is normal and the scene is reset. I also noticed that the camera is at an angle sometimes
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CrosshairMove : MonoBehaviour
{
public float sens = 100f;
public Rigidbody rb;
public Transform cam;
float xRotation = 0f;
float yRotation = 0f;
public float sceneused = 0f;
public float currentscene = 0f;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
void FixedUpdate()
{
float mouseX = Input.GetAxis("Mouse X") * sens * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * sens * Time.deltaTime;
xRotation -= mouseY;
yRotation -= mouseX;
//xRotation -= Mathf.Clamp(xRotation, -90f, 90f);
//transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
cam.Rotate(Vector3.up * mouseX);
cam.Rotate(Vector3.left * mouseY);
}
}
I would:
Try different gameObject for independent rotation and avoid gimbal lock. For this, you can put the camera in the child object, and when parent is rotated in its local axis, the children "suffers" that same rotation.
Clamp xrot 180º is usual thing in FPS camera
Use FixedUpdate only for physics. For anything else use normal Update
Suggested snippet with all of the above:
public GameObject parentGO; // drag ref to parent go here in the editor
void Update {
float mouseX = Input.GetAxis("Mouse X") * lookAtSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * lookAtSensitivity *
Time.deltaTime;
xRot -= mouseY;
xRot = Mathf.Clamp(xRot, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRot, 0f, 0f);
parentGO.transform.Rotate(Vector3.up * mouseX);
}
I have only been able to rotate it in the x axis but I would also like to do it in the z with the movement of the mouse. Sorry for the mistakes is google translator.
[SerializeField] private float camRotationAmount = 0.2f;
public Quaternion newRotation;
newRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.deltaTime * camSmoothness);
I would like to add Input.GetAxis ("Mouse Y") for Vector3.left without tilting the camera. it's for a rts game. Thanks
In general you will want to separate the Y and X rotation the following way:
rotate around Y in global space
rotate around X in local space.
Whether you do this purely by logic or using a parent-child hierarchy is up to you ... second is easier to understand in my opinion.
Using the Hierarchy
There you would simply have a hierarchy like e.g.
CameraAnchor
|--Camera
and have a script on the CameraAnchor like e.g.
public class CameraAnchorController : MonoBehaviour
{
public float cameraSmoothness = 5f;
private Quaternion targetGlobalRotation;
private Quaternion targetLocalRotation;
private Transform child;
private void Start()
{
child = transform.GetChild(0);
targetGlobalRotation = transform.rotation;
targetLocalRotation = transform.GetChild(0).localRotation;
}
private void Update()
{
targetGlobalRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
targetLocalRotation *= Quaternion.Euler(Vector3.right * -Input.GetAxis("Mouse Y"));
var lerpFactor = cameraSmoothness * Time.deltaTime;
transform.rotation = Quaternion.Lerp(transform.rotation, targetGlobalRotation, lerpFactor);
child.localRotation = Quaternion.Lerp(child.localRotation, targetLocalRotation, lerpFactor);
}
}
Using Quaternion math
As said you could do the same thing in one single object but I would still keep both rotations separated:
public class CameraController : MonoBehaviour
{
public float cameraSmoothness = 5f;
private Quaternion targetGlobalRotation;
private Quaternion targetLocalRotation = Quaternion.identity;
private void Start()
{
targetGlobalRotation = transform.rotation;
}
private void Update()
{
targetGlobalRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
targetLocalRotation *= Quaternion.Euler(Vector3.right * -Input.GetAxis("Mouse Y"));
transform.rotation = Quaternion.Lerp(transform.rotation, targetGlobalRotation * targetLocalRotation, cameraSmoothness * Time.deltaTime);
}
}
Now why does this work when we are still using Vector3.right now?
By doing targetGlobalRotation * targetLocalRotation we first rotate around the global Y axis and then apply the rotation on the X axis based on this already applied rotation -> it is now an additional local rotation!
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;
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 :/