You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#实现相机(GameObject)面板间慢移动画需求

实现Unity相机在面板间的平滑慢移动画

嘿,我来帮你把相机的瞬间移动改成平滑的慢动画效果!你现在的代码是直接设置相机位置,所以会瞬间跳转,我们可以用Unity自带的插值方法来实现过渡动画,这里给你两种实用的方案:

方案一:用Vector3.MoveTowards实现帧率无关的平滑移动

这种方法适合通过移动速度来控制快慢,每帧逐步靠近目标位置,简单易上手:

public class MoveCanvas : MonoBehaviour
{
    // 目标位置变量,用来存储要移动到的位置
    private Vector3 _targetPosition;
    // 移动速度(单位:每秒移动的像素/距离),数值越小移动越慢
    public float moveSpeed = 200f;

    // 定义各个面板的位置
    private readonly Vector3 _resetPosition = new Vector3(0, 0, -10);
    private readonly Vector3 _leftPanelPosition = new Vector3(-205.5f, 0, 0);
    private readonly Vector3 _rightPanelPosition = new Vector3(205.5f, 0, 0);

    void Start()
    {
        // 初始化相机到初始位置
        _targetPosition = _resetPosition;
        transform.position = _targetPosition;
    }

    void Update()
    {
        // 检测按键,设置对应目标位置
        if (Input.GetKeyDown(KeyCode.A))
        {
            SetTargetPosition(_leftPanelPosition);
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            SetTargetPosition(_rightPanelPosition);
        }
        // 可以加个重置按键,按R回到初始位置
        if (Input.GetKeyDown(KeyCode.R))
        {
            SetTargetPosition(_resetPosition);
        }

        // 每帧平滑移动到目标位置,Time.deltaTime保证帧率无关
        transform.position = Vector3.MoveTowards(transform.position, _targetPosition, moveSpeed * Time.deltaTime);
    }

    // 封装设置目标位置的方法,避免重复代码
    private void SetTargetPosition(Vector3 newTarget)
    {
        _targetPosition = newTarget;
    }
}

方案说明:

  • Vector3.MoveTowards会让相机每帧向目标位置移动固定距离,结合Time.deltaTime可以保证不管帧率高低,移动速度都是一致的
  • 你可以在Inspector面板调整moveSpeed的值:数值越小,移动越慢;数值越大,移动越快

方案二:用协程+Vector3.Lerp实现固定时长的动画

这种方法适合通过动画时长精确控制移动快慢,比如固定0.5秒完成移动,适合需要统一动画节奏的场景:

public class MoveCanvas : MonoBehaviour
{
    // 移动时长(单位:秒),数值越大移动越慢
    public float moveDuration = 0.5f;
    // 标记是否正在移动,避免重复触发动画
    private bool _isMoving = false;

    // 定义各个面板的位置
    private readonly Vector3 _resetPosition = new Vector3(0, 0, -10);
    private readonly Vector3 _leftPanelPosition = new Vector3(-205.5f, 0, 0);
    private readonly Vector3 _rightPanelPosition = new Vector3(205.5f, 0, 0);

    void Start()
    {
        // 初始化相机到初始位置
        transform.position = _resetPosition;
    }

    void Update()
    {
        // 只有不在移动时才响应按键
        if (Input.GetKeyDown(KeyCode.A) && !_isMoving)
        {
            StartCoroutine(MoveToPosition(_leftPanelPosition));
        }
        if (Input.GetKeyDown(KeyCode.D) && !_isMoving)
        {
            StartCoroutine(MoveToPosition(_rightPanelPosition));
        }
        if (Input.GetKeyDown(KeyCode.R) && !_isMoving)
        {
            StartCoroutine(MoveToPosition(_resetPosition));
        }
    }

    // 协程处理平滑移动逻辑
    private IEnumerator MoveToPosition(Vector3 targetPos)
    {
        _isMoving = true;
        Vector3 startPos = transform.position;
        float elapsedTime = 0f;

        // 逐步插值移动,直到到达目标位置
        while (elapsedTime < moveDuration)
        {
            // 用时间进度(0到1)做插值,实现平滑过渡
            float progress = elapsedTime / moveDuration;
            // 如果想要更自然的缓动效果,可以用Mathf.SmoothStep(0, 1, progress)代替progress
            transform.position = Vector3.Lerp(startPos, targetPos, progress);
            
            elapsedTime += Time.deltaTime;
            yield return null; // 等待下一帧
        }

        // 最后强制设置到目标位置,避免误差
        transform.position = targetPos;
        _isMoving = false;
    }
}

方案说明:

  • 协程可以让我们在一段时间内逐步执行移动逻辑,Vector3.Lerp根据时间进度(0到1)计算当前位置
  • 如果你想要更自然的缓动效果(比如先慢后快,或者先快后慢),可以把progress改成Mathf.SmoothStep(0, 1, progress),或者用AnimationCurve自定义速度曲线
  • _isMoving变量可以防止用户连续按键触发多个移动动画,避免相机位置混乱

额外小贴士:

  • 确保相机的Z轴保持固定值(比如你的初始-10),因为UI相机的Z轴会影响UI元素的渲染层级,移动时不要改变Z轴
  • 你可以把面板位置做成可配置的变量(比如用[SerializeField]标记),这样可以直接在Inspector面板拖拽调整,不用硬编码数值

内容的提问来源于stack exchange,提问作者Ammar Ismaeel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:00:37