Unity相机的移动

由于项目中开发离不开相机视角的移动缩放等等,每次重新写比较麻烦,于是小编总结了一些移动效果较好一点的代码,分鼠标事件和触摸事件(EasyTouch)的2个版本。

鼠标版代码如下:

/*
 * 1.通过鼠标的操作对相机的控制
 * 
 * 2.操作方式: a.鼠标左键按下时拖动移动视角
 *             b.滑轮滚动对应视角拉进或拉远
 *             c.鼠标右键拖动进行视角的左右上下旋转
 *             d.是否锁定相机
 * 
 * 3.旋转相机时采用发射射线获取碰撞点并以其中心进行旋转的方式,
 *   当获取的碰撞点为NULL时,代表视角超出可视范围,此时停止相机的移动以及旋转;
 * 
 * 4.与此脚本想关联的脚本: StaticFunction.cs
 * 
 * 5.与此脚本相关联的插件: DoTween
 */

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class CameraMove : MonoBehaviour {

    public static CameraMove Instance = null;

    public LayerMask m_layerMask;

    private Transform m_camera = null;
    private GameObject m_tempObj = null;

    //相机可拉进拉远的最远距离
    private float m_Max;

    //相机的可移动范围(判断条件时使用世界坐标)
    private float m_XMax = 0;
    private float m_XMin = 0;
    private float m_YMax = 0;
    private float m_YMin = 0;
    public Transform LeftTop = null;
    public Transform RightBottom = null;

    public Transform Center = null;     //创建一个空物体使其在地图中心,并将其赋值

    private Vector2 m_ScreenCenterPoint = Vector2.zero;

    private void Awake()
    {
        if (Instance == null) Instance = this;
        else if (Instance != this) Destroy(this);
    }

    // Use this for initialization
    void Start () {
        m_camera = Camera.main.transform;

        m_tempObj = new GameObject("TempObj");
        m_tempObj.transform.parent = m_camera;
        m_tempObj.transform.localPosition = Vector3.zero;

        CorrectEulerAngles();

        m_ScreenCenterPoint = new Vector2(Screen.width / 2.0f, Screen.height / 2.0f);

        m_Max = m_camera.GetComponent<Camera>().fieldOfView + 20;

        m_XMin = LeftTop.position.x;
        m_XMax = RightBottom.position.x;
        m_YMin = RightBottom.position.z;
        m_YMax = LeftTop.position.z;
    }
	
	// Update is called once per frame
	void FixedUpdate () {

        if (Config.CameraIsLocked) return;

        if (Input.GetMouseButton(0))
        {
            MoveCamera(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 1);
        }
        else if (Input.GetMouseButton(1))
        {
            CorrectEulerAngles();
            RotateCamera(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 5);
        }
        else if (Input.GetMouseButtonUp(1))
        {
            
        }

        PullInOrPullAway(Input.GetAxis("Mouse ScrollWheel"), 10);
	}

    private void RotateCamera(float _MouseX, float _MouseY, float _Speed)  //旋转相机
    {
        Vector3 temp = GetScreenCenterHitPoint();
        m_camera.RotateAround(temp, Vector3.up, _MouseX * _Speed);

        float incremental = 10.0f;   //弧度的增量

        ///通过m_camera.eulerAngles.x的弧度来限制旋转角度

        //if (_MouseY * _Speed >= incremental) return;    //控制旋转幅度

        //if (m_camera.eulerAngles.x >= incremental && m_camera.eulerAngles.x <= (90 - incremental))
        //{
        //    m_camera.RotateAround(temp, m_camera.right, -_MouseY * _Speed);
        //}
        //else if (m_camera.eulerAngles.x < incremental)
        //{
        //    if (_MouseY < 0) m_camera.RotateAround(temp, m_camera.right, -_MouseY * _Speed);
        //}
        //else if (m_camera.eulerAngles.x > (90 - incremental))
        //{
        //    if (_MouseY > 0) m_camera.RotateAround(temp, m_camera.right, -_MouseY * _Speed);
        //}

        ///end


        //通过通过m_camera.forward与m_tempObj.transform.forward向量的夹角限制相机的旋转角度

        if (_MouseY * _Speed >= incremental) return;    //控制旋转幅度

        float angles = Vector3.Angle(m_camera.forward, m_tempObj.transform.forward);
        if (angles > incremental && angles < (90 - incremental))
        {
            m_camera.RotateAround(temp, m_camera.right, -_MouseY * _Speed);
        }
        else if (angles <= incremental)
        {
            if (_MouseY < 0) m_camera.RotateAround(temp, m_camera.right, -_MouseY * _Speed);
        }
        else if (angles >= (90 - incremental))
        {
            if (_MouseY > 0) m_camera.RotateAround(temp, m_camera.right, -_MouseY * _Speed);
        }

        //end
    }

    private void MoveCamera(float _MouseX, float _MouseY, float _Speed)     //移动相机
    {
        m_camera.Translate(Vector3.right * -_MouseX * _Speed, m_tempObj.transform);
        m_camera.Translate(Vector3.forward * -_MouseY * _Speed, m_tempObj.transform);
        
        ///控制相机的移动范围

        //if (m_camera.position.x <= m_XMin)
        //{
        //    m_camera.position = new Vector3(m_XMin, m_camera.position.y, m_camera.position.z);
        //}
        //else if (m_camera.position.x >= m_XMax)
        //{
        //    m_camera.position = new Vector3(m_XMax, m_camera.position.y, m_camera.position.z);
        //}

        //if (m_camera.position.z <= m_YMin)
        //{
        //    m_camera.position = new Vector3(m_camera.position.x, m_camera.position.y, m_YMin);
        //}
        //else if (m_camera.position.z >= m_YMax)
        //{
        //    m_camera.position = new Vector3(m_camera.position.x, m_camera.position.y, m_YMax);
        //}

        ///end
    }

    private void PullInOrPullAway(float _MouseScrollWheel, float _Speed)    //拉进拉远相机
    {
        ///通过改变相机的fieldOfView的值实现其效果

        //Camera temp = m_camera.GetComponent<Camera>();

        //if (_MouseScrollWheel > 0)
        //{
        //    if (temp.fieldOfView >= 10 + _Speed)
        //    {
        //        temp.fieldOfView -= _Speed;
        //    }
        //}

        //if (_MouseScrollWheel < 0)
        //{
        //    if (temp.fieldOfView <= m_Max)
        //    {
        //        temp.fieldOfView += _Speed;
        //    }
        //}

        ///end

        m_camera.Translate(Vector3.forward * _MouseScrollWheel * _Speed, Space.Self);
    }

    private bool IsOutOfRange()   //判断是否超出可视区域的范围,超出范围时停止相机的移动
    {
        Vector3 temp = GetScreenCenterHitPoint();
        if (temp != Vector3.zero)
        {
            return false;
        }

        return true;
    }

    private void CorrectEulerAngles()    //做相机以及TempObj游戏物体的轴方向的校正,便于相机的移动
    {
        m_tempObj.transform.eulerAngles = new Vector3(0, m_camera.eulerAngles.y, m_camera.eulerAngles.z);
    }

    private Vector3 GetScreenCenterHitPoint()
    {
        Vector3 temp = StaticFunction.GetClickedPoint(m_ScreenCenterPoint, m_layerMask);

        if (temp != Vector3.zero) return temp;

        return Vector3.zero;
    }

    public void SetEastPoint()
    {
        Vector3 point = new Vector3(LeftTop.position.x, m_camera.position.y, LeftTop.position.z - (LeftTop.position.z - RightBottom.position.z) / 2.0f);

        m_camera.position = point;
        m_camera.LookAt(Center);
    }

    public void SetSouthPoint()
    {
        Vector3 point = new Vector3(LeftTop.position.x + (RightBottom.position.x - LeftTop.position.x)/2.0f, m_camera.position.y, LeftTop.position.z);

        m_camera.position = point;
        m_camera.LookAt(Center);
    }

    public void SetWestPoint()
    {
        Vector3 point = new Vector3(RightBottom.position.x, m_camera.position.y, LeftTop.position.z - (LeftTop.position.z - RightBottom.position.z) / 2.0f);

        m_camera.position = point;
        m_camera.LookAt(Center);
    }

    public void SetNorthPoint()
    {
        Vector3 point = new Vector3(LeftTop.position.x + (RightBottom.position.x - LeftTop.position.x) / 2.0f, m_camera.position.y, RightBottom.position.z);

        m_camera.position = point;
        m_camera.LookAt(Center);
    }

    public void SetTopView()    //顶视图
    {
        m_camera.eulerAngles = new Vector3(90.0f, m_camera.eulerAngles.y, m_camera.eulerAngles.z);
        m_camera.DOMove(new Vector3(Center.position.x, m_camera.position.y, Center.position.z), 0.5f);
        CorrectEulerAngles();
    }
}

