instantiation problem

ok so I’m working on a 2D top-down plane shooter and I am having a problem instantiating the bullets. I’ve only got the simple instantiation part down (will add forces and stuff later), to make sure I have no problems instantiating it. Well I am, it gives me the error “Object reference is not set to an instance of an object.” so I’m not quite sure what’s wrong with my code. Can anyone help?

public GameObject BasicWeapon(GameObject bPref){
		GameObject go = Instantiate(bPref, GameObject.Find("BulletSpawn").transform.position, Quaternion.identity) as GameObject;
			Debug.Log(go.name);
		return go;
	}

that’s in the WeaponsSystems.cs file. The next block of code is in PlayerControl.cs which inherits from WeaponsSystems.cs

private void FireWeapons(){
		
		if(Input.GetButton("Fire1")){
			GameObject goz = BasicWeapon(bulletPrefab);
		}
		
	}

basically what I’m doing is using WeaponsSystems.cs to setup all my weapons (being an arcade-style game I want lots of them! hehe) and using PlayerControl.cs to call the weapon(s) it has available. so can anyone see where I’m going wrong with the instantiation? the “bullet” appears just fine but I still get the object error and it says that the line of error is the instantiation.

Edit: I got the wrong line, the error is appearing on Line 13, which is the Debug.Log(go.name); line.

My guess is it has some thing to do with the GameObject.Find(“BulletSpawn”).transform.position, your code looks fine, it’s just not getting all the info it needs (thats all null reference exceptions usually mean).

Try Debug.Log(GameObject.Find(“BulletSpawn”)); see if that gives a null reference, if it does than it’s just not finding the game object you specified, and you probably just have a naming issue.

nope :frowning: I did this.

Debug.Log(GameObject.Find("BulletSpawn").transform.position.x);

and it came out with clear numbers.

also I just noticed I got the wrong line, the error is appearing on the Debug.Log(); line, so I’m guessing it must be the way I’m storing the variable or something?

Ok, I’m not sure, but I think “as GameObject” is js (don’t quote me on that, only recently first saw it).

In any case try deleting it and using (GameObject) in front of your Instantiate instead.

yeah tried that already said that the typecast was done wrong. and yeah “as GameObject” works for C# (idk about js) learned it in the BurgZergArcade tutorial.

Ah, you know what? Your instantiating, but your never assigning a name. Try Debug.Log(go==null); if that returns true then go is indeed null, if not your fine and go.name is just unset. (Not sure, but the inspector might just display a generated name if it is null)

ohh ok. yeah I’ll give that a try.

yeah go==null returns true :frowning:

Edit: just tried that method with all the parts of my instantiate function. all 3 parts (the transform, position, and Quaternion.identity) all returned false (so they’re actually there right?) so idk.

… maybe like the reference shows you have to have the variable declaration and the assignment in separate lines? Not sure why that would make any difference!

Could try pasting one of the examples into a script and debug it like you did before, make sure its not doing the same thing.

If it is I’d just file a bug report.

btw the (GameObject) giving a typecast error probably just means you have to have the Instantiate(…) in parenthesis.
(GameObject)(Instantiate(…)); and I see from the examples the as GamObject will work, in fact thats what they use (my bad).

Disregard, I just ran:

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    public GameObject projectile;
    void Start() 
	{
		GameObject clone = Instantiate(projectile, transform.position, transform.rotation) as GameObject;
		Debug.Log(clone==null);
    }
}

and it doesn’t return any error (and returns false like it should), so that wasn’t it.

Got me stumped!

ah ok. yeah I’ll give that typecast a try.

didn’t work :frowning:

and yeah I’m lookin at the reference right now. maybe I’ll have to reinstall unity3d? idk. I’ve had this problem in other projects too I just can’t seem to remember how I worked around it. I’ll go back and reread those scripts again see if I can’t get something out of them this time lol.

thanks for the help tho hopefully I figure this out lol.

yeah, post if you do. This is a weird one!

I just ran

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
	public GameObject BPrefab;
	public GameObject BasicWeapon(GameObject bPref){
			GameObject go = Instantiate(bPref, GameObject.Find("BulletSpawn").transform.position, Quaternion.identity) as GameObject;
				Debug.Log(go.name);
			return go;
		}
	void Start()
	{
		BasicWeapon(BPrefab);
	}
}

