相机围绕物体旋转,并且有Y轴角度限制,可通过parameters.offset 修改使目标物不在画面中心
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class CameraController : MonoBehaviour
{
public static CameraController instance;
public Transform ModelRoot; //目标物
public Transform[] targets; //空物体
[HideInInspector]
public int index; // 当前的场景
private int comeBack = 0; // 返回主页计数
private Transform curtarget; // 当前摄像机锁定的目标
[System.Serializable]
public class CameraParameters
{
public bool smoothFollow; // 是否开启平滑跟随
public float followSpeed; // 跟随速度
public float distance; // 相机的初始距离
public float minDistance; // 最小距离
public float maxDistance; // 最大距离
public float zoomSpeed; // 缩放速度
public float zoomSensitivity; // 缩放灵敏度
public float rotationSensitivity; // 旋转灵敏度
public float yMinLimit; // 垂直最小值
public float yMaxLimit; // 垂直最大值
public Vector3 offset; // 偏移量
public float inFade = 0.6f; // 材质淡入
public float outFade = 1.0f; // 材质淡出
}
public CameraParameters parameters; // 相机相关参数
public float x { get; private set; } // 相机X方向旋转量
public float y { get; private set; } // 相机Y方向旋转量
public float distanceTarget { get; private set; } // 目标距离
private Vector3 position;
private Quaternion rotation = Quaternion.identity;
private Vector3 smoothPosition;
private Camera cam;
[HideInInspector]
public bool isRay = true; // 射线检测开关,在主场景才开启射线拾取
private GameObject rayTarget;
// 设备开机相关参数
public static bool isStart = false;
void Awake()
{
instance = this;
parameters = new CameraParameters();
InitCameraParaDefault(); // 设置相机的默认参数
index = 0;
curtarget = targets[index];
Vector3 angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
//目标距离
distanceTarget = parameters.distance;
smoothPosition = transform.position;
cam = Camera.main;
}
void Update()
{
if (isRay)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
Debug.DrawLine(ray.origin, hitInfo.point, Color.blue);//划出射线,只有在scene视图中才能看到
rayTarget = hitInfo.collider.gameObject;
}
else
{
rayTarget = null;
}
}
UpdateTransform();
}
#region 相机控制脚本
// 默认的相机参数设置
private void InitCameraParaDefault()
{
parameters.smoothFollow = false;
parameters.followSpeed = 2.0f;
parameters.minDistance = 0.0f;
parameters.maxDistance = 10.0f;
parameters.distance = 2f;
parameters.zoomSpeed = 10.0f;
parameters.zoomSensitivity = 1.0f;
parameters.rotationSensitivity = 3.5f;
parameters.yMinLimit = 0;
parameters.yMaxLimit = 8;
parameters.offset = new Vector3(-1.31f, 0.18f, -10.44f);
}
// 单个模型场景的相机参数设置
/// <summary>
/// maxDistance参数大于或等于distance参数
/// </summary>
/// <param name="distance"></param>
/// <param name="minDistance"></param>
/// <param name="maxDistance"></param>
/// <param name="offsetY"></param>
private void InitCameraParaOneModel(float distance, float minDistance, float maxDistance, float offsetY = 0.0f)
{
parameters.smoothFollow = false;
parameters.followSpeed = 5.0f;
parameters.minDistance = minDistance;
parameters.maxDistance = maxDistance;
parameters.distance = distance;
parameters.zoomSpeed = 5.0f;
parameters.zoomSensitivity = 1.0f;
parameters.rotationSensitivity = 3.5f;
parameters.yMinLimit = 0;
parameters.yMaxLimit = 8;
parameters.offset = new Vector3(0.0f, offsetY, 0.0f);
}
void LateUpdate()
{
UpdateInput();
}
// 获取用户鼠标信息
public void UpdateInput()
{
if (curtarget == null || !cam.enabled) return;
bool rotate = Input.GetMouseButton(0); // 判断鼠标是否右键按下
//delta rotation
if (rotate)
{
x += Input.GetAxis("Mouse X") * parameters.rotationSensitivity;
y = ClampAngle(y - Input.GetAxis("Mouse Y") * parameters.rotationSensitivity, parameters.yMinLimit, parameters.yMaxLimit);
}
// Distance
distanceTarget = Mathf.Clamp(distanceTarget + zoomAdd, parameters.minDistance, parameters.maxDistance);
}
// 更新相机位置
public void UpdateTransform()
{
UpdateTransform(Time.deltaTime);
}
public void UpdateTransform(float deltaTime)
{
if (curtarget == null || !cam.enabled) return;
// Distance
parameters.distance += (distanceTarget - parameters.distance) * parameters.zoomSpeed * deltaTime;
// Rotation
rotation = Quaternion.AngleAxis(x, Vector3.up) * Quaternion.AngleAxis(y, Vector3.right);
// Smooth follow
if (!parameters.smoothFollow) smoothPosition = curtarget.position;
else smoothPosition = Vector3.Lerp(smoothPosition, curtarget.position, deltaTime * parameters.followSpeed);
// Position
position = smoothPosition + rotation * (parameters.offset - Vector3.forward * parameters.distance);
// Translating the camera
transform.position = position;
transform.rotation = rotation;
}
// Zoom input 放大缩小
private float zoomAdd
{
get
{
float scrollAxis = Input.GetAxis("Mouse ScrollWheel");
if (scrollAxis > 0) return -parameters.zoomSensitivity;
if (scrollAxis < 0) return parameters.zoomSensitivity;
return 0;
}
}
// Clamping Euler angles
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
#endregion
}