- Home /
A NullReferenceException even though I'm sure that object was assigned?
OK - I've been following the Stealth game project example - didn't really like the way the guy's been organizing the code - so I thought I could do better - so basically, what I have is:
1- a game object called 'gameController' (much like in the tuts) that has: A) a script attached to it called "GameControllerScript" B) a number of child objects (you don't have to know about all of them) - one of them is "music"
2- now 'music' has: A) a script attached to it called "MusicScript" B) two child objects: NormalMusic, PanicMusic each with NormalMusicScript and PanicMusicScript attached to respectively.
Logically, I made NormalMusicScript and PanicMusicScript inherit from MusicScript, here's my codes:
public class Music : MonoBehaviour {
public float maxVolume = .8f;
public float minVolume = .1f;
public float fadeSpeed = 2f;
protected GameControllerScript gameController;
protected float targetVolume;
public virtual void Awake()
{
gameController = transform.parent.gameObject.GetComponent<GameControllerScript>();
}
public void FadeTo(float volume)
{
audio.volume = Mathf.Lerp(audio.volume, volume, fadeSpeed * Time.deltaTime);
}
}
public class PanicMusicScript : Music {
void Update()
{
if (gameController.PlayerHasBeenSpotted())
{
targetVolume = maxVolume;
}
else
{
targetVolume = 0;
}
FadeTo(targetVolume);
}
}
(The NormalMusicScript has similar code so no need to post it)
Now the problem is: when I run the game, I get a NullReferenceException at the line
if (gameController.PlayerHasBeenSpotted())
saying that gameController is null - So I debugged to check the problem - I put a breakpoint at the assignment of gameController in the Awake of MusicScript parent class - it got assigned no problem - but then after I stepped, the same Awake of the parent got executed again! - but this time, gameController returned null! - I didn't know what that was about - so I thought that if I didn't override the Awake in the child, the Awake of the parent will also get called on the child - so I tried this:
public override void Awake()
{
return;
}
When I debugged again - it didn't execute Awake twice - but still broke at the same line saying that gameController is null I tried to use the constructor instead of Awake (cuz I remember having similar problem in the past and managed to solve it that way) but no luck - got some other errors saying not to use the constructor or something... I also tried to initialize in Start instead of Awake - same.
Why is this happening? - any help would be appreciated - thanks a lot in advance.
Are you certain the same $$anonymous$$onoBehaviour is being executed twice? Can you try logging the name of the transform in the awake function? Then try logging the name of the transform.parent.
O$$anonymous$$ - that's pretty much weird. In the parent $$anonymous$$usicScript class, I logged its transform - I checked out the address, first time it was something like 0x146b38 - As expected - awake got executed again but this time the log gave something else - as if there's 2 'music' objects with $$anonymous$$usicScripts! - I also logged the parent's transform the child's Awake, guess what? - it was 0x146b38 and it only got executed once - so the issue's in the 'music' game object somehow :/
It's as if Unity is telling us not to use inheritance and OOP? :( what's the better approach then? - I'm confused.
I'm not sure whether or not the issue is with inheritance. I've certainly never seen anything like what you're describing, so I do wonder if there's something weird in your project.
As with all debugging, it all comes down to narrowing where the issue lies :) Are your two classes defined in separate script files? Having two $$anonymous$$onoBehaviour-derived classes in a single script could definitely be confusing to Unity.
What happens if you start a new project, add the two classes you have defined here, attach Pan$$anonymous$$usicScript to a single GameObject, and hit play?
Transform is a component, and GameObject is the container that holds components.
'transform' is just shorthand for GetComponent(); All GameObjects have to have a transform component, so you're guaranteed that transform will never return null.
So transform.parent.gameobject is: "get the transform component, get its parent transform component, get the gameObject container for that transform component."
Note that GameObject itself doesn't store parenting information ( it's just a container) - the parenting is stored in the transform. So your second example wouldn't compile. You could do "transform.parent.gameObject.transform.parent", but that would be redundant :)
Since parent is of type transform, you can certainly do things like transform.parent.parent.parent....
Answer by Julien-Lynge · Jun 06, 2013 at 05:51 PM
correct - transform always means the transform of the script it's being called from. So you could have a bunch of different PanicMusic scripts, and each would have a different transform (assuming they're all attached to different game objects).
In OOP, remember that there is no connection between instances of objects, even if they share similar class traits. There is no connection between your MusicScript and you PanicMusicScript instances within Unity either.
So to clarify, in the setup you have above, the parent of MusicScript's transform (e.g. music) is game controller, and the parent of PanicMusicScript's transform (e.g. PanicMusic) is music.
Your answer
Follow this Question
Related Questions
How to call child overide function? 1 Answer
Multiple Cars not working 1 Answer
Javascript Inheritance; how to not override functions? 1 Answer
Distribute terrain in zones 3 Answers
Function GUI with a Return value 1 Answer