Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Coins script error

Discussion in 'Scripting' started by Kraznetor, Apr 4, 2020.

  1. Kraznetor

    Kraznetor

    Joined:
    May 7, 2019
    Posts:
    23
    Can someone help me with this coins script?
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using TMPro;
    6.  
    7. public class Coins : MonoBehaviour
    8. {
    9.  
    10.     public int TotalCoins;
    11.     public int numberOfCoins;
    12.  
    13.    
    14.     public TextMeshProUGUI coinsText;
    15.  
    16.     void Start()
    17.     {
    18.         TotalCoins = PlayerPrefs.GetInt("Coins", 0);
    19.         numberOfCoins  = 0;
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update()
    24.     {
    25.        // transform.Rotate(0, 100 * Time.deltaTime, 0);
    26.     }
    27.  
    28.     private void OnTriggerEnter(Collider other)
    29.     {
    30.         if(other.tag == "Player")
    31.         {
    32.             numberOfCoins += 1;
    33.             coinsText.text = "Coins: " + numberOfCoins;
    34.  
    35.             PlayerPrefs.SetInt("Coins", TotalCoins + numberOfCoins); //Here we are setting (saving) the coins to be sum of the old coins + the new coins!
    36.  
    37.  
    38.             Destroy(gameObject);
    39.  
    40.         }
    41.     }
    42. }
    43.  
    The problem is in the numberOfCoins variable, which is the number of coins in the actual game, until you die. TotalCoins is referred to the total amount of coins the player has. If I collect one or two coins, I have no problems since in the menu I'll have x + 1 or 2 coins. But if I collect the third coin, the value decrease to 1, then increase to 2 and again after picking a coin decrease to 1, and this value is normally added to total coins(which i think is correct in term of coding)
     
  2. Kraznetor

    Kraznetor

    Joined:
    May 7, 2019
    Posts:
    23
    If I remove numberofcoins = 0 in the start function, at the start of the match i'll have the same amount of coins I had when I died.
     
  3. kasztelan

    kasztelan

    Joined:
    Nov 3, 2014
    Posts:
    11
    I'm not sure what's supposed to happen here. You destroy the object just after increasing the numberOfCoins value. This value is associated with this particular class instance so it's also lost. Unless gameObject is pointing to something different and you ommited that part of code?
     
    Kraznetor likes this.
  4. Kraznetor

    Kraznetor

    Joined:
    May 7, 2019
    Posts:
    23
    I put numberOfCoins in another script attached to player which is always active, now the script works well, you were right. The old script used to set numberofcoins to 0 every time it spawned a coin, so it didn't increase, thanks
     
  5. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,064
    I take it that this
    Coins
    script is on every coin
    GameObject

    But you're making the mistake of writing the value at the wrong place.

    If you want to increase the number of coins of the player, the player should have some kind of Coin Wallet
    Here's an example:
    Code (CSharp):
    1. public class Coins : MonoBehaviour
    2. {
    3.     // Value of the coin, default = 10 unless overwritten in the inspector
    4.    [SerializeField]
    5.    private int CoinValue = 10;
    6.    
    7.     // Update loop which is triggered every frame
    8.     private void Update()
    9.     {
    10.         // Coin Rotation
    11.         transform.Rotate(0, 100 * Time.deltaTime, 0);
    12.     }
    13.     private void OnTriggerEnter(Collider other)
    14.     {
    15.         // Check if it is the player triggering this GameObject
    16.         if(other.CompareTag("Player"))
    17.         {
    18.             // Try get the wallet of the player
    19.             if(other.gameObject.TryGetComponent(out CoinWallet coinWallet))
    20.             {
    21.                 // If the player has a coin wallet, add the value
    22.                 coinWallet.Add(CoinValue);
    23.                 // Destroy this coin game object
    24.                 Destroy(gameObject);
    25.             }
    26.             else Debug.LogError($"CoinWallet not found on {other.gameObject.name}", other.gameObject);
    27.         }
    28.     }
    29. }
    30.  
    31. public class CoinWallet : MonoBehaviour
    32. {
    33.     // The visual text representation for the player
    34.     [SerializeField]
    35.     private TextMeshProUGUI CoinsText = null;
    36.  
    37.     // The amount of coins in this coin wallet
    38.     [SerializeField]
    39.     private int Coins;
    40.    
    41.     // Player pref key
    42.     private const string CoinsPrefKey = "Coins";
    43.    
    44.     private void Start()
    45.     {
    46.         // Initializes the Coins value to the player prefs stored value.
    47.         Coins = PlayerPrefs.GetInt(CoinsPrefKey, 0);
    48.         UpdateCoinsText();
    49.     }
    50.    
    51.     public void Add(int value)
    52.     {
    53.         // Add the value to the Coins variable
    54.         Coins += value;
    55.         // Save the new value to the player prefs.
    56.         PlayerPrefs.SetInt(CoinsPrefKey, Coins);
    57.         UpdateCoinsText();
    58.     }
    59.    
    60.     private void UpdateCoinsText() => CoinsText.text = $"Coins: {Coins}";
    61. }

    So On Trigger, check if it is triggered by the player. If so, get the player's script which stores the coins and increase that value.

    The Coins script should only have a value of its worth and on trigger add it to the player then destroy itself.

    This is separation of functionality, a coin should only add value to the wallet and then destroy itself.
    A wallet should only store the coins and update the visual representation.

    But the key problem here is to understand what you're editting.
    Each and every instance has it's own values. You can place coins in the scene with different values. The value of the coin is by default 10 but can be overwritten in the inspector because it is a serialized variable.
    So you could create a coin with a value of 200 and call it the epic big coin. Give it an extra scale of 1.5 ~ 2.

    What you did was:
    On start of the script, read out the player prefs and set the total coins.
    Then when the player triggers the coin, increase the number of coins (which is its own instance, every coin has its own value) then set the text to that specific value and destroy the coin object.
    Resulting in that every coin is still carrying their own value and applying that to the text, rather than storing it somewhere at one place.
     
    Kraznetor likes this.