• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by blubbr · Jan 23, 2019 at 03:46 AM · function callreturn value

Returns NaN when referencing function from another script

So I'm a beginner to unity. My first game i'm making is a top-down shooter game. The enemy chases the player and shoots bullets at him. I have a HealthSystem script that manages all the damages and heals and in it, I have a function called Damage(). Inside my projectile script, I reference the Damage() function in my projectile script. The problem is, when I try to Debug.Log my health, it returns NaN. The function works fine in my Game Handler script though. The GameHandeler and HealthSystem script are both on an empty gameobject and the projectile script is on a bullet prefab.


Ill include my GameHandler, HealthSystem, and Projectile Scripts.

Projectile

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Projectile : MonoBehaviour {
 
     public float speed;
 
     private Transform player;
     private Vector2 target;
 
     public HealthSystem healthSystem;
  
 
     public void Start()
     {
         player = GameObject.FindGameObjectWithTag("Player").transform;
 
         target = new Vector2(player.position.x, player.position.y);
 
         healthSystem = GameObject.Find("GameHandler").GetComponent<HealthSystem>();
 
     }
 
     public void Update()
     {
         transform.position = Vector2.MoveTowards(transform.position, target, speed * Time.deltaTime);
 
             if (transform.position.x == target.x && transform.position.y == target.y)
             {
                 DestroyProjectile();
             }
     }
 
     public void OnTriggerEnter2D(Collider2D other)
     {
             if (other.CompareTag("Player"))
             {
                 DestroyProjectile();
                 healthSystem.Damage(10);
                 Debug.Log("Health: " + healthSystem.GetHealthPercent());
             }
     }
     
      public void DestroyProjectile()
      {
             Destroy(gameObject);
      }
 }

Additional Question: I have to create reference to the script to use healthSystem.Damage(), but in the GameHandeler, I don't have to. Is it because they are on the same object?


GameHandeler

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class GameHandeler : MonoBehaviour {
 
     public Transform pfHealthBar;
     private Transform player;
 
     public void Start()
     {
         player = GameObject.FindGameObjectWithTag("Player").transform;
         HealthSystem healthSystem = new HealthSystem(100);
 
         Transform healthBarTransform = Instantiate(pfHealthBar, new Vector3(0, 1), Quaternion.identity);
         HealthBar healthBar = healthBarTransform.GetComponent<HealthBar>();
         healthBarTransform.transform.parent = player;
         healthBar.Setup(healthSystem);
 
 
         Debug.Log("Health: " + healthSystem.GetHealthPercent());
         healthSystem.Damage(10);
         Debug.Log("Health: " + healthSystem.GetHealthPercent());
         healthSystem.Heal(10);
         Debug.Log("Health: " + healthSystem.GetHealthPercent());
 
     }
 
 }


HealthSystem

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using System;
 
 public class HealthSystem : MonoBehaviour
 {
 
     public event EventHandler OnHealthChanged;
     private int health;
     private int healthMax;
 
     public HealthSystem(int healthMax)
     {
         this.healthMax = healthMax;
         health = healthMax;
     }
 
     public int GetHealth()
     {
         return health;
     }
 
     public float GetHealthPercent()
     {
         return (float)health / healthMax;
     }
 
     public void Damage(int damageAmount)
     {
         health -= damageAmount;
         if (health < 0) health = 0;
         if (OnHealthChanged != null) OnHealthChanged(this, EventArgs.Empty);
     }
 
     public void Heal(int healAmount)
     {
         health += healAmount;
         if (health > healthMax) health = healthMax;
         if (OnHealthChanged != null) OnHealthChanged(this, EventArgs.Empty);
     }
 
 
 }
 

I got the Projectile script from a blackthornprod tutorial and the HealthSystem + GameHandeler is from a Code Monkey tutorial. Sorry for the lengthy explanation and question. Thanks alot for the help. This has been driving me crazy for two days.alt text

screenshot-2.png (98.3 kB)
Comment

People who like this

0 Show 0
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
Best Answer

Answer by Klarzahs · Jan 23, 2019 at 10:49 AM

Hi,

Appearently, your healhtMax is not set, which is why on GetHealthPercentage() your current health gets divided by 0 => NaN.

I think this is caused by two different health systems that you create. I cant say for sure, but I assume you already assigned a HealthSystem component to your GameHandler object in the editor, right? So, on starting the game, your GameHandler.Start() function creates a new HealthSystem with HealthSystem healthSystem = new HealthSystem(100);.

The problem now is that you look for the HealthSystem component in your Projectile on Start(). I again assume projectiles are created at runtime, so Projectile.Start() will be called later than GameHandler.Start(). Now, as you assigned a HealthSystem and created a new HealthSystem with your function call, the projectile only assigns the first one. Which has an unset MaxHealth, as only your second HealthSystem was initialized properly.

Takeaway: Don't create something deriving from MonoBehaviour with a "new XYZ()" call. If you are using VisualStudio, it should flag this. If you did not assign a HealthSystem in the Editor, so you dont create two, this is probably still the cause.

You should be using

 HealthSystem hs = AddComponent<HealthSystem>();
 hs.SetMaxHP(100);

instead (or add the component via the editor)

Comment
blubbr

People who like this

1 Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image blubbr · Jan 24, 2019 at 12:15 AM 0
Share

Im so confused about the solution you put, I understand why its not working but where should i put the code and how do I add HealthSystem as a component. I bet this is a stupid question

avatar image Klarzahs blubbr · Jan 24, 2019 at 08:27 AM 0
Share

You have two options for adding a component. You can either do it

1. in the Editor, by simply drag&drop the HealthSystem script onto the GameHandler object. You then don't call HealthSystem hs = AddComponent<HealthSystem>(); as you already did that by hand. You simply have to set the maxHP in the start function of the GameHandler.
2. By code. As you did not already create a component by dragging/dropping, you'll need to add one dynamically. That is, call HealthSystem hs = AddComponent<HealthSystem>();



Hope this makes it a little bit clearer :)

avatar image blubbr Klarzahs · Jan 25, 2019 at 01:08 AM 0
Share

Thanks so much man! You really helped with this problem!! Your reply didn't fix it, but i guided me toward the solution. My GameHandler object already had the HealthSystem component, so I used HealthSystem healthSystem = GetComponent(); instead of AddComponent. Thank you for such fast replies and good answer :) +rep


Solution I used for anyone who needs it.

  1. As @Klarzahs said, use AddComponent if you don't have the HealthSystem script already on the object.

      private GameObject gameHandeler
             
     public void Start(){
         gameHandeler = GameObject.Find ("GameHandler");
         
             HealthSystem healthSystem = gameHandeler.AddComponent<HealthSystem>();
             
                     healthSystem.healthMax = 100;
                     healthSystem.health = 100;
         }
    
    
  2. If you already have the HealthSystem script, use GetComponent

      public void Start(){
             HealthSystem healthSystem = GetComponent<HealthSystem>();
             
                 healthSystem.healthMax = 100;
                 healthSystem.health = 100;
     }
    
    

Basically reworded what he said XD.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

98 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Return value inexplicably becomes null 1 Answer

Calling a Unity C# method that returns a value from Android/Java 0 Answers

Function being called twice when it shouldn't be 1 Answer

[C#] Am I using events right? 2 Answers

how to check button click in between running function ? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges