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.

Goals/Missions/Objective System

Discussion in 'Scripting' started by binsint, May 19, 2014.

  1. binsint

    binsint

    Joined:
    Jul 16, 2011
    Posts:
    83
    hi everyone!

    How do i make goals in my game?What would be the most preferred way to do it?
    Examples are:
    1. Collect 200 coins
    2. Kill 30 Enemies in One Game

    How do I start this? Thank you!
     
  2. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    Code (csharp):
    1.  
    2. class Goal : Monobehaviour
    3. {
    4.  public event System.Action completed;
    5.  protected void GoalCompleted()
    6.  {
    7.     if(completed!=null)
    8.        completed();
    9.  }
    10. }
    11.  
    12. class CollectCoins : Goal
    13. {
    14.    ...
    15. }
    16. ...
    17.  
    etc..

    If that doesn't answer the question, I'm not sure I have understood it
     
  3. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    11,958
    This is a very broad topic.
    • To keep track of goals, you can store data and methods on a GameObject. I'll sketch out the code below. If you need something more sophisticated, examine the design of quest systems available on the Asset Store.
    • If you want to show the progress onscreen, you need some kind of HUD (heads-up display). Goals need to be aware of each other so they can position themselves correctly onscreen. Otherwise, if every goal tries to draw itself in the same location (e.g., upper left corner), they'll overlap.
    • If you want to keep track of goal progress between play sessions, you need to save the game. To do this, you need to implement a save system -- for example, saving a small amount of information in PlayerPrefs, or more information to a local file or network database.

    Say you have a GameObject named GoalManager. Riffing on A.Killingbeck's code, you could do this:
    Code (csharp):
    1.  
    2. // Add this script to the GoalManager GameObject. It keeps track of all goals.
    3. public class GoalManager : MonoBehaviour {
    4.  
    5.     public Goal[] goals;
    6.  
    7.     void Awake() {
    8.         goals = GetComponents<Goal>();
    9.     }
    10.  
    11.     void OnGUI() {
    12.         foreach (var goal in goals) {
    13.             goals.DrawHUD();
    14.         }
    15.     }
    16.  
    17.     void Update() {
    18.         foreach (var goal in goals) {
    19.             if (goal.IsAchieved()) {
    20.                 goal.Complete();
    21.                 Destroy(goal);
    22.             }
    23.         }
    24.     }
    25.     }
    26. }
    27.  
    28.  
    29. // This is the abstract base class for all goals:
    30. public abstract class Goal : MonoBehaviour {
    31.     public abstract bool IsAchieved();
    32.     public abstract void Complete();
    33.     public abstract void DrawHUD();
    34. }
    35.  
    36.  
    37. // Add this to GoalManager to run a "collect the coins" goal:
    38. public class CollectCoins : Goal {
    39.  
    40.     public int coins = 0;
    41.     public int requiredCoins = 50;
    42.  
    43.     public override bool IsComplete() {
    44.         return (coins >= requiredCoins);
    45.     }
    46.  
    47.     public override void Complete() {
    48.         ScoreSingleton.score += 10;
    49.     }
    50.  
    51.     public override void DrawHUD() {
    52.         GUILayout.Label(string.Format("Collected {0}/{1} coins", coins, requiredCoins));
    53.     }
    54.  
    55.     public OnTriggerEnter(Collider other) {
    56.         if (string.Equals(other.tag, "Coin")) {
    57.             coins++;
    58.             Destroy(other.gameObject);
    59.         }
    60.     }
    61. }
    62.  
    63.  
    64. // Add this to GoalManager to run a "kill the enemies" goal:    
    65. public class KillEnemies : Goal {
    66.  
    67.     public int requiredKills= 50;
    68.     public AudioClip trumpetSound;
    69.  
    70.     private PlayerStats playerStats;
    71.  
    72.     void Awake() {
    73.         playerStats = GameObject.Find("Player").GetComponent<PlayerStats>();
    74.     }
    75.  
    76.     public override bool IsAchieved() {
    77.         return (playerStats.kills >= requiredKills);
    78.     }
    79.  
    80.     public override void Complete() {
    81.         ScoreSingleton.score += 50;
    82.         audio.Play(trumpetSound);
    83.     }
    84.  
    85.     public override void DrawHUD() {
    86.         GUILayout.Label(string.Format("Killed {0}/{1} enemies", playerStats.kills, requiredKills));
    87.     }
    88. }
    89.  
     
  4. binsint

    binsint

    Joined:
    Jul 16, 2011
    Posts:
    83
    Thank you TonyLi... tried this and it works... Will try to experiment integrating it on NGUI too.. and for other goals... Thanks you so much!
     
  5. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    11,958
    Happy to help! I based my example off A.Killingbeck's response, so credit goes there, too! :)
     
  6. spounyboy

    spounyboy

    Joined:
    Aug 18, 2015
    Posts:
    5
    Anyone still folowing this thread ?
    I have a similar problem but I don't really understand the answers.
    I need to put a goal on my game (the game is basicly the space shooter tutorial code).
    I would like to have a WIN screen après aavoir détruit 100 asteroid.
    I finished the basic tutorial so I have the HUD (GUItext), the Game over and restart fuction to.
    Thanks
     
  7. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    11,958
    Since you only have the one goal (destroy 100 asteroids), it's probably easiest to write a simple script for that. Here's one way.

    1. Make a WIN scene. Let's say it's called "WIN".

    2. Add a C# script named AsteroidGoal to an empty GameObject in your gameplay scene:
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3.  
    4. public class AsteroidGoal : MonoBehaviour {
    5.     public int goal = 100; // Player must destroy this many asteroids.
    6.     private int destroyed = 0; // Counts how many asteroids destroyed so far.
    7.  
    8.     public void AsteroidDestroyed() { // Called by asteroids when they're destroyed.
    9.         destroyed++;
    10.         if (destroyed >= goal) SceneManager.LoadScene("WIN");
    11.     }
    12. }
    3. Add a C# script named Asteroid to your asteroids:
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class Asteroid : MonoBehaviour {
    4.     void OnDestroy() {
    5.         FindObjectOfType<AsteroidGoal>().AsteroidDestroyed();
    6.     }
    7. }
     
  8. spounyboy

    spounyboy

    Joined:
    Aug 18, 2015
    Posts:
    5
    Thanks
    Actually I used the score count to trigger the win sequence, I use a small part of the code of the first tutorial (with the sphere) and some stuff online but in the end the code was 3 or 4 line long :) :


    Code (CSharp):
    1. if (score >= 300)
    2.             {
    3.                 winText.text = "Systeme nettoye \r\n avec succes";
    4.                 break;

    With a GUItext to display the "winning" phrase

    Thank anyway, I'm new to this stuff (i'm a 3D graphic designer) and coding is quite frustrating because I don't understand half of the stuff I put together so I' just patching things up, like a patchwork.
    I guess practice will make this more natural ...

    Thanks

    PEACE
     
    xpcrepair23 likes this.
unityunity