I have a camera with 2 scripts on it.
The mouse rotation script and a "building script" that does instantiate an object and let it follow the mouseposition (and place it, but thats not necessery here).
The part I don't understand is when I turn the rotation script off so that I have a fixed camera, the building script works well and I don't see any jittering/stuttering or whatever when I move the mouse with the object - even when close to the camera everything works fine.
When the rotate script is on im encountering an ugly jittering on the object when moving the mouse with it.
Fullscreen GIF:
https://giphy.com/gifs/mk7qW316Yheqilobuq/fullscreen
I googled a lot and didn't find any solution this while I guess is not that hard. I printed the hit.point and it looked like there was a jitter.
What I already tried that made it worse or didn't help:
Replace Update with FixedUpdate and check input events in Update method separately
add a Vector3.Lerp (you can see it in code...that was horrible...like a smooth jittering oO)
i just cant fix it...and i already tried different rotate controllers like first person starter asset where i first encountered this problem...
definitely has something to do with the rotation...
any help appreciated :)
rotate script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseLook : MonoBehaviour
{
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
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);
}
}
building script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RTSBuildingSystem : MonoBehaviour
{
[SerializeField]
private GameObject _placeholderBuilding;
private GameObject _placeholder;
private LayerMask layer = 3;
[SerializeField]
private GameObject _building;
private Vector3 _mousePosition;
private float _previousX;
private float _previousZ;
private float rotSpeed = 25f;
private Building _buildingScript;
public bool buildingMode;
private void Start()
{
}
private void Update()
{
if (Input.GetKeyDown("q"))
{
if (buildingMode)
{
buildingMode = false;
Debug.Log("BUILD OFF");
Destroy(_placeholder);
}
else
{
buildingMode = true;
Debug.Log("BUILD ON");
_placeholder = Instantiate(_placeholderBuilding);
_buildingScript = _placeholder.GetComponent<Building>();
}
}
if (buildingMode)
{
_mousePosition = Input.mousePosition;
Ray ray = Camera.main.ScreenPointToRay(_mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, layer))
{
float positionX = hit.point.x;
float positionZ = hit.point.z;
float rot = Input.GetAxis("Mouse ScrollWheel") * rotSpeed;
_placeholder.transform.Rotate(0f, rot, 0f, Space.Self);
if (_previousX != positionX || _previousZ != positionZ)
{
_previousX = positionX;
_previousZ = positionZ;
_placeholder.transform.position = new Vector3(positionX, 0f, positionZ);
// _placeholder.transform.position = Vector3.Lerp(_placeholder.transform.position, new Vector3(positionX, 0f, positionZ), 0.07F);
}
if (Input.GetMouseButtonUp(0))
{
if (_buildingScript.isBuildable)
Instantiate(_building, _placeholder.transform.position, _placeholder.transform.rotation);
}
}
}
}
Related
Ive been trying to add recoil to my fps game (Used Brackeys tutorials for the base), but the camera looking script is causing the rotation to be set each frame. I cant figure out how to change the camera rotation without the script resetting it
Code for the looking script is attatched below
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseLook : MonoBehaviour
{
public float mouseSensitivity = 1500f;
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);
}
}
To change the camera rotation without the script resetting it I would use an if statement to check if a different rotation should be applied ex:
bool canLook = true;
if(canLook == false) {
//apply your desired rotation
}
else
{
//run your looking code
}
//When you want to apply your rotation set canLook to false
//And when you want to return to the camera movement set canLook to true
I am making code for a first person physics-based character controller in Unity. The movement is mostly smooth, but when I go up a slope, instead of sliding back down, the character floats in the air slightly while slowly moving downward until it gets back to the ground. This behavior is very strange and unexpected, and I don't really know why this is happening.
The character is an empty object with a capsule and a sphere childed to it. The script is on the empty object, and the rigidbody is on the capsule which is a child to the empty.
Here is the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
float mouseSensitivity;
private float cameraXRotation;
private float cameraYRotation;
private float movementX;
private float movementY;
private Transform playerHeadTransform;
private Transform playerBodyTransform;
private Rigidbody playerRigidBody;
private bool IsJumping;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
playerBodyTransform = transform.GetChild(0).gameObject.GetComponent<Transform>();
playerHeadTransform = transform.GetChild(0).transform.GetChild(0).gameObject.GetComponent<Transform>();
playerRigidBody = transform.GetChild(0).gameObject.GetComponent<Rigidbody>();
playerHeadTransform.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
mouseSensitivity = 750;
IsJumping = false;
}
// Update is called once per frame
void Update()
{
#region CameraStuff
float cameraMouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float cameraMouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
cameraXRotation -= cameraMouseY;
cameraYRotation += cameraMouseX;
cameraXRotation = Mathf.Clamp(cameraXRotation, -90f, 60);
playerHeadTransform.localRotation = Quaternion.Euler(cameraXRotation, 0f, 0f);
playerBodyTransform.localRotation = Quaternion.Euler(0f, cameraYRotation, 0f);
#endregion
//Movement input variables
movementX = Input.GetAxis("Horizontal") * mouseSensitivity * Time.deltaTime;
movementY = Input.GetAxis("Vertical") * mouseSensitivity * Time.deltaTime;
}
void FixedUpdate()
{
playerRigidBody.velocity = playerBodyTransform.TransformDirection(movementX*2, 0, movementY*2);
}
}
Your player not falling down is most probably related to you setting
void FixedUpdate()
{
playerRigidBody.velocity = playerBodyTransform.TransformDirection(movementX*2, 0, movementY*2);
}
if there is gravity involved you rather want to make sure to not overwrite the Y axis and do e.g.
var currentVelocity = playerRigidbody.velocity;
var newVelocity = playerBodyTransform.TransformDirection(movementX * 2, 0, movementY * 2);
// keep the velocity on Y but only if it is currently downwards
// so you can still move up on a slope but fall down with gravity
if(currentVelocity.y < 0) newVelocity.y = currentVelocity.y;
playerRigidBody.velocity = newVelocity;
So i am really really new to Unity and C# and i was just trying out some things. Now i want to kinda polish the overall control experience. So i want the Camera to rotate 5° on the Z axis when the Button A is pressed.
Thats what i tried:
if (Input.GetKeyDown(KeyCode.A))
{
if (zRotation < 5f)
{
transform.localRotation = Quaternion.Euler(zRotation, 5f, 5f);
}
}
It somewhat works, the camera rotates to 5° on the Z but only for i split second and then returns to it's normal state.
Full Code of the Camera Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mouseLook : MonoBehaviour
{
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
float zRotation = 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);
if (Input.GetKeyDown(KeyCode.A))
{
if (zRotation < 5f)
{
transform.localRotation = Quaternion.Euler(zRotation, 5f, 5f);
}
}
}
}
I want the Camera to rotate 5° on the Z axis when the Button A is pressed.
You don't need any variables to achieve this, it should be as simple as:
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
cameraTransform.Rotate(0, 0, 5);
}
}
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);
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);
}
}