how to save a float from 1 instantiated object to another

im making a game where enemies spawn randomly and you get 100 points everytime you kill one enemy, but whenever an enemy dies and a new one spawns the score sets itself to 0 again, i really don’t know how to explain this, maybe the code will help you understand better

EnemyScript in Enemy GameObject:

public ScoreScript scoreScript;
public float health = 100;
public float Score;

void Update()
{
    scoreScript = GameObject.FindObjectOfType<ScoreScript>();
    Score = GameObject.FindObjectOfType<ScoreScript>().Score;
}

void OnCollisionEnter2D(Collision2D col)
{
    if(col.gameObject.tag.Equals("Bullet"))
    {
        health = health - 15;
        Destroy(col.gameObject);
        if(health <= 0)
        {
            StartCoroutine(DeathFrame());
        }
        else return;
    }

    if(col.gameObject.tag.Equals("Player"))
    {
        if(isDashing == true)
        {
            health = health - 40;
            if(health <= 0)
            {
                StartCoroutine(DeathFrame());
            }
            else return;
        }
    }
}

IEnumerator DeathFrame()
{
    Score = Score + 100;
    scoreScript.SetScore(Score);
    yield return new WaitForEndOfFrame();
    Destroy(this.gameObject);
}

ScoreScript in ScoreValue TMP Text:

    public TMP_Text scoreTxt;

    public float Score = 0;

    public void Update()
    {
        Debug.Log(Score); //always prints 0
    }

    public void SetScore(float Score)
    {
        Score = GameObject.FindObjectOfType<EnemyScript>().Score;
        scoreTxt.text = Score.ToString("0"); //score shows 100 after killing an enemy, shows 0 if killing an enemy while there are more than 2 enemies in the scene unless killing the last one that spawned
    }

Don’t use GameObject.Find of any type in Update. If you have to use it at all, use it in Start and save a reference.

I would suggest you look into a Manager pattern for your ScoreScript. Simply put, you would want to do something like this in your game scene.

Class ScoreScript : MonoBehaviour
{
   public static ScoreScript instance;
   private int score;

   void Awake()
   {
       instance = this;
   }

   public void AdjustScore(int value)
   {
      score += value;
      //Add code to adjust gui
   }
}

Then in your enemy script, when they die or whatever the condition is to increment score.

ScoreScript.instance.AdjustScore(myEnemyScorevalue);

It can be that simple, but the basic idea is your ScoreScript should not care about what enemies are on the screen. It should only worry about tracking score and displaying it. Thus it just takes input (negative or positive) before displaying it.

Your enemies should just have data on them to determine what needs to be sent off to other scripts. Stuff like how much damage they deal, hp, score value. They can also have methods on them dealing with that data, such as taking damage and adjusting HP, dealing damage, determining if they die, sending off values to the appropriate other scripts.

Your FindObjectOfType calls are definitely screwing things up.

Note that the above is a suggestion and isn’t the only way, but I do think it will improve your code.

3 Likes

This is an excellent fix to the problem. You could, perhaps, go a step further and make the Score value and AdjustScore method static, eschewing the use of a Singleton, as such:

public class ScoreScript : MonoBehaviour
{
   private static int score;

   public static void AdjustScore(int value)
   {
      score += value;
      //Other code
   }
}

In which case, when an enemy dies you’d merely have to call

ScoreScript.AdjustScore(value);
And to repeat what Brathnann said, FindObjectOfType calls aren’t very performant. If you MUST use it, then store the value to a variable or a property, as in this example:

public class ExampleScript : MonoBehaviour
{
   private static ScoreScript scoreScript;

   public static ScoreScript ScoreScript
   {
      get
      {
         if (!scoreScript)
            scoreScript = FindObjectOfType<ScoreScript>();
         return scoreScript;
      }
   }
}

Then you could reference the ScoreScript property to retrieve the cached reference to your desired script.