the problem is that if the player touches something that rotate, the player automatically starting rotating too because the object that is rotation right now pushed the player's colliders and and player starting rotating. I want to make my player un rotatable to another objects in the game but rotatable if the player rotate by himself
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camera : MonoBehaviour
{
public enum RotationAxis
{
MouseX = 1,
MouseY = 2
}
public RotationAxis axes = RotationAxis.MouseX;
public float minimumVert = -45.0f;
public float maximumVert = 45.0f;
public float sensHorizontal = 10.0f;
public float sensVertical = 10.0f;
public float _rotationX = 0;
// Update is called once per frame
void Update()
{
if (axes == RotationAxis.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensHorizontal, 0);
}
else if (axes == RotationAxis.MouseY)
{
_rotationX -= Input.GetAxis("Mouse Y") * sensVertical;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert); //Clamps the vertical angle within the min and max limits (45 degrees)
float rotationY = transform.localEulerAngles.y;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
}
}
You could store the rotation in a field and thus making sure the only thing changing it is your script:
move it to LateUpdate in order for it to be the last thing called in a frame (also see Order of Execution for Event Functions)
float xRotation;
float yRotation;
void Start()
{
xRotation = transform.localEulerAngles.x;
yRotation = transform.localEulerAngles.y;
}
void LateUpdate()
{
if (axes == RotationAxis.MouseX)
{
yRotation += Input.GetAxis("Mouse X") * sensHorizontal;
}
else if (axes == RotationAxis.MouseY)
{
xRotation -= Input.GetAxis("Mouse Y") * sensVertical;
//Clamps the vertical angle within the min and max limits (45 degrees)
xRotation= Mathf.Clamp(lastXRotation , minimumVert, maximumVert);
}
// always overwrite with fixed values instead of using transform.rotation based ones
transform.localRotation = Quaternion.Euler(xRotation, yRotation, 0);
}
just to be sure you could also additionally but it to FixedUpdate in order to also reset changes from the Physics. If there is any RigidBody in play this should be the way to go anyway but then not using the Transform but rather the Rigidbody component.
void FixedUpdate()
{
transform.localRotation = Quaternion.Euler(xRotation, yRotation, 0);
}
Note however: As you currently have it setup you will get unexpected rotations. Rotating around the two axis here has the problem of also rotating along the local coordinate system.
In general you should rather have a parent object for the Y rotation and only do the X rotation on the object itself.
Related
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraScript : MonoBehaviour
{
[SerializeField] private float sensitivityHor = 9.0f;
[SerializeField] private float sensitivityVert = 9.0f;
[SerializeField] private float minimumVert = -45.0f;
[SerializeField] private float maximumVert = 45.0f;
private float _rotationX = 0;
private Rigidbody PlayerRigidbody;
void Start()
{
PlayerRigidbody = GetComponent<Rigidbody>();
if (PlayerRigidbody != null)
{
PlayerRigidbody.freezeRotation = true;
}
}
void Update()
{
_rotationX -= Input.GetAxis("Mouse Y") * sensitivityVert;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert);
float delta = Input.GetAxis("Mouse X") * sensitivityHor;
float rotationY = transform.localEulerAngles.y + delta;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
}
Good evening. I have written a script to rotate the camera by swiping a finger across the screen
(it is on my camera), everything works correctly with one finger, but if you touch with two fingers at the same time, the application will react incorrectly (suddenly change the camera rotation). How can I fix it using Input.GetAxis or what can I use to write a script for multiple touches?
You may use only the first touch for your movement, so that if there is a second nothing happens and change Input.GetAxis("Mouse Y") by Input.GetTouch(0).deltaPosition.y with x and y respectively. Like this:
if (Input.touchCount > 0) {
_rotationX -= Input.GetTouch(0).deltaPosition.y * sensitivityVert;
_rotationX = Mathf.Clamp(_rotationX, minimumVert, maximumVert);
float delta = Input.GetTouch(0).deltaPosition.x * sensitivityHor;
float rotationY = transform.localEulerAngles.y + delta;
transform.localEulerAngles = new Vector3(_rotationX, rotationY, 0);
}
Code not debugged, as its just your code with the substitution.
If handling the first touch acts weird, you can handle the rotation with the middle point maybe. Like this:
//get the touch middle when the second finger touches
if (Input.GetTouch(1).phase == TouchPhase.Began) {
touchMiddle = (Input.GetTouch(0).position +
Input.GetTouch(1).position) / 2;
touchDistSqr = (Input.GetTouch(0).position -
Input.GetTouch(1).position).sqrMagnitude;
return;
}
if (Input.touchCount == 2) {
var deltaMidde = touchMiddle - (Input.GetTouch(0).position + Input.GetTouch(1).position) / 2;
transform.localEulerAngles = new Vector3(deltaMidde.x, deltaMidde.y, 0);
}
All the code in the LateUpdate().
Preferably camera movements needs to be done in the LateUpdate() for the objects that might have moved inside Update to be at their final state for each frame. As per adviced in the documentation.
Not really relevant but note that you can use Vector2 instead of Vector3for the screen operations most of the time.
Also it is very interesting in the Update or LateUpdate operations to have them multiplied by Time.deltaTime so that the movement is frame rate independent.
So, I'm making a Survival Game in First Person and this is my code for the Player. But the error is the layer keeps laying down. Even tho there is no gravity. Here is my code:
using UnityEngine;
public class Movement : 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);
}
}
In your Mathf.Clamp function you use -90 two times, thus setting the xRotation to -90 every time. You propably want to Clamp it between -90 and 90.
Edit: xRotation is reduced using mouseY every frame, but it is never reset. This means, that moving the mouse to the right will cause the camera to continue rotating even after the mouse has stopped moving. You propably want to set xRotation using -mouseY (or plus? not sure) instead of reducing it by mouseY. This should make the camera stop spinning while the mouse is not moved.
I create a game, like minigolf/pool. I want to have a camera which follow player.
Position is normally ok, I get the ball direction and I lerp.
Rotation is almost ok. Currently, rotation by Y axis is ok, but camera look straigth forward, and don't look down to the player :
I already try many thing , quaternion angleToaxis, quarternion lookat ... but doesn't look good, the camera go look away ...
Here my code
namespace CameraManagerNameSpace
{
public class CameraManager : MonoBehaviour
{
public float cameraHeight=13f;
public PlayerNameSpace.Player playerToFollow;
public float followSpeed = 3f;
public float rotationSpeed = 1f;
float distance;
Vector3 position;
Vector3 newPos;
Quaternion rotation;
Quaternion newRot;
Vector3 playerPrevPos, playerMoveDir;
bool firstMoveDone=false;
void Start()
{
playerPrevPos = playerToFollow.player_transform.position;
distance = Vector3.Distance(transform.position,playerToFollow.player_transform.position);
}
void FixedUpdate()
{
if(Vector3.Distance(playerToFollow.player_transform.position ,playerPrevPos)>0.5f || firstMoveDone)
{
playerMoveDir = playerToFollow.player_transform.position - playerPrevPos;
firstMoveDone = true;
}
else
{
playerMoveDir = new Vector3(0,0,0);
}
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.Normalize();
newPos = playerToFollow.player_transform.position - playerMoveDir * distance;
newRot =Quaternion.LookRotation(playerMoveDir,Vector3.up);
position = Vector3.Lerp(transform.position, new Vector3(newPos.x,newPos.y+cameraHeight,newPos.z), followSpeed * Time.deltaTime);
rotation = Quaternion.Lerp(transform.rotation, newRot, rotationSpeed * Time.deltaTime);
transform.position = position;
transform.rotation = rotation;
playerPrevPos = playerToFollow.player_transform.position;
}
}
}
}
Also, I don't know why, but after the balls stop the camera continue to do some movement very jerky, jolting, halting.
Well in
newRot = Quaternion.LookRotation(playerMoveDir,Vector3.up);
you are saying the camera to look in the same direction the player is moving ... not to look at the player. This would work if you wouldn't give the camera an extra position offset in the Y axis.
You might want to rather try
// vector pointing from the camera towards the player
var targetDirection = playerToFollow.player_transform.position - transform.position;
newRot = Quaternion.LookRotation(targetDirection, Vector3.up);
You should also rather use Update since FixedUpdate is only used for physics related stuff (also see Update & FixedUpdate)
I have a problem with the Fixed joystick when I apply rotation to the main camera. The controls are mixed. How can I resolve this problem? Do I need to use other type of joystick? Where I should put "-" ? in front of which number
using System.Collections.Generic;
using UnityEngine;
[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 (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
float turnAngleChange = (touch.deltaPosition.x / Screen.width) * sensitivityX;
float pitchAngleChange = (touch.deltaPosition.y / Screen.height) * sensitivityY;
// Handle any pitch rotation
if (axes == RotationAxes.MouseXAndY || axes == RotationAxes.MouseY)
{
rotationY = Mathf.Clamp(rotationY + pitchAngleChange, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0f);
}
// Handle any turn rotation
if (axes == RotationAxes.MouseXAndY || axes == RotationAxes.MouseX)
{
transform.Rotate(0f, turnAngleChange, 0f);
}
}
void Start()
{
//if(!networkView.isMine)
//enabled = false;
// Make the rigid body not change rotation
//if (rigidbody)
//rigidbody.freezeRotation = true;
}
}
}
I don't really get your question so I'm gonna answer both of my interpretations.
If the rotation of the camera is inverted (if you put your stick to the left the camera rotates to the right) you just need to add a minus in front of the speed you're rotating the camera with.
If the rotation of the camera happens when you use the left stick and you want to use the right stick. Then you should define in your input a field called something like camera-rotation-x and use the axis shown on the following pictures in the article here: https://gamedev.stackexchange.com/questions/150323/unity3d-how-to-use-controller-joystick-to-look-around If you follow that article, your camera rotation should work.
I am creating a game where the world is 3D yet the characters are 2D. This means that my Y rotation must not change or else the 2D sprite rotates. I have a been scripting an AI and while the enemy does attract towards my player, he also rotates by 90 degrees. How can I modify my code to make it so that the sprite follows my player in the X and Z axis but the Y axis rotation stays zero.
//CODE STARTS
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AISimple : MonoBehaviour
{
public Transform player;
float distancefrom_player;
public float look_range = 20.0f;
public float agro_range = 10.0f;
public float move_speed = 5.0f;
public float damping = 6.0f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
distancefrom_player = Vector3.Distance(player.position, transform.position);
if (distancefrom_player < look_range)
{
lookAt();
}
if (distancefrom_player < agro_range)
{
attack();
}
}
void lookAt()
{
Quaternion rotation = Quaternion.LookRotation(player.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
}
void attack()
{
transform.Translate(Vector3.forward * move_speed * Time.deltaTime);
}
}
rigidbody has this functionality, if you tick freeze y rotation you'll be fine
okay, then try to modify y rotation before you set it
void lookAt()
{
Quaternion rotation = Quaternion.LookRotation(player.position - transform.position);
var euler = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping).eulerAngles;
euler.y = 0f;
transform.rotation = Quaternion.Euler(euler);
}