and it also worked, so maybe just try copy and pasting that, and change what you need. See whats different, if any thing.

yeah your code is working for me. this is real strange lol. (now if only unity would stop crashing on me so I could test edits to my other code >.> lol).

I even changed the code around. here’s my PlayerControl.cs script in whole.

/// <summary>
/// This file controls our player.
/// It will receive all input made by the player and act accordingly.
/// It will also call all weapons systems in the WeaponsSystems.cs file.
/// </summary>
using UnityEngine;
using System.Collections;

public class PlayerControl : MonoBehaviour {
	public int moveSpeed;							//Set how fast we will be moving multiplied by Time.deltaTime.
	public GameObject bulletPrefab;					//The prefab for our basic bullet.
	
	private Vector3 _moveDir;						//Get a reference to a new vector3 we will use to move.
	private CharacterController _controller;		//Get a reference to our character controller.
	
	private GameObject _go;
	
	public GameObject BasicWeapon(GameObject bPref){
		GameObject temp = GameObject.Find("BulletSpawn");
		_go = Instantiate(bPref, temp.transform.position, Quaternion.identity) as GameObject;
			Debug.Log("GO: "+(_go==null));
		return _go;
	}
	
	// Use this for initialization
	void Start(){
		
		_moveDir = new Vector3();
		_controller = GetComponent<CharacterController>();
		
			BasicWeapon(bulletPrefab);
	}
	
	// Update is called once per frame
	void Update(){
		PlayerMove();
		FireWeapons();
	}
	
	private void PlayerMove(){
		
		if(_controller){
			
			_moveDir = new Vector3(Input.GetAxis("Vertical"),
			                       0,
			                       Input.GetAxis("Horizontal")*-1);
			_moveDir = transform.TransformDirection(_moveDir) * moveSpeed;
			
			_controller.Move(_moveDir * Time.deltaTime);
			
		}
		
	}
	
	private void FireWeapons(){
		
		if(Input.GetButton("Fire1")){
			//GameObject goz = BasicWeapon(bulletPrefab);
			//Debug.Log("GOZ: "+(goz==null));
		}
		
	}
}

Edit: changed it around to look similar to yours. before I had it inheriting from WeaponsSystems.cs where all the weapon functions are stored.

weird.

I just put in the script as you have it and it works great.
even returns “GO: False”

btw I just changed the Debug back to Debug.Log("GO: " GO.name); and it works as well, I was wrong about the name thing… I’m just use to grabbing that from the transform.

I’d submit a bug report, under help though, that script should work and I don’t think it’s version issues or any thing (even if your on 2.6 or some thing). Instantiate hasn’t really changed the whole time I’ve been on unity, since 2.6.

Ack, the insanity! Heh…

  1. Find is slow so don’t use it unless you have to and even then, do it somewhere where you can cache the result as few times as possible. I have never needed to use Find though. Use a class Variable for drag and drop from the inspector if you can.

  2. whenever you get or find something, always check to see if the result was null. If these functions fail for any reason, you’ll get null, and therefore null errors. Check for null and print a nice Debug.logError() for yourself.

  3. don’t use the ‘as’ keyword, When no generic is available, cast with round brackets: (MyType)MyFunction();

  4. Check out PoolManager. It will save you from a lot of performance issues doing massive amounts of instanciation work. This isn’t just a plug, we do a lot of this in our game, that is why we made it. We have support forums as well and are always happy to help. We are releasing a major new version by tomorrow night PST if everything goes well, including a new website and more docs with code examples.

WARNING: I did NOT test this. I just reformatted it in a way that I think makes for a more understandable approach. I am only posting it as an example. I hope this helps:

public class PlayerControl : MonoBehaviour
{
    public int moveSpeed;
    public GameObject bulletPrefab;
    public Transform bulletSpawnPoint;

    private CharacterController controller;
    private GameObject bulletGO;


    // Use this for initialization
    void Awake()
    {
        // Cache
        this.controller = GetComponent<CharacterController>();
        if (this.controller == null)
            Debug.LogError("Character constroller not found.");
    }

    // Update is called once per frame
    void Update()
    {
        PlayerMove();
        FireWeapons();
    }

    private void PlayerMove()
    {
        if (this.controller)
        {
            float x = Input.GetAxis("Vertical");
            float y = Input.GetAxis("Horizontal") * -1;
            var moveDir = new Vector3(x, 0, y);

            // There should be a more direct way to do this, but if it works....
            moveDir = transform.TransformDirection(moveDir) * moveSpeed;
            controller.Move(moveDir * Time.deltaTime);
        }
    }

    private void FireWeapons()
    {
        if (Input.GetButton("Fire1"))
        {
            // Using 'var' because this is obviosuly a GameObject
            var bulletGO = (GameObject)Instantiate(bulletPrefab,
                                                    bulletSpawnPoint.position,
                                                    Quaternion.identity);
            // Make it move here....
        }
    }

This is a major aside, but… I recommend NOT using underscores before private variables. Coming from Python it pains me to admit this, but there is a cool little trick in Unity and an important concept in C# that supersedes this.

First, in C# it is common to use an underscore for a “backing field” which is just a private variable that is used by a property or class to hold some information while an interface is provided for public use. For example, here is a way to make a variable read-only from outside a class, but setable from inside:

    private float _speed;
    public float speed
    {
        get 
        {
            Debug.Log("returning speed");
            return _speed;
        }
    }

In Unity, you can use an underscore in front of a public variable and it will still show up in the inspector, but without the underscore. This means you can have a public backing field! This is an awesome little workaround. For example, say you wanted the variable in the example to be settable in the inspector, but only read-onyl from code with extra stuff.

    public float _speed;
    public float speed
    {
        get 
        {
            Debug.Log("returning speed");
            return _speed;
        }
    }

Notice the only difference is I made it public. This isn’t as clean as we would like, design wise, but unless Unity starts supporting properties in the inspector, which wouldn’t be easy without a custom editor, it still works pretty great.

lol gahh that sucks my script works correctly it just think it has a day off! no more coffee breaks for my scripts! :stuck_out_tongue: but thanks for the help I’ll file a bug report about it then.

Edit: I’m not worried about performance at this point in time, I’m still in like the first .05% of the game I have a long way to go before I really need to worry about performance. I just want to get stuff working atm and do optimizations later on down the road (best way to do it? idk maybe not). I plan on messing with caching everything later on when I have the need.

also I try the (GameObject)Instantiate(); typecast, it returns an error.

PoolManager sounds pretty cool, I saw it just a few days ago (can’t think of much I need Instantiated at the moment) but I’m going to look into it when I do.

Rafes is right though Akinon93, GameObject.Find is very slow! You might not be even one percent into your game, but I can tell you from what I’ve been working on, thinking ahead defiantly helps! I can’t tell you the number of times and different ways I’ve recoded my runtime world editor!!! I finally learned that its probably a good idea to think ahead enough to leave nice clean variable names, simple descriptive comments galore, and objectified code that I can easily delete or change individual functions. (That and with my incessant logic, not to use so many dang nested if statements, 5 birds nests of if statements is probably simplifiable!)

Back on topic though you might want to just add GameObject Found; as a global variable and then just do, if(Found!=null) GameObject.Find(…);

Might not be as good as a pool, but hey… least it prevents you from going through some 30-200 finds every second! :wink:

Hi, Sorry I updated my last post while you typed that. This isn’t so much about performance as how you approach Unity as a framework for your code. I think the basic concepts here are well worth exploration at an early phase. Like doing away with Find() entirely in most cases. It will change how you think about implementing things.

EDIT: Regarding the casting not working… It should. I am using this exact code right now just fine:

        var inst = (Transform)Object.Instantiate(this.prefab, pos, rot);

Did not realize you could color code the text with php tags! cool!

Why in the heck doesn’t every one do that?!

Because it says “PHP” I guess, hehe. I saw it just a few weeks ago myself. I posted asking Unity if they would think about adding languages we actually use, but no answer…

yeah, probably it… oh well.

There is an easier way to do this though:

ignore the PHP Code, this is C#! lol

// There should be a more direct way to do this, but if it works.... 
            moveDir = transform.TransformDirection(moveDir) * moveSpeed; 
            controller.Move(moveDir * Time.deltaTime);

instead you could use:

controller.Move(transform.rotation*moveDir*moveSpeed * Time.deltaTime);

Should do the same thing since all you need from the transform.TransformDirection is to rotate your vector relative to the object. This is just how it does it. (Nice little thing about Quaternion based rotations, just make sure you put them before the vector when multiplying or you’ll get an error.)