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

Unity 2D实现小球碰撞墙体后反弹的脚本编写方法

小球碰撞墙体反弹实现方案

一、HTML5 Canvas 原生实现

核心逻辑是实时检测小球边缘是否触达画布边界,触达后反转对应方向的速度分量,从而实现反弹效果。

完整代码示例:

<canvas id="canvas" width="400" height="300"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// 小球参数
const ball = {
  x: 50,
  y: 50,
  radius: 15,
  speedX: 3,
  speedY: 2
};

// 绘制小球
function drawBall() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath();
  ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
  ctx.fillStyle = '#ff5722';
  ctx.fill();
  ctx.closePath();
}

// 更新小球位置与碰撞检测
function updateBall() {
  // 碰撞左右边界,反转X轴速度
  if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
    ball.speedX = -ball.speedX;
  }
  // 碰撞上下边界,反转Y轴速度
  if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
    ball.speedY = -ball.speedY;
  }

  // 更新位置
  ball.x += ball.speedX;
  ball.y += ball.speedY;
}

// 动画循环
function animate() {
  drawBall();
  updateBall();
  requestAnimationFrame(animate);
}

animate();
</script>

二、Unity 引擎实现

针对Unity场景,提供两种实现方式:

方式1:基于物理引擎(推荐)

利用Unity内置物理系统实现自然反弹:

  1. 给小球添加Rigidbody2D(2D场景)或Rigidbody(3D场景)组件,取消Use Gravity(无需重力时)。
  2. 小球添加CircleCollider2D,墙体添加BoxCollider2D,确保两者Is Trigger均未勾选。
  3. 创建材质并设置Bounciness为1(控制反弹力度)、Friction为0(消除摩擦干扰),将材质赋值给小球。

若需代码自定义反弹逻辑,可添加以下脚本:

using UnityEngine;

public class BallBounce : MonoBehaviour
{
    public float bounceForce = 5f;

    private void OnCollisionEnter2D(Collision2D collision)
    {
        // 仅对标签为"Wall"的墙体生效
        if (collision.gameObject.CompareTag("Wall"))
        {
            // 通过碰撞法线计算反弹方向
            Vector2 bounceDir = Vector2.Reflect(GetComponent<Rigidbody2D>().velocity, collision.contacts[0].normal);
            GetComponent<Rigidbody2D>().velocity = bounceDir * bounceForce;
        }
    }
}

方式2:手动边界检测(无物理引擎)

适合简单场景,无需依赖物理组件:

using UnityEngine;

public class BallManualBounce : MonoBehaviour
{
    public float speed = 5f;
    private Vector3 moveDir;

    void Start()
    {
        // 初始化随机移动方向
        moveDir = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), 0).normalized;
    }

    void Update()
    {
        transform.position += moveDir * speed * Time.deltaTime;

        // 获取屏幕世界坐标边界
        Vector2 screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 0));
        float ballRadius = GetComponent<SpriteRenderer>().bounds.extents.x;

        // 左右边界碰撞检测
        if (transform.position.x + ballRadius > screenBounds.x || transform.position.x - ballRadius < -screenBounds.x)
        {
            moveDir.x = -moveDir.x;
        }
        // 上下边界碰撞检测
        if (transform.position.y + ballRadius > screenBounds.y || transform.position.y - ballRadius < -screenBounds.y)
        {
            moveDir.y = -moveDir.y;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:25:16