Search Unity

2D character and level selection with UI

Discussion in 'Scripting' started by simone9725, Mar 18, 2015.

  1. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Hi,
    in my game I'm building a menu with the UI with 3 different character,I would use the coin eraned in the game to unlock the inactive image of te player if I have for example 500 coins. I know something about player classes,but I haven't the knowledge to create a good menu .Someone could help with a code pls,this is the final step of my game :(
    Thanks in advance :)
     
    Adam-Buckner likes this.
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
  3. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    There are some UI tutorials in my signature you could leverage.
     
  4. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    You can write something like this in your game controller:

    Code (CSharp):
    1. public bool unlockAGuy(int GuyNo){
    2. if ((money<500) || (Guy[GuyNo].unlocked))
    3. return;
    4. Guy[GuyNo].unlocked=true;
    5. money-=500;
    6. SetLock (int GuyNo);
    7. }
    Now you can make a character icons into buttons and link this code to every of those, and while doing so you will be able to set GuyNo value.

    Code (CSharp):
    1.  
    2. public lockIndicators[];
    3.  
    4. public void SetLock (int GuyNo){
    5. if (Guy[GuyNo].unlocked) lockindicator[GuyNo].SetActive(false);
    6. else
    7. lockindicator[GuyNo].SetActive(true);
    8. }
    There will be some linking to do, and code is not vary elegant.

    I would advice you to follow what people before me said and go trough the tutorials. Even if you already got it working.

    I garanty you'll be pausing every 10 minutes to implement what you have learned into your game.
     
    Last edited: Mar 20, 2015
  5. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    There are two separate pieces to this: the underlying logic and the UI elements.

    For the logic, each character needs a state: locked or unlocked. This could be a Boolean (character.locked = true). This could be an enum state (character.state = State.locked). This state value you can set, change and save like any other value in your game.

    For the UI elements, you will need to build all of your character icons so they have a clickable unlocked state and a disabled locked state. See button states in the learn section, and note the disabled state. You could also have a lock icon on top.

    Now,with your logic, when you access you screen that has these characters, you'll have to set the states of the buttons and lock icon if you have one, based on the state of the character.
     
    Brainswitch likes this.
  6. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Thanks for your replies but How Can I unlock them with coins?
     
  7. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    The logic is the same.

    You will need some variable to hold the number of coins. Coins usually won't be partial, so it's probably an int:
    Code (CSharp):
    1. private int coins;
    You will need some code to add up coins when you pick them up in the world:
    Code (CSharp):
    1. void AddCoins (int newCoins) {
    2.    coins += newCoins;
    3. }
    You'll need to test to make sure you have enough coins:
    Code (CSharp):
    1. if (coins > someCost) {
    2.    // code for unlocking character
    3.    // code for subtracting coins from coins value
    4. }
    Does this make sense?
     
  8. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Thank You now has sense The problema is how
    To write The code of selection.I ve already created a code about coins And how To Store coins
     
  9. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Selection will probably not be code driven.

    If you mean "How do I select a character?", that will be button driven.

    For that, I definitely feel you should watch the button video in the learn section:
    http://unity3d.com/learn/tutorials/modules/beginner/ui

    This will explain better than I can here.

    You will need some code. You will need a public function that the button can call when clicked. You will need to do this for the unlocked characters to select a new character, and you'll also need one to unlock the character.

    What might be good is to design your UI on paper or in photoshop and then figure out the functionality of each button or field in Unity once you know what UI elements you need.
     
  10. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Last edited: Mar 19, 2015
  11. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
  12. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
  13. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Great!

    That looks like a level selector, not a character selector, but the principle is the same.

    What I would suggest is that you mock up the entire UI the way you want to see it in your game:


    This will allow you to break down all of the element that you will need:

    This way, at first you don't need to know what all your elements will do, and it's easy to break them down.

    This way you can see, in my example, we need:
    • 2 drop shadows (could be done with a component)
    • 2 background images for our windows (in this case, the artwork includes the title text)
    • 6 Buttons (which will need images and text!)
    • 3 additional images (which will be shared)
    • 2 additional text fields
    Some of these items will be shared. For example the image on the Character Selection button and the image on the Purchase screen will share the same image for each character; all of the lock icons will be the same image, the button backgrounds (which I didn't specify in the .gif) can be shared!

    (TBH: The buttons should be broken down into Button [functionality], Background Image, Character Image and Text, which build up the button, but I don't want to rebuild the .gif!)



    Long story short:

    You now know you need 2 windows and 6 buttons, and of the 6 buttons they only do 3 different things (and I forgot a CLOSE or CANCEL button on the "purchase" window, which will be pretty much the same!)
    • Close Window (Cancel Purchase by doing nothing)
    • Purchase Character
    • Activate Character
    So, you will need 3 public functions to make this work:
    • pubic void CloseWindow () {}
    • public void PurchaseCharacter () {}
    • public void ActivateCharacter () {}
    We've discussed the basics of what these functions need. Once you have written these functions, you only need to hook them up to the button's "OnClick" list:


    Hooking these up is covered in the UI Button video linked above.

    -

    Why did he take so long to say something so simple?

    What I want to show here is that so much about making our games is breaking down the seemingly impossible tasks confronting us down into bite sized pieces. You're not cooking Christmas Dinner in one bowl, you're making Sushi, Tapas or Dim Sum! (And you can break Christmas Dinner down into steps as well!)

    So - figure out what you want to make, break it down into elements, and tackle each one, one at a time.
     
  14. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Could you write an example of this functions while they are working,because I have the backbone but I haven't the bones
     
  15. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Well, this is where it gets tricky. It all depends upon your own game and the way you're laid it out.

    I don't know how you've saved your characters, so I don't know how to either lock them, unlock them or activate them to play with.

    Also, even tho' this isn't advanced scripting or architecture in any way, it is also not-trivial. To have a set of playable characters that you can interchange and buy, you need a thought-thru solution. There are many many ways to approach this.

    Do you have it working so that you can use an character in the game?

    I would make sure the underlying game works first before getting to this stage.

    • Step one: Get a working game with one character.
    • Step two: Get a working game with swappable characters, but they are unlocked
    • Step three: Work on locking and unlocking your characters.

    How far down this list are you?
     
    jtsmith1287 likes this.
  16. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    And important thing is: how your characters differ from each other?

    One thing is for sure: you should have all your characters linked to one script.

    Here is a variation on what I wrote above.

    GameControllerScript:

    Code (CSharp):
    1. public bool[ ] unlocked;
    2. public GameObject[] Characters;
    3. public int SelectedChar;
    4. public int money;
    5.  
    GameObject[] Characters are game objects with pictures of your characters, by default there may be sort of a shadow for each one under this picture.

    To Load data:

    Code (CSharp):
    1. void Start (){ // Needs a capital S [fixed - moderator]
    2.    int count=Characters.Length;
    3.    unlocked = new bool[count];
    4.    money=PlayerPrefs.GetInt("money");
    5.    for (int i=0; i<count; i++){
    6.       unlocked[i]=PlayerPrefs.GetInt("PlayerUnlocked"+i)  == 1 ? true : false ;
    7.       Characters[i].SetActive(unlocked[i]);
    8.    }
    9. }

    Script for the button:

    Code (CSharp):
    1. public void CharacterButtonScript(int no){
    2.    if (unlocked[no])
    3.       SelectedChar=no;
    4.    else if (money>=Cost){
    5.       money-=Cost;
    6.       unlocked[no]=true;
    7.       Characters[no].SetActive(true);
    8.    }
    9. }

    To save:

    Code (CSharp):
    1. public void Save(){
    2.    for (int i=0; i<unlocked.Length; i++)
    3.       PlayerPrefs.SetInt("PlayerUnlocked"+i, unlocked[i] ? 1 : 0);
    4.    PlayerPrefs.SetInt("money",money);
    5. }
    I am relatively new to Unity too, so it may not be the best way, but this pretty much your code for saving progression.

    PlayerPrefs are not ideal. If you want to make game more hack-prof, consider saving in binary:

    http://stackoverflow.com/questions/25746380/saving-loading-unity3d

    [edit: Code Formatting && Code Correction (mod)]
     
    Last edited by a moderator: Mar 20, 2015
  17. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    I will try your script thanks a lot, I'm At The step I create the menu With different characters.Personally I prefer the playerprefs methods to save
     
    Last edited: Mar 20, 2015
  18. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    The code proposed above unfortunately doesn't work I need another solution. I would use The sane logica To buy leve And unlock them in another scene
     
  19. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    You offended the code - Not cool.
    There is no another solution:
    bool array to operate your unlocks, PlayerPrefs to save and Button to make it interactable.

    You don't know how to use a button, don't you?
     
  20. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    No I know very well The UI. The problema is The logic in my game .I will try again The problem i how To use then when they are unlocked
     
  21. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Well, there are quite a few different solutions, but they are all based on the same logic.

    You need somewhere to store your lock state.
    You need somewhere to store your coins.
    You need a function that checks the coins and changes the status of your character's lock status.
    You need a button to call the function to change the lock state.

    How you decide to do thus depends a lot on the architecture of your game. Quizcanner's solution may not work for you, but his code is perfectly good, and could provide a base to work from.



    If it were me, no offence to Quizcanner, as it's all a matter of taste, I would make a character class, which included a locked state, then when working with my characters, I could query the character's locked state:

    Code (csharp):
    1. public class Character {
    2.  
    3.    public GameObject characterObject;
    4.    public bool isLocked;
    5.    // more properties to define my character...
    6.    // ... Like speed, strength, special abilities...
    7. }
    Then in my GameController I could have a list of characters:
    Code (csharp):
    1. public Character[] characters;
    ... and then in my code I can pass that character as a value and query that character's state:
    Code (csharp):
    1. if (currentCharacter.isLocked == false) {
    2.    DoSomething ();
    3. } else {
    4.    DoSomethingElse ();
    5. }
    Now, if any of these things don't make sense to you, I can walk you thru it one step at a time, if you can follow along show me how you are integrating the code.

    Don't forget, not one is going to write your code for you. You can look on the asset store or the wiki if you want pre-made code. Often these need to be adapted, as well.
     
  22. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    In fact the problem was in my game with the solution of Quizrunner I say thanks to everyone who help :).
    Thanks a lot for your patience
    Ok now I have a list of character in my shop everyone with a button with his price. I have a Script who can store the coins collected in my game,I want reduce the number of coins when I click on my button made up with UI system with the function On click.If i want use onclick event I know that I have to use a public void I wrote this simple code
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4. public class MenuShop : MonoBehaviour {
    5.     public int coinCount = 0;
    6.     private bool level1;
    7.  
    8.     // Use this for initialization
    9.     void Start () {
    10.    
    11.     }
    12.    
    13.     // Update is called once per frame
    14.     void Update () {
    15.    
    16.     }
    17.     public void PurchaseLevel () {
    18.         if (coinCount >=20)
    19.             coinCount -= 20;
    20.         level1 = true;
    21.     }
    22. }
    23.  
     
  23. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Looks good!

    In that configuration, you will always unlock your level, whether you have coins or not.

    You could also include a public function that you can call from within your game to add coins:

    Code (csharp):
    1. public void AddCoins (int newCoins)
    2. {
    3.    coinCount += newCoins;
    4.    PlayerPrefs.SetInt("Coins", coinCount);
    5. }
    ( the player prefs thing is just in case you want to save the coins between levels or games... )
     
  24. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    I've got another script called coinCounter who save my coins with playerprefs.Now how could I unlock the stage by clicking the button when i Have 500 coins?.The click has to unlock another gameobject in scene selection called Button 1 who is the link for the level/character
     
  25. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Link the game object that needs to be unlocked with a reference :

    Code (csharp):
    1. public GameObject myGameObject;

    I expect, however, you want to access a script on that game object, so I would use in that case:

    Code (csharp):
    1. public ScriptName myScriptName;
    ... then you can say in a function:

    Code (csharp):
    1. if (myScriptName.coins > someCost)
    2. {
    3.    level.locked = false;
    4.    myScriptName.coins -= someCost;
    5. }
     
  26. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Thank you but how can I say if my level is locked or unlocked ? In the script linked above I've already created the reducion of coins but when I click in my game it doesn't work
     
  27. quizcanners

    quizcanners

    Joined:
    Feb 6, 2015
    Posts:
    109
    Code (CSharp):
    1. public void PurchaseLevel () {
    2.         if (coinCount >=20)
    3.             coinCount -= 20;
    4.         level1 = true;
    5.     }
    It should be:

    Code (CSharp):
    1. public void PurchaseLevel () {
    2.         if (coinCount >=20)
    3.               {
    4.               coinCount -= 20;
    5.               level1 = true;
    6.               }
    7.     }
    Post more code.
     
  28. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Thank You so much for your nswer I attached the code to main camera and I used the onclick funcion of the button but when I click I haven't the reduction of coins :(
     
  29. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    This could be because we don't know what the rest of your scripts are, nor how they are working together.

    All of the code examples that the other helpful people and I are posting, are not necessarily full and complete scripts. They won't drop into your project and work instantly. We aren't going to write your code for you. They are examples of how to solve specific issues in your game, like "How can I reduce coins?" or "How can I unlock a level?". You will need to put these together into a working system.

    What I'm trying to help you with is how to break down an idea or problem in your project into solvable pieces, and then how to approach each piece, so you have a solution for each piece, that you can then build together - at the same time, trying to teach some of the basic concepts you need so you can go on and make your own solutions.

    You need to slow down and understand the "bricks and the mortar" of Unity, so you can build up good and stable solutions.

    Take the example above:

    Code (CSharp):
    1.        public void PurchaseLevel () {
    2.        if (coinCount >=20)
    3.             coinCount -= 20;
    4.        level1 = true;
    5. }
    ... which needed to be:

    Code (CSharp):
    1.        public void PurchaseLevel () {
    2.        if (coinCount >=20)
    3.        {
    4.               coinCount -= 20;
    5.               level1 = true;
    6.        }
    7.     }
    There are two issues here:
    • Understanding code blocks
    • Understanding when you need and don't need braces
    With the if statement "if (coinCount >=20)" this will be a conditional check for either the next line of code only (eg: coinCount -= 20;) or this will be a conditional check for all of the code in a block contained in braces {}.

    Without braces, we are saying "When I call PurchaseLevel, I will check my coinCount. If my coinCount is greater than 20, I will reduce the coinCount by 20. Next, I'll set level1 to true. Next, I will exit the function."

    With braces, we are saying "When I call PurchaseLevel, I will check my coinCount. If my coinCount is greater than 20, I will reduce the coinCount by 20 and then I'll set level1 to true. Next, I will exit the function."

    I can see that you are strongly goal oriented and are trying to get your project finished as soon as possible. I would suggest that taking a moment and getting the basics completely understood may make this project drag out a bit longer but will help you on the next one.

    When it comes to:
    Try posting more of your code and how it works together with the rest of your project, and we'll see what we can do to help.
     
  30. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    This is coin script
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. using System.Collections;
    4.  
    5. public class Coin : MonoBehaviour
    6.  
    7. {
    8.  
    9.     private CoinCounter coinCounter;
    10.  
    11.     void Awake()
    12.  
    13.     {
    14.  
    15.         coinCounter = GameObject.Find("CoinCount").GetComponent<CoinCounter>();
    16.  
    17.         coinCounter.coinCount = PlayerPrefs.GetInt("coins", 0);
    18.  
    19.     }
    20.  
    21.     void OnTriggerEnter2D(Collider2D other)
    22.  
    23.     {
    24.  
    25.         if (other.gameObject.tag == "Player") {
    26.  
    27.             print("You picked up a coin!");
    28.  
    29.             //Update the GUI
    30.  
    31.  
    32.  
    33.             coinCounter.coinCount++;
    34.  
    35.  
    36.  
    37.             PlayerPrefs.SetInt("coins", coinCounter.coinCount);
    38.  
    39.             PlayerPrefs.Save();
    40.  
    41.  
    42.  
    43.             Destroy(gameObject);
    44.  
    45.         }
    46.  
    47.     }
    48.  
    49. }
    50.  
    51.  
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. using UnityEngine.UI;
    4.  
    5. using System.Collections;
    6.  
    7.  
    8.  
    9. public class CoinCounter : MonoBehaviour
    10.  
    11. {
    12.  
    13.     public int coinCount = 0;
    14.  
    15.     Text text;
    16.  
    17.  
    18.  
    19.     void Start()
    20.  
    21.     {
    22.  
    23.         text = GetComponent<Text>();
    24.  
    25.     }
    26.  
    27.  
    28.  
    29.     void Update ()
    30.  
    31.     {
    32.  
    33.         //Set the coin count text
    34.  
    35.         text.text = coinCount.ToString();
    36.  
    37.    
    38.  
    39.     }
    40.  
    41. }
    42.  
    43.  
    CoinCounter
    Ok I Will go on step by step
     
    Last edited: Mar 24, 2015
  31. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Those are the only scripts working in the scene
     
  32. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    One of the things to thing about when coding is "single responsibility".

    Each script should be simple and be responsible for just one thing.

    With these two scripts, there is a bit of a confusion about which script is responsible for what.

    Currently "Coin" is:
    • Setting the coin count on another script ( coinCounter.coinCount=PlayerPrefs.GetInt("coins", 0); )
    • Adding to the coin count ( coinCounter.coinCount++; )
    • Saving the coin count found on another script ( PlayerPrefs.SetInt( "coins", coinCounter.coinCount); PlayerPrefs.Save(); )
    • Destroying itself ( Destroy(gameObject); )
    Currently "CoinCount" is:
    There are two thing to this... One is "Who should be responsible for what?" and the other is "Think through what's happening on a global game scene level".

    Who should be responsible for what?
    The coin should only be responsible for:
    • Being collected
    • Having a value
    ... the coin doesn't need to *do* anything else. Arguably the coin only needs to have a value! If you look at the "Roll a Ball" project in the Learn section, you will see that the collectables don't "do" anything, you could have the player object "do" the collecting.

    The "CoinCount" should be responsible for keeping track of everything about coin counting:
    • Holding the coin count
    • Loading the coin count
    • Adding to the coin count
    • Saving the coin count
    Think through what's happening on a global game scene level:
    • Every coin is going to have the "coin" script attached.
    • On the very first frame of the game
      • Every coin is going to find a reference to the coin counter script
      • Every coin is going to get the coin value from player prefs
      • Every coin is going to set the "coinCount" value on the "CoinCount" script
    • When collected:
      • Every coin is going to add to the "coinCount" value on the "CoinCount" script
      • Every coin is going to save the new value of "coinCount" to PlayerPrefs
    • The CoinCount script is setting the value of the CoinCount Text element every frame
    When thinking this through, we can see that some of the responsibilities are wrong, and some of the code has very redundant and repetitive behaviors.

    You should rearrange these scripts to come more into line with responsibility.
    • The coin only needs to have a value, even if it's only one. (public int coinValue)
      • This will allow you to have a value to pass to your CointCount script
      • This will allow you to be able to have coins with different values in your game
    • The coin does need a reference to the CoinCount script
      • This could be private and a lookup as it is now
      • This could be public and set in the inspector in edit-time if you wish
    • When the coin is triggered, it should access a public function on your CoinCount script
    • CoinCount should:
      • Have a way to hold the coinCount value
      • Have a way to grab this value from PlayerPrefs
      • Have a reference to the display Text element
      • Have a public function on CoinCount for the coins to access when they are collected. This function should be responsible for:
        • Taking in the coin value as a parameter
        • Adding this value to coin count
        • Updating the display text value
        • Saving this value to PlayerPrefs
    Give this a go, and see how you get on.
     
  33. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    would prefer keep on what I 've done I spent 1 month To create The Current system coin is the most important script Coin counter only update The string
     
  34. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    But this is not the correct way of doing things and will cause problems for you in the future. It may already be causing problems for you now.

    I'll help you walk thru this, so you won't get stuck, but we should be able to rewrite these two scripts this afternoon.

    Give it a go, and I'll help you through it.
     
  35. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    Perfect now how Can I change Them?
     
  36. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Start with this and give it your best shot:

    • The coin only needs to have a value, even if it's only the value of one. (public int coinValue)
      • This will allow you to have a value to pass to your CointCount script
      • This will allow you to be able to have coins with different values in your game
    • The coin needs a reference to the CoinCount script
      • This could be private and a lookup as it is now, so it's there...
    • When the coin is triggered, it should access a public function on your CoinCount script
      • You have the trigger...change it to call the public function on CoinCount

    • CoinCount should:
      • Have a way to hold the coinCount value
      • Have a way to grab this value from PlayerPrefs
      • Have a reference to the display Text element
      • Have a public function on CoinCount for the coins to access when they are collected. This function should be responsible for:
        • Taking in the coin value as a parameter
        • Adding this value to coin count
        • Updating the display text value
        • Saving this value to PlayerPrefs
     
  37. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    I've changed the script but now I have a big problem I can't store the coin data,for this reason I said It's to difficult pls could you help me write the new codes?
    CoinCounter
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4. [ExecuteInEditMode]
    5.  
    6. public class CoinCounter : MonoBehaviour
    7. {
    8.     public int coinCount = 0;
    9.     private CoinCounter coinCounter;
    10.     void Awake()
    11.     {
    12.  
    13.         coinCounter.coinCount = PlayerPrefs.GetInt("coins", 0);
    14.     }
    15.     // Update is called once per frame
    16.     void Update ()
    17.     {
    18.         //Set the coin count text
    19.         GetComponent<Text>().text = coinCount.ToString();
    20.  
    21.     }
    22.     void OnTriggerEnter2D(Collider2D other)
    23.     {
    24.         if (other.gameObject.tag == "Player") {
    25.             print("You picked up a coin!");
    26.             //Update the GUI
    27.            
    28.             coinCounter.coinCount++;
    29.            
    30.             PlayerPrefs.SetInt("coins", coinCounter.coinCount);
    31.             PlayerPrefs.Save();
    32.            
    33.             Destroy(gameObject);
    34.         }
    35.          }
    36.     public void Coin () {}
    37.  
    38. }
    39.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Coin : MonoBehaviour
    4. {
    5.     public int coinCount = 0;
    6.     private CoinCounter coinCounter;
    7.     void Awake()
    8.     {
    9.         coinCounter = GameObject.Find("CoinCount").GetComponent<CoinCounter>();
    10.         coinCounter.coinCount = PlayerPrefs.GetInt("coins", 0);
    11.     }
    12.  
    13. }
     
  38. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    NNNNNooooooooooooooooo *fades*

    Not the playerPrefs! That's not what that's for. :(

    (I know I'm nowhere close to on topic at this point but I felt the overwhelming urge to type words)
     
  39. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Look, we're being simple here. At this stage we are not going to be serialising data and saving to a file. One thing at a time.
     
  40. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Good attempt.

    A couple of things off the top:

    CoinCounter, line 9: The script doesn't need a reference to itself. Which leads on to line 13: you can access the variable coinCount directly, as it's declared in this script with "coinCount = ...". There is a rule for this. This is called scope. The rule here is, variables that you declare in the script are known by that script. If you declare a new variable inside a function, it's only known inside that function, and can't be accessed outside that function. If you declare a variable in another script, you cannot access it unless it's public and you have a reference to it.

    Whenever you see the "GetComponent<SomeType>()", this takes time to do the look up, so it's best that you make a reference variable and get the reference in Start or Awake, and use the reference. Try creating a "private Text countDisplayText;" variable, set this with the get component in Start or Awake, and use the reference.

    With the Update Function: don't use this to set the text value. This only needs to be set when the value changes. As I stated above, out this in your public function called by the coin.

    At this point you need to decide who's in charge of activating the trigger. Is it the player? Or is it the coin? This works either way. For the game logic, either the player collects the coins by bumping into their trigger and detecting the coin, or the coins collect themselves by detecting the player.

    The on trigger enter as written should be moved back to the coin, if the coin is detecting the collision. If the CoinCount script is on the player and can come into contact with the coin, then, you need to change the tag to detect a coin and tag the coins.

    Once you have worked out who is in charge of the trigger, we can talk about who has the code for that.

    In coin, on line 5, this needs to be a public coin value to hold the value of the coin, and you don't need line 10 at all.
     
  41. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Re-reading this thread and our conversation, I have a suggestion on how to proceed and not get confused.

    Open your Coin and CoinCounter scripts.
    Select all the existing code and comment it out:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Coin : MonoBehaviour
    4. {
    5. //    public int coinCount = 0;
    6. //    private CoinCounter coinCounter;
    7. //    void Awake()
    8. //    {
    9. //        coinCounter = GameObject.Find("CoinCount").GetComponent<CoinCounter>();
    10. //        coinCounter.coinCount = PlayerPrefs.GetInt("coins", 0);
    11. //    }
    12. }
    (this is so you won't feel like you are erasing your code)

    ... and then go through the list I presented above and make one new line of code for each item.

    In the first case we have: The coin only needs to have a value, even if it's only the value of one. (public int coinValue); We will do this with public int coinValue; (Note: we don't need to initialize this, as this value will be set in the inspector!)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Coin : MonoBehaviour
    4. {
    5.       public int coinValue;
    6.  
    7. //    public int coinCount = 0;
    8. //    private CoinCounter coinCounter;
    9. //    void Awake()
    10. //    {
    11. //        coinCounter = GameObject.Find("CoinCount").GetComponent<CoinCounter>();
    12. //        coinCounter.coinCount = PlayerPrefs.GetInt("coins", 0);
    13. //    }
    14. }
    The next step is "The coin needs a reference to the CoinCount script" add this to the script. Go through each line and in my check list and get it into the script, then we can go from there.
     
  42. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    I understand that. I was just mentioning this in another thread. You should either comment that it's just an example, or just use pseudo code. But now any new person coming in reading this will go, "Oh player prefs for saving, cool!" and then they're off on a long unfortunate rabbit trail that may never get corrected. I'm not trying to be a pest... just my due diligence to help the community. I was mostly just trying to sneak in the quick comment to at least spark thought. :) You can ignore me now.
     
  43. simone9725

    simone9725

    Joined:
    Jul 19, 2014
    Posts:
    234
    I 've made some changes.Coin is attached to every coin spawned in the game Coincounter is attached to a gameobject called CoinCount and the script is inactive
    V2.0
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4. [ExecuteInEditMode]
    5.  
    6. public class CoinCounter : MonoBehaviour
    7. {
    8.     public int coinCount = 0;
    9.     public int coinCounter;
    10.     private Text countDisplayText;
    11.     void Awake()
    12.     {
    13.  
    14.  
    15.     }
    16.  
    17.        
    18.     public void Coin ()
    19.     {
    20.         GetComponent<Text>().text = coinCount.ToString();
    21.  
    22.     }
    23.  
    24. }
    25.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class Coin : MonoBehaviour
    4. {
    5.     public int coinCount = 0;
    6.     public int coinValue;
    7.     private CoinCounter coinCounter;
    8.     void Awake()
    9.     {
    10.         coinCounter = GameObject.Find("CoinCount").GetComponent<CoinCounter>();
    11.         coinCounter.coinCount = PlayerPrefs.GetInt("coins", 0);
    12.     }
    13.  
    14.     void OnTriggerEnter2D(Collider2D other)
    15.     {
    16.         if (other.gameObject.tag == "Player") {
    17.             print("You picked up a coin!");
    18.             coinCounter.coinCount++;
    19.             PlayerPrefs.SetInt("coins", coinCounter.coinCount);
    20.             PlayerPrefs.Save();
    21.             Destroy(gameObject);
    22. }
    23.     }
     
  44. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    I'll not step on Adam's toes with any instruction on what you're working on. But what I will point out is that, if you're using a lot of coins in your game, you should considering using object pooling. You're currently destroying the coin which is going to cause bad spikes of CPU usage and memory (Caused from garbage collection, but worry about that later). So to avoid that issue you can just "turn off" the coin and then use it again later without destroying it. It's actually an incredibly simple concept that, based on the code you've written already, I am confident you're capable of implementing. Here's a link to the video. Don't worry about it for now though. Just get what you're working on finished and then come back to the pooling idea later. I'm just planting the seed.
    https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/object-pooling

    Good luck! It looks like you're learning well and improving quickly.

    Kudos to you sir for putting so much time and effort into this. It's cool to see such dedication helping the community! I have a bad habit of checking out once threads get super long and complicated, haha.
     
  45. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Thanks!

    "Leave no one behind!"

    As long as someone is willing to try and try hard to learn, I'll help!
     
  46. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    This is a good suggestion, but I think it's a concept that might come a little later.
     
  47. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    When it comes to the code, we're getting closer, but we've not done what I was hoping. This was to remove (or comment out) all of the code that was in the original script, and then go through the list line by line adding in new logic.

    TBH, you could just remove the code and start from scratch, but I thought that might be a little scary, so that's why I suggested commenting out the old code, and starting with new code above it.

    What I'm trying to show is that you can make a list of the logical steps you need, and write the code for it.

    Does this makes sense?

    Try this: This is more of a fill in the blanks...
    Start with this and give it your best shot:

    • The coin only needs to have a value, even if it's only the value of one. (public int coinValue)
      • This will allow you to have a value to pass to your CointCount script
      • This will allow you to be able to have coins with different values in your game
    • The coin needs a reference to the CoinCount script
      • This could be private and a lookup as it is now, so it's there...
    • When the coin is triggered, it should access a public function on your CoinCount script
      • You have the trigger...change it to call the public function on CoinCount

    • CoinCount should:
      • Have a way to hold the coinCount value
      • Have a way to grab this value from PlayerPrefs
      • Have a reference to the display Text element
      • Have a public function on CoinCount for the coins to access when they are collected. This function should be responsible for:
        • Taking in the coin value as a parameter
        • Adding this value to coin count
        • Updating the display text value
        • Saving this value to PlayerPrefs

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CoinCounter : MonoBehaviour {
    5.  
    6.     // Public value for the coin - I'll do this one, you do the rest!
    7.     public int coinValue;
    8.  
    9.     // Private reference to the CoinCounter Script
    10.  
    11.     void Start () {
    12.         // Set the reference to the CoinCounter script
    13.     }
    14.  
    15.     //When the coin is Triggered
    16.     void OnTriggerEnter () {
    17.         // Call a public function on the CoinCounter when Triggered
    18.     }
    19. }
    ... and ...

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CoinCounter : MonoBehaviour {
    5.  
    6.     // A value for the total number of coins the player has
    7.     // A reference to the Text element
    8.  
    9.  
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.         // Set the number of coins from player prefs
    14.         // Set the reference to the Text element
    15.     }
    16.  
    17.     // public function to take the value of the coin and "DO" something with it, called by the coin when the coin is triggered {
    18.  
    19.        // Uses the value of the coin to add to the total number of coins the player has
    20.        // Updates the text to display the new total number of coins
    21.        // Saves the new total number of coins the player has to Player prefs.
    22.     // }
    23.  
    24. }
     
    jtsmith1287 likes this.