触摸版(EasyTouch)代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class CameraMove : MonoBehaviour {

    private bool m_isRotate = false;
    public Transform m_gameObject = null;
    private bool m_isThreeViewDrawing = false;    //是否开启三视图的功能

    private int m_speedControl = 40;    //视角移动速度的控制
    private int m_distance = 50;   //进行三视图观察时相机离游戏物体的距离

    private Vector3 m_replacePos = Vector3.zero;    //记录相机的俯视视角的坐标点

    private void OnEnable()
    {
        EasyTouch.On_TouchStart += On_TouchStart;
        EasyTouch.On_TouchDown += On_TouchDown;
        EasyTouch.On_TouchUp += On_TouchUp;
        EasyTouch.On_DoubleTap += On_DoubleTap;
        
        EasyTouch.On_TouchStart2Fingers += On_TouchStart2Fingers;
        EasyTouch.On_Cancel2Fingers += On_Cancel2Fingers;

        EasyTouch.On_PinchIn += On_PinchIn;
        EasyTouch.On_PinchOut += On_PinchOut;
        EasyTouch.On_PinchEnd += On_PinchEnd;

    }

    // Use this for initialization
    void Start () {
        
    }
	
	// Update is called once per frame
	void Update () {
        if (Config.IsRotate)
        {
            m_isRotate = true;
        }
        else if (!Config.IsRotate)
        {
            m_isRotate = false;
        }

        if (m_isThreeViewDrawing)
        {
            ThreeViewDrawing(Config.state_ThreeViewDrawing);
        }
    }

    private void OnDisable()
    {
        UnsubscribeEvent();
    }

    private void OnDestroy()
    {
        UnsubscribeEvent();
    }

    private void UnsubscribeEvent()
    {
        EasyTouch.On_TouchStart -= On_TouchStart;
        EasyTouch.On_TouchDown -= On_TouchDown;
        EasyTouch.On_TouchUp -= On_TouchUp;
        EasyTouch.On_DoubleTap -= On_DoubleTap;

        EasyTouch.On_TouchStart2Fingers -= On_TouchStart2Fingers;
        EasyTouch.On_Cancel2Fingers -= On_Cancel2Fingers;

        EasyTouch.On_PinchIn -= On_PinchIn;
        EasyTouch.On_PinchOut -= On_PinchOut;
        EasyTouch.On_PinchEnd -= On_PinchEnd;
    }

    // At the touch beginning 
    private void On_TouchStart(Gesture gesture)
    {
        Debug.Log("Touching Start");

        
    }

    // During the touch is down
    private void On_TouchDown(Gesture gesture)
    {
        Debug.Log("Touching Down");

        if (m_isRotate)   //旋转视角
        {
            RotateCamera(gesture);
        }
        else if (!m_isRotate)  //移动视角
        {
            MoveCamera(gesture);
        }
    }

    // At the touch end
    private void On_TouchUp(Gesture gesture)
    {
        Debug.Log("Touching Up");
        
    }

    // Double tap  
    private void On_DoubleTap(Gesture gesture)
    {
        Debug.Log("Double Tap");

        Ray ray = Camera.main.ScreenPointToRay(gesture.position);//从摄像机发出到触摸点坐标的射线
        RaycastHit hitInfo;
        if (Physics.Raycast(ray, out hitInfo))
        {
            if (hitInfo.collider.gameObject.tag == "House")
            {
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                m_gameObject = hitInfo.collider.gameObject.transform;
                Debug.Log("Find House And Name is " + m_gameObject.name);
                FocusOn(m_gameObject);
                m_replacePos = this.transform.position;
                m_isThreeViewDrawing = true;
            }
        }
    }

    // At the 2 fingers touch beginning
    private void On_TouchStart2Fingers(Gesture gesture)
    {
        Debug.Log("Touch Start 2Fingers");
        // Verification that the action on the object
        //if (gesture.pickedObject == gameObject)
        //{
        //    // disable twist gesture recognize for a real pinch end
        //    EasyTouch.SetEnableTwist(false);
        //    EasyTouch.SetEnablePinch(true);
        //}
    }

    // At the pinch in
    private void On_PinchIn(Gesture gesture)
    {
        Debug.Log("Pinch In");

        m_isThreeViewDrawing = false;

        Shrunk(gesture);

        // Verification that the action on the object
        //if (gesture.pickedObject == gameObject)
        //{
        //    float zoom = Time.deltaTime * gesture.deltaPinch;

        //    Vector3 scale = transform.localScale;
        //    transform.localScale = new Vector3(scale.x - zoom, scale.y - zoom, scale.z - zoom);
        //}

    }

    // At the pinch out
    private void On_PinchOut(Gesture gesture)
    {
        Debug.Log("Pinch Out");

        

        Enlarge(gesture);

        // Verification that the action on the object
        //if (gesture.pickedObject == gameObject)
        //{
        //    float zoom = Time.deltaTime * gesture.deltaPinch;

        //    Vector3 scale = transform.localScale;
        //    transform.localScale = new Vector3(scale.x + zoom, scale.y + zoom, scale.z + zoom);

        //}
    }

    // At the pinch end
    private void On_PinchEnd(Gesture gesture)
    {
        Debug.Log("Pinch End");
        //if (gesture.pickedObject == gameObject)
        //{
        //    transform.localScale = new Vector3(2.5f, 2.5f, 2.5f);
        //    EasyTouch.SetEnableTwist(true);
        //}

    }

    // If the two finger gesture is finished
    private void On_Cancel2Fingers(Gesture gesture)
    {
        Debug.Log("Cancel 2Fingers");
        //EasyTouch.SetEnablePinch(true);
        //transform.rotation = Quaternion.identity;
    }

    private void MoveCamera(Gesture _gesture)    //相机的移动
    {
        transform.Translate(Vector3.left * _gesture.deltaPosition.x / Screen.width * m_speedControl * 2);
        transform.Translate(Vector3.forward * -_gesture.deltaPosition.y / Screen.height * m_speedControl * 2, Space.World);
    }

    private void RotateCamera(Gesture _gesture)   //旋转相机
    {
        if (_gesture.position.x - _gesture.startPosition.x < 0)
        {
            transform.RotateAround(m_gameObject.position, Vector3.up, _gesture.deltaTime * m_speedControl);
        }
        else if (_gesture.position.x - _gesture.startPosition.x > 0)
        {
            transform.RotateAround(m_gameObject.position, Vector3.up, -_gesture.deltaTime * m_speedControl);
        }
    }

    private void Enlarge(Gesture _gesture)   //放大
    {
        //Camera.main.fieldOfView -= _gesture.deltaPinch * Time.deltaTime * m_speedControl * 0.5f;
        transform.Translate(Vector3.forward * _gesture.deltaPinch * Time.deltaTime * m_speedControl * 0.5f, Space.Self);
    }

    private void Shrunk(Gesture _gesture)   //缩小
    {
        //Camera.main.fieldOfView += _gesture.deltaPinch * Time.deltaTime * m_speedControl * 0.5f;
        transform.Translate(Vector3.forward * -_gesture.deltaPinch * Time.deltaTime * m_speedControl * 0.5f, Space.Self);
    }

    private void FocusOn(Transform _gameObject)    //把指定游戏物体作为中心的观察视角
    {
        Vector3 vec = _gameObject.transform.position;
        //vec.y += m_distance - 10;
        //vec.z -= m_distance - 10;
        //Sequence mySequence = DOTween.Sequence();
        //mySequence.Append(this.transform.DOMove(vec, 0.25f));
        //mySequence.Append(this.transform.DOLookAt(_gameObject.position, 0.01f));
        //mySequence.Play();

        this.transform.position = vec;
        this.transform.position -= this.transform.forward * m_distance;
    }

    private void ThreeViewDrawing(Config.State_ThreeViewDrawing _state)    //三视图视角的切换
    {
        Debug.Log("Enter ThreeViewDrawing");

        switch (_state)
        {
            case Config.State_ThreeViewDrawing.Left:
                this.transform.position = new Vector3(m_gameObject.position.x - m_distance, m_gameObject.position.y, m_gameObject.position.z);
                this.transform.DOLookAt(m_gameObject.position, 0.5f);
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                break;
            case Config.State_ThreeViewDrawing.Right:
                this.transform.position = new Vector3(m_gameObject.position.x + m_distance, m_gameObject.position.y, m_gameObject.position.z);
                this.transform.DOLookAt(m_gameObject.position, 0.5f);
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                break;
            case Config.State_ThreeViewDrawing.Front:
                this.transform.position = new Vector3(m_gameObject.position.x, m_gameObject.position.y, m_gameObject.position.z + m_distance);
                this.transform.DOLookAt(m_gameObject.position, 0.5f);
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                break;
            case Config.State_ThreeViewDrawing.Behind:
                this.transform.position = new Vector3(m_gameObject.position.x, m_gameObject.position.y, m_gameObject.position.z - m_distance);
                this.transform.DOLookAt(m_gameObject.position, 0.5f);
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                break;
            case Config.State_ThreeViewDrawing.Top:
                this.transform.position = new Vector3(m_gameObject.position.x, m_gameObject.position.y + m_distance, m_gameObject.position.z);
                this.transform.DOLookAt(m_gameObject.position, 0.5f);
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                break;
            case Config.State_ThreeViewDrawing.Replace:
                this.transform.position = m_replacePos;
                this.transform.DOLookAt(m_gameObject.position, 0.5f);
                Config.state_ThreeViewDrawing = Config.State_ThreeViewDrawing.Nothing;
                break;
            //case default:

            //    break;
        }
    }

    private void Border()    //相机移动的边界判断
    {

    }

    private void OcclusionCulling()   //相机的遮挡剔除
    {

    }
}

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值