_xiaofang/xiaofang/Assets/Script/hylScripts/CameraSmoothMove.cs
2024-12-18 16:35:39 +08:00

141 lines
4.1 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 = 0.5f; // 绕目标旋转的速度(度/秒)
public float smoothSpeed = 0.125f; // 平滑移动的速度
public float minDistance = 2f; // 最小距离
public float maxDistance = 15f; // 最大距离
public float scrollSpeed = 2f; // 鼠标滚轮控制距离的速度
private bool isOrbiting = true; // 是否正在绕建筑物旋转
private float orbitDuration = 10f; // 绕建筑物转一圈所需的时间
private Vector3 fixedPosition; // 相机停留的固定位置
private Quaternion fixedRotation; // 相机停留时的旋转
private float currentDistance; // 当前与目标的距离
private Transform mainCameraTransform; // Main Camera 的位置和旋转
private void Start()
{
if (target == null)
{
Debug.LogError("目标建筑物未设置!");
return;
}
// 获取 Main Camera 的 Transform
mainCameraTransform = Camera.main.transform;
// 设置初始距离
currentDistance = -offset.z;
// 计算旋转结束时相机应该停留的位置和旋转
fixedPosition = mainCameraTransform.position;
fixedRotation = mainCameraTransform.rotation;
if (isOrbiting)
{
StartOrbit();
}
}
private void Update()
{
// 响应鼠标滚轮输入,控制与目标的距离
float scrollInput = Input.GetAxis("Mouse ScrollWheel");
currentDistance -= scrollInput * scrollSpeed; // 增加或减少距离
currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
}
// 启动围绕建筑物旋转
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 void HideCamera()
{
// 方法 1禁用 Camera 组件
GetComponent<Camera>().enabled = false;
// 方法 2禁用整个 GameObject
// gameObject.SetActive(false);
Debug.Log("相机已隐藏");
}
}