Unity中如何正确生成继承MonoBehaviour的子弹投射物游戏对象?
问题解答
第二次实现是否正确
你的第二次实现仍然不正确。核心原因是:所有继承自MonoBehaviour的类都不允许直接使用new关键字实例化,Unity的组件必须挂载在GameObject对象上,才能正常触发Awake/Start/Update等生命周期函数,手动new出来的MonoBehaviour实例没有对应的GameObject载体,既无法挂载到场景,也无法正常运行逻辑。
正确实现方案
步骤1:制作子弹预制体
首先在Unity场景中创建一个空GameObject,按需求完成以下配置:
- 挂载
Bullet脚本 - 挂载
Rigidbody组件,调整重力、质量等物理参数 - 添加子弹模型、碰撞体等必要资源
- 将配置完成的GameObject拖入Project面板,制作成子弹预制体,删除场景中的临时对象
步骤2:修改Gun类引用预制体
在Gun类中添加公共字段引用子弹预制体:
public class Gun : MonoBehaviour { // 新增字段,用于在Inspector面板赋值子弹预制体 public Bullet bulletPrefab; // 其余原有代码保持不变 }
回到Unity编辑器,将步骤1制作的子弹预制体拖入Gun组件的bulletPrefab字段完成赋值。
步骤3:修改子弹生成逻辑
将performShoot方法中的子弹生成逻辑替换为以下代码:
public void performShoot() { if (canShoot()) { shotCoolDown = FRAMES_BETWEEN_SHOTS; // 实例化子弹预制体,生成位置/旋转和枪口保持一致 Bullet bullet = Instantiate(bulletPrefab, transform.position, transform.rotation) .setLoft(LOFT) .setWobble(WOBBLE) .setInitialVel(INITIAL_VEL) .setDirectionOffset(internalRecoil.getRecoil()); } }
可选优化(解决时序问题)
如果出现参数未赋值就执行子弹初始逻辑的问题,是因为默认状态下预制体实例化后会立刻执行Start方法,可能早于参数赋值的时机。可以做如下调整:
- 删除Bullet类中的
Start方法,新增公开初始化方法:
public class Bullet : MonoBehaviour { // 原有代码保持不变 public void Init() { transform.Rotate(initialDirectionOffset); rigidbody.AddForce(initialVel*transform.forward); rigidbody.AddForce(loft*transform.up); } }
- 完成子弹参数赋值后手动调用初始化方法:
Bullet bullet = Instantiate(bulletPrefab, transform.position, transform.rotation) .setLoft(LOFT) .setWobble(WOBBLE) .setInitialVel(INITIAL_VEL) .setDirectionOffset(internalRecoil.getRecoil()); bullet.Init();
内容的提问来源于stack exchange,提问作者Jake Gergen
相关产品推荐
相关产品推荐

