- Home /
how to reference a healthbar from another gameobject
I know! This must be the noobiest of all nooby questions but I cannot work it out. I've done it in scripts when the vitals script was initialised in start, but I cannot do that in this instance.
Basically, the script is attached to the camera, it selects a player unit with left click and an enemy unit with right click. The script selects and deselects well enough. The problem is that when an enemy dies (is destroyed) the camera is 'missing an object', i.e., the object fails to become null. I need to access the vitals script so I can make it null as soon as the health hits 0 but everytime I try and reference the script it says that I need to make an instance of the object. It's driving me crazy!!! Here's the script:
using UnityEngine; using System.Collections;
public class CameraDetectClick : MonoBehaviour { Ray ray; RaycastHit hit; public GameObject currentlySelectedPlayer; public GameObject currentlySelectedFoe; private EnemyVitals currentlySelectedFoeHealth; public bool selected;
void Start()
{
//I suspect the solution lies here but not sure what to do with it.
}
void Update()
{
if(Input.GetMouseButton(0))
{
ray = camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.transform.FindChild("SelectedPlayer"))
{
currentlySelectedPlayer = hit.collider.transform.FindChild ("SelectedPlayer").gameObject;
currentlySelectedPlayer.active = true;
selected = true;
}
else if (Physics.Raycast(ray, out hit, Mathf.Infinity) && (hit.collider.name == "Ground"))
{
if(currentlySelectedPlayer != null)
{
currentlySelectedPlayer.active = false;
currentlySelectedPlayer = null;
selected = false;
}
}
}
if(Input.GetMouseButton(1))
{
ray = camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.transform.FindChild("SelectedFoe"))
{
currentlySelectedFoe = hit.collider.transform.FindChild ("SelectedFoe").gameObject;
currentlySelectedFoe.active = true;
selected = true;
//here, the beasty foe has been selected, so I need to grab and monitor its vitals script so I
//can see when it drops to zero. This does not work as it says I need to set it to an instance of an object.
currentlySelectedFoeHealth = currentlySelectedFoe.GetComponent<EnemyVitals>();
if(currentlySelectedFoeHealth.currentBeastHealth == 0)
{
currentlySelectedFoe.active = false;
currentlySelectedFoe = null;
selected = false;
}
}
else if (Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.name == "Ground")
{
if(currentlySelectedFoe != null)
{
currentlySelectedFoe.active = false;
currentlySelectedFoe = null;
selected = false;
}
}
}
}
}
Answer by devstudents · Sep 18, 2014 at 11:39 PM
Someone on stackexchange solved the problem for me. The issue was that I was using raycast to find an a child that did not possess the script I was looking for. I had to use the GetComponentInChildren line to find the child that had the script I was searching for.
Once I found the script using this advice, I realised that another mistake I was making was calling the if statement in the Input.GetMouseButton(1) block. This means that it would only be able to execute the code if I clicked the mouse button again on the target, but since the enemy is destroyed when it's health hits zero that wouldn't be possible. Besides, it would be stupid to have to click a dead enemy in order to make it null. Bellow is the adjusted script if anyone is interested.
using UnityEngine; using System.Collections;
public class CameraDetectClick : MonoBehaviour { Ray ray; RaycastHit hit; public GameObject currentlySelectedPlayer; public GameObject currentlySelectedFoe; public EnemyVitals enemyVitals; public bool selected;
void Start()
{
}
void Update()
{
if(Input.GetMouseButton(0))
{
ray = camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.transform.FindChild("SelectedPlayer"))
{
currentlySelectedPlayer = hit.collider.transform.FindChild ("SelectedPlayer").gameObject;
currentlySelectedPlayer.active = true;
selected = true;
}
else if (Physics.Raycast(ray, out hit, Mathf.Infinity) && (hit.collider.name == "Ground"))
{
if(currentlySelectedPlayer != null)
{
currentlySelectedPlayer.active = false;
currentlySelectedPlayer = null;
selected = false;
}
}
}
if(Input.GetMouseButton(1))
{
ray = camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.transform.FindChild("SelectedFoe"))
{
enemyVitals = hit.collider.transform.root.GetComponentInChildren<EnemyVitals>();
currentlySelectedFoe = hit.collider.transform.FindChild ("SelectedFoe").gameObject;
currentlySelectedFoe.active = true;
selected = true;
}
if (Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.name == "Ground")
{
if(currentlySelectedFoe != null)
{
currentlySelectedFoe.active = false;
currentlySelectedFoe = null;
selected = false;
enemyVitals = null;
}
}
}
if(enemyVitals != null && enemyVitals.currentBeastHealth == 0)
{
currentlySelectedFoe.active = false;
currentlySelectedFoe = null;
selected = false;
enemyVitals = null;
}
}
}
Answer by Slev · Sep 18, 2014 at 04:31 PM
Make a public variable to hold the object containing the health bar. Then we can use GetComponent () to access the script and alter its values.
Answer by dmg0600 · Sep 19, 2014 at 05:41 AM
I think you might want to move this code to Update (putting it into the first if):
if (currentlySelectedFoe != null && currentlySelectedFoeHealth != null)
{
if (currentlySelectedFoeHealth.currentBeastHealth == 0)
{
currentlySelectedFoe.SetActive(false);
currentlySelectedFoe = null;
selected = false;
}
}
That way you will look each frame if the enemy has died in order to deselect it. The first if is to check that you actually have and enemy with a healthbar seleted.
If it doesn't work, could you show as the exact error Unity is prompting?
That's a good point but it seems to work now even without doing it like that. I should change it though as I can imagine my ordering getting me in trouble in another script. Thanks for the advice :)
The problem I'm having now is trying to code it so that the first enemy is deselected when I right click another duplicated enemy. I've got it so I can right click, deselect with left on the terrain or anywhere really, and select another enemy with right again. It's cumbersome but hopefully I'll find a way around it!
To do so, simply deactive the previously selected enemy when selecting a new one.
if(Physics.Raycast(ray, out hit, $$anonymous$$athf.Infinity) && hit.collider.transform.FindChild("SelectedFoe"))
{
if (currentlySelectedFoe != null)
{
currentlySelectedFoe.SetActive(false);
}
enemyVitals = hit.collider.transform.root.GetComponentInChildren<EnemyVitals>();
currentlySelectedFoe = hit.collider.transform.FindChild ("SelectedFoe").gameObject;
currentlySelectedFoe.SetActive(true);
selected = true;
}
I recommend you use gameObject.SetActive(bool value) ins$$anonymous$$d of gameObject.active, as gameObject.active is deprecated.
Hope this helps, good luck with your project!
thanks a lot! it worked! I had no idea the unity community would be so awesome.
Your answer
Follow this Question
Related Questions
Null reference.. 2 Answers
C# class public variables null in all methods but start() 0 Answers
C# Null Object Reference - Driving me mad! 1 Answer