Create A Star Rating / Reward System - Unity 4.6 GUI

This post will be a continuation of the Level Select Scroll Menu and the Level Lock / Unlock System. Follow the two posts in order so as to get a grip of this post which will be on How to create a three star rating system, just like the one you see in games like Angry Birds, using unity's new GUI.

Create A Star Rating System using Unity 4.6 GUI - The Result



If you have followed the previous tutorials then you would have a scene named World1, and the Hierarchy of this scene would look something like below:

World1 Scene Hierarchy
World1 Scene Hierarchy
Now, if I expand the Level1, Level2 buttons, I see a Text component in each of them. To this Level buttons we'll add four images for no stars, one star, two star and three stars respectively. We will place these star images inside a Panel, which in turn will be inside the Level buttons.

1. Create a Panel inside the Level1 button. Rename it to StarPanel. Change the color of this panel to any color you like and which is different from the background color. Also, resize the panel and place it to the right edge of the button as shown in the image below. Make sure you move the anchor points to the edge of the panel.

Panel Properties

Change the font size of the Text component of the Level buttons in case the whole text is not visible.

2. Add an Image component inside the Panel and name it 1star0. 1 stands for the level number and 0 stands for no stars. Resize this image to fit the panel and also place the anchors to the edges of this image.

Panel Image Properties
.  
3. Download the images from this link and import them into your project. Add the three_stars_empty to the Source Image field of the Image component added above. 

Star Images Placement

4. Duplicate the image component thrice and name them as 1star1, 1star2 and 1star3. Add the source images from the images downloaded above. Disable the Image (Script) component of these Images you just added so that they are not visible by default.

Star Images Duplication

5. Repeat the above steps for the other level buttons as well. Remember, you have to name the images as 2star0, 2star1, 2star2 and 2star3 for level 2 images and so on.

Level Buttons Hierarchy

6. Open the LevelSelectScript attached to the Main Camera and replace the old code with the below code. This new code has some additions to it which are well commented for you to easily understand it.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LevelSelectScript : MonoBehaviour {
 private int worldIndex;   
 private int levelIndex;
 //variable which holds the stars obtained   
 private int stars=0;

 void  Start (){
  //loop thorugh all the worlds
  for(int i = 1; i <= LockLevel.worlds; i++){
   if(Application.loadedLevelName == "World"+i){
    worldIndex = i;  //save the world index value
    CheckLockedLevels(); //check for the locked levels 
   }
  }
 }

 //Level to load on button click. Will be used for Level button click event 
 public void Selectlevel(string worldLevel){
  Application.LoadLevel("Level"+worldLevel); //load the level
 }

 //uncomment the below code if you have a main menu scene to navigate to it on clicking escape when in World1 scene
 /*public void  Update (){
  if (Input.GetKeyDown(KeyCode.Escape) ){
   Application.LoadLevel("MainMenu");
  }   
 }*/
 
 //function to check for the levels locked
 void  CheckLockedLevels (){
  //loop through the levels of a particular world
  for(int j = 1; j < LockLevel.levels; j++){
   //get the number of stars obtained for that particular level
   //used to enable the image which should be displayed in the World1 scene beside the individual levels
   stars = PlayerPrefs.GetInt("level"+worldIndex.ToString() +":" +j.ToString()+"stars");
   levelIndex = (j+1);
   //enable the respective image based on the stars variable value
   GameObject.Find(j+"star"+stars).GetComponent<Image>().enabled = true;
   Debug.Log(j+"star"+stars);
   //check if the level is locked 
   if((PlayerPrefs.GetInt("level"+worldIndex.ToString() +":" +levelIndex.ToString()))==1){    
    //disable the lock object which hides the level button
    GameObject.Find("LockedLevel"+levelIndex).SetActive(false);
   }
  }
 }
}

Save the script and return to unity.

7. Save this scene and switch to the Level1.1 scene. The hierarchy of this scene should have the following components.

Level1.1 Hierarchy

Before we proceed with the next step, I would like to let you know how are we going to detect what star the player has obtained. We give 3 stars if the player reaches the goal within 5 sec, 2 stars for within 10 sec and 1 star for anything greater than 10 sec. 

8. Add a Text component inside the Canvas and name it as Time. Change the text to be displayed of the Text (Script) to TIME: 0.0, which is the initial time to be displayed. 
   
Time Text Placement

