由于项目中开发离不开相机视角的移动缩放等等,每次重新写比较麻烦,于是小编总结了一些移动效果较好一点的代码,分鼠标事件和触摸事件(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().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();
//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() //相机的遮挡剔除
{
}
}