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

Unity 2D:如何让经墙壁反弹的小球移动一定距离后停止

问题:如何让发射后的小球移动一定距离后停止?

我通过rb2d.AddForce将小球朝鼠标位置发射,代码如下:

if (Input.GetKeyDown(KeyCode.Space))
{
    Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    _rb.AddForce(mousePos * ballSpeed);
}

小球碰到带有Physics2D组件且设置了弹性的墙壁时会持续反弹,现在想实现小球移动一定距离后停止运动,该怎么处理?


解决方案

方法1:精确记录累计移动距离,到达阈值后停止

在脚本中添加变量记录小球的总移动路径长度,每帧更新距离,当达到设定阈值时直接停止刚体运动:

public float stopDistance = 10f; // 设定触发停止的距离阈值
private float totalMovedDistance;
private Vector3 lastFramePos;

void Start()
{
    lastFramePos = transform.position;
}

void FixedUpdate()
{
    // 计算当前帧小球移动的距离
    float frameMoveDist = Vector3.Distance(transform.position, lastFramePos);
    totalMovedDistance += frameMoveDist;
    lastFramePos = transform.position;

    // 达到距离阈值后停止
    if (totalMovedDistance >= stopDistance)
    {
        _rb.velocity = Vector2.zero;
        _rb.angularVelocity = 0f;
        // 可选:设置刚体为运动学,彻底禁用物理交互
        _rb.isKinematic = true;
    }
}

注意:如果需要的是从发射点到当前位置的直线距离(而非路径总长度),可以把累计逻辑替换为Vector3.Distance(launchStartPos, transform.position),记得在发射时记录launchStartPos = transform.position。

方法2:动态增加阻尼实现渐进停止

如果不需要严格的距离控制,可通过增大刚体的线性阻尼,让小球逐渐减速直至停止。同时修正原代码中发射力的问题(直接用鼠标坐标计算力会导致力的大小异常):

public float ballSpeed = 5f;
public float dragIncreaseRate = 0.2f;
private bool isBallMoving = false;

void FixedUpdate()
{
    if (isBallMoving && _rb.velocity.magnitude > 0.1f)
    {
        // 动态增加阻尼,让小球减速
        _rb.drag += dragIncreaseRate * Time.fixedDeltaTime;
    }
    else if (_rb.velocity.magnitude <= 0.1f)
    {
        isBallMoving = false;
        _rb.drag = 0; // 重置阻尼,方便下次发射
    }
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        mousePos.z = transform.position.z; // 确保Z轴一致,避免空间计算错误
        // 计算从小球到鼠标位置的方向向量(归一化后保证力的方向正确)
        Vector2 launchDir = (mousePos - transform.position).normalized;
        
        _rb.AddForce(launchDir * ballSpeed, ForceMode2D.Impulse);
        isBallMoving = true;
        _rb.drag = 0; // 发射前重置阻尼
        totalMovedDistance = 0; // 如果用方法1,记得重置累计距离
    }
}

方法3:触发区域停止

如果停止位置固定,可以在场景中添加一个带Collider2D的触发区域,当小球进入区域时停止:

// 给小球的Collider2D勾选Is Trigger
void OnTriggerEnter2D(Collider2D other)
{
    if (other.CompareTag("StopZone"))
    {
        _rb.velocity = Vector2.zero;
        _rb.angularVelocity = 0f;
    }
}

记得给触发区域设置StopZone标签,确保检测逻辑生效。


内容的提问来源于stack exchange,提问作者Yakup Erdem Yılmaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:15:37