0
votes

I'm trying to implement a "Shoot" MonoBehaviour. I want it to do something very simple, it should take a Prefab as "Input" (storing it in a "projectile" public variable for the time being), and then simply Instantiate it and add a Forward force to it's RigidBody (relative to the object it is attached to, for example, a Tank).

However, I don't want my game to crash if I accidentally insert a Prefab that doesn't have a RigidBody. (In fact, it would be great if it didn't even allow me to add Prefabs without RigidBodies as projectiles).

I've tried using the "RequireComponent" attribute, but it looks like it only works for classes. Is there any way to do this without having to check if the Projectile has a RigidBody each time I want to shoot it?

I tried the Code Below, but it gives me an error saying I can't Instantiate a RigidBody as a GameObject. Which is understandable, but I'm running out of ideas here.

public class Shoot : MonoBehaviour
{

    public Rigidbody projectile;
    public float firePower = 5f;

    public void Fire()
    {
        GameObject projectileInstance = Instantiate(projectile) as GameObject;
        //maybe add some particles/smoke effect
        projectile.GetComponent<Rigidbody>().AddForce(firePower * transform.forward);
    }
}
4

4 Answers

2
votes

You can add in the components that you want at runtime, for example:

    // First check if there is no rigidbody component on the object
    if (!currentPrefab.GetComponent<Rigidbody>()){
        // Add the Rigidbody component
        currentPrefab.AddComponent<Rigidbody>();

        // You can also add a collider here if you want collisions
        var bc = currentPrefab.AddComponent<BoxCollider>();

        // And you'll have to calculate the new collider's bounds
        Renderer[] r = t.GetComponentsInChildren<Renderer>();
        for(var i=0; i<r.length; i++) {
            bc.bounds.Encapsulate(r[i].bounds);
        }
    }
1
votes

You can do a check on the prefab to see if it has a Rigidbody component like so:

if (currentPrefab.GetComponent<Rigidbody>()){

    // Do something

}

The GameObject.GetComponent() method will return null if the type you enter as a parameter is not present.

0
votes

I believe you are already on the write track. You just have to fix your error by doing the following :

public Rigidbody projectile;
public float firePower = 5f;

public void Fire()
{
    if( projectile == null )
    {
         Debug.LogError( "You forgot to provide a projectile prefab");
         return;
    }
    Rigidbody projectileInstance = Instantiate(projectile) as Rigidbody;
    projectileInstance.AddForce(firePower * transform.forward);
}

However, with this method, you can't require the prefab to have multiple components. If you need this, then, go with the method provided by the other answers.

0
votes

The others here already gave you some examples on how you would do this at runtime, however I would recommend you add a [RequireComponent(typeof(RigidBody))] to your projectile class (if you have one).

What that does is every time you attach your component to a gameObject Unity will automatically add the required components as well without having a performance impact on your game on runtime. Just add this over the class declaration on your projectile script.

You do however need to manually assign your components via the Inspector or by GetComponent. But this makes sure that your object has the right components attached.

You need some sort of script on your projectiles for this to work tho. So if you do not have that you should use another option pointed out here.

The documentation can be found here if you are interested.