I have a script for my camera controls and the panning seems to be difficult to get working, ScreenToWorldPoint() is returning weird values and while the mouse is not even being moved.
The panning should have the world stick the cursor (Kind of like the unity editor it's self)
Create a CS file called "CameraControls" and paste the code below, asign it to a camera, and try to pan using middle click, It will move the camera crazily.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControls : MonoBehaviour {
public float ZoomSpeed = 0.5f;
public float MinZoom = 0.5f;
public float MaxZoom = 20f;
// Update is called once per frame
void Update() {
// Zoom out
if (Input.GetAxis("Mouse ScrollWheel") < 0) {
if (Camera.main.orthographicSize < MaxZoom) {
Camera.main.orthographicSize += ZoomSpeed;
}
}
// Zoom in
if (Input.GetAxis("Mouse ScrollWheel") > 0) {
if (Camera.main.orthographicSize > MinZoom) {
Camera.main.orthographicSize -= ZoomSpeed;
}
}
// Pan
if (Input.GetMouseButton(2)) {
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); //<-- Problem
transform.position = new Vector3(mousePos.x, mousePos.y, transform.position.z);
}
}
}
Related
Should I use Cinemachine for that or it's better to do it with a script from scratch ?
The script is attached to the Main Camera.
Now it's orbit only left right. I want it to orbit 360 degrees with clamp so it wont move down to the floor and to up back.
I should also the Y and not only the X but not sure how.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFollow : MonoBehaviour {
public Transform PlayerTransform;
private Vector3 _cameraOffset;
[Range(0.01f, 1.0f)]
public float SmoothFactor = 0.5f;
public bool LookAtPlayer = false;
public bool RotateAroundPlayer = true;
public float RotationsSpeed = 5.0f;
// Use this for initialization
void Start () {
_cameraOffset = transform.position - PlayerTransform.position;
}
// LateUpdate is called after Update methods
void LateUpdate () {
if(RotateAroundPlayer)
{
Quaternion camTurnAngle =
Quaternion.AngleAxis(Input.GetAxis("Mouse X") * RotationsSpeed, Vector3.up);
_cameraOffset = camTurnAngle * _cameraOffset;
}
Vector3 newPos = PlayerTransform.position + _cameraOffset;
transform.position = Vector3.Slerp(transform.position, newPos, SmoothFactor);
if (LookAtPlayer || RotateAroundPlayer)
transform.LookAt(PlayerTransform);
}
}
I want to rotate camera around a gameObject (Say a cube) on a drag of my mouse to simulate a feeling that the gameObject is rotating (Just like we rotate object in scene editor and like in shopping websites).
The script below is the one that I'm using. But sometimes the script behaves very weirdly. The camera rotates in the opposite direction than the anticipated direction. Why is this happening? What changes do I need to make in the code to make it work? Please help.
using UnityEngine;
using System.Collections;
public class ExampleBehaviourScript : MonoBehaviour
{
public Camera cameraObj;
public GameObject myGameObj;
public float speed = 2f;
void Update()
{
RotateCamera();
}
void RotateCamera()
{
if(Input.GetMouseButton(0))
{
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.up,
-Input.GetAxis("Mouse X")*speed);
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.right,
-Input.GetAxis("Mouse Y")*speed);
}
}
}
I think it is caused by the reference axis.
Because you used Vector3.up, Vector3.right, not the camera's one, it wasn't rotated the anticipated direction.
So, you should change like below.
void RotateCamera()
{
if(Input.GetMouseButton(0))
{
cameraObj.transform.RotateAround(myGameObj.transform.position,
cameraObj.transform.up,
-Input.GetAxis("Mouse X")*speed);
cameraObj.transform.RotateAround(myGameObj.transform.position,
cameraObj.transform.right,
-Input.GetAxis("Mouse Y")*speed);
}
}
My solution to rotate the camera in Unity with Mouse or Touch
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class CameraRotator : MonoBehaviour
{
public Transform target;
public Camera mainCamera;
[Range(0.1f, 5f)]
[Tooltip("How sensitive the mouse drag to camera rotation")]
public float mouseRotateSpeed = 0.8f;
[Range(0.01f, 100)]
[Tooltip("How sensitive the touch drag to camera rotation")]
public float touchRotateSpeed = 17.5f;
[Tooltip("Smaller positive value means smoother rotation, 1 means no smooth apply")]
public float slerpValue = 0.25f;
public enum RotateMethod { Mouse, Touch };
[Tooltip("How do you like to rotate the camera")]
public RotateMethod rotateMethod = RotateMethod.Mouse;
private Vector2 swipeDirection; //swipe delta vector2
private Quaternion cameraRot; // store the quaternion after the slerp operation
private Touch touch;
private float distanceBetweenCameraAndTarget;
private float minXRotAngle = -80; //min angle around x axis
private float maxXRotAngle = 80; // max angle around x axis
//Mouse rotation related
private float rotX; // around x
private float rotY; // around y
private void Awake()
{
if (mainCamera == null)
{
mainCamera = Camera.main;
}
}
// Start is called before the first frame update
void Start()
{
distanceBetweenCameraAndTarget = Vector3.Distance(mainCamera.transform.position, target.position);
}
// Update is called once per frame
void Update()
{
if (rotateMethod == RotateMethod.Mouse)
{
if (Input.GetMouseButton(0))
{
rotX += -Input.GetAxis("Mouse Y") * mouseRotateSpeed; // around X
rotY += Input.GetAxis("Mouse X") * mouseRotateSpeed;
}
if (rotX < minXRotAngle)
{
rotX = minXRotAngle;
}
else if (rotX > maxXRotAngle)
{
rotX = maxXRotAngle;
}
}
else if (rotateMethod == RotateMethod.Touch)
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
//Debug.Log("Touch Began");
}
else if (touch.phase == TouchPhase.Moved)
{
swipeDirection += touch.deltaPosition * Time.deltaTime * touchRotateSpeed;
}
else if (touch.phase == TouchPhase.Ended)
{
//Debug.Log("Touch Ended");
}
}
if (swipeDirection.y < minXRotAngle)
{
swipeDirection.y = minXRotAngle;
}
else if (swipeDirection.y > maxXRotAngle)
{
swipeDirection.y = maxXRotAngle;
}
}
}
private void LateUpdate()
{
Vector3 dir = new Vector3(0, 0, -distanceBetweenCameraAndTarget); //assign value to the distance between the maincamera and the target
Quaternion newQ; // value equal to the delta change of our mouse or touch position
if (rotateMethod == RotateMethod.Mouse)
{
newQ = Quaternion.Euler(rotX , rotY, 0); //We are setting the rotation around X, Y, Z axis respectively
}
else
{
newQ = Quaternion.Euler(swipeDirection.y , -swipeDirection.x, 0);
}
cameraRot = Quaternion.Slerp(cameraRot, newQ, slerpValue); //let cameraRot value gradually reach newQ which corresponds to our touch
mainCamera.transform.position = target.position + cameraRot * dir;
mainCamera.transform.LookAt(target.position);
}
public void SetCamPos()
{
if(mainCamera == null)
{
mainCamera = Camera.main;
}
mainCamera.transform.position = new Vector3(0, 0, -distanceBetweenCameraAndTarget);
}
}
To move your cube in the direction of mouse moves change your code like blow:
void RotateCamera()
{
if (Input.GetMouseButton(0))
{
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.up,
Input.GetAxis("Mouse X") * speed);
cameraObj.transform.RotateAround(myGameObj.transform.position,
Vector3.right,
-Input.GetAxis("Mouse Y") * speed);
}
}
I have a problem with camera movement using joystick in Unity. I wrote this code to my joystick
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class VirtualJoystick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler {
private Image bgImg;
private Image joystickImg;
private Vector2 pos;
private void Start()
{
bgImg = GetComponent<Image>();
joystickImg = transform.GetChild(0).GetComponent<Image>();
}
public virtual void OnDrag(PointerEventData ped)
{
Vector2 pos;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(bgImg.rectTransform, ped.position, ped.pressEventCamera, out pos))
{
pos.x = (pos.x * 2 + 1) / bgImg.rectTransform.sizeDelta.x;
pos.y = (pos.y * 2 - 1) / bgImg.rectTransform.sizeDelta.y;
pos = (pos.magnitude > 1.0f) ? pos.normalized : pos;
// Move Joystrick IMG
joystickImg.rectTransform.anchoredPosition = new Vector2(pos.x * (bgImg.rectTransform.sizeDelta.x / 3), pos.y * (bgImg.rectTransform.sizeDelta.y / 3));
}
}
public virtual void OnPointerDown(PointerEventData ped)
{
OnDrag(ped);
}
public virtual void OnPointerUp(PointerEventData ped)
{
pos = Vector2.zero;
joystickImg.rectTransform.anchoredPosition = Vector2.zero;
}
public float Horizontal()
{
if (pos.x != 0)
{
return pos.x;
}
else
{
return Input.GetAxis("Horizontal");
}
}
public float Vertical()
{
if (pos.y != 0)
{
return pos.y;
}
else
{
return Input.GetAxis("Vertical");
}
}
}
This code works well and return dynamicly Vector2(x,y). So, now I want to move camera (change position X,Y) using this joystick and these coordinates. Do you have any idea how to do it? Everyones show how to move cube or sphere and nowhere how to translate a camera...
Camera behave like any other game object in the scene
you translate , rotate , scale (will not be shown )
cause it is have Transform component .
This can be easily be done with the Translate function
Camera.main.transform.Translate(pos, Space.World);
You need to also multiply it a number(speed) and Time.deltaTime to make sure the movement is the-same on every devices.
So, this is how the code should look like:
private Vector2 pos;
public float moveSpeed = 100f;
Then, in your OnDrag or Update function:
Vector3 newPos = new Vector3(pos.x * moveSpeed, pos.y * moveSpeed, 0);
newPos *= Time.deltaTime;
Camera.main.transform.Translate(newPos, Space.World);
Edit : I need an answer for a 2D implementation, not 3D. So the 'Asked Before' question doesn't work for my project.
Edit : Using the accepted answer below, this is my working script. It's slightly off because the 0.1F part of the Vector3 is hard to get right, but it works. Time.deltaTime didn't work though.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour
{
private float zoom = 10;
Vector3 newPosition;
void Update()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
Camera.main.orthographicSize = zoom;
newPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.position = Vector3.Lerp(transform.position, newPosition, 0.1F);
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
Camera.main.orthographicSize = zoom;
}
}
}
Original Question : I have a basic script for zooming in and out, but when I zoom back in with the mouse-wheel, I want to zoom in to the point of the mouse cursor. I think you can see something similar in the Paradox Games (EU4 etc), where you zoom out, hold your mouse over a country off to the left of the screen, then zoom in and the country zooms in and becomes centered.
Here's my basic script so far, attached to my camera, which just zooms in and out in a straight line.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour {
public float zoom = 10F;
void Update () {
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
}
GetComponent<Camera>().orthographicSize = zoom;
}
}
I haven't tried this myself but I hope this will work.
Vector3 newPosition;
bool canZoom;
bool isMoving;
void Update ()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
canZoom = true;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
canZoom = true;
}
if (canZoom)
{
isMoving = true;
Camera.main.orthographicSize = zoom;
newPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
}
if (isMoving)
{
transform.position = Vector3.Lerp (transform.position, newPosition, Time.deltaTime);
}
if(transform.position == newPosition)
{
isMoving = false;
}
}
Note: If you want the camera to maintain certain camera height, adjust newPosision's y value before moving.
Hope this helps.
Calculate the difference in world space and move towards it while zooming.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour {
public float zoom = 10F;
void Update () {
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
}
Camera cam = GetComponent<Camera>();
RaycastHit hit;
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
Vector3 targetPos;
if (Physics.Raycast(ray , out hit))
{
targetPos = hit.point;
}
Camera cam = GetComponent();
cam.orthographicSize = zoom;
cam.transform.position += (targetPos - transform.position) / 5f;
}
}
I have an object called Ball, and I added keyboard interactivity to it(WASD to move the ball)
I need the camera to stay behind and follow the ball, but I am getting errors.
using UnityEngine;
using System.Collections;
public class ballmain : MonoBehaviour {
public bool isMoving = false;
public string direction;
public float camX;
public float camY;
public float camZ;
// Use this for initialization
void Start () {
Debug.Log("Can this run!!!");
}
// Update is called once per frame
void Update () {
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
camZ = rigidbody.transform.position.z;
camera.transform.position = new Vector3(camX, camY, camZ);
//followed by code that makes ball move
}
}
I get error "Assets/ballmain.cs(18,44): error CS1612: Cannot modify a value type return value of 'UnityEngine.Transform.position'. Consider storing the value in a temporary variable"
Does anyone know the answer? If I comment out the code about the camera the ball can move around.
here you go . a full code.
Simple Following
using UnityEngine;
using System.Collections;
public class Follow: MonoBehaviour {
public Transform target;
public float smooth= 5.0f;
void Update (){
transform.position = Vector3.Lerp (
transform.position, target.position,
Time.deltaTime * smooth);
}
}
Advanced Following
using UnityEngine;
using System.Collections;
public class SmoothFollowScript: MonoBehaviour {
// The target we are following
public Transform target;
// The distance in the x-z plane to the target
public int distance = 10.0;
// the height we want the camera to be above the target
public int height = 10.0;
// How much we
public heightDamping = 2.0;
public rotationDamping = 0.6;
void LateUpdate (){
// Early out if we don't have a target
if (TargetScript.russ == true){
if (!target)
return;
// Calculate the current rotation angles
wantedRotationAngle = target.eulerAngles.y;
wantedHeight = target.position.y + height;
currentRotationAngle = transform.eulerAngles.y;
currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position.y = currentHeight;
// Always look at the target
transform.LookAt (target);
}
}
}
If you just simply want to follow the target object align the position of the camera the way you want it and make the camera the child of the target object and the rest will do
Here're one script I found useful during my game development. I didn't create them so I give credit to wiki.unity3d.com for providing this amazing script.
Smooth Follow:
using UnityEngine;
using System.Collections;
public class SmoothFollow2 : MonoBehaviour {
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
}
More information about my work
Include Standard Mobile Asset to your project. It contains a SmoothFollow2D.js code in its script section. Attach this code with the gameobject and initialize public variables. This will simply do the job for you.
I found this simple and useful unity 2d camera follow script.
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start () {
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate () {
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp( transform.position, targetPos + offset, 0.25f);
}
}
}
source unity2d camera follow script
The -= in these lines:
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
is wrong. The -= will attempt to modify the rigidbody.transform.position. You just want -.
However, as it stands, the camera won't track changes in the target's Z position, nor will it track properly if the camera is rotated. To get the correct position you need (in vectors):-
cam_pos = target_pos - dist_to_target * cam_look_at