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
相关产品推荐
相关产品推荐

