Hi ive been following this guys tutorials and his code works perfectly fine yet my doesnt i get this error i read about it yet i cant figure out what is actually wrong, im trying to make a health bar using a image on a canvas the script is linked to the image and i am using fillamount to change the fill of the bar relating to the current hp/ max hp.
“Image healthBar;” is null.
You defined it as a variable but you’ve never assigned anything to it, nor is it exposed to the editor for it to be set there. So every time you access it you’re getting a null reference error.
You attempt to assign to it in your Start function. But you’re doing so by calling .GetComponent() on healthBar (which is null). So that line throws a null reference error too.
change it to
healthBar = GetComponent<Image>();
or better yet, change the declaration to public or put [SerializeField] on it. That will make it show up in the editor window so that you can set the reference in the editor and not have to worry about finding components at runtime.
Thank you for your answer ;d i did as you asked, i changed it to “healthBar = GetComponent();” and using debug.log to display the fillAmount. it does have access to the image now. And displays the value. yet the error persists.
After some Debugging i found that the error is also related to “player.Health” as it will not display the value and produces the same error as it did at the start but for this line of code this time. This is what the script looks like;
using UnityEngine;
using System.Collections;
public class PlayerInteractionEnemny : BaseClass {
public static Transform opponent;
public static bool isAttacking;
public static PlayerInteractionEnemny player;
Animation animation1;
public AnimationClip attackAnimation;
public float attackImpact;
// Use this for initialization
void Awake ()
{
//player = GetComponent<PlayerInteractionEnemny>(); tried to set to get component.
player = this;
Health = maxHealth;
InitAnimations();
isAttacking = false;
}//end awake
void InitAnimations()
{
//deal with animations
animation1 = GetComponent<Animation>();
AnimationEvent attackEvent = new AnimationEvent();
attackEvent.time = attackImpact;
attackEvent.functionName = "Impact";
attackAnimation.AddEvent(attackEvent);
}//end of animations
void Impact()
{
opponent.GetComponent<EnemnyScript>().GetHit(Damage);
}//end of impact
void Start()
{
}//end of start
// Update is called once per frame
void Update ()
{
Attack();
}//end update
protected override void Attack()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (opponent != null && Vector3.Distance(opponent.position, transform.position) < range)
{
isAttacking = true;
animation1.CrossFade(attackAnimation.name);
//opponent.GetComponent<EnemnyScript>().GetHit(Damage);
}//end of if opponent
if (!animation1.IsPlaying(attackAnimation.name))
{
isAttacking = false;
}//end of if not animation
}//end of if input
}//end attack
}
and it uses the base class of ;
using UnityEngine;
using System.Collections;
public abstract class BaseClass : MonoBehaviour {
public string Name;
public int Health;
public int maxHealth;
public int Damage;
public float range;
public float attackspeed = 2f; // as is described 1 attack per second
public void GetHit(int playerDamage)
{
Health = Health - playerDamage;
}//end of get hit
protected abstract void Attack();
}
From what he is explaining in the tutorial he is accessing the playerEnemy Interaction script using static without actually calling or accessing the script. The worst part is that my code looks exactly like his yet his doesnt produce any errors.
I have solved the problem by using inheritance so that the PlayerHealthBar class inherits PlayerInteractionEnemy. It works fine.
However, my question is, how do i access the PlayerInteractionEnemy script without using inheritance?
Also another issue, The code is made so that when the player attacks the attack animation should stop and go back to idle and from idle to run when moving, yet the animation does not change to idle and get stuck on the end of attack animation, after going out of range of the enemy and pressing spacebar the run animation starts playing again. Any thoughts?
Putting your code into a project and running it i’m not getting the null reference error; but i think i may know why you are, so lets go through it.
If you’re having trouble with null errors the trick is to look at where it’s being assigned and think about how that’s happening and what could cause it to fail.
From what you’re describing i am assuming that the ‘player’ object variable in the PlayerHealthbar class is null.
The player variable is set in the start function here:
player = PlayerInteractionEnemny.player;
it’s getting the value from the static variable ‘player’ in the PlayerInteractionEnemny class. So lets follow that and see where that was assigned to; because if it hasn’t been assigned to yet it will be null when we get the value from it.
It’s assigned to in the Awake() method of PlayerInteractionEnemny class here
player = this;
So, there’s better ways of going about this, but lets address why you’re getting a null reference exception first.
What’s likely happening is that when your PlayerHealthbar component tries to access the static variable ‘player’ on the PlayerInteractionEnemny class, the ‘awake’ function on PlayerInteractionEnemny has never been called. Thus the static variable has never been assigned to and is null. Following that when PlayerHealthbar copies the value from it, it’s copying a null value and when you try and use it you get a null reference exception.
The likely reason why this is so is that you haven’t actually put a PlayerInteractionEnemy component on a game object. Thus no game object ever runs the ‘awake’ function of that class and the static variable is null when you copy the value from it.
Now, why does changing PlayerHealthbar to inherit from PlayerInteractionEnemy fix this? Because PlayerHealthbar now has all the same functionality as PlayerInteractionEnemy, including its awake function. PlayerHealthbar runs its awake function that it inherited from PlayerInteractionEnemy and assigns a copy of itself to the static variable. So when your PlayerHealthbar calls PlayerInteractionEnemy.player it’s now getting a reference to itself.
Well my PlayerInteractionEnemy script is found on the GameObject of SkeletonPlayer which is the “player” in the game. Therefore the script is actually runs the awake function as it uses it to control the player ingame,and it should not return a null value.
From what i understand is that a PlayerInteractionEnemy script is used to create an object of “player” in the “HealthBar script”, the the awake of this script the player = PlayerInteractionEnemy.player should get the values of the PlayerInteractionEnemy script which is set to player.this, refering to itself. therefore i do not understand why it should return a null.
Is there another way i could use that would get the values of player in the PlayerInteractionEnemy script that would make more sense to me?
Its hard for me to tell you whats wrong there then. When i copy paste the code in and set it up on game objects it runs fine, i can’t debug an error can’t reproduce except to tell you what ‘might’ be happening based on the code. There are only 2 reasons i can think of that that variable will be null. The first is if the Awake function is never called such as if you’ve forgotten to add the component, the second is if the Awake function is called but not until after the Start function on PlayerHealthbar which may happen if you’re spawning the player gameobject in after the object containing the playerhealthbar component.
Double check you have the component on a gameobject, and that you’re not spawning it into the world AFTER the gameobject containing PlayerHealthbar (it’s why i don’t like this way of structuring code, things break depending on the order unrelated things are done).
Check that the awake function is being executed and that its being executed before Start on the PlayerHealthbar script. Place a break point on both in your editor, or a debug.log(“”) and see if & in what order they’re happening.
The only reason why it would be null is if the “player=this;” line in the awake function has not been executed yet when PlayerHealthbar grabs the value from it (or if the gameobject/component has been destroyed/removed).
If you’re trying to get a reference to another object, both of which are there at the start of game, the easiest way is to assign it in the editer.
Add [SerializeField] to the “PlayerInteractionEnemny player;” variable in your healthbar class. Then it will show up in the editer window and you can just drag the player object onto it to assign it.
Alternatively use the gameObject.Find() function to get a reference to the player gameobject when the game starts then use .getcomponent to get the playerinteractionenemny component.
Thank you so much, i used the serialize field and it works like a dream, that you for all the explanations as i have learned a lot through it
If i could bother you with one more thing. The player uses animations and animations are to play attack when attacking swap back to idle animation and back to run animations if not playing attacking. but it freezes at the end of the attack animation and doesnt go back to idle or run. Much appreciated if this is not something you are samiliar with its fine i will figure it out eventually ;p here the part of the code that does the animations
protected override void Attack()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (opponent != null && Vector3.Distance(opponent.position, transform.position) < range)
{
isAttacking = true;
animation1.CrossFade(attackAnimation.name);
//opponent.GetComponent<EnemnyScript>().GetHit(Damage);
}//end of if opponent
if (!animation1.IsPlaying(attackAnimation.name))
{
isAttacking = false;
animation1.CrossFade(idleAnimation.name);
}//end of if not animation
}//end of if input
}//end attack
Animation is not something i’m familiar with, and only a quick 2 minutes to read it before i go to work. but.
i think your problem is that this
if (!animation1.IsPlaying(attackAnimation.name))
{
isAttacking = false;
animation1.CrossFade(idleAnimation.name);
}//end of if not animation
I think the problem that is that this is in the attack function in the if block checking that the attack key is down.
If i’m understanding it right, this piece of codes job is to check if the attack animation is over and to change back to the idle animation if it is. But you’re only ever calling it immediately after the code telling the attack animation to start. So the attack animation is not over yet when it reaches it (as it only just started an instant ago), and you don’t call it at any other time. Perhaps move it somewhere where it will be checked more regularly? I have no idea how people normally structure scripts about animation, it’s not something i do sorry.