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

Unity C#问题:Projectile速度随鼠标与角色距离异常变化

解决Unity抛射体速度随鼠标距离变化的问题

嘿,这个问题我之前帮不少开发者排查过,核心原因基本都是方向向量的归一化环节出了问题——你以为已经把方向归一化了,但实际上要么是计算时空间不匹配,要么是归一化的时机/方式不对,导致最终的移动向量长度跟着鼠标到角色的距离变来变去,靠近时短(速度慢),远离时长(速度快)。

下面一步步给你排查和解决的思路:

1. 先检查方向计算的核心逻辑(RotateMouse()函数)

最常见的错误是把屏幕坐标和世界坐标直接做减法,两个不在同一空间的向量差值是没有意义的,更别说归一化了。举个例子:

错误的方向计算(大概率是你现在的写法)

Vector3 mousePos = Input.mousePosition; // 这是屏幕坐标,范围是(0,0)到(ScreenWidth, ScreenHeight)
Vector3 direction = mousePos - transform.position; // 角色坐标是世界空间,两者维度不匹配
direction.Normalize(); // 这里的归一化根本没用,因为原始向量的长度是屏幕空间的距离,和实际世界距离无关

正确的方向计算(分2D/3D场景)

2D场景(比如Top-Down游戏)

Camera mainCam = Camera.main;
// 把鼠标屏幕坐标转成世界空间,注意要设置Z值(相机到平面的距离,2D游戏里一般设为相机的nearClipPlane)
Vector3 worldMousePos = mainCam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, mainCam.nearClipPlane));
// 计算角色到鼠标的世界空间向量
Vector3 direction = worldMousePos - transform.position;
// 2D游戏忽略Z轴,避免不必要的深度移动
direction.z = 0;
// 最后归一化,得到纯方向向量(模长为1)
direction.Normalize();

3D场景(比如第三人称射击)

Camera mainCam = Camera.main;
// 发射一条从相机到鼠标位置的射线,检测地面/目标平面
Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hitInfo, 100f, LayerMask.GetMask("Ground")))
{
    // 用射线命中点作为目标点,计算方向
    Vector3 direction = hitInfo.point - transform.position;
    // 忽略Y轴(如果是水平移动的抛射体)
    direction.y = 0;
    direction.Normalize();
}

2. 给抛射体移动脚本加一层“保险”

就算你在RotateMouse()里做了归一化,也可能在传递过程中被意外修改。建议在抛射体的移动脚本里,初始化时再强制归一化一次:

public class ProjectileMovement : MonoBehaviour
{
    public float moveSpeed;
    private Vector3 _moveDirection;

    // 初始化抛射体时调用这个方法传入方向
    public void SetupMovement(Vector3 targetDirection)
    {
        // 强制归一化,确保方向向量的模长是1
        _moveDirection = targetDirection.normalized;
    }

    void Update()
    {
        // 用归一化方向 × 固定速度 × Time.deltaTime(保证帧率无关)
        transform.Translate(_moveDirection * moveSpeed * Time.deltaTime, Space.World);
    }
}

3. 验证方向向量是否真的归一化了

在实例化抛射体前,打印方向向量的模长,看看是不是接近1:

Vector3 fireDirection = RotateMouse();
Debug.Log($"Fire direction magnitude: {fireDirection.magnitude:F2}");
// 正常输出应该是1.00左右,如果是0.1、2.5这种随鼠标距离变化的数值,说明你的归一化没生效

4. 排查其他小概率问题

  • 有没有其他脚本动态修改了抛射体的moveSpeed变量?比如不小心写了根据鼠标距离调整速度的逻辑;
  • 3D场景下,是不是射线检测没命中任何物体,导致方向向量是无效值?可以给射线检测加个默认方向;
  • 是不是用了transform.localPosition而不是transform.position来计算差值?

按照这个流程排查,基本就能解决问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:24:46