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

顶视角3D相机跟随问题:除ScreenToWorldPoint外的替代方案?

顶视角3D相机平滑跟随鼠标与玩家的问题修复

问题根源

  1. 位置计算逻辑错误:你当前的newCurserPos.x/z = speed * curserPos.x/z + playerPos.x/z会导致位置不断叠加——每次更新都基于上一次的鼠标世界坐标计算,相当于把偏移量持续放大,最终出现指数增长的问题。
  2. ScreenToWorldPoint误用:透视相机下,ScreenToWorldPoint的z参数是从相机到目标点的距离,而非固定值。你直接赋值为seeAbleDistance,会导致得到的鼠标世界坐标随相机位置变化而偏移,逻辑完全错误。

解决方案

我们需要准确获取鼠标在玩家所在平面的世界坐标,再让相机基于玩家位置+鼠标偏移的平滑值移动,同时保持固定高度。以下是修正后的实现:

修正代码

using UnityEngine;

public class CameraScript : MonoBehaviour
{
    public GameObject Player;
    public float cameraHeight = 7.5f; // 相机在玩家上方的固定高度
    public float followSensitivity = 0.3f; // 鼠标跟随灵敏度(0-1,值越大越灵敏)
    public float smoothSpeed = 5f; // 相机平滑移动速度

    private Plane playerHorizontalPlane;

    void Update()
    {
        if (Player == null) return;

        // 定义玩家所在的水平面(Y轴与玩家位置一致)
        playerHorizontalPlane = new Plane(Vector3.up, Player.transform.position);

        // 从鼠标位置发射射线,检测与玩家平面的交点
        Ray mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (playerHorizontalPlane.Raycast(mouseRay, out float rayDistance))
        {
            // 获取鼠标在玩家平面上的世界坐标
            Vector3 mouseWorldPos = mouseRay.GetPoint(rayDistance);

            // 计算相机目标位置:玩家位置 + 鼠标与玩家的偏移量 * 灵敏度,保持Y轴高度
            Vector3 targetCameraPos = Player.transform.position + (mouseWorldPos - Player.transform.position) * followSensitivity;
            targetCameraPos.y = Player.transform.position.y + cameraHeight;

            // 平滑插值移动相机,保证帧率无关的平滑效果
            transform.position = Vector3.Lerp(transform.position, targetCameraPos, smoothSpeed * Time.deltaTime);
        }
    }
}

关键逻辑说明

  • 射线检测获取鼠标平面坐标:用Plane和Raycast可以精准获取鼠标在玩家所在水平面的世界坐标,完全不受相机位置、透视参数的影响,比ScreenToWorldPoint更可靠。
  • 正确的目标位置计算:(mouseWorldPos - Player.transform.position) * followSensitivity取鼠标相对于玩家偏移的一部分,让相机始终处于玩家与鼠标之间的位置,不会出现叠加增长。
  • 平滑移动处理:Vector3.Lerp配合Time.deltaTime确保平滑速度在不同帧率下一致,避免卡顿或移动过快。

对你其他问题的解答

  1. 能否将屏幕坐标转换为指定GameObject的本地坐标?
    可以。如果要获取鼠标相对于玩家的本地坐标(玩家自身坐标系下),可以在得到mouseWorldPos后用以下代码:
Vector3 mouseLocalPos = Player.transform.InverseTransformPoint(mouseWorldPos);

这个值就是鼠标在玩家transform坐标系下的位置。

  1. 是否错误使用了ScreenToWorldPoint?
    是的。透视相机下ScreenToWorldPoint的z参数是相机到目标点的距离,你固定赋值为seeAbleDistance会导致计算出的坐标随相机位置偏移,逻辑错误。射线检测是顶视角场景下获取鼠标世界坐标的标准方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:28:10