简体   繁体   English

“生成”游戏对象的正确方法。 (我想生成射弹)

[英]Proper way to "spawn" game objects. (I want to spawn projectiles)

Hey all I made the following class to act as "bullets" in my game and I don't know how to construct these bullet objects with the params that I want (determined at runtime) and spawn them in the game.嘿,我让以下类在我的游戏中充当“子弹”,但我不知道如何使用我想要的参数(在运行时确定)构造这些子弹对象并在游戏中生成它们。

My first attempt looked like this:我的第一次尝试是这样的:

 if (canShoot())
        {
            shotCoolDown = FRAMES_BETWEEN_SHOTS;
            Bullet bullet = new Bullet().setLoft(LOFT).setWobble(WOBBLE).setInitialVel(INITIAL_VEL).setDirectionOffset(internalRecoil.getRecoil());
        }

but i get the following warnign from the unity editor:但我从统一编辑器中得到以下警告:

You are trying to create a MonoBehaviour using the 'new' keyword.您正在尝试使用“new”关键字创建 MonoBehaviour。 This is not allowed.这是不允许的。 MonoBehaviours can only be added using AddComponent(). MonoBehaviours 只能使用 AddComponent() 添加。 Alternatively, your script can inherit from ScriptableObject or no base class at all或者,您的脚本可以从 ScriptableObject 继承或根本没有基类

What is the proper way to spawn these bullets and to set the fields as I want them?产生这些子弹并根据需要设置字段的正确方法是什么?

For more info here is the bullet class欲了解更多信息,这里是子弹类

 public class Bullet : MonoBehaviour
{
    private Rigidbody rigidbody;
    private float wobble;
    private float loft;
    private float initialVel;
    private Vector2 initialDirectionOffset;
    private bool wobbleDirection = false;
    
    private void Awake()
    {
        this.rigidbody = this.GetComponent<Rigidbody>();
    }

    private void Start()
    { 
        transform.Rotate(initialDirectionOffset); 
        rigidbody.AddForce(initialVel*transform.forward);
        rigidbody.AddForce(loft*transform.up);
    }

    private void FixedUpdate()
    {
        if (wobbleDirection)
        {
            rigidbody.AddForce(transform.right * wobble);
            wobbleDirection = false;
        }
        else
        {
            rigidbody.AddForce(-transform.right * wobble);
            wobbleDirection = true;
        }
    }

    public Bullet setWobble(float wobble)
    {
        this.wobble = wobble;
        return this;
    }
    
    public Bullet setLoft(float loft)
    {
        this.loft = loft;
        return this;
    }
    
    public Bullet setInitialVel(float initialVel)
    {
        this.initialVel = initialVel;
        return this;
    }

    public Bullet setDirectionOffset(Vector2 offset)
    {
        this.initialDirectionOffset = offset;
        return this;
    }
}

For more info here is the full "gun" class that spawns the bullets.有关更多信息,请参阅生成子弹的完整“枪”类。

public class Gun : MonoBehaviour
{
    private int FRAMES_BETWEEN_SHOTS = 10;
    private int shotCoolDown = 0;
    private const float LOFT = 100F;
    private const float WOBBLE = 100F;
    private const float INITIAL_VEL = 100F;
    private Vector3 directionOffset;
    private Recoil internalRecoil;
    

    private void Awake()
    {
        internalRecoil = this.GetComponent<Recoil>();
        if (internalRecoil == null)
        {
            throw new Exception("Could not find recoil component");
        }
    }

    private void FixedUpdate()
    {
        if (shotCoolDown > 0)
        {
            shotCoolDown--;
        }
    }

    private bool canShoot()
    {
        return shotCoolDown == 0;
    }

    public void performShoot()
    {
        if (canShoot())
        {
            //need to have a recoil component that reacts to bullet fire. then adjusts back to 0,0,0
            shotCoolDown = FRAMES_BETWEEN_SHOTS;
            Bullet bullet = new Bullet().setLoft(LOFT).setWobble(WOBBLE).setInitialVel(INITIAL_VEL).setDirectionOffset(internalRecoil.getRecoil());
        }
    }
}

My second attempt looks like:我的第二次尝试看起来像:

 GameObject.Instantiate(new Bullet().setLoft(LOFT).setWobble(WOBBLE).setInitialVel(INITIAL_VEL)
                .setDirectionOffset(internalRecoil.getRecoil()));

is this the right way to do it???这是正确的方法吗???

As 3Dave mentioned, the best way to do this would be to instantiate a prefab.正如 3Dave 所提到的,最好的方法是实例化一个预制件。 Assuming you will be dealing with multiple projectiles, I like to separate this into a utility function for instantiating prefabs at a given position.假设您将处理多个射弹,我喜欢将其分离为一个实用函数,用于在给定位置实例化预制件。

public static class UnityUtil {

    public static GameObject instantiatePrefab(
        Object prefab, 
        Vector3 position,
        Transform? parent = null
    ){
        // Create an instance of the prefab
        GameObject instance = Object.Instantiate(prefab, position, Quaternion.identity) as GameObject;

        // Set the parent
       if(parent != null){
          instance.transform.parent = parent;
       }

       return instance;
    }

}

Then you could have code like然后你可以有这样的代码

Transform projectileHolder;
GameObject myBulletPrefab;
Vector3 bulletPosition;

...setup variables...


var BulletGameObj = UnityUtil.instantiatePrefab(myBulletPrefab, bulletPosition, projectileHolder);
Bullet bullet = BulletGameObj.GetComponent<Bullet>();

I keep some other functions in my util for dealing with generic gameobject cases, you can see my full UnityUtil class here我在我的 util 中保留了一些其他函数来处理通用游戏对象案例,您可以在此处查看我的完整 UnityUtil 类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM