首页/ 第 13 章 · 2D 游戏开发/ 第 215 课
LESSON 215 · 2D 游戏开发

2D 子弹与弹幕

弹幕系统完成。下一课做 2D 摄像机跟随。

⏱ 约 15 分钟📊 难度:入门🗂 第 13 章 · 2D 游戏开发📍 第 215 / 300 课
课程进度
215 / 300

🎯本节学习目标

  • 实现多种弹道
  • 实现扇形弹幕
  • 实现旋转环绕

🚀课程导读

“单发”太单调,来点“弹幕”!本课实现扇形、环绕、追踪等多样化子弹。

多种发射方式

按方向算。

  1. 【扇形弹幕】一次发射多颗、角度分散:
  2. void FireFan(int count, float spreadAngle) {
  3. float baseAngle = AimAngle(); // 朝玩家的角度
  4. for (int i = 0; i < count; i++) {
  5. float offset = (i - (count-1)/2f) * spreadAngle / count;
  6. float angle = baseAngle + offset;
  7. Vector2 dir = new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad));
  8. SpawnBullet(dir);
  9. }
  10. }
  11. 【圆形弹幕】360 度:for 遍历 0-360 度每 30 度发射一颗。
  12. 【追踪弹】朝玩家当前位置:每帧修正子弹方向(Transform.LookAt/方向 Lerp)。
  13. 【螺旋弹】基础角度随时间递增(baseAngle += Time.deltaTime * 50)。
  14. 【方向计算】Mathf.Atan2/Cos/Sin 是弹幕基本功。
  15. 【注意】角度转方向:dir = (cos θ, sin θ)。
  16. 【实战】Boss 发射圆形+螺旋弹幕。
  17. 【完成】弹幕系统“炫”起来了!
💡
弹幕核心公式:角度 → 方向(cosθ, sinθ),遍历角度=各种弹幕。

子弹管理优化

弹幕多了不卡。

  1. 【问题】弹幕大量 Instantiate/Destroy 造成卡顿。
  2. 【对象池】子弹用对象池(第 198 课):
  3. ObjectPool.Instance.GetBullet(pos, dir);
  4. 【实现】预创建 100 颗子弹隐藏,取出时设置位置/方向/速度,撞击或超时回收。
  5. 【Bullet 脚本调整】
  6. public void Init(Vector2 pos, Vector2 dir) {
  7. transform.position = pos;
  8. GetComponent<Rigidbody2D>().velocity = dir * speed;
  9. gameObject.SetActive(true);
  10. StartCoroutine(AutoDeactivate());
  11. }
  12. IEnumerator AutoDeactivate() { yield return new WaitForSeconds(3f); gameObject.SetActive(false); }
  13. 【碰撞】OnTriggerEnter2D 里命中后 gameObject.SetActive(false) 而非 Destroy。
  14. 【注意】对象池子弹要正确重置(速度、旋转、tag)。
  15. 【性能】上千子弹也能流畅。
  16. 【完成】弹幕再多也不怕!
  17. 【进阶】子弹用 ScriptableObject 配置(伤害/速度/颜色)。
  18. 【注意】对象池 Get 时确保子弹状态清零。
  19. 【推荐】所有高频物(子弹、粒子)一律对象池。
弹幕性能:对象池 + 循环复用 + 速度重置。1000 颗子弹也流畅。

常见错误与排查

错误:对象池子弹复用后“卡住”?
原因:速度/旋转没重置
解决:Init 时重置 velocity、rotation、tag、颜色后再激活。

动手练习

课后小任务(做出来才算真的学会)

  • 实现扇形与圆形弹幕
  • 实现追踪子弹
  • 用对象池优化大量子弹

本节小结

弹幕系统完成。下一课做 2D 摄像机跟随。

完成打卡后,主站会实时更新你的学习进度 🎯

← 上一课2D 射击游戏基础