This is a question of scope and reference. What the error message is telling you is, that in the scope that you are currently operating in, there is no variable called Health. This makes pretty good sense, if you consider the case where both scripts had a variable with the same name. How would your code know what one to pick, if they were both available directly to you. So what you need to do is establish a reference to the other script, so you can point to it and say ‘the variable health I want to change is on that gameobject, in that script’. When you don’t use a reference, the code assumes that the variable you are looking for is in the script you are currently in, and that is obviously not the case here.
[01] Getting a reference to the gameobject:
The easiest and fastest way to do this is to create a public transform or gameobject variable, and then manually drag the gameobject that holds the other script onto the field in the inspector. You can also do this with the following code. But a very important thing to note is, this is only required if your two scripts are on different gameobjects, since before we can point to the script, we need to point to the gameobject it is on. In the case where both scripts are on the same gameobject, you can skip this step somewhat. The second code example here, is when you want to do this from within the script, if you don’t want to drag the gameobject, or for various reasons can’t do it before you start the game.
[Food.js]
// Assign the reference manually before running!
public var reference : Transform;
[Food.js]
// Find the reference automatically at runtime!
private var reference : Transform;
function Awake ()
{
reference = GameObject.Find("NameOfGameObject").transform;
}
[02] Getting a reference to the script:
Now that we know what gameobject (transform) to point to, we can then find the script on it, and establish a reference directly to it, so we can change it in any way we like, as it were our own. This is done by looking up the script, remember that a script is a component. So by using the ‘GetComponent’ we can find a reference to the script. Note that before you call GetComponent you should tell it on what gameobject or transform it should look for it. So we will use the ‘reference’ variable we established above, or simply ‘transform’ if they are on same script. Finally, there’s something very notable that I am skipping, since that is not the question, but in the future you should look into storing the reference to the script, so you don’t have to get the component each time you need it. In this example I will just call it when you want to change the variable, but for performance, look into caching it!
i added the var: public var reference : Transform;
and took the “Burger” object with the food script and dragged it to the “players” Transform, but i stil lget “unknown Health yada yada stuff”…
when i do it, it tells me an error: NullReferenceException: Object reference not set to an instance of an object Food.Update () (at Assets/Food.js:10) My code looks like this:
#pragma strict
private var drawGUI = false;
var Burger : int = 10;
function Update ()
{
if (drawGUI == true && Input.GetKeyDown(KeyCode.E))
{
gameObject.GetComponent(PlayerHealthV2).Health += Burger;
}
}
function OnTriggerEnter (theCollider : Collider)
{
if (theCollider.tag == "Player")
{
drawGUI = true;
}
}
function OnTriggerExit (theCollider : Collider)
{
if (theCollider.tag == "Player")
{
drawGUI = false;
}
}
function OnGUI ()
{
if (drawGUI == true)
{
GUI.Box (Rect (Screen.width*0.5-51, 200, 102, 22), "Press E to eat");
}
}
don’t use direct access to another script’s attributes. You’ll just walk into the “how do i stop the health value going over the maximum” question next…
add a function to Health which takes a value as a parameter. It can then handle “what happens when anything tries to add some health”, clamp to 0/max/whatever, play sounds, trigger effects etc.
food then just needs a reference (i.e. Health myHealth = …) to the specific health script attached to the same gameobject (as above) and call
He says what i have to do and thats great, but when i ask and someone says i should make a parameter and stuff, i prefer to get told what to do in scripting.
I´m pretty new to this and i dont know what all in coding is yet, so when he says that i should do that, again, i would like to have an example of how you do it in coding
the error you posted is because you didn’t follow both steps in dee’s post. You just did the second one.
my post was regarding the “health += food” vs “Health.AddHealth(food)”… once you’ve got a reference to the “health” you want to improve from what Dee has posted.
I’m usually more of a “teach to fish” guy, but I’ve just put two and two together and realised you were the forum member having trouble with the health/hunger script linkage a few days back… so I threw the below together as an example. Bare in mind I’m usually a c# scripter and I’ve not got a compiler handy to check for errors so typos are likely.
Things to note:
no script directly modifies another scripts variables (they’re all public so they show up in the inspector, you might want to make some private etc. when you understand more).
each script does “it’s own thing” without worrying about what another script is doing (in reference to the previous threads).
functionality is put into functions, so they can be reused (i.e. Apply####Damage functions are the only place where the values are reduced and it is there which the value is clamped)
Hunger, Health and Player go on a player object (you’ll need to add some sort of movement management either in Player or in another script attached to the same game object). Food goes on the food (obviously?).
Food doesn’t have “eat” function, food doesn’t eat, it is eaten. The player Eats, so it makes more sense for a script to do with the player to handle that, when you Eat you eat Food, so Eat takes a Food object parameter. (note: sentence being turned into Objects and Functions here.)
I’d suggest you look into “Object Orientated Design Principles” (i.e. google it) and try to understand how Objects, Functions and Attributes should be arranged.
//---------- Food ----------\\
public var hungerValue : float = 10; // different values for health and hunger
public var healthValue : float = 2;
function Eaten()
{
//handle other stuff before being destroyed
Destroy(gameObject);
}
//---------- Hunger ----------\\
public var myHealth : Health;
public var currentHunger : float;
public var maximumHunger : float = 100;
public var intervalDuration : float = 5;
public var intervalStart : float = 0;
public var hungerDamage : float = 1;
public var healthDamage : float = 5;
function Start()
{
myHealth = gameObject.GetComponent(Health);
if(!myHealth)
{
Debug.Log("Health script missing on " + gameObject.name);
}
currentHunger = maximumHunger;
}
function Update()
{
if(Time.time >= intervalStart + intervalDuration) // check hunger
{
intervalStart = Time.time; // reset for next interval
ApplyHungerDamage(hungerDamage);
if(IsHungry()) // we're hungry take damage
{
myHealth.ApplyHealthDamage(healthDamage);
}
}
}
function ApplyHungerDamage(d: float);
{
currentHunger -= d; // apply the damage
currentHunger = Mathf.Clamp(currentHunger, 0, maximumHunger); // make sure we don't go negative or over maximum
}
function IsHungry() : bool
{
return currentHunger <= 0;
}
function Eat(Food foodItem)
{
myHealth.ApplyHealthDamage(-foodItem.healthValue);
ApplyHungerDamage(-foodItem.hungerValue);
foodItem.Eaten();
}
//---------- Health ----------\\
public var currentHealth : float;
public var maximumHealth : float = 100;
function Start()
{
currentHealth = maximumHealth;
}
function ApplyHealthDamage(d : float)
{
currentHealth += d;
currentHealth = Mathf.Clamp(currentHealth, 0, maximumHealth);
}
//---------- Player ----------\\
public var myHealth : Health;
public var myHunger : Hunger;
function Start()
{
myHealth = gameObject.GetComponent(Health);
myHunger = gameObject.GetComponent(Hunger);
if(!myHealth)
{
Debug.Log("Health script missing on " + gameObject.name);
}
if(!myHunger)
{
Debug.Log("Hunger script missing on " + gameObject.name);
}
}
function OnTriggerEnter(other : Collider) // assuming "walk into food => eat food"
{
oFood = other.GetComponent(Food); // try to get the food component
if(oFood) // if we find one we can use it
{
myHunger.Eat(oFood);
}
}