- Home /
(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'd hate to be a douche and bump it, but none of these Answers have helped me any further.
Anyone, with the slightest guidance is welcome.
Answer by fafase · Jan 23, 2014 at 06:17 PM
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>();
but.. what im trying to do, is getting a value from a script on objectA assigned to a variable in objectB.
And the value is a variable from the scripts "class"-that it is inheriting for.
(hope this can kinda visualise it :S )
Itemclass -> weaponclass -> beginnersword.script
player collides sword
begginersword.script(_$$anonymous$$O$$anonymous$$) -> Player.equip.script.
The way you do things do not matter. What matters is that you have your inner object instant oater in the outer class with the new command. This is probably the missing part of your implementation. After whether you want to assign or use a value in the class is the same.
But how would i apply this
public class OuterA:$$anonymous$$onoBehaviour
{
public class Inner
{
public int val
public Inner(int value)
{
val = value;
}
}
public Inner inner = new Inner(10);
}
to this
using UnityEngine;
using System.Collections;
public class BEGINNERSWORD : $$anonymous$$onoBehaviour {
public class BEGINNERSWORD_01 : WEAPONS{
void Start() {
_NA$$anonymous$$E = "beginner sword";
_TYPE = 1;
_VALUE = 001;
_$$anonymous$$O$$anonymous$$ = Resources.Load("SWORD_$$anonymous$$O$$anonymous$$", typeof(GameObject)) as GameObject;;
_ATTD$$anonymous$$G = 10;
}
}
}
$$anonymous$$y advice, you are going the wrong way. Do yourself a favor and take this class out and make everything simple. Your design actually does not make sense since ITE$$anonymous$$S and WEAPONS are normal class and then a sub class is declared public within another one... And in the end it does not work. Do yourself a favor and get it out.
On top of that it seems Unity does not appreciate nested $$anonymous$$onoBehaviour classes. It could be the reason why you get the Null reference. It seems Unity requires a script with the class as title of the script. I could be wrong but that is what the error I get seems to say.
All in all, you need your BEGINNERSWORD_01 in its own script.
i changed the BEGINNERSWORD to this -
using UnityEngine; using System.Collections; public class BEGINNERSWORD : $$anonymous$$onoBehaviour { static GameObject model; public void Awake(){ model = Resources.Load("SWORD_$$anonymous$$O$$anonymous$$", typeof(GameObject)) as GameObject; } public WEAPONS wep01 = new WEAPONS("beginnersword",null,001,1,model,10f,0); }
and in Equip i did this
BEGINNERSWORD bs = col.gameObject.GetComponent<BEGINNERSWORD>();
Weapon = bs.wep01._$$anonymous$$O$$anonymous$$;
but it still just gives me "Object reference not set to an instance of an object"
Answer by Nanobrain · Jan 22, 2014 at 12:15 AM
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.
Unfortnualy , "_$$anonymous$$O$$anonymous$$" is from the Weapon-class, and it is declared public in there already.
and, when i remove the bs1 , and do "bs.BEGINNERSWORD_01.$$anonymous$$O$$anonymous$$" It tells me "`BEGINNERSWORD_01': cannot reference a type through an expression; try BEGINNERSWORD.BEGINNERSWORD_01' ins$$anonymous$$d" and when i do that it says "An object reference is required to access non-static member
WEAPONS.$$anonymous$$O$$anonymous$$'"
Answer by KellyThomas · Jan 22, 2014 at 05:03 PM
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?
Hello kelly$$anonymous$$, the reason i said it is already public , is because it is public in the class that "BEGINNERSWORD_01" inherits from("WEAPONS").
This is the Debug Log after trying yours. Although, when i tried this
public void OnCollisionEnter(Collision col){
if(col.gameObject.tag == "SWORD"){
BEGINNERSWORD bs = col.gameObject.GetComponent<BEGINNERSWORD>();
Weapon = BEGINNERSWORD.BEGINNERSWORD_01._$$anonymous$$O$$anonymous$$;
Destroy(col.gameObject);
}
it said -
An object reference is required to access non-static member `WEAPONS._$$anonymous$$O$$anonymous$$'
if that is to any help at all :-)
Which GO's inspector did you want you want to see?:-)
To solve that most recent error:
Weapon = bs._$$anonymous$$O$$anonymous$$;
If we can see the inspector for the game object you have these scripts on it may clear up some questions.
"the reason i said it is already public , is because it is public in the class t,at "BEGINNERSWORD_01" inherits from("WEAPONS"). " If it is defined in a base class there is no need to redefine, however if you do mask it in a child class then you should provide a full definition including specifying the required access modifier.
I'm not sure what you are trying to achieve, but I think you may be going about it the hard way. There is no real need for an inner class (the only advantage I can think of at the moment is a slightly tidier namespace), but a couple of disadvantages. The largest of which is that when scripts are assigned to a game object they are done as a file i.e. there is no way to assign an inner class as a Component using the unity GUI. This may not be an issue now should be a restriction to bear in $$anonymous$$d. .
The reason i redefine it in another script it because that is a weapon, and shouldent it derive from my "WEAPON"-class? And the reason for the inner class is, else it wouldent allow me to attach it to a gameobject. If you know any other way to do this it would be greatly appreaciated :-)
There is really nothing to see in the inspector, other than R-Hand is my characters hand's transform.
what i am trying to achieve is - when my char collides with the weapon, he will equip it. and then later, i will make the Inventory it will be put into.
this is my weapon class although :-)
WEAPON
using UnityEngine;
using System.Collections;
public class WEAPONS : ITE$$anonymous$$S {
public int _TYPE;
public GameObject _$$anonymous$$O$$anonymous$$;
public float _ATTD$$anonymous$$G;
public int _INFUSED;
public int infusement(int curATT){
int gain;
int newAtt;
gain = curATT - 3;
newAtt = curATT + gain;
return newAtt;
}
}
ITE$$anonymous$$(if you were wondering)
using UnityEngine;
using System.Collections;
public class ITE$$anonymous$$S : $$anonymous$$onoBehaviour{
public string _NA$$anonymous$$E;
public Texture2D _ICON;
public int _VALUE;
public ArrayList _ASPECTS = new ArrayList(5);
}
Any non-nested class that derives from Component (typically extending $$anonymous$$onoBehaviour) can be attached to a game object. This should be as simple as drag-and-drop or calling GameObject.AddComponent()
.
Given that the previous should be a non-issue I wonder if the difficulty was assigning values to an instance field. If so please consider the following example classes (each in their on .cs file). If SampleScript
was attached to a game object in scene then an instance of WeaponBase
, WeaponPointy
, or WeaponBlunt
could be assigned to the WeaponInHand
field (including by use of the inspector). Note that to have an instance of one of these scripts available at design time it would need to be attached to a game object in scene. Of course WeaponInHand
can also hold any instances created programmatically at runtime.
public class SampleScript: $$anonymous$$onoBehaviour {
public WeaponBase WeaponInHand;
void Update() {
Debug.Log("Wielding: " + WeaponInHand.Name);
}
public class WeaponBase: $$anonymous$$onoBehaviour {
public String Name = Base;
}
public class WeaponPointy: $$anonymous$$onoBehaviour {
void Awake() {
Name="Pointy";
}
}
public class WeaponBlunt: $$anonymous$$onoBehaviour {
void Awake() {
Name="Blunt";
}
}
Now the console log you posted earlier indicated that the "`col.gameObject.GetComponent()`" call was returning null. This will only occur if:
col.gameObject
does not have a component of typeBEGINNERSWORD.BEGINNERSWORD_01
orUnity getting confused the inner class.
$$anonymous$$y inclination is to think the first scenario is most likely, especially as I believe it is impossible add an inner class as Component using the inspector.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
homing missiles and transform and colission help c# 1 Answer
How to call OnTriggerEnter once 5 Answers
Distribute terrain in zones 3 Answers
Hiding a GUI Texture upon death. 1 Answer