9. Add a Panel inside the Canvas named StarPanel and make its background transparent by setting the alpha value to 0.

10. Add an Image component inside this StarPanel. Name it as star1 and in the Source Image field drag and drop the one star sprite.
Duplicate the image twice and name the duplicated images as star2 and star3 respectively. Drag and drop the respective images into their Source Image field.
Make sure you place these images somewhere in the middle of the scene as in the image below:

Stars Image Placement - Play Scene

Note the position of the anchor points.

11. Next we add a Button inside the Canvas to move to the World1 level once the level is completed and this button is clicked. Name this button as Next. Change the Text to be displayed as Next.

You should have a PlayerMovement script. Add the below code to it.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class PlayerMovement : MonoBehaviour {
 
 //reference to star images
 private GameObject star1;
 private GameObject star2;
 private GameObject star3;

 //reference to next button
 private GameObject buttonNext;
 
 protected string currentLevel;
 protected int worldIndex;
 protected int levelIndex;
 bool isLevelComplete ;
 //timer text reference
 public Text timerText;
 //time passed since start of level
 protected float totalTime = 0f;

 // Use this for initialization
 void Start () {
  //set the level complete to false on start of level
  isLevelComplete = false;
  //get the star images
  star1 = GameObject.Find("star1");
  star2 = GameObject.Find("star2");
  star3 = GameObject.Find("star3");
  //get the next button
  buttonNext = GameObject.Find("Next");
  //disable the image component of all the star images
  star1.GetComponent<Image>().enabled = false;
  star2.GetComponent<Image>().enabled = false;
  star3.GetComponent<Image>().enabled = false;
  //disable the next button
  buttonNext.SetActive(false);
  //save the current level name
  currentLevel = Application.loadedLevelName;
 }
 
 // Update is called once per frame
 void Update () {
  //check if the level is completed
  if(!isLevelComplete){
   //update the timer value
   totalTime += Time.deltaTime;
   //display the timer value 
   timerText.text = "TIME: "+totalTime.ToString();
   Debug.Log(totalTime);
   //move the player based on left and right arrow keys
   transform.Translate(Input.GetAxis("Horizontal")*Time.deltaTime*10f, 0, 0); //get input
  }
 }

void OnTriggerEnter(Collider other){
  if(other.gameObject.name=="Goal"){
   //set the isLevelComplete flag to true if the player hits an object with name Goal
   isLevelComplete = true;
   if(totalTime<5){
    star3.GetComponent<Image>().enabled = true;
    UnlockLevels(3);   //unlock next level funxtion 
   }
   else if(totalTime<10){
    star2.GetComponent<Image>().enabled = true;
    UnlockLevels(2);   //unlock next level funxtion 
   }
   else if(totalTime<15){
    star1.GetComponent<Image>().enabled = true;
    UnlockLevels(1);   //unlock next level funxtion 
   }
   buttonNext.SetActive(true);

  }
 }

public void OnClickButton(){
  //load the World1 level 
  Application.LoadLevel("World1");

 }

 protected void  UnlockLevels (int stars){

  //set the playerprefs value of next level to 1 to unlock
  //also set the playerprefs value of stars to display them on the World levels menu
  for(int i = 0; i < LockLevel.worlds; i++){
   for(int j = 1; j < LockLevel.levels; j++){               
    if(currentLevel == "Level"+(i+1).ToString() +"." +j.ToString()){
     worldIndex  = (i+1);
     levelIndex  = (j+1);
     PlayerPrefs.SetInt("level"+worldIndex.ToString() +":" +levelIndex.ToString(),1);
     //check if the current stars value is less than the new value
     if(PlayerPrefs.GetInt("level"+worldIndex.ToString() +":" +j.ToString()+"stars")< stars)
      //overwrite the stars value with the new value obtained
      PlayerPrefs.SetInt("level"+worldIndex.ToString() +":" +j.ToString()+"stars",stars);
    }
   }
  }

 }


}


Save the script and return to unity. Notice that this script attached to the Player now expects a Timer Text field to be filled with a Text component. Drag and drop the Time text component here.

12. Finally, we will add an OnClick event to the Next button. Click on the + symbol to add an event. Drag and drop the Player object into the Object field. Select the PlayerMovement->OnClickButton function in the function field.


Save the scene and repeat the same steps for the Level1.2 and the other scenes as well.
Now you are ready to test this beauty. Click play and try it out.

