C# How to access a parent class variable when parent class isn't attached to object?

I’ve spent the last few days trying to figure this out but this has me stumped. I have a script named GameGUI.cs attached to my player object. I have another gameobject on the screen that has the script named weakCreature.cs that is a child of enemyCreature.cs.

Inside enemyCreature.cs are several variables that I would like to access in GameGUI.cs to display on screen.

Can anyone point me in the right direction on what I should do?

hi, it’s very simple, inside GameGUI.cs you declare a public GameObject enemy and Object linking enemyCreature at enemy (drag).

After doing this you can read variables enemyCreature.cs by GetComponent:

public GameObject enemy;

enemy.GetComponent<enemyCreature>().sample = "sample";
1 Like

enemyCreature.cs is the parent class that isn’t attached to any gameobject at all. I’m assuming I should make a prefab from an empty game object and attach the script to it and then drag it to the declared public gameobject inside GameGUI.cs? To me, it seems a bit crude (but it will work).

Are there any other ways of accessing the variables inside enemyCreature.cs in a more… elegant way?

Typically (as far as I can tell), central scripts that have no actual location can go on an empty GameObject that exists in every (similar) scene, such as “Game Manager” or “Control Center”. Then, you can use the following code:

public GameObject Control;

void Start(){
    Control = GameObject.Find("Control Center");
}

void Update(){
    Control.GetComponent<"Script">.such = ...
}

This generally saves time and the possibility of forgetting to attach it every time you attach this script to a general game object. Really helpful for making general scripts in “large” scenes. You can probably even shorten it more by assigning the Script its own Component variable (never used it yet, but assuming one exists) and such. You can also call functions as well.

Edit: By the way, is the “()” after GetComponent<> necessary? I know you don’t need it in UnityScript but can’t find a C# example in the Unity docs.

Yes you need the “()” like most methods(all? I forget the syntax for anonymous methods).

It worked-kind of. I can print the variables out and access them, but they don’t seem to change at all now. In enemyCreature.cs, there are two boolean variables that get switched to true or false based on the OnMouseOver() and OnMouseExit() functions. However, they seem to be stuck at false (their default values) when passed to GameGUI.cs. Any ideas what I should do?

Please post your scripts. Then we’ll be able to see what’s going on. Right now, I can’t see what’s the exact problem with that description.

My GUI code:

public class GameGUI : MonoBehaviour {
	
	public GameObject hostileEnemy;
	
	public bool isHovering;
	public bool isTargeting;
	
	public int EnemyHealthOffsetX = 0;
	public int EnemyHealthOffsetY = 0;	

	void Start () {
		isHovering = hostileEnemy.GetComponent<enemyCreature>().isHovered;
		isTargeting = hostileEnemy.GetComponent<enemyCreature>().isTargeted;

	}
	
	void Update () {

	}
	
	void OnGUI(){

		
		if(isHovering == true){
			Debug.Log ("Mouse hover detected");
			GUI.Box(new Rect((Screen.width/2)-EnemyHealthOffsetX,(Screen.height/16)-EnemyHealthOffsetY, 250, 50), " Testing");
		}
	}
}

My enemyCreature parent class:

public class enemyCreature : MonoBehaviour {
	public bool isTargeted = false;
	public bool isHovered = false;
	
	public enemyCreature (){

	}
	
	void Start () {
	
	}
	

	void Update () {
	
	}
	
	void OnMouseOver(){
		isHovered = true;
		isTargeted = true;
	}
	
	void OnMouseExit(){
		isHovered = false;
		isTargeted = false;
	}
}

Weak enemy child class (the parent class is enemyCreature) is empty at the moment but the script is attached to a gameobject for testing.

Edit: I removed the debug statements.

public class GameGUI : MonoBehaviour {

    

    public GameObject hostileEnemy;
    public enemyCreature Enemy;
    

    public int EnemyHealthOffsetX = 0;
    public int EnemyHealthOffsetY = 0;  

 

    void Start () {

        Enemy = hostileEnemy.GetComponent<enemyCreature>();

    }

    

    void Update () {

    }

    

    void OnGUI(){

 

        

        if(Enemy.isHovered == true){

            Debug.Log ("Mouse hover detected");

            GUI.Box(new Rect((Screen.width/2)-EnemyHealthOffsetX,(Screen.height/16)-EnemyHealthOffsetY, 250, 50), " Testing");

        }

    }

}

I tried what Na-Ra-Ku posted but I’m getting nothing so far. I assumed I have to manually assign the gameobject with the enemyCreature script to the public enemyCreature Enemy, but nothing so far is happening.

You shouldn’t manually assign anything to that variable. Make it private.

You are fetching the reference to the enemyCreature script from the hostileEnemy object in the start function

Does the object with the enemyCreature script attached have a collider? If it doesn’t mouseover wont work.

enemyCreature is the parent class and as such, will not be on any gameobject with a collider. It’s stored in an empty gameobject because it’s used as a template for all other enemy types I plan to work on.

