Unable to change values for objects that are not in scene in Unity

Hi all,

I know this is one of the most asked questions but I simply can’t figure it out and I’ve tried everything I could find about it.

What I’m struggling with is a pickup system. When the player picks a power up, I want to boost all of the bullets he’s using (there are different types of bullets with different stats). If I do something like this:

Projectile projectiles;

public void Start()
{
projectiles = GameObject.FindGameObjectWithTag("Projectile").GetComponent<Projectiles>();
}

I get the null reference to an object error in Unity. And I think that’s since the bullets are not necessarily in scene when the player collides with the pickup.

I don’t think that using static values would help either, since I have different values for each type of projectile.

I know it shouldn’t be that difficult, but I simply can’t figure it out… and also I’m really new to C# and Unity. I had no problems with power ups for the player for example, but I have no idea why this isn’t working.

The closest I got was using foreach but the new values would remain changed after starting the game from the beginning.

In the Projectile script I have public int damage and public float speed.

The PowerBoost script is as follows:

public class PowerBoost : MonoBehaviour
{
  
    public GameObject[] projectiles;
  

    public int damageBoost;
    public float speedBoost;



    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Player")
        {
          
         
            foreach (GameObject pr in projectiles)
            {

                        pr.GetComponent<Projectile>().speed += speedBoost;
                        pr.GetComponent<Projectile>().damage += damageBoost;
     
            }
         
            Destroy(gameObject);
        }
    }
}

Thank you in advance!

I havent tried anything like this regarding projectiles, but i think i have a possible solution (there are probably many).

You could have a singleton script that persists over scenes. If you arent familiar with singletons, look them up, but a quick version is they are used when you only want ONE single instance of something at all times, regardless of scene changes. So it works well with Game Managers, Event Controllers, Score Controllers, etc.

You create this singleton script that isnt attached to the player, it just exists on its own gameobject. This will have your projectile info like dmg, speed, quantity, etc. It should basically just be a bunch of variables.

Then, your player has a script that accesses the singleton script to determine its dmg, speed, etc.

Then, you have power up scripts that can temporarily (or permanently) edit those variables from the singleton script.

I think this should work, but again, i havent tried it before. If you do want to keep the projectile script on the player, you can just use PlayerPrefs to keep the data of the variables between scenes.

1 Like

Hi man, thank you so much for your answer!

In the meantime I found out a workaround that issue which was much simpler since the game is not that complex. The way I did it was by using statics in the Projectile script.

     public static float extraSpeed = 0;
     public static int extraDamage = 0;
     public float speed;
     public int damage;
   
     public void Start()
     {
     speed += extraSpeed;
     damage += extraDamage;
     }

Then on the PowerBoost script I got Projetile.extraSpeed = speedBoost; and Projetile.extraDamage = damageBoost;. This way I could keep the damage and speed unique for each projectile type prefab and add the boost via the pickup system. Since I want the boost to stack throughout the game on all the projectiles.

I 100% sure I’ve tried this method way before posting, maybe the 2nd thing I’ve tried but somehow didn’t manage to get it working back then so I assumed that isn’t the solution. Of course I did it wrong the first time and I can’t even remember how I did it.

Glad you found a way! Nice work

1 Like