See you around.

Also check out,
Unity 4.6 GUI - Create A Dynamic Menu With The New UI
Unity 4.6 GUI - Create A Health Bar HUD
Unity 4.6 GUI - Create A Level Select Scroll Menu
Unity 4.6 GUI - Create An Animated Menu
Unity 4.6 GUI - Create A Level Lock/Unlock System
Share on Google+

About Sujit Horakeri

Sujit Horakeri is a game freak just like any other next door guy you would come across. He is a Web Developer by Profession, Game Developer by Choice.
Connect with him on:
    Blogger
    Facebook

34 comments:

  1. Thank you for this great tutorial. I have a problem wherever in the scripts you use

    on the getcomponent part of the Image where you say img

    sorry but the system does not let me write code it says Tag is not allowed as comment
    it is in line 35 of your code in the playermovement script

    ReplyDelete
    Replies
    1. Hi.. actually there is no img tag, it's an html tag which popped in automatically when I had pasted the code from my editor, I should have read the code once I had posted it, my bad...Anyway, I have removed the unwanted tags in the script. Do let me know if you still face any issues...
      Also let me know if this is working fine now...
      Good day!

      Delete
  2. Hi I tried your tutorial and it works on Level1.1 and it also works for Level1 on World1 scene, it actually shows the highest rank of stars for level1.

    But when i play the Level1.2 even though it works in the level it does not work on World1. Which means the stars are not assigned to Level2 button in the World1 scene. Any help ?

    ReplyDelete
    Replies
    1. The highest star is saved in the playerprefs and it is not overwritten when you complete the same level with lower rating..

      Make sure you follow the same steps as you followed for Level1.1...
      Also, make sure the hierarchy of the Level2 button is as shown in the image captioned "Level Buttons Hierarchy"

      Delete
    2. Everything looks as it should. This is what is written in the playerprefs file

      UnityPrf

      Delete
    3. UnityPrf
      LanguageCode gr
      LanguageName greek
      Level:Unlocked:Level-0-1-Sceneþ
      Level:Unlocked:Level-0-2-Sceneþ
      Level:Unlocked:Level-0-3-Sceneþ
      Level:Unlocked:Level-0-4-Sceneþ
      Level:Unlocked:Level-0-5-Sceneþ

      i have only 2 levels and 1 world

      Delete
    4. I must be doing something wrong cause i am trying to implement it within my program and it is not working there while i re did your tutorial and it works there. Can you help me in what direction to look? it seems that as i have it implemented it is not saving the level2 stars on the world1 scene. Thanks

      Delete
    5. I cannot be sure until I see what's goin on in your game / scene. But, there are some things you can look for -
      Print the value of stars using Debug.Log and see if the correct stars value is being stored in the PlayerPrefs...
      As in step 4 make sure you have "Disabled the Image (Script) component of the Images"
      Try debugging, you will definitely get to know where the problem lies in your scene...

      Delete
    6. I got it working! thank you so much

      Delete
  3. Hi,

    I seem to have a problem getting this to go to from level 1 to level 2.

    I get an error after clicking on the next button.

    NullReferenceException: Object reference not set to an instance of an object
    LevelSelectScript.CheckLockedLevels () (at Assets/LevelSelectScript.cs:64)
    LevelSelectScript.Start () (at Assets/LevelSelectScript.cs:24)

    Which comes down to this being null:

    //disable the lock object which hides the level button
    GameObject.Find("LockedLevel"+levelIndex).SetActive(false);

    Any idea how I can resolve it.

    The code is as set out here.

    John

    ReplyDelete
    Replies
    1. Have you followed the previous two tutorials before moving to this one, the ones mentioned in the beginning of this post?
      Looks like the error might be due to the naming of the lock images.
      You are supposed to name the lock images as "LockedLevel2", "LockedLevel3" and so on...
      Check out this image
      http://i.imgur.com/OB4KA0a.jpg?1

      Delete
    2. Hi,

      Thankyou, yes I followed the tutorial as you said and made the typo on the name of the "LockedLevel2" as LockedLevel 2". Unity did not like the space.

      It is working great now, thankyou for your very explained Tutorials.

      John

      Delete
    3. Cool.. Its great that you got it working. And thanks for letting us know that it's working fine now. Cheers!

      Delete
  4. Hi. Great tutorial. It helped me a lot implementing the level unlock system in my game. However, I can't seem to make the star reward system to work. My game is written mostly in JS, so when I incorporated your scripts, I had to translate them from C#. Level unlock worked fine, but Star Reward just won't go. Must be my poor translating skills.
    Could you please help me out?

    ReplyDelete
    Replies
    1. well, I managed to make it work somehow, my translation of
      star1.GetComponent().enabled = true;
      was wrong. It ended up looking like this :
      - declaring the variable private var star1 : GameObject;
      -in function Start ():
      star1 = GameObject.Find("star1");
      star1.GetComponent.().enabled = false;

      That did the trick, in case anyone else has the same issue. Thanks again!


      Delete
    2. Hi Castravetele,

      I would like to thank you for your kind gesture and I would seriously like to see our other readrs doing this.
      Glad you visited us and hopefully you will find the other posts interesting too.
      Cheers!

      Delete

  5. in the play mode, an error in the console: NullReferenceException: Object reference not set to an instance of an object
    LevelSelectScript.CheckLockedLevels () (at Assets / scriptscreen / LevelSelectScript.cs: 47)
    LevelSelectScript.Start () (at Assets / scriptscreen / LevelSelectScript.cs: 15)
    Help please!

    ReplyDelete
    Replies
    1. Refer the Level Button Hierarchy image in the post above and make sure you have the same naming conventions. The reason you are getting the null reference exception is because you have either named the objects something else or the object themselves are not present.

      Delete
    2. This is my hierarchy, but still informs custom error messages to the console. What to do? I did everything according to your lessons. http://i.imgur.com/KfKCDRF.jpg

      Delete
    3. You might want to change the value of levels in the LockLevel script which was added in the Lock/Unlock system post from 8 to the number of levels you have in your game.. Also use a for loop to get the star images instead of getting them individually...

      Delete
  6. Hi, I also have an error occurred in this line.

    This is the error:
    NullReferenceException: Object reference not set to an instance of an object
    LevelSelectScript.CheckLockedLevels () (at Assets/Battles/scripts/LevelSelectScript.cs:41)
    LevelSelectScript.Start () (at Assets/Battles/scripts/LevelSelectScript.cs:15)

    This is the line that has an error:
    GameObject.Find(j+"star"+stars).GetComponent().enabled = true;

    Please help me out. Thank you, Sujit! :)

    ReplyDelete

  7. please tell me how to make time with minutes and seconds?

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. I have a problem in my game, in the "World1" not change the stars, however I make 3 stars in "Level1.1" but World1 not change stars, heelp pleas

    ReplyDelete
    Replies
    1. problem solved, thanks for this tutorial:)

      Delete
  11. Hi. First of all , thank you for these excellent tutorials. They help us a lot to those who started .

    I want to set a totalTime variable for 1, 2 and 3 stars, and can set from unity without edit the script every time, and reuse the script for all maps, and put diferents times to win Stars each maps.

    I think to use something like:
    public float timerStar1;
    public float timerStar2;
    public float timerStar3;
    And create something to replace if ( totalTime < 5) with timerStar1 , or what we can , and so with the other stars .
    But my c # skills are not very good. Could you give me a hand to implement this?

    Excuse me for my bad english.

    ReplyDelete
  12. i followed this tut but couldnt get it to work, i can see the stars on my lock panel allthough there black due to disabling them when i got to my level and play it i see the timer running and when i complete the level it stops, however i dont see any stars pop up, or the next button if i click pause and then look at my scene i see that my stars are still set to disabled anyone will to help

    ReplyDelete
  13. Hi , This is the error:
    NullReferenceException: Object reference not set to an instance of an object
    LevelSelectScript.CheckLockedLevels

    This is the line that has an error:
    GameObject.Find(j+"star"+stars).GetComponent().enabled = true;

    ReplyDelete
  14. Hi, thank you for this great tutorial it helps me very much and I really need your help, how about 2 goal object one is the yes goal or the goal that can gain star and the other one is Not or it can gain no star..!

    can you help me how to do that..

    And can you help me how to reset new game the world1 scene. I use Playerprefs.DeleteAll(); but still the zero star still there even the level2 is locked...


    thank you in advance and i wish somebody can help me resolve this for my project purposes...
    THANK YOU

    ReplyDelete
  15. apakah ada tutorialnya dalam bentuk vidio.? help

    ReplyDelete