skip to Main Content

I have created coins in a scene in unity that the player can collect and will disappear upon collection. however when the player leaves the scene and then comes back the coins reappear how can I prevent the coins from reappearing?

I have already tried using playerPrefs and that has not worked. I also know that I will need to use XML or JSON files in some way. I have tried using some basic saving and load mechanics with a Boolean that is false on start but when a coin is picked up it is set to true to prevent coins from respawning. However this has not worked as it applies to all coins in the scene not just the one picked up.

My current Idea is that I would use an array to get the positions of all the coins and other essentially data and iterate though it when the scene loads to check if the coin should spawn. However I do not know what code for this would look like.


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;


public class CoinScript : MonoBehaviour
{ 
  private Transform myTransform;

  [SerializeField] float rotationSpeed;

  CoinCounterScript coinCounterScript; 
    
  public Transform CoinCounterText;

  public GameObject CoinCounterTextOBJ;

  public GameObject player;

  public GameObject bullet;

  [SerializeField] public bool isCollected;

  [SerializeField] float speed;

  public Boolean coinStored;
  
  private string dataPath;
  

    void Awake()
    {
      dataPath = Application.persistentDataPath + "/Player_Data/";
     
      SaveObject coinStatus = new SaveObject
      {
        hasBeenCollected = false
      };
      
      string json = JsonUtility.ToJson(coinStatus);
      Debug.Log(json);

      SaveObject loadedSaveObject = JsonUtility.FromJson<SaveObject>(json);
   
      saveData();

      //loadData();

    
    }


   private void saveData()
   {
    SaveObject CoinStatusCollected = new SaveObject
    {
      //hasBeenCollected = true,
    };

      if(CoinStatusCollected.hasBeenCollected == false)
      {
        this.gameObject.SetActive(true); 
        Debug.Log("not collected");
      }
      else if(CoinStatusCollected.hasBeenCollected == true)
      {
        this.gameObject.SetActive(false);
      }
   
    string json = JsonUtility.ToJson(CoinStatusCollected);
    Debug.Log(json);

    // create file and place it in the data path
    File.WriteAllText(dataPath + "CoinTestSave.txt", json);

   }

   public void loadData()
   {
    Debug.Log("calling loadData");
    if(File.Exists(dataPath + "CoinTestSave.txt"))
    {
      string saveString = File.ReadAllText(dataPath + "CoinTestSave.txt");
    
      SaveObject saveObject = JsonUtility.FromJson<SaveObject>(saveString);
      Debug.Log("Coin status " + saveObject.hasBeenCollected);
      //saveObject.hasBrokenDoor = true;

      if(saveObject.hasBeenCollected == false)
      {
        this.gameObject.SetActive(true); 
        Debug.Log("not collected");
      }
      else if(saveObject.hasBeenCollected == true)
      {
        this.gameObject.SetActive(false);
        Debug.Log("has been collected");
      }
    } 
    else 
    {
      Debug.Log("no save"); 
    }
   }

    // Start is called before the first frame update
    void Start()
    {
      myTransform = this.GetComponent<Transform>();
      coinCounterScript = GameObject.FindObjectOfType<CoinCounterScript>();
      isCollected = false;

      loadData();
    }

    void OnEnable() 
    {

      // code below is used to ignore collisions 
      //with projectiles elsewhere in my game
      GameObject[] otherObjects = GameObject.FindGameObjectsWithTag("PlayerProjectile");
     
      foreach (GameObject obj in otherObjects) 
      {
        Physics2D.IgnoreCollision(obj.GetComponent<Collider2D>(), GetComponent<Collider2D>()); 
      }
      
    }

    // Update is called once per frame
    void Update()
    {
      //while it not collected coin plays anim
      if(isCollected == false)
      {
        myTransform.Rotate(rotationSpeed * Time.deltaTime, 0 ,0);
      }
      
      // when coin is collected it moves towards the
      // coin counter on the left hand side of the screen
      if(isCollected == true)
      {
        var step = speed * Time.deltaTime;
        myTransform.Rotate(0, 0 ,0);
        transform.position = Vector3.MoveTowards(transform.position, CoinCounterText.position, step);
        Invoke("DestroySelf", 5);
      }
      

      // code to handle edgecases of class fields
      //becoming null
      if(player == null)
      {
        player = GameObject.FindGameObjectWithTag("Player");
        //playerCol = player.GetComponent<BoxCollider2D>();
      }
      
      if(CoinCounterText == null)
      {
        CoinCounterTextOBJ = GameObject.FindGameObjectWithTag("UITestTag");
        CoinCounterText = CoinCounterTextOBJ.GetComponent<Transform>();
      }

    }

    public void OnCollisionEnter2D(Collision2D col)
    {
      //Destroy(gameObject);
      if(col.gameObject.tag == "Player")
      {
       //coinCounterScript.CoinCounterTXT.enabled = true;
       if(isCollected == false)
       {
        isCollected = true;
        int collectedCollectableLayer = LayerMask.NameToLayer("CollectibleUnCollideable");
        this.gameObject.layer = collectedCollectableLayer;
       }
      }

    }

    public void OnTriggerEnter2D(Collider2D col)
    {
      //when coin hits the coinCounter
      // it is destroyed and the amount of coins 
      // the player has increases
      if(col.gameObject.tag == "UITestTag")
      {
       Destroy(gameObject);
       SaveObject saveObject = new SaveObject();
       saveObject.hasBeenCollected = true;
       saveData();
       
      }
    }


    public void DestroySelf()
    {
      Destroy(gameObject);
    }

    public class SaveObject
    {
      public Boolean hasBeenCollected;

    }

   
}

2

Answers


  1. playerprefs can work quite nicely, at least if you dont have thousands of coins.
    give each coin an id
    then when you get the coin, do this

    PlayerPrefs.SetInt("Coin"+id,1);
    

    and in your coins start method do this

    if(PlayerPrefs.GetInt("Coin"+id)!=0){
        Destroy(gameObject);
    }
    

    if you have a lot more coins
    then use a package that creates a better playerprefs. or just go json

    Login or Signup to reply.
  2. try using set active false use a script to detect collisions with the player, add a trigger event, and disable the coin after collection

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search