_xiaofang/xiaofang/Assets/Script/hylScripts/CameraSmoothMove.cs
2024-12-24 19:28:00 +08:00

207 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
public class CameraSmoothMove : MonoBehaviour
{
public Transform target; // 相机围绕的目标(建筑物)
public Vector3 offset = new Vector3(0f, 2f, -5f); // 相机初始偏移量
private float orbitSpeed = 1f; // 绕目标旋转的速度(度/秒)
public float smoothSpeed = 1f; // 平滑移动的速度
public float minDistance = 70f; // 最小距离
public float maxDistance = 80f; // 最大距离
public float scrollSpeed = 2f; // 鼠标滚轮控制距离的速度
private bool isOrbiting = true; // 是否正在绕建筑物旋转
private float orbitDuration = 7f; // 绕建筑物转一圈所需的时间
private Vector3 fixedPosition; // 相机停留的固定位置
private Quaternion fixedRotation; // 相机停留时的旋转
private float currentDistance; // 当前与目标的距离
private Transform mainCameraTransform; // Main Camera 的位置和旋转
// 俯瞰视角的位置和旋转
public Vector3 overlookPosition = new Vector3(0f, 70f, 90f); // 俯瞰视角的初始位置
public Quaternion overlookRotation = Quaternion.Euler(90f, 0f, 0f); // 俯瞰视角的旋转
public GameObject Canvas;
private void Start()
{
if (target == null)
{
Debug.LogError("目标建筑物未设置!");
return;
}
// 获取 Main Camera 的 Transform
mainCameraTransform = Camera.main.transform;
// 设置初始距离
currentDistance = 20f; // 初始俯瞰距离
// 计算旋转结束时相机应该停留的位置和旋转
fixedPosition = mainCameraTransform.position;
fixedRotation = mainCameraTransform.rotation;
Canvas.gameObject.SetActive(false);
// 开始整个流程
StartCameraSequence();
}
private void Update()
{
// 响应鼠标滚轮输入,控制俯瞰视角与目标的距离
if (!isOrbiting)
{
float scrollInput = Input.GetAxis("Mouse ScrollWheel");
currentDistance -= scrollInput * scrollSpeed; // 增加或减少距离
currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
// 更新俯瞰视角的位置
overlookPosition = target.position + new Vector3(0f, currentDistance, 0f);
}
}
// 开始相机控制流程
public async void StartCameraSequence()
{
// 1. 从当前视角移动到俯瞰视角
await MoveToOverlookPointAsync();
// 2. 从俯瞰视角移动到环绕开始点
await MoveToOrbitStartPointAsync();
// 3. 环绕目标
StartOrbit();
}
// 启动围绕建筑物旋转
public async void StartOrbit()
{
isOrbiting = true;
await OrbitAsync();
StopOrbit();
}
// 停止围绕建筑物旋转,平滑过渡到 Main Camera 的位置和旋转
public async void StopOrbit()
{
isOrbiting = false;
// 获取 Main Camera 的最新位置和旋转
fixedPosition = mainCameraTransform.position;
fixedRotation = mainCameraTransform.rotation;
await MoveToFixedPositionAsync();
}
// 异步方法:通过 async 实现绕建筑物平滑旋转一圈
private async Task OrbitAsync()
{
float elapsedTime = 0f;
while (elapsedTime < orbitDuration)
{
if (!isOrbiting) break; // 提前退出
elapsedTime += Time.deltaTime;
// 计算旋转角度
float angle = Mathf.Lerp(0, 360f, elapsedTime / orbitDuration);
Vector3 offsetPosition = new Vector3(
Mathf.Cos(Mathf.Deg2Rad * angle) * currentDistance,
offset.y,
Mathf.Sin(Mathf.Deg2Rad * angle) * currentDistance
);
// 更新相机位置
transform.position = target.position + offsetPosition;
transform.LookAt(target); // 保持相机面向目标
await Task.Yield(); // 等待下一帧
}
}
// 异步方法:平滑过渡到 Main Camera 的位置和旋转
private async Task MoveToFixedPositionAsync()
{
float elapsedTime = 0f;
Vector3 startPosition = transform.position;
Quaternion startRotation = transform.rotation;
while (elapsedTime < 1f)
{
elapsedTime += Time.deltaTime * smoothSpeed;
// 平滑地插值相机位置和旋转
transform.position = Vector3.Lerp(startPosition, fixedPosition, elapsedTime);
transform.rotation = Quaternion.Lerp(startRotation, fixedRotation, elapsedTime);
await Task.Yield(); // 等待下一帧
}
// 确保最终位置和旋转与 Main Camera 对齐
transform.position = fixedPosition;
transform.rotation = fixedRotation;
// 隐藏相机
HideCamera();
}
// 异步方法:从俯瞰视角移动到环绕开始点
private async Task MoveToOrbitStartPointAsync()
{
float elapsedTime = 0f;
Vector3 startPosition = transform.position;
Quaternion startRotation = transform.rotation;
Vector3 orbitStartPosition = target.position + offset;
while (elapsedTime < 1f)
{
elapsedTime += Time.deltaTime * smoothSpeed;
// 平滑地插值到环绕起始点
transform.position = Vector3.Lerp(startPosition, orbitStartPosition, elapsedTime);
transform.rotation = Quaternion.Lerp(startRotation, Quaternion.LookRotation(target.position - orbitStartPosition), elapsedTime);
await Task.Yield(); // 等待下一帧
}
}
// 异步方法:从当前视角移动到俯瞰视角
private async Task MoveToOverlookPointAsync()
{
float elapsedTime = 0f;
Vector3 startPosition = transform.position;
Quaternion startRotation = transform.rotation;
while (elapsedTime < 1f) // 调整平滑过渡的持续时间
{
elapsedTime += Time.deltaTime * smoothSpeed;
// 从当前位置平滑移动到俯瞰位置
transform.position = Vector3.Lerp(startPosition, overlookPosition, elapsedTime);
transform.rotation = Quaternion.Lerp(startRotation, overlookRotation, elapsedTime);
await Task.Yield(); // 等待下一帧
}
// 确保到达俯瞰视角位置
transform.position = overlookPosition;
transform.rotation = overlookRotation;
}
// 隐藏相机的方法
private void HideCamera()
{
// 方法 1禁用 Camera 组件
GetComponent<Camera>().enabled = false;
Canvas.gameObject.SetActive(true);
Debug.Log("相机已隐藏");
}
}