samedi 26 mai 2012

Comment pauser un jeu dans Unity?

Pauser le jeu dans Unity est relativement facile. Si toutes vos fonctions sont dépendantes du taux de rafraîchissement (c'est le cas des animations), la commande suivante va pauser le jeu:
Time.timeScale = 0; 
La variable timeScale contrôle à qu'elle vitesse le temps s'écoule dans l'engin de jeu Unity. Une valeur inférieure à 1 va créer un effet de ralentie et 0, fige tout dans le temps. Pour résumer le jeu, remettez la valeur de timeScale à 1:
Time.timeScale = 1; 
Pour le code indépendant du taux de rafraîchissement, je suggère d'utiliser des messages (la fonction SendMessage). Une classe PauseGame contient deux fonctions statique: Pause et Resume. La fonction Pause met timeScale à 0 et envoie un message OnPauseGame à tous les objets dans la scène. De même, la fonction Resume remet timeScale à 1 et envoie le message global OnResumeGame. Les messages s'utilisent dans le code comme les fonctions Update et Start de Unity. La classe qui a besoin de pauser et de résumer implémente les fonctions OnPauseGame et OnResumeGame et ajoute le code spécifique pour cette classe:
public class A : MonoBehaviour
{
 void OnPauseGame()
 {
  //Do something to pause.
 }
 
 void OnResumeGame()
 {
  //Do something to resume.
 }
}
Pour mon script PauseGame (ci-dessous), j'ai ajouter la variable paused. Cette variable indique si le jeu est pausé ou non. Cette variable est utile pour bloquer du code dans la fonction Update comme suit:
public class B : MonoBehaviour
{
 void Update()
 {
  if ( !PauseGame.paused )
  {
   //Do something
  }
 }
}
Le script PauseGame (ci-dessous) pause le jeu lorsque la touche du bouton Pause est pressée. Vous devez définir ce bouton dans le menu Edit->Project Settings->Input. Dans mon cas, j'ai utilisé les touches P et Esc. Le script suit le modèle Singleton, d'où la variable s_instance. Ce modèle assure qu'une seule instance du script est créée. J'ai ajouté ce script sur ma caméra. Vous pouvez placer ce script n'importe où, mais il est important d'en avoir une copie dans votre scène pour pouvoir pauser le jeu.
/**
 * \file
 * 
 * \author Mentalogicus
 * \date 2012
 * 
 */

using UnityEngine;
using System.Collections;
using Mentalogicus;


/// \brief Pause the game with the button "Pause" defined in Unity Editor.
/// 
/// 
/// This class use the singleton modèle.
/// 
/// The game is paused by setting Time.timeScale to 0. Also, two messages are send:
/// - OnPauseGame: when the game is paused
/// - OnResumeGame: when the game is restarted
/// 
/// Those messages must be used in you script to manage codes that are not
/// frame independant (like those using absolute Time).
/// 
/// To use it, place the function OnPauseGame like this:
/// 
/// void OnPauseGame()
/// {
///  Do something.
/// }
/// 
/// 
/// 
[AddComponentMenu("Mentalogicus/Behaviour/PauseGame")]
public class PauseGame : MonoBehaviour
{
 #region Public members
 
 /// 
 /// Name of the message sent when pausing the game.
 /// 
 public const string ON_PAUSE_GAME = "OnPauseGame";
 
 /// 
 /// Name of the message sent when resuming the game
 /// 
 public const string ON_RESUME_GAME = "OnResumeGame";
 
 /// 
 /// Name of the button to pause or resume the game.
 /// 
 public const string BUTTON_NAME = "Pause";
 
 #endregion
 
 #region Private members
 
 /// 
 /// Flag that indicate if the game is paused.
 /// True-> the game is paused.
 /// False-> the game is running.
 /// 
 private bool _paused = false;
 
 /// 
 /// The s_instance store the single instance of PauseGame.
 /// 
 private static PauseGame s_instance = null;
 
 #endregion
 
 #region Properties
 
 /// 
 /// Return the instance of PauseGame.
 /// 
 /// 
 /// The instance.
 /// 
 public static PauseGame instance
 {
  get 
  {
   if ( !s_instance )
   {
    FindInstance();
   }
   return s_instance; 
  }
 }
 
 /// 
 /// Gets a value indicating whether the game is paused.
 /// 
 /// 
 /// true if paused; otherwise, false.
 /// 
 public static bool paused
 {
  get { return instance._paused; } 
 }
 
 #endregion
 
 #region Constructors
 
 /// 
 /// Initializes a new instance of the  class.
 /// 
 private PauseGame()
 {
  this._paused = false;
 }
 
 #endregion
 
 #region Static methods
 
 /// 
 /// Pause the game.
 /// 
 public static void Pause()
 {
  s_instance.PauseFunc();
 }
  
 /// 
 /// Resume the game.
 /// 
 public static void Resume()
 {
  s_instance.ResumeFunc();
 }
 
 /// 
 /// Finds the instance in the game.
 /// 
 private static void FindInstance()
 {
  s_instance = FindObjectOfType( typeof(PauseGame)) as PauseGame;
  
  if (!s_instance)
  {
   s_instance = null;
   throw( new UnityException("You need to add an active PauseGame script on a GameOjbect in your scene."));
  }

 }
 
 #endregion
 
 #region Private Methods
 
 /// 
 /// Awake this instance.
 /// 
 private void Awake()
 {
  FindInstance();
 } 
 
 /// 
 /// Pause the game and broadcast an OnPauseGame message to all GameObject of the game.
 /// 
 private void PauseFunc()
 {
  this._paused = true;
  
  Time.timeScale = 0;
  
  //Broadcasst the OnPauseGame event to all object in the game.
  Object[] objects = FindObjectsOfType (typeof(GameObject));
  
  foreach (GameObject go in objects) 
  {
   go.SendMessage (ON_PAUSE_GAME, SendMessageOptions.DontRequireReceiver);
  }
 }
 
 /// 
 /// Resume the game and broadcast an OnResumeGame message to all GameObject in the game.
 /// 
 private void ResumeFunc()
 {
  this._paused = false;
  
  Time.timeScale = 1;
  
  //Broadcasst the OnResumeGame event to all object in the game.
  Object[] objects = FindObjectsOfType (typeof(GameObject));
  
  foreach (GameObject go in objects) 
  {
   go.SendMessage (ON_RESUME_GAME, SendMessageOptions.DontRequireReceiver);
  }
 }
 
 /// 
 /// When Pause button is pressed, pause or resume the game
 /// depending on the actual state of the game.
 /// 
 private void Update ()
 {
  if ( Input.GetButtonUp( BUTTON_NAME ) )
  {
   if ( !this._paused )
   {
    this.Pause();
   }
   else
   {
    this.Resume();
   }
  }
 }
 
 #endregion
 
} //End class
PauseGame.cs by Mentalogicus is licensed under a Creative Commons Attribution 3.0 Unported License.