2018-11-25修改:加入防止UI穿透,如果相机有PhysicsRaycaster组件,考虑检测到UI是否向下传递给3D物体
这时使用 EventSystem.current.IsPointerOverGameObject()的判断 不合适
2018-11-23修改:加入相机2D视角 和3D视角控制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
[System.Serializable]
public class LimitPoint
{
public Transform left;
public Transform right;
public Transform up;
public Transform down;
}
public class MoustControl : MonoBehaviour
{
public float minFov = 1f;
public float maxFov = 100f;
public float sensitivity = 15f;
enum RotationAxes { MouseXAndY, MouseX, MouseY }
RotationAxes axes = RotationAxes.MouseXAndY;
//@HideInInspector
float sensitivityX = 1.5f;
//@HideInInspector
float sensitivityY = 1.5f;
//private float minimumX = -360; 原文有此行但并未使用此变量
//private float maximumX = 360; 同上
float minimumY =-7;
float maximumY = 70;
private float rotationY = 0;
private float moveSpeed=0.3f;
private Vector3 lastPos;
private float fixedY = 0;
public bool is3D=false;
private bool isHoverUI;
private void Awake()
{
fixedY = transform.position.y;
}
void Update()
{
if (is3D)
{
float fov = Camera.main.fieldOfView;
fov += -Input.GetAxis("Mouse ScrollWheel") * sensitivity;
fov = Mathf.Clamp(fov, minFov, maxFov);
Camera.main.fieldOfView = fov;
//相机旋转
if (Input.GetMouseButton(1))
{
if (axes == RotationAxes.MouseXAndY)
{
float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
rotationY = transform.localEulerAngles.x + Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp(Mathf.Abs(rotationY), minimumY, maximumY);
transform.localEulerAngles = new Vector3(rotationY, rotationX, 0);
}
else if (axes == RotationAxes.MouseX)
{
transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
}
else
{
rotationY = transform.localEulerAngles.x + Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = Mathf.Clamp(Mathf.Abs(rotationY), minimumY, maximumY);
transform.localEulerAngles = new Vector3(rotationY, transform.localEulerAngles.y, 0);
}
}
}
if (Input.GetMouseButtonDown(0))
{
if (IsPointerOverUIObject(Input.mousePosition))//点击到UI上
{
//屏蔽UI 渗透场景下层
isHoverUI = true;
}
if (!isHoverUI)
{
lastPos = Input.mousePosition;
fixedY = transform.position.y;
}
}
else if (Input.GetMouseButton(0))
{
if (!isHoverUI)
{
Vector3 offset = (Input.mousePosition - lastPos) * moveSpeed;
if (is3D)
{
transform.Translate(new Vector3(-offset.x, 0, -offset.y));
}
else
{
transform.Translate(new Vector3(-offset.x, -offset.y, 0));
}
lastPos = Input.mousePosition;
transform.position = new Vector3(transform.position.x, fixedY, transform.position.z);
}
}
else if (Input.GetMouseButtonUp(0))
{
isHoverUI = false;
lastPos = Vector3.zero;
}
}
private void OnDestroy()
{
}
/// <summary>
///相机有Physics Raycaster组件 通过EventSystem 可以检测到UI,3D物体
///没有Physics Raycaster组件 通过EventSystem 只可以检测到UI
/// 如果Physics Raycaster组件 可以考虑选择是否要过滤3D物体
/// </summary>
/// <param name="screenPosition"></param>
/// <returns></returns>
public bool IsPointerOverUIObject(Vector2 screenPosition)
{
//实例化点击事件
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
//将点击位置的屏幕坐标赋值给点击事件
eventDataCurrentPosition.position = new Vector2(screenPosition.x, screenPosition.y);
List<RaycastResult> results = new List<RaycastResult>();
//向点击处发射射线
EventSystem.current.RaycastAll(eventDataCurrentPosition, results)
for (int i=results.Count-1;i>=0; i-- )
{
if (results[i].gameObject.layer==LayerMask.NameToLayer("Default"))
{
results.RemoveAt(i);
}
}
return results.Count > 0;
}
}