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

Unity3D实现相机沿朝向垂直方向移动并添加移动限制

旋转相机的侧向移动与范围限制实现

当相机处于旋转状态时,不能直接依赖世界坐标系的X/Z轴做移动限制,核心思路是基于相机自身的局部坐标系来处理移动逻辑与边界约束:

  • 移动时,确保拖拽方向贴合相机的左右/前后朝向(局部X/Z轴)
  • 限制时,将相机位置相对于初始锚点的偏移转换到局部空间做范围约束,再转回世界空间。

以下是修改后的完整实现代码:

using UnityEngine;

[RequireComponent(typeof(Camera))]
public class CameraController : MonoBehaviour
{
    Camera cam;
    Vector3 dragOriginScreen; // 用屏幕坐标存拖拽起点,规避WorldPoint的Z轴误差
    Vector3 initialCamPosition; // 相机初始位置,作为移动限制的锚点
    bool isDragging = false;

    // 相机局部坐标系下的移动范围:X=左右最大距离,Z=前后最大距离
    [Header("移动限制参数")]
    public Vector2 moveLimits = new Vector2(5f, 5f);

    void Awake()
    {
        cam = GetComponent<Camera>();
        initialCamPosition = transform.position; // 记录初始位置作为移动锚点
    }

    void LateUpdate()
    {
        HandleCameraDrag();
    }

    void HandleCameraDrag()
    {
        if (Input.GetMouseButtonDown(0))
        {
            isDragging = true;
            dragOriginScreen = Input.mousePosition;
            return;
        }

        if (Input.GetMouseButtonUp(0))
        {
            isDragging = false;
            return;
        }

        if (!isDragging) return;

        // 计算屏幕拖拽的差值
        Vector3 screenDelta = Input.mousePosition - dragOriginScreen;
        // 把屏幕差值转换成世界空间的移动量
        Vector3 worldDelta = cam.ScreenToWorldPoint(screenDelta + dragOriginScreen) - cam.ScreenToWorldPoint(dragOriginScreen);
        // 2D视角下固定Z轴高度,3D视角可根据需求调整此逻辑
        worldDelta.z = 0;

        // 计算无限制的目标位置
        Vector3 targetPosition = initialCamPosition + worldDelta;

        // 应用移动范围限制
        targetPosition = ClampCameraPosition(targetPosition);

        // 更新相机位置,并重置拖拽起点避免累积误差
        transform.position = targetPosition;
        dragOriginScreen = Input.mousePosition;
    }

    Vector3 ClampCameraPosition(Vector3 targetPos)
    {
        // 计算目标位置相对于初始锚点的偏移量
        Vector3 offsetFromInitial = targetPos - initialCamPosition;

        // 将世界空间偏移转换为相机局部坐标系下的偏移
        Vector3 localOffset = transform.InverseTransformVector(offsetFromInitial);

        // 在局部坐标系内限制X(左右)和Z(前后)的移动范围
        localOffset.x = Mathf.Clamp(localOffset.x, -moveLimits.x, moveLimits.x);
        localOffset.z = Mathf.Clamp(localOffset.z, -moveLimits.y, moveLimits.y);

        // 把受限后的局部偏移转换回世界空间,得到最终合规位置
        Vector3 clampedWorldOffset = transform.TransformVector(localOffset);
        return initialCamPosition + clampedWorldOffset;
    }
}

关键逻辑说明

  1. 屏幕拖拽计算优化:
    改用屏幕坐标存储拖拽起点,避免ScreenToWorldPoint因相机近平面Z轴导致的计算偏差,让拖拽移动更流畅稳定。

  2. 局部坐标系的限制逻辑:

    • transform.InverseTransformVector:将世界空间的位置偏移转换为相机自身局部空间的偏移,这样就能用相机的左右(X轴)、前后(Z轴)来判断是否越界。
    • Mathf.Clamp:对局部空间的X/Z轴偏移做范围约束,确保相机始终在设定的矩形区域内移动。
    • transform.TransformVector:将受限后的局部偏移转回世界空间,得到符合限制的最终相机位置。
  3. 视角适配:
    代码中默认固定Z轴高度(适配2D视角),如果是3D视角,可删除worldDelta.z = 0的逻辑,同时调整moveLimits的Z轴参数来控制相机的前后移动范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:21:00