Ray, I’m not sure how to say this gently, but your question here doesn’t seem to make any sense. You seem to be confusing classes and instances, but that alone doesn’t explain all the confusion. You also talk about a parent class, but in your code, the parent of enemyCreature is MonoBehaviour, so there is no other class involved. If you have some subclass as well, please post the code for that. Further, your GUI code is accessing some particular enemy; the enemy code updates its properties based on OnMouseOver and OnMouseExit; but you claim that the code is attached to an empty GameObject, which of course will never receive any mouse events. I can see why this doesn’t do anything useful, but I can’t guess what it is you’re trying to accomplish.

Can you back up and describe what you’re trying to do? And also post any other code involved in the process?

if weakCreature is a child of enemyCreature then weakCreate IS enemyCreature. That means that weakCreature contains all variables and methods that enemyCreature has, because of inheritance.

public class Parent : MonoBehaviour
{
  public bool Foo;
}

public class Child : Parent
{
  public bool Bar;
}

In the example above the Child class contains 2 bool values, Foo and Bar

I wonder if perhaps Ray is shadowing (hiding) parent properties in the subclass. That’s why we need to see the subclass (weakCreature) code.

Don’t worry about phrasing things gently. I’m all about getting to the point so it’s absolutely fine if you be blunt and honest about things.

As for what I’m trying to do, I’m trying to have my gui (eventually) display the health meter of the enemy creatures when moused over and to have said health meter disappear when the mouse isn’t hovering on a particular enemy.

To give an example: I have three enemy gameobjects in one area, I move my mouse over each enemy and each time the mouse is over a particular enemy, their particular health meter will be displayed along with their name. Whenever the mouse isn’t on one particular enemy, then no enemy health bar with name will be displayed.

As for posting the code, sure, I have one other gameobject “enemyCreatureWeak” with the following script attached:

public class enemyCreatureWeak: enemyCreature{
	
	public enemyCreatureWeak(){
		
	}
	
	// Use this for initialization
	void Start () {

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

	}
}

I’m using this gameobject to test out if I can get the GameGUI to display the name “enemyCreatureWeak” because eventually, there will be an “enemyCreatureMedium,” “enemyCreatureStrong,” etc. Also, I’m trying to get the mouse cursor to change–I know how to do it, but I want to get the mouseover and mouseexit working first.

Edit: So why not use enemyCreatureWeak instead of enemyCreature? Because I want to have alot more future enemy types whose parent class is enemyCreature and typing/copy + pasting the code into each enemy type just doesn’t seem that efficient.

Essentially, what I want to do is to be able to display the name and health meters of each individual enemy when mousing over them. I can add a health variable to enemyCreature.cs, alter it in the enemyCreatureWeak, and print the statement out in the debug log, but getting it to show up on the GUI is much harder for me at the moment.

OK, thanks, that clears things up quite a lot.

So, I don’t think you need to worry about the subclasses here. As dterbeest said, an enemyCreatureWeak is an enemyCreature; all other code (such as your GUI code) can simply look for enemyCreatures, deal with what it finds as enemyCreatures, and doesn’t need to know what specific type (subclass) of enemyCreature it’s dealing with.

So now the issue is: how to display some GUI stuff for the creature you mouse over? I think you’re trying to approach this from the perspective of the GUI object. That won’t work… you need to let the enemyCreatures control this, because they’re the ones that can detect mouseOver and mouseExit. However, all they have to do is note which enemy is being moused over, and provide that data to other scripts somehow.

There are lots of ways to crack that nut, but a very simple approach would be to use a static variable. So, in the enemyCreature class, add this:

  public static enemyCreature hoverTarget = null;

Then, define enemyCreature’s mouse methods like this:

void OnMouseOver() {
        hoverTarget = this;
}

void OnMouseExit() {
        if (hoverTarget == this) hoverTarget == null;
}

Now, any other script that cares about such things can simply look at enemyCreature.hoverTarget, to get the enemyCreature the mouse is over (or null, if none). This includes your GUI script, which can then position itself above the hoverTarget and stats of that, or hide itself entirely when enemyCreature.hoverTarget == null.

Annndd… Done. Thank you so much!

Sorry, I happened across your post looking for something else, but I thought I’d comment here, it looks like your issue is that you aren’t updating the isHovering and isTargeting variables. You set them when the GameGUI object is created, but never update them. I think what your looking for is something along these lines:

public class GameGUI : MonoBehaviour {
	
	public GameObject hostileEnemy;
	
	public bool isHovering;
	public bool isTargeting;
	
	public int EnemyHealthOffsetX = 0;
	public int EnemyHealthOffsetY = 0;	

	void Start () {
		isHovering = hostileEnemy.GetComponent<enemyCreature>().isHovered;
		isTargeting = hostileEnemy.GetComponent<enemyCreature>().isTargeted;
	}
	
	void Update () {
		isHovering = hostileEnemy.GetComponent<enemyCreature>().isHovered;
		isTargeting = hostileEnemy.GetComponent<enemyCreature>().isTargeted;
	}
	
	void OnGUI(){

		
		if(isHovering == true){
			Debug.Log ("Mouse hover detected");
			GUI.Box(new Rect((Screen.width/2)-EnemyHealthOffsetX,(Screen.height/16)-EnemyHealthOffsetY, 250, 50), " Testing");
		}
	}
}

You could further simplify things by simply storing a link to the enemyCreature component and avoiding the GetComponent lookup on every update.