unity3d实现点击按钮平滑切换相机到目标点位置的功能
场景里面只有一个主相机MainCamera,写一函数,传入目标点的位置和旋转角度,点击按钮,使当前相机跳转到目标点镜头,相机跳转过程中部僵硬,过渡平滑。为了封装复用,写成单例的形式,方便其他页面调用。
效果如下所示:
点击前

点击后

项目结构如下:


完整代码:
CameraSwitcher.cs
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 相机切换控制器 - 提供平滑的相机位置和旋转过渡功能
/// 使用单例模式设计,确保全局唯一实例并可静态访问
/// </summary>
public class CameraSwitcher : MonoBehaviour
{
// 单例实例引用,外部可通过CameraSwitcher.Instance访问
public static CameraSwitcher Instance { get; private set; }
[Header("配置")]
// 要控制的主相机
public Camera mainCamera;
// 相机过渡动画持续时间(秒)
public float transitionDuration = 1.0f;
// 控制过渡速度的动画曲线,默认使用缓入缓出效果
public AnimationCurve transitionCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
// 相机是否正在过渡中
private bool isTransitioning = false;
void Awake()
{
// 单例模式初始化:确保场景中只有一个CameraSwitcher实例
if (Instance == null)
Instance = this;
else
Destroy(gameObject); // 销毁重复的实例
// 自动获取相机引用(如果未手动指定)
if (mainCamera == null)
mainCamera = GetComponent<Camera>();
}
/// <summary>
/// 平滑切换相机到指定位置和旋转
/// </summary>
/// <param name="targetPosition">目标位置</param>
/// <param name="targetRotation">目标旋转(四元数)</param>
public static void SwitchTo(Vector3 targetPosition, Quaternion targetRotation)
{
// 安全检查:确保实例存在且未在过渡中
if (Instance == null || Instance.isTransitioning)
return;
// 启动相机过渡协程
Instance.StartCoroutine(Instance.MoveCameraSmoothly(targetPosition, targetRotation));
}
/// <summary>
/// 相机平滑过渡的协程实现
/// </summary>
/// <param name="targetPosition">目标位置</param>
/// <param name="targetRotation">目标旋转</param>
private System.Collections.IEnumerator MoveCameraSmoothly(Vector3 targetPosition, Quaternion targetRotation)
{
// 标记为过渡中,防止重复触发
isTransitioning = true;
// 记录起始位置和旋转
Vector3 startPosition = mainCamera.transform.position;
Quaternion startRotation = mainCamera.transform.rotation;
float elapsedTime = 0;
// 随时间进行插值过渡
while (elapsedTime < transitionDuration)
{
// 基于动画曲线计算插值因子(0-1范围)
float t = transitionCurve.Evaluate(elapsedTime / transitionDuration);
// 线性插值计算当前位置和旋转
mainCamera.transform.position = Vector3.Lerp(startPosition, targetPosition, t);
mainCamera.transform.rotation = Quaternion.Slerp(startRotation, targetRotation, t);
// 更新已过时间
elapsedTime += Time.deltaTime;
// 暂停协程,等待下一帧
yield return null;
}
// 确保最终位置精确对齐(避免浮点误差)
mainCamera.transform.position = targetPosition;
mainCamera.transform.rotation = targetRotation;
// 标记过渡完成
isTransitioning = false;
}
}
UIManger.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIManger : MonoBehaviour
{
public Button switchButton;
void Start()
{
if (switchButton != null)
{
switchButton.onClick.AddListener(() => {
CameraSwitcher.SwitchTo(new Vector3(17.84f, 1.64f, -0.38f), Quaternion.Euler(0, -90, 0));
});
}
}
void Update()
{
}
}
更多推荐



所有评论(0)