Have Coins disappear from Scene forever when picked up, even after reloading it. C#

Hello, so i’ve been struggling with this for a couple of Days now. I want my player to be able to go through a Level(Scene), pick up as many coins as he would like and then exit the Level(Scene), when he comes back to this Scene i want those coins he picked up not to be existent however those he didn’t pick up to still need to be there for him to pick up. I have found a way to do this but it requires me to hardcode for every coin ( See my messy Code). I’m looking for a more efficient way to do this and i would like to avoid additiveSceneLoading for performance reasons.
Thank you in advance :slight_smile:

this is my code for picking up coins, which runs on the Coin GameObject;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class coin_pickup : MonoBehaviour
{
   
    public void OnTriggerEnter2D(Collider2D collider)
    {


        if (collider.CompareTag("PlayerTrigger"))
        {
            //Destroy(gameObject);

            coinScore.coins_collected++;

            if (this.gameObject.name == "C1S1")
            {
                CoinKillerScript.hasC1S1 = true;
                Debug.Log("this is C1S1"); //---> Coin1Scene1
            }
            if (this.gameObject.name == "C2S1")
            {
                Debug.Log("this is C2S1");
                CoinKillerScript.hasC2S1 = true;
            }
            if (this.gameObject.name == "C1S2")
            {
                Debug.Log("this is C1S2");
                CoinKillerScript.hasC1S2 = true;
            }
        }
       
    }
}

And this is my "coinKillerScript which runs on an empty DontDestroyOnLoad() Object

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CoinKillerScript : MonoBehaviour
{
   
    public static bool hasC1S1 = false;
    public static bool hasC2S1 = false;
    public static bool hasC1S2 = false;

    public void Awake()
    {
        DontDestroyOnLoad(gameObject);
    }
   
    public void FixedUpdate()
    {
       if(hasC1S1 == true)
        {         
            Destroy(GameObject.Find("C1S1"));          
        }
        if (hasC2S1 == true )
        {
            Destroy(GameObject.Find("C2S1"));
        }
        if (hasC1S2 == true)
        {
            Destroy(GameObject.Find("C1S2"));
        }
                   
    }      
}

The quickest way to do this would be to create a script with the “Coin” class for each coin with a UniqueId, and then put it on the Coin GameObject. Then, you can have a GameObject that persists (i.e. with DontDestroyOnLoad) between scenes and stores a dictionary from the UniqueId to a boolean for the status of the coin. Then when loading a scene, you just check the dictionary to see if it was picked up or not.

public class Coin : MonoBehaviour {
  [UniqueIdentifier]
  public string uniqueId;
  public bool pickedUp;
}

A more scalable solution would be to use the same idea with a file system instead of persisting a GameObject. You can create an event system that tells each coin to ‘Save’ its UniqueId and status to a file when you switch to a new scene, and ‘Load’ the information back up when you enter the scene again.

Similar to @marcsmann method, but possible more effecient… Try both!

Assuming you have a “Game Manager” of sorts, most games do. A script/object that lives across scenes, with the DontDestroyOnLoad() method.

Sore an int list of picked up coins. Create a singleton reference, then from the coin do a reference check when level loads. Some sudo.

public class GameManager{
    public static GameManager singleton;
    public list<int> pickedUpCoinIDs = new;
    public GameManager () => singleton = this;
}

public class Coin {
    void Start(){
        if (GameManager.singleton.pickedUpCoinIDs.containst(this.Gameobject.GetInstanceID())){
            destroy this;
        }
    }
   
    void OnPickup(){
        GameManager.singleton.pickedUpCoinIDs.Add(this.Gameobject.GetInstanceID());
    }
}