I have a ball which is focusing by a camera at random height and distance. On mouse scroll I want to zoom in-out my camera towards the ball. I have tried this weird code and its behaving weird as I expected.
void ZoomInOut() {
if(Input.GetAxis("Mouse ScrollWheel") > 0){
Debug.Log("mouse scroll wheel greater");
distance += 20.0f;
Vector3 negDistance = new Vector3(targetFollow.transform.position.x, targetFollow.transform.position.y, -distance);
Vector3 pos = transform.rotation * negDistance + targetFollow.transform.position;
transform.position = pos;
}
if(Input.GetAxis("Mouse ScrollWheel") < 0){
Debug.Log("mouse scroll wheel less");
distance -= 20.0f;
Vector3 negDistance = new Vector3(targetFollow.transform.position.x, targetFollow.transform.position.y, -distance);
Vector3 pos = transform.rotation * negDistance + targetFollow.transform.position;
transform.position = pos;
}
}
If want to zoom directly forwards/backwards, can use this: ZoomWithMouse.cs
It just moves camera along transform.forward axis.
using UnityEngine;
// Zoom forward and backward with mousewheel, Attach this script to camera
public class ZoomWithMouse : MonoBehaviour
{
public float zoomSpeed = 300;
void Update()
{
var mouseScroll = Input.GetAxis("Mouse ScrollWheel");
if (mouseScroll!=0)
{
transform.Translate(transform.forward * mouseScroll * zoomSpeed * Time.deltaTime, Space.Self);
}
}
}
source:
https://github.com/UnityCommunity/UnityLibrary/blob/master/Scripts/Camera/ZoomWithMouse.cs
using UnityEngine;
using System.Collections;
public class Zoom : MonoBehaviour
{
private float _speed = 10;
private void Update()
{
float mouseScroll = Input.GetAxis("Mouse ScrollWheel");
if (mouseScroll!=0)
{
transform.Translate(Mathf.Sign(mouseScroll) * transform.forward * _speed * Time.deltaTime, Space.World);
}
}
}
Related
I want to rotate my player for where my mouse is pointing and move the player with "WASD" keys.
I'm actually succesfully rotating my player and moving it, but it doesn't move right depending where my mouse is pointing.. the player just move everytime to the same position.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public int playerSpeed = 5;
public float sensitivity = 5.0f;
public bool blockMouse = true;
private float mouseX;
void Start(){
BlockMouse();
}
void Update() {
Move();
Rotate();
}
void Move()
{
Vector3 movement = new Vector3 (Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
transform.position += movement * playerSpeed * Time.deltaTime;
if(Input.GetKeyDown(KeyCode.LeftShift)) {
playerSpeed=10;
} else if(Input.GetKeyUp(KeyCode.LeftShift)) {
playerSpeed=5;
}
}
void Rotate() {
mouseX += Input.GetAxis("Mouse X") * sensitivity;
transform.eulerAngles = new Vector3(0, mouseX, 0);
}
void BlockMouse() {
if (!blockMouse) {
return;
}
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
}
``
Assuming the rotation is working as you said
transform.position += movement * playerSpeed * Time.deltaTime;
by doing this you change the objects world space absolute position, not taking any rotation into account.
Now there are probably a lot of ways how do rather do this
You could simply take the rotation into account
transform.position += transform.rotation * movement * playerSpeed * Time.deltaTime;
This simply stays in world space but rotates your world space vector accordingly
You could rather use Translate
transform.Translate(movement * playerSpeed * Time.deltaTime);
which basically does the same, takes orientation into account but is not affected by scaling
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 have a player in the game, which I can move using the keyboard and rotate only on the horizontal axis using the mouse. That means, I can aim only horizontally and I can not aim it up and down.
I have the Main Camera and another VM Camera from Cinemachine. The current state of the game is like this:
On the horizontal axis, I rotate the player, but on the vertical axis I only want the player's camera/FOV to be moved up and down.
My movement script attached to the player is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController characterController;
public float speed = 35f;
public Animator animator;
// camera and rotation
public Transform cameraHolder;
public float mouseSensitivity = 2f;
public float upLimit = 50;
public float downLimit = -50;
// gravity
private float gravity = 9.87f;
private float verticalSpeed = 0;
void Update()
{
Move();
Rotate();
}
public void Rotate()
{
float horizontalRotation = Input.GetAxis("Mouse X");
float verticalRotation = Input.GetAxis("Mouse Y");
transform.Rotate(0, horizontalRotation * mouseSensitivity, 0);
cameraHolder.Rotate(-verticalRotation * mouseSensitivity, 0, 0);
Vector3 currentRotation = cameraHolder.localEulerAngles;
if (currentRotation.x > 180) currentRotation.x -= 360;
currentRotation.x = Mathf.Clamp(currentRotation.x, upLimit, downLimit);
cameraHolder.localRotation = Quaternion.Euler(currentRotation);
}
private void Move()
{
float horizontalMove = Input.GetAxis("Horizontal");
float verticalMove = Input.GetAxis("Vertical");
if (characterController.isGrounded) verticalSpeed = 0;
else verticalSpeed -= gravity * Time.deltaTime;
Vector3 gravityMove = new Vector3(0, verticalSpeed, 0);
Vector3 move = transform.forward * verticalMove + transform.right * horizontalMove;
characterController.Move(speed * Time.deltaTime * move + gravityMove * Time.deltaTime);
}
}
This is the code i use, it works for me, it's super easy to implement, and stops moving the camera when you aren't focusing the game, is the script from one of Brackey's tutorials modified for this purpose:
using UnityEngine;
public class CameraController : MonoBehaviour
{
public PlayerController player;
public float sensitivity = 150f;
public float clampAngle = 85f;
public bool look = true;
private float verticalRotation;
private float horizontalRotation;
private void Start()
{
verticalRotation = transform.localEulerAngles.x;
horizontalRotation = player.transform.eulerAngles.y;
// Defines the state of the cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void Update()
{
// Looks around if the user is in the window
if (look)
{
Look();
}
Debug.DrawRay(transform.position, transform.forward * 2, Color.red);
// If the player presses ESC while in the game, it unlocks the cursor
if (look && Input.GetKeyDown(KeyCode.Escape))
{
look = false;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else if (Input.GetMouseButtonDown(0) && !look)
{
look = true;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
private void Look()
{
float _mouseVertical = -Input.GetAxis("Mouse Y");
float _mouseHorizontal = Input.GetAxis("Mouse X");
verticalRotation += _mouseVertical * sensitivity * Time.deltaTime;
horizontalRotation += _mouseHorizontal * sensitivity * Time.deltaTime;
verticalRotation = Mathf.Clamp(verticalRotation, -clampAngle, clampAngle);
transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);
player.transform.rotation = Quaternion.Euler(0f, horizontalRotation, 0f);
}
}
I have two scripts one is the MouseHandler and the other is the SimpleMovement. rotating the camera works and moving works however when the camera turns the movement doesn't go in that direction. E.G i turn the camera 90 degrees to the right but the forward doesn't change. The forward doesn't go to where the camera is facing. Sorry if i'm just being stupid. Any help would be appreciated
MouseHandler script:
public class MouseHandler : MonoBehaviour
{
// horizontal rotation speed
public float horizontalSpeed = 1f;
// vertical rotation speed
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, -90, 90);
cam.transform.eulerAngles = new Vector3(xRotation, yRotation, 0.0f);
}
}
SimpleMovement Script:
public class SimpleMovement : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private void Start()
{
characterController = GetComponent<CharacterController>();
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
characterController.Move((Vector3.right * horizontal + Vector3.forward * vertical) * Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
}
}
First, get a reference to the main cmaera and cache it, because you're going to be referencing it frequently, and simply using Camera.main is a bit expensive:
private Camera mainCam;
...
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
Then, use mainCam.transform.right and mainCam.transform.forward but with the y set to 0 and normalized instead of Vector3.right and Vector3.forward. This will make the movement be based on the rotation of the camera:
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0f,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0f,
mainCam.transform.forward.z).normalized;
characterController.Move(
(camRightFlat * horizontal + camForwardFlat * vertical) * Time.deltaTime);
Altogether:
public class SimpleMovement : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * MovementSpeed;
float vertical = Input.GetAxis("Vertical") * MovementSpeed;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0f,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0f,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
}
}
The spaceship start moving from point A. The spaceship is facing the moving direction.
Now when i click one on the L key i want that the spaceship will rotate and will face to the original position it was start moving from. But even if the spaceship is now rotated by axis Z or Y or X to rotate it first to the regular rotation values and to face to the start moving position.
using UnityEngine;
using System.Collections;
public class Control : MonoBehaviour
{
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private Vector3 originalPosition;
private Quaternion originalRotation;
// Use this for initialization
void Start()
{
originalPosition = transform.position;
originalRotation = transform.rotation;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey("p"))
{
isPKeyDown = Input.GetKey("p");
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
if (Input.GetKey("l"))
{
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0);
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
}
IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
{
float lerpSpeed = 0;
while (lerpSpeed < 1)
{
ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
lerpSpeed += Time.deltaTime * smooth;
yield return null;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is where i click the L button but i tried some things but can't yet find how to do it.
The main goal is if i click once on L the spaceship should automatic rotate if needed and move back to the original position and then land on ground. L stand for landing that's the main goal.
Add a variable on top -
...
private Vector3 originalPosition;
private Quaternion originalRotation;
private bool landShip = false;
...
And use following code in update function -
if (Input.GetKey("l"))
{
landShip = true;
//StartCoroutine(TurnShip(transform, transform., originalRotation.eulerAngles, 1));
//transform.position += transform.forward * Time.deltaTime * movementspeed;
}
if(landShip){
transform.rotation = Quaternion.Slerp(transform.rotation, originalRotation, 0.5f);
}
Once the spaceship lands, set the landShip value back to false.