362 lines
11 KiB
C#
362 lines
11 KiB
C#
using Cinemachine;
|
||
using DG.Tweening;
|
||
using HXSJFrameWork;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Reflection;
|
||
using UnityEngine;
|
||
|
||
public class CameraManager : MonoBehaviour
|
||
{
|
||
public static CameraManager _instance;
|
||
|
||
public Camera mainCam;//主相机
|
||
public Camera singleCam;//单体化展示相机
|
||
public GameObject curentSingleObj;//当前单体化的模型
|
||
|
||
//第一人称巡查
|
||
public CinemachineDollyCart firstcart;
|
||
public CinemachineSmoothPath firstPath; //第一人称巡查
|
||
public CinemachineDollyCart globalcart;
|
||
public List<CinemachineSmoothPath> globalpaths; //上帝视角巡查
|
||
|
||
|
||
|
||
public bool isInFirstRoam;//是否在第一人称漫游中
|
||
private float _roamSpeed = 1.5f;//巡查速度
|
||
|
||
private float camMoveSpeed = 10;//相机切换视角时的移动速度
|
||
|
||
private Vector3 camInitPos;//相机初始位置
|
||
private Vector3 camInitAngle;//相机初始角度
|
||
|
||
//待机时长
|
||
private float waitTime = 18;
|
||
|
||
Tweener t_camAnimAngle;//相机转动动画
|
||
Tweener t_camAnimPos;//相机移动动画
|
||
private void Awake()
|
||
{
|
||
_instance = this;
|
||
}
|
||
|
||
// Start is called before the first frame update
|
||
void Start()
|
||
{
|
||
camInitPos = mainCam.transform.position;
|
||
camInitAngle = mainCam.transform.eulerAngles;
|
||
}
|
||
|
||
private float UnFocusTime = 0;
|
||
//是否开始检测鼠标状态
|
||
private bool isStartCheck;
|
||
//是否在漫游过程中
|
||
private bool isInRoam;
|
||
|
||
// Update is called once per frame
|
||
void Update()
|
||
{
|
||
//if (Input.GetKeyDown(KeyCode.O))
|
||
//{
|
||
// GlobalRoam(true);
|
||
//}
|
||
//if (Input.GetKeyDown(KeyCode.P))
|
||
//{
|
||
// GlobalRoam(false);
|
||
//}
|
||
//return;
|
||
|
||
//处于第一人称漫游和不在第一个模块时,不计算待机时长
|
||
if (isInFirstRoam || MainUIManager._instance.curModuleIndex != 0)
|
||
return;
|
||
//鼠标有动静,清空计算无动静时长
|
||
if (Input.anyKey || Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
|
||
{
|
||
UnFocusTime = 0;
|
||
isStartCheck = true;
|
||
if (isInRoam)
|
||
{
|
||
Debug.Log("停止漫游");
|
||
isInRoam = false;
|
||
GlobalRoam(false);
|
||
}
|
||
}
|
||
if (isStartCheck)
|
||
{
|
||
//鼠标长时间未动,自动进入漫游
|
||
UnFocusTime += Time.deltaTime;
|
||
if (UnFocusTime > waitTime)
|
||
{
|
||
UnFocusTime = 0;
|
||
Debug.Log("长时间未动鼠标!");
|
||
isStartCheck = false;
|
||
isInRoam = true;
|
||
GlobalRoam(true);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 回到初始视角
|
||
/// </summary>
|
||
public void InitView(Action call = null)
|
||
{
|
||
CameraMoveTarget(camInitPos, Quaternion.Euler(camInitAngle), () => {
|
||
if (call != null)
|
||
call();
|
||
});
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 第一人称漫游
|
||
/// </summary>
|
||
/// <param name="args">true:开始巡查,false:结束巡查</param>
|
||
public void FirstAutoRoam(bool isRoam)
|
||
{
|
||
if (isRoam)
|
||
{
|
||
isInFirstRoam = true;
|
||
//从头开始
|
||
firstcart.m_Position = 0;
|
||
firstcart.m_Speed = 0.01f;
|
||
CameraStartRoam(firstcart.transform.position, Quaternion.Euler(firstcart.transform.eulerAngles), ()=>{
|
||
mainCam.GetComponent<ModelViewer>()._enabled = false;
|
||
firstcart.m_Speed = _roamSpeed;
|
||
mainCam.transform.parent = firstcart.transform;
|
||
mainCam.transform.localPosition = Vector3.zero;
|
||
mainCam.transform.localEulerAngles = Vector3.zero;
|
||
});
|
||
}
|
||
else
|
||
{
|
||
firstcart.m_Speed = 0;
|
||
mainCam.transform.parent = transform;
|
||
isInFirstRoam = false;
|
||
//回到初始视角
|
||
CameraMoveTarget(camInitPos, Quaternion.Euler(camInitAngle));
|
||
}
|
||
}
|
||
|
||
//全局漫游协程
|
||
Coroutine i_globalroam;
|
||
/// <summary>
|
||
/// 长时间不动鼠标,全局俯视漫游
|
||
/// </summary>
|
||
public void GlobalRoam(bool start)
|
||
{
|
||
if (start)
|
||
{
|
||
//开始全局漫游
|
||
i_globalroam = StartCoroutine(StartGlobalRoam());
|
||
}
|
||
else {
|
||
//停止全局漫游
|
||
StopCoroutine(i_globalroam);
|
||
StopGlobalRoam();
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 循环楼层
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public IEnumerator StartGlobalRoam()
|
||
{
|
||
//(从零开始)
|
||
int index = -1;
|
||
while (true)
|
||
{
|
||
index++;
|
||
index = index % MainUIManager._instance.buildFloorCount;
|
||
//根据索引选择路径漫游
|
||
//globalcart.m_Path = globalpaths[index];
|
||
StartGlobalRoam(globalpaths[index]);
|
||
//根据索引隐藏模型
|
||
MainUIManager._instance.ChangeFloor(index + 1);
|
||
//第一次结束
|
||
Debug.Log("全局漫游索引"+index);
|
||
Debug.Log(globalpaths[index].name +"长度"+ globalpaths[index].PathLength);
|
||
Debug.Log("时间" + (globalpaths[index].PathLength / _roamSpeed));
|
||
yield return new WaitForSeconds(globalpaths[index].PathLength / _roamSpeed);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 开始全局漫游(其中一层)
|
||
/// </summary>
|
||
/// <param name="cart">漫游路线</param>
|
||
public void StartGlobalRoam(CinemachineSmoothPath path)
|
||
{
|
||
if (t_camAnimAngle != null)
|
||
t_camAnimAngle.Kill();
|
||
if (t_camAnimPos != null)
|
||
t_camAnimPos.Kill();
|
||
globalcart.m_Path = path;
|
||
globalcart.m_Position = 0;
|
||
globalcart.m_Speed = 0.01f;
|
||
CameraStartRoam(globalcart.transform.position, Quaternion.Euler(globalcart.transform.eulerAngles.x + 75f, globalcart.transform.eulerAngles.y, globalcart.transform.eulerAngles.z), () =>
|
||
{
|
||
mainCam.GetComponent<ModelViewer>()._enabled = false;
|
||
|
||
globalcart.m_Speed = _roamSpeed;
|
||
mainCam.transform.parent = globalcart.transform;
|
||
mainCam.transform.localPosition = Vector3.zero;
|
||
mainCam.transform.localEulerAngles = new Vector3(75f, 0, 0);
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止全局漫游
|
||
/// </summary>
|
||
private void StopGlobalRoam()
|
||
{
|
||
globalcart.m_Speed = 0;
|
||
mainCam.transform.parent = transform;
|
||
//恢复观察楼层
|
||
MainUIManager._instance.ChangeFloor(MainUIManager._instance.curfloor);
|
||
//回到默认视角
|
||
InitView();
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 相机开始漫游,移动到漫游处,相机不可操作
|
||
/// </summary>
|
||
/// <param name="endPos"></param>
|
||
/// <param name="endAngle"></param>
|
||
/// <param name="call"></param>
|
||
public void CameraStartRoam(Vector3 endPos, Quaternion endAngle, Action call = null)
|
||
{
|
||
if (t_camAnimAngle != null)
|
||
t_camAnimAngle.Kill();
|
||
if (t_camAnimPos != null)
|
||
t_camAnimPos.Kill();
|
||
mainCam.GetComponent<ModelViewer>()._enabled = false;
|
||
float dis = float.Parse((mainCam.transform.position - endPos).magnitude.ToString("f3"));
|
||
//Debug.Log(dis+"@@@@@@");
|
||
float time = dis / camMoveSpeed;
|
||
t_camAnimPos = mainCam.transform.DOMove(endPos, time);
|
||
t_camAnimAngle = mainCam.transform.DORotate(endAngle.eulerAngles, time).OnComplete(() => {
|
||
if (call != null)
|
||
call();
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 相机直接移到目标位置(点击设备、人物等移动视角)
|
||
/// </summary>
|
||
/// <param name="endPos">相机终点位置</param>
|
||
/// <param name="endAngle">相机终点角度</param>
|
||
public void CameraMoveTarget(Vector3 endPos, Quaternion endAngle, Action call = null)
|
||
{
|
||
if (t_camAnimAngle != null)
|
||
t_camAnimAngle.Kill();
|
||
if (t_camAnimPos != null)
|
||
t_camAnimPos.Kill();
|
||
mainCam.GetComponent<ModelViewer>()._enabled = false;
|
||
float dis = float.Parse((mainCam.transform.position - endPos).magnitude.ToString("f3"));
|
||
//Debug.Log(dis+"@@@@@@");
|
||
float time = dis / camMoveSpeed;
|
||
t_camAnimPos = mainCam.transform.DOMove(endPos, time);
|
||
t_camAnimAngle = mainCam.transform.DORotate(endAngle.eulerAngles, time).OnComplete(() => {
|
||
if (call != null)
|
||
call();
|
||
CameraEnable();
|
||
});
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 移动相机:先拉高,再移动到目标视角
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <param name="angle"></param>
|
||
public void CamerMoveAnimAfter(Vector3 endPos, Quaternion endAngle, Action call = null)
|
||
{
|
||
if (t_camAnimAngle != null)
|
||
t_camAnimAngle.Kill();
|
||
if (t_camAnimPos != null)
|
||
t_camAnimPos.Kill();
|
||
mainCam.GetComponent<ModelViewer>()._enabled = false;
|
||
float dis = (mainCam.transform.position - camInitPos).magnitude;
|
||
float time = dis / camMoveSpeed;
|
||
Vector3 hightpoint = new Vector3(mainCam.transform.position.x, ModelManager.instance.wudingHeight+10f, mainCam.transform.position.z);
|
||
t_camAnimPos = mainCam.transform.DOMove(hightpoint, time);
|
||
t_camAnimAngle = mainCam.transform.DORotate(camInitAngle, time).OnComplete(() => {
|
||
t_camAnimPos.Kill();
|
||
t_camAnimAngle.Kill();
|
||
t_camAnimPos = mainCam.transform.DOMove(endPos, time);
|
||
t_camAnimAngle = mainCam.transform.DORotate(endAngle.eulerAngles, time).OnComplete(() =>
|
||
{
|
||
|
||
if (call != null)
|
||
call();
|
||
CameraEnable();
|
||
});
|
||
});
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 开启相机可操作性
|
||
/// </summary>
|
||
private void CameraEnable()
|
||
{
|
||
mainCam.GetComponent<ModelViewer>().InitTarget();
|
||
mainCam.GetComponent<ModelViewer>()._enabled = true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移动相机:相机在房间内,先回到初始角度再移至目标位置,相机在房间外,直接移动到目标位置
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <param name="angle"></param>
|
||
public void CameraMoveAnim(Vector3 endPos, Quaternion endAngle, Action call = null)
|
||
{
|
||
|
||
bool inview = true;
|
||
|
||
//判断物体是否在相机视角内TODO:前方是否有物体遮挡
|
||
Vector3 viewPos = mainCam.WorldToViewportPoint(endPos);
|
||
|
||
// z<0代表在相机背后
|
||
if (viewPos.z < 0)
|
||
inview = false;
|
||
//太远了!看不到了!
|
||
if (viewPos.z > mainCam.farClipPlane)
|
||
inview = false;
|
||
// x,y取值在 0~1之外时代表在视角范围外;
|
||
if (viewPos.x < 0 || viewPos.y < 0 || viewPos.x > 1 || viewPos.y > 1)
|
||
inview = false;
|
||
if (inview)
|
||
{
|
||
CameraMoveTarget(endPos, endAngle, call);
|
||
}
|
||
else
|
||
{
|
||
CamerMoveAnimAfter(endPos, endAngle, call);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 视角居中
|
||
/// </summary>
|
||
/// <param name="curPoint">当前居中的点位</param>
|
||
/// <param name="forward">当前居中的点位</param>
|
||
/// <param name="dis">当前居中的点位</param>
|
||
public void ViewCenterPoint(GameObject curPoint, Vector3 forward, float dis = 3, Action call = null)
|
||
{
|
||
Debug.Log("web:" + curPoint.name);
|
||
//获取模型中心点位置(加上模型方向*3)
|
||
Vector3 playerPos = curPoint.transform.position + forward * dis;
|
||
Quaternion angle = Quaternion.LookRotation(-forward); ;
|
||
Debug.Log("pos" + playerPos + ";angle" + angle);
|
||
CameraMoveAnim(playerPos, angle, call);
|
||
}
|
||
}
|