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

Unity中如何实现拖拽结束后相机继续移动一段距离?

问题描述

若问题较为基础,还请见谅我的知识储备不足。我希望实现以下效果:拖拽屏幕时相机向滑动的反方向移动,当拖拽结束后,相机继续向该方向再移动一小段距离。我已在YouTube和谷歌搜索相关解决方案但未找到结果,恳请提供相关实现思路。

当前代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PanZoom : MonoBehaviour
{
    Vector3 touchStart;

    [SerializeField] float moveCameraSpeed = 3f;
    // Update is called once per frame
    void LateUpdate()
    {
        if (Input.GetMouseButtonDown(0))
        {
            touchStart = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }
        if (Input.GetMouseButton(0))
        {
            Vector3 direction = touchStart - Camera.main.ScreenToWorldPoint(Input.mousePosition);
            transform.position = Vector3.Lerp(Camera.main.transform.position,
            Camera.main.transform.position + direction, Time.deltaTime * moveCameraSpeed);
        }
    }
}
实现思路与修改方案

核心是通过记录拖拽时的移动速度,在拖拽结束后做减速运动模拟惯性滑动,具体实现步骤如下:

  • 添加变量记录拖拽过程中的速度、惯性衰减系数、停止阈值,以及是否处于惯性状态
  • 拖拽时实时计算移动速度,同时执行相机移动
  • 拖拽结束后,基于记录的速度继续移动相机,并逐渐衰减速度直至停止

修改后的完整代码:

using UnityEngine;

public class PanZoom : MonoBehaviour
{
    Vector3 touchStart;
    Vector3 lastMousePos; // 记录上一帧鼠标位置
    Vector3 currentVelocity; // 当前移动速度
    bool isInertiaMoving = false; // 是否处于惯性滑动状态

    [SerializeField] float moveCameraSpeed = 3f;
    [SerializeField] float inertiaDecay = 0.9f; // 惯性衰减系数,越小停得越快
    [SerializeField] float minInertiaSpeed = 0.01f; // 停止惯性的最小速度阈值

    void LateUpdate()
    {
        // 拖拽开始
        if (Input.GetMouseButtonDown(0))
        {
            touchStart = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            lastMousePos = Input.mousePosition;
            isInertiaMoving = false; // 开始拖拽时停止惯性
            currentVelocity = Vector3.zero;
        }

        // 拖拽过程中
        if (Input.GetMouseButton(0))
        {
            Vector3 currentMousePos = Input.mousePosition;
            // 计算鼠标移动的世界空间距离,得到移动方向和速度
            Vector3 worldDelta = Camera.main.ScreenToWorldPoint(lastMousePos) - Camera.main.ScreenToWorldPoint(currentMousePos);
            currentVelocity = worldDelta / Time.deltaTime; // 计算速度(单位时间移动距离)

            // 移动相机
            transform.position += currentVelocity * Time.deltaTime * moveCameraSpeed;

            lastMousePos = currentMousePos;
        }

        // 拖拽结束后的惯性滑动触发
        if (Input.GetMouseButtonUp(0))
        {
            isInertiaMoving = true;
        }

        // 执行惯性滑动逻辑
        if (isInertiaMoving)
        {
            // 移动相机
            transform.position += currentVelocity * Time.deltaTime * moveCameraSpeed;
            // 衰减速度
            currentVelocity *= inertiaDecay;

            // 当速度低于阈值时停止惯性
            if (currentVelocity.magnitude < minInertiaSpeed)
            {
                isInertiaMoving = false;
                currentVelocity = Vector3.zero;
            }
        }
    }
}
关键细节说明
  • inertiaDecay:设置为0.9左右效果比较自然,数值越小惯性消失越快,越大滑得越久
  • minInertiaSpeed:防止相机因为微小速度一直抖动,达到阈值就停止惯性
  • 拖拽时的速度计算:通过前后帧鼠标位置的世界空间差值除以时间,得到真实的移动速度,保证不同分辨率下惯性效果一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:26:34