Problems compiling script for iPhone that don't appear when running in unity.

Hi all,

Hoping someone can help me here, keep getting errors when I build my code to iOS, it's this sample of code which screws up on me:

    var bulletPrefab:Transform;

    function Update ()

{
    if(Input.GetButtonDown("Fire1"))
    {
        if(Collisions.BULLET_AMMO > 0)
        {

        //create the bullet Prefab
        var bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);

        //add force to the bullet
        bullet.rigidbody.AddForce(transform.forward * 2000);

        Collisions.BULLET_AMMO --;
        GameObject.Find("G_Ammo").guiText.text = ""+Collisions.BULLET_AMMO;
        }

    }
}

Now I've tried writing:

var bullet : GameObject = Instantiate(bulletPrefab, transform.position, Quaternion.identity);

But when I do it stops me applying force to the rigidbody, stating that it cannot cast from source type to destination type.

This all works fine when I'm running the game within unity, but the second I go to compile to iOS I get errors pointing to these!

If anyone could help I would be eternally grateful,

many thanks

Dan

var bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity);

//add force to the bullet
bullet.rigidbody.AddForce(transform.forward * 2000);

This is called dynamic typing. Since you have not declared a type for `bullet`, Unity will infer that it is an `Object` because that is what Instantiate() returns. Declaring a type like you did will partially solve this problem. BUT that leaves the InvalidCastException which will be explained below.

Then, by calling `.rigidbody`, Unity has to figure out if this object supports that getter, and if it does then use it. This is also a dynamic feature. Both of which are supported on the desktop since it is JIT compiled but not on the iOS which is AOT compiled.

The Fix

var bullet : GameObject = Instantiate(bulletPrefab, transform.position, Quaternion.identity) as GameObject;
//You need a cast to GameObject from Object since there is a chance of losing data.

//add force to the bullet
bullet.rigidbody.AddForce(transform.forward * 2000);
//Now we know that bullet is a GameObject and supports the .rigidbody getter.

You have to declare a type for bullet like you did above. Now Unity knows that it is a GameObject. But, you will get an InvalidCastException because there is the risk of losing data. In this case, you have an object that stores information about everything associated with the object you just created. By casting to a GameObject, this reference is losing all information that isn't a property or method of GameObject (Although in this case you can still access the information through GameObject's properties such as `rigidbody`). So you have to tell the compiler that you know you could lose data and that it should do it anyway.

2 more points

  • On iOS, memory is an issue, you don't want to instantiate new objects during gameplay if you don't have to. If you can, create a system that reuses old objects and switches them on and off.

  • You can cast directly to rigidbody then not have to use the getter to call AddForce()

EX:

bullet : Rigidbody = Instantiate() as Rigidbody;
bullet.AddForce();

do this

var bullet : Transform= Instantiate(bulletPrefab, transform.position, Quaternion.identity) as Transform;

//add force to the bullet
bullet.gameObject.rigidbody.AddForce(transform.forward * 2000);