(C#)Accessing a GameObject from a class, inside another class. On collision with other object.

Hello whoever might be reading this.

First off, i’d like to apologize for any bad grammar that might occur.

English is not my main Language.

So, my problem is so :

I got a script(lets call it scriptA), where i got a class inside of it(lets call it classA), that is attached to a gameobject.

and i got another script, at another gameobject(lets call this scriptB), and i am trying to assign a variable from script scriptA’s classA to a variable in scriptB, on collision.

now, ive tried dozen of things, without luck. and the most common error it gives me is

“NullReferenceException: Object reference not set to an instance of an object
Equip.OnCollisionEnter (UnityEngine.Collision col) (at Assets/Player/SCRIPTS/Equip.cs:42)”

Any help would be insanely appreaciated.

scriptA :

using UnityEngine;
using System.Collections;

public class BEGINNERSWORD : MonoBehaviour {
	static GameObject MODEL = Resources.Load("SWORD_MODEL", typeof(GameObject)) as GameObject;

	public class BEGINNERSWORD_01 : WEAPONS {

	void Init () {
		_NAME = "Beginner Sword";
		_TYPE = 1;
		_VALUE = 001;
		_MODEL = MODEL;
		_ATTDMG = 10;
	}
	}
	//public BEGINNERSWORD_01 BS_01 = new BEGINNERSWORD_01;
}

scriptB:

using UnityEngine;
using System.Collections;

public class Equip : MonoBehaviour {
	public GameObject Weapon = null;
	public Transform rHand;
	bool equiped = false;
	GameObject t = null;
	// Use this for initialization
	void Start () {

	}

	void equip(){ 
		if(!equiped){
		t = Instantiate (Weapon, rHand.position, rHand.rotation)as GameObject;
		t.transform.parent = rHand.transform;
		equiped = true;
		}
		else if (equiped){
		Destroy((GameObject)t);
		equiped = false;
		}
	}

	// Update is called once per frame
	void Update () {
		if(Input.GetKeyDown(KeyCode.E)){
			if(Weapon = null){
				Debug.Log("NoWeapon" + Weapon.tag);
			}
			else{
				equip ();
			}
		}
	}

	public void OnCollisionEnter(Collision col){
		if(col.gameObject.tag == "SWORD"){
			BEGINNERSWORD bs = col.gameObject.GetComponent<BEGINNERSWORD>(); 
			BEGINNERSWORD.BEGINNERSWORD_01 bs1 = GetComponent<BEGINNERSWORD.BEGINNERSWORD_01>();
			Weapon = bs1._MODEL;
			
		
		} 
	}
}

I think that this line is not necessary:

BEGINNERSWORD.BEGINNERSWORD_01 bs1 = GetComponent<BEGINNERSWORD.BEGINNERSWORD_01>();

BEGINNERSWORD.BEGINNERSWORD_01 is not a component, but an inner class of a component.

So, do this:

Weapon = bs.BEGINNERSWORD_01._MODEL;

However, note that _MODEL is declared as a local variable within your Init method. You will need to declare it as a public member outside of a method within your inner class.

Try running this and see what the console says:

    public void OnCollisionEnter(Collision col){
       if(col.gameObject.tag == "SWORD"){
         Debug.Log(col.gameObject.GetComponent<BEGINNERSWORD>());
         BEGINNERSWORD bs = col.gameObject.GetComponent<BEGINNERSWORD>();

         Debug.Log(col.gameObject.GetComponent<BEGINNERSWORD.BEGINNERSWORD_01>());
         BEGINNERSWORD.BEGINNERSWORD_01 bs1 = GetComponent<BEGINNERSWORD.BEGINNERSWORD_01>();

         Weapon = bs1._MODEL;
       } 

This will test if the GetComponent() calls are returning anything.

It may also be helpful if we can see a screenshot of the Inspector for this object.

In a reply to Nanobrain you say that BEGINNERSWORD.MODEL is public, this is not the case in the code you have posted. Are we seeing an out of date version?

Here is a quick example that works:

public class OuterA:MonoBehaviour
{
     public class Inner
     {
         public int val
         public Inner(int value)
         {
             val = value;
         }
     }
     public Inner inner = new Inner(10);
}

public class OuterB:MonoBehaviour
{
     public OuterA outer:
     void Start()
     {
         print(outer.inner.val);
     }
}

Now you get the OuterA component just like any component in Unity using GetComponent. You need an instance of Inner object, simply declaring the class is not enough, it just means you cannot instantiate an object of that class outside of the OuterA without using OuterA as well.

public class OuterB
{
    OuterA.Inner inner = new OuterA.Inner(20);
}

Once you got the OuterA component, the inner instance shows up and the val variable as well after two dereferenciation.

It is not really common to see an inner class that should be public and seen from outside. Or then via a method is more appropriate. Inner classes and structs are more likely to be a container used within the class it is declared and not really known to the other classes.

EDIT: In the case of MonoBehaviour, it is not possible to nest one class into another (at least it does not work in the most simple way), the compiler complains that the script does not have the same name than the component we are trying to use.

So the easiest solution is to take the class out and make it a basic script to be added using :

gameObject.AddComponent<Component>();