Affichage des articles dont le libellé est Unity 3D. Afficher tous les articles
Affichage des articles dont le libellé est Unity 3D. Afficher tous les articles

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.

jeudi 10 mai 2012

Comment compiler un jeu PC dans Unity 3D?

Pour compiler un jeu dans Unity, sélectionner le menu File->Build Settings... ou File->Build. Aux fins de ce tutoriel, je clique sur Build Settings.
Le menu suivant apparaît:
L'encadré du haut offre la liste des scènes dans le projet. Le numéro à droite indique l'ordre des scènes. La scène la plus en haut est chargée en premier. Pour changer l'ordre des scènes, glissez la scène à l'endroit désiré. Les scènes doivent être cochées pour être ajoutées au jeu final.

L'encadré Platform indique la plate-forme sur lequel nous voulons que le jeu soit exécuté. Dans le cas présent, je choisis PC and Mac Standalone.

Avant de construire le jeu, cliquons sur le boutons Player Settings. Un menu apparaît dans l'inspecteur:
Ce menu permet d'ajuster avec plus de détails l'aspect visuel de l'exécutable du jeu, de sélectionner les tailles d'écran, si par défaut le jeu démarre en plein écran, etc. L'encadré Default Icon et le menu Icon change l'icône de votre exécutable. Donc, au lieu d'avoir l'icône d'Unity sur votre fichier .exe, vous aurez votre propre icône.
C'est tellement plus jolie et professionnel!
Le menu Splash Image vous permet d'ajouter une image qui va apparaître dans la fenêtre qui ouvre juste après avoir exécuté le jeu:
La fenêtre de démarrage d'un jeu en Unity.
Une fois que vous avez terminé avec les paramètres, appuyez sur Build ou Build and Run. Unity va demander l'emplacement de l'exécutable.

Important:
Unity crée un exécutable et un dossier de données. Dans mon exemple, j'utilise un projet nommé Space Junk. Lorsque je construis l'exécutable, je me retrouve avec le fichier Space Junk.exe et le dossier Space Junk_Data.
Si vous voulez distribuer votre jeu, vous devez fournir l'exécutable et le dossier de données. J'ai appris cette leçon à la dure. Je voulais montrer mon démo Space Junk à un ami. J'ai partagé l'exécutable sur Dropox. Dans ma tête, un exécutable contient le jeu en entier. Je pensais en terme d'installateur à l'époque. Unity ne crée par un installateur, mais un jeu avec ces données. Mon ami l’essaie et ne réussit pas à l'exécuter. J’essaie sur une machine différente et rien ne fonctionne. J'ai finalement découvert le problème en cherchant sur le Web.

vendredi 4 mai 2012

Comment documenter les scripts dans Unity?

Les commentaires dans les scripts sont importants pour expliquer leur fonctionnement. L'utilisation des commentaires varie d'une école de pensée à une autre. Certains prônent l'utilisation massive de commentaires pour expliquer les intentions du code. D'autres croient que le code devrait être auto explicatif et libre de commentaires. Ma position sur le sujet est mitoyenne. J'utilise des noms de fonctions et de variables évocatrices, claires et indiquant leur fonction le plus souvent possible. Malgré tout, si je ne commente pas régulièrement, j'ai de la difficulté à saisir mon propre code après quelques mois. Alors, je documente.

L'ajout d'un commentaire se fait en ajoutant deux barres obliques "//":
//Un commentaire vraiment inutile.
string action = "Commente moi!"
ou pour un bloc de commentaires, avec "/*" et "*/":
/*
Il était une fois, dans l'ouest, une princesse prisonnière
dans une taverne miteuse gardée par des truands à la peau
tannée par le soleil et au regard sauvage, etc., etc., etc.
*/
string action = "Commente, mais commente égal!"
et aussi avec "///":
///Parce que // fait tellement 1990.
string action = "Commente moi!"

Dans MonoDevelop, si vous tapez "///" avant une entité (une variable, une fonction, une classe, etc.) vous obtenez:
/// 
/// Du XML???
/// 
private string action = "Commente moi!" 
MonoDevelop crée un commentaire avec un tag XML. Ce code XML est utilisé par un programme externe pour générer automatiquement la documentation. Les générateurs de documentation sont des programmes qui lisent le code source et les commentaires, l'analysent et retournent une documentation en format texte, HTML, XML, Latex, etc. qu'il est possible de consulter et d'effectuer des recherches. C'est très pratique pour se retrouver dans un gros projet avec des centaines de scripts. Mon générateur de documentation favori est Doxygen. Je vais parler de Doxygen dans un prochain billet.

L'utilisation du système de documentation avec l'XML amène un autre énorme avantage, en plus de la génération automatique de la documentation. Si vous glisser votre souris au-dessus d'une entité du code (une variable, une fonction, un enum, etc.), une info bulle jaune apparaît qui ressemble à ceci:

L'information de cet encadré n'est pas très utile. Nous apprenons que _selected est un booléen. Avec l'ajout d'un commentaire XML, voici le résultat:
Notre commentaire apparaît dans l'info bulle jaune! Cette description va apparaître si le curseur glisse au-dessus de la variable _selected quel que soit sa position dans le code. Si une variable publique est commentée, la description va aussi apparaître si la variable est utilisée dans une autre classe. Ce petit encadré peut sauver du temps. Imaginer que vous êtes dans le code. Vous travaillez sur une fonction, mais vous ne vous souvenez plus de l'intention d'une fonction ou de ce que stocke une variable. Normalement, vous naviguez dans le code, allez à la fonction ou à la variable, lisez la description et revenez à votre fonction. C'est long et inutile. Avec les commentaires XML, glisser le curseur sur la variable ou la fonction mystérieuse et voilà la description (si bien sur vous l'avez documentée).

Les commentaires en XML sont plus longs que les commentaires normaux, mais je recommande de les utiliser systématiquement pour permettre de générer la doc automatiquement et pour les info bulles. La longueur des commentaires n'est pas un problème réel avec les éditeurs modernes. Mono Develop permet de cacher les commentaires en appuyant sur le symbole +:
Avant.
Après.
Peu importe la longueur du commentaire, une fois refermé, il ne prendra qu'une ligne, vous permettant de lire le code sans obstruction.

lundi 16 avril 2012

Comment faire des captures d'images en Unity?

Vous avez ce jeu magnifique ou ce superbe effet et vous voulez le présenter au monde entier. Vous démarrez votre jeu et pressez la touche Print Screen (en mode Windowed, sinon l'image est noire). Vous allez dans Photoshop ou, comme moi dans GIMP et sélectionner l'écran de jeu et vous le copiez dans une nouvelle image. Vous avez votre capture d'écran. Jusqu'à maintenant, c'est la procédure que j'utilisais à défaut de connaître mieux.

Aujourd'hui, j'ai appris une commande magnifique: Application.CaptureScreen. Cette fonction prend une capture d'écran directement du jeu! Fini les manipulations dans GIMP! La fonction requière un argument obligatoire, le chemin d'accès au fichier comprenant le nom du fichier et la taille de l'image. La taille du fichier est un entier qui détermine combien de fois plus grande sera l'image. Si j'entre 3, la capture d'image sera 3 fois la taille de l'écran!

Voici le script que j'ai utilisé:
using UnityEngine;
using System.Collections;

public class ScreenShot : MonoBehaviour 
{

 // Update is called once per frame
 void Update () 
 {
  if ( Input.GetKeyUp( KeyCode.F3 ) )
  {
   Debug.Log("Screen captured.");
    Application.CaptureScreenshot("Screenshot.png"); 
  }
 }
}
et le résultat (j'ai utilisé le Prefab Big Tree dans Standard Asset/Tree Creator pour l'arbre):


J’utilise la touche F3 pour déclencher la capture d'image. La question maintenant: où est enregistrée l'image? Lors de l’exécution dans l'éditeur d'Unity, l'image est enregistrée dans le répertoire du projet. C'est le répertoire qui contient le répertorie Assets. Pour l'exécutable, c'est différent. La compilation du projet crée un .exe et un dossier nommé nom_du_exe_data. Par exemple, si mon .exe se nomme screenshot.exe, le répertoire sera screenshot_data. Ce dossier est le répertoire de base et c'est l'endroit où les captures d'images sont enregistrées. La fonction ne fait rien si déclencher à partir du lecteur Web.

vendredi 13 avril 2012

Comment ajouter un script n'importe où dans le menu Component d'Unity?

Par défaut, Unity ajoute les scripts dans le menu Component->Scripts. Ce sous-menu se remplit rapidement avec l'ajout de scripts et devient difficile à utiliser. Un peu de classification serait le bienvenu. La solution est de créer ses propres sous-menus dans le menu Component. Pour ce faire, l'attribut AddComponentMenu est ajouté avant la déclaration de la classe avec comme argument une chaîne de caractère contenant le nom du sous-menu suivi du nom du script:
[AddComponentMenu("SousMenuName/SousSousMenuName/NomDuScript")]
Reprenons le script RandomObjectsCreator.cs utilisé pour instancier des prefabs lorsque la touche "Espace" est pressée. Je veux que ce script apparaisse dans le menu Component->Mentalogicus->Creator. J'ajoute l'attribut AddComponentMenu de la manière suivante:
using UnityEngine;
using System.Collections;

[AddComponentMenu("Mentalogicus/Creator/RandomObjectsCreator")]
public class RandomObjectsCreator : MonoBehaviour 
{
 public Transform _prefab;
 public float _radius = 10;
 
 // Update is called once per frame
 void Update () 
 {
  if ( Input.GetKey("space") )
  {
   //Create a random position.
   //The insideUnitSphere return a random 
   //position inside a sphere of radius 1.
   Vector3 rndPos = Random.insideUnitSphere * _radius;
   
   //Create a random rotation.
   Quaternion rndRotation = Random.rotation;
   
   //Instantiate a new object at a random 
   //position with a random rotation.
   Transform newGameObj = Instantiate( _prefab, 
    rndPos, rndRotation) as Transform; 
  }
 }
}

RandomObjectsCreator.cs by Mentalogicus is licensed under a Creative Commons Attribution 3.0 Unported License.

Unity compile le script et le menu apparaît à l'endroit désiré!

jeudi 12 avril 2012

Sierpinski Cake

J'ai créé un gâteau de Sierpinski, qui est une fractale, dans Unity 3D. Une fois terminé et vue le résultat de face: je me suis demandé à quoi le gâteau de Sierpinski ressemble vue de l'intérieur. Pour ce faire, j'ai ajouté un petit script pour bouger la caméra à l'aide du clavier.
-->

Contrôle:

  • Flèche droite ou a: tourne vers la droite.
  • Flèche gauche ou d: tourne vers la gauche.
  • Flèche haut ou w: tourne vers le haut.
  • Flèche bas ou s: tourne vers le bas.
  • Barre espace: Accélération.
  • r: Repositionne la caméra à sa position initiale.

mardi 10 avril 2012

Comment faire une caméra orbitale en Unity?

Aujourd’hui, nous allons apprendre à faire une caméra orbitale en Unity. Une caméra orbitale est une caméra qui orbite un objet choisi comme cible. La caméra est tournée au moyen de la souris en appuyant sur le bouton gauche. Les mouvements de la souris sont transformés en rotations de la caméra. La caméra tourne en fixant constamment la cible choisie. De plus, je veux que la caméra zoom et dé zoom à volonté. Comme le dicton dit: une image vaut mille mots et un vidéo vaut au moins 24 images par secondes (pour 24 000 mots/s!!!). Voici le résultat final de ce que je veux implémenter:
Unity Web Player | WebPlayer -->
Principe de bases Lorsque le bouton droit de la souris est pressé, je convertis le mouvement du curseur en degrés selon les coordonnées x et y. J’utilise ces angles pour indiquer la rotation de la caméra. La rotation de la caméra autour du château implique deux mouvements: la rotation de la caméra sur elle-même et son déplacement dans l’espace.


Rotation de la caméra sur elle-même
Commençons par réglé le cas de la rotation de la caméra sur elle-même. Bougeons la caméra d’un angle a:

Sur le diagramme, la caméra du bas est la caméra dans sa position initiale. La caméra du haut est la caméra qui a tourné d’un angle a. La caméra ne pointe plus sur la cible. Pour corriger, la caméra doit être bougé d’un angle b. Les angles a et b sont alternes-internes; par conséquent, a=b. Vive la géométrie!

Unity utilise les quaternions pour représenter les rotations. Les quaternions sont des nombres hyper complexes (c’est-à-dire une extension des nombres complexes). Pour ceux intéresser à approfondir leur connaissance en math, je recommande chaudement Khan Academy. Il n’est pas essentiel de connaître les quaternions pour les utiliser. Je le mentionne pour que vous pensiez de convertir vos angles en quaternion. Les rotations en degrés sont converties en quaternion comme suit (aide Unity pour Quaternion.Euler):
 
Quaternion rotation = Quaternion.Euler( a,b,0 );
où a et b sont les angles de rotation par rapport à l’axe des x et y respectivement. L’axe des x est l’horizontale, l’axe y la verticale et l’axe z est la profondeur. Pourquoi le nom Euler et non pas Angle comme nom de fonction? Il y a une fonction Angle dans Unity. Elle retourne l’angle minimal entre deux rotations. Ici, il faut entrer 3 angles. C’est Leonhard Euler qui a introduit l’utilisation des 3 angles pour décrire l’orientation d’un corps solide. Le nom est resté. La caméra est tournée en modifiant la propriété rotation du composant transform:
 
transform.rotation = rotation;
Deux commandes, et la caméra est tournée!

Déplacement de la caméra
La caméra est à une distance d la cible et doit maintenir cette distance lors de la rotation. La caméra tourne comme attacher à une corde fixée à la cible.

La position de la caméra est égale à la somme des vecteurs \( \vec{p} \) et \( \vec{r} \). Le vecteur \( \vec{p} \) est connu, c’est la position de la cible. La longueur du vecteur \( \vec{r} \) est d, la distance de la caméra à la cible. Le changement de direction du vecteur \( \vec{r} \) est donné par la rotation de la caméra. Posons \( Fr \) comme une fonction de la rotation. La position de la caméra est: \( Fr(\vec{r}) + \vec{p} \). Ok, mais c’est quoi \( Fr \)? Vous vous rappelez les quaternions? Et bien, une de leurs fantastiques propriétés est que lorsqu’ils sont multipliés avec un vecteur, ils retournent un vecteur ayant subit la bonne rotation. Posons \(  Q \) comme étant le quaternion. La position de la caméra est fourni par l’équation: \[  Q \vec{r} + \vec{p} \] Une multiplication suivi d’une addition. Le code C# pour la position de la caméra est:
 
transform.position = rotation * r + p;
La combinaison du code pour la rotation de la caméra sur elle-même et le code pour modifier la position est:
 
void Rotate( float x, float y )
 {
  Quaternion rotation = Quaternion.Euler(y,x,0.0f);

  Vector3 position = 
   rotation * _distanceVector + _target.position;

  transform.rotation = rotation;
  transform.position = position;
 }

Les contrôles
La rotation de la caméra est activée en pressant le bouton gauche de la souris. La méthode GetButton de la classe statique Input  est ce qu’il nous faut. Cette fonction accepte une chaîne de caractère en entrée qui détermine le type de bouton et retourne un booléen qui indique si le bouton a été pressée. La chaîne de caractère pour le bouton gauche de la souris est  Fire1 dans Unity (pour plus de détails voir ici). Le code pour détecter que le bouton gauche a été pressée est:

void RotateControls()
 {
  if ( Input.GetButton("Fire1") )
  {
  
  }
 }
Maintenant, la position du curseur détermine l’angle de rotation. Pour déterminer la position du curseur, la méthode GetAxis de la classe Input est utilisée. Cette fonction retourne le mouvement de la souris suivant un axe en pixel. L’axe doit être spécifié. Pour la souris, les axes sont nommés Mouse X et Mouse Y. Le code est inséré à l’intérieur du If comme suit:
 
void RotateControls()
 {
  if ( Input.GetButton("Fire1") )
  {
   _x += Input.GetAxis("Mouse X") * _xSpeed;
   _y += -Input.GetAxis("Mouse Y") * _ySpeed;

   this.Rotate(_x,_y);
  }
 }
L’appel à la fonction Rotate, vu précédemment, complète le code pour la rotation. 

Zoom
Pour le zoom, j’utilise la roulette de la souris. Pour déterminer si la roulette a été tournée, la méthode GetAxis est appelée en utilisant la chaîne de caractères: Mouse ScrollWheel. Selon la direction de rotation, j’incrémente ou je décrémente la distance de la caméra à la cible. Ensuite, j’appelle la fonction Rotate pour repositionner la caméra au bon endroit. 

Le code complet est fourni ci-dessous.

OrbitCamera.cs

   
using UnityEngine;
using System.Collections;

/**
 * Change the camera into an orbital camera. An orbital is a camera
 * that can be rotated and that will automatically reorient itself to
 * always point to the target.
 * 
 * The orbit camera allow zooming and dezooming with the mouse wheel.
 * 
 * By clicking the mouse and dragging on the screen, the camera is moved. 
 * The angle of rotation  correspond to the distance the cursor travelled. 
 *  
 * The camera will keep the angular position when the button is pressed. To
 * rotate more, simply repress the mouse button et move the cursor.
 *
 * This script must be added on a camera object.
 *
 * @author Mentalogicus
 * @date 11-2011
 */
public class OrbitCamera : MonoBehaviour
{
 
 //The target of the camera. The camera will always point to this object.
 public Transform _target;
 
 //The default distance of the camera from the target.
 public float _distance = 20.0f;
 
 //Control the speed of zooming and dezooming.
 public float _zoomStep = 1.0f;
 
 //The speed of the camera. Control how fast the camera will rotate.
 public float _xSpeed = 1f;
 public float _ySpeed = 1f;
 
 //The position of the cursor on the screen. Used to rotate the camera.
 private float _x = 0.0f;
 private float _y = 0.0f;
 
 //Distance vector. 
 private Vector3 _distanceVector;
 
 /**
  * Move the camera to its initial position.
  */
 void Start ()
 {
  _distanceVector = new Vector3(0.0f,0.0f,-_distance);
  
  Vector2 angles = this.transform.localEulerAngles;
  _x = angles.x;
  _y = angles.y;
    
  this.Rotate(_x, _y);
  
 }

 /**
  * Rotate the camera or zoom depending on the input of the player.
  */
 void LateUpdate()
 {
  if ( _target )
  {
   this.RotateControls();
   this.Zoom();
  }
 }
 
 /**
  * Rotate the camera when the first button of the mouse is pressed.
  * 
  */
 void RotateControls()
 {
  if ( Input.GetButton("Fire1") )
  {
   _x += Input.GetAxis("Mouse X") * _xSpeed;
   _y += -Input.GetAxis("Mouse Y")* _ySpeed;
     
   this.Rotate(_x,_y);
  }
 
 }
 
 /**
  * Transform the cursor mouvement in rotation and in a new position
  * for the camera.
  */
 void Rotate( float x, float y )
 {
  //Transform angle in degree in quaternion form used by Unity for rotation.
  Quaternion rotation = Quaternion.Euler(y,x,0.0f);
  
  //The new position is the target position + the distance vector of the camera
  //rotated at the specified angle.
  Vector3 position = rotation * _distanceVector + _target.position;
    
  //Update the rotation and position of the camera.
  transform.rotation = rotation;
  transform.position = position;
 }
 
 /**
  * Zoom or dezoom depending on the input of the mouse wheel.
  */
 void Zoom()
 {
  if ( Input.GetAxis("Mouse ScrollWheel") < 0.0f )
  {
   this.ZoomOut();
  }
  else if ( Input.GetAxis("Mouse ScrollWheel") > 0.0f )
  {
   this.ZoomIn();
  }

 }
 
 /**
  * Reduce the distance from the camera to the target and
  * update the position of the camera (with the Rotate function).
  */
 void ZoomIn()
 {
  _distance -= _zoomStep;
  _distanceVector = new Vector3(0.0f,0.0f,-_distance);
  this.Rotate(_x,_y);
 }
 
 /**
  * Increase the distance from the camera to the target and
  * update the position of the camera (with the Rotate function).
  */
 void ZoomOut()
 {
  _distance += _zoomStep;
  _distanceVector = new Vector3(0.0f,0.0f,-_distance);
  this.Rotate(_x,_y);
 }
 
} //End class

OrbitCamera.cs by Mentalogicus is licensed under a Creative Commons Attribution 3.0 Unported License.

jeudi 17 novembre 2011

Comment sauver et ouvrir les préférences du joueur dans Unity?

Il existe deux méthodes dont je connais l'existence pour enregistrer des données dans Unity:
  • la classe PlayerPrefs de Unity;
  • le XML.
PlayerPrefs est idéal pour enregistrer une petite quantité de données. La taille maximale permise est de 1 MO. Le site d'Unity pour cette classe est:
http://unity3d.com/support/documentation/ScriptReference/PlayerPrefs.html .
Le XML est plus versatile que PlayerPrefs. Vous pouvez enregistrer la quantité d’informations que vous voulez avec le format que vous voulez. Je vous réfère à ce site si vous voulez plus d'information sur le XML avec Unity:
http://answers.unity3d.com/questions/8480/how-to-scrip-a-saveload-game-option.html .

Dans ce tutoriel, je vais me concentrer uniquement sur PlayerPrefs. Cette classe offre trois fonctions pour mémoriser des données: SetFloat, SetInt et SetString et trois fonctions pour lire: GetFloat, GetInt et GetString. Disons que dans notre jeu, nous voulons sauver le nom du joueur qui est stocké dans la variable playerName, le code C# sera:
 PlayerPrefs.SetString( "PlayerName", playerName );
Le premier paramètre est la clé qui va permettre de retrouver la valeur et le second, la variable que nous voulons enregistrer. PlayerPrefs est un dictionnaire. Nous lui fournissons une valeur et une clé. Pour lire le nom du joueur, le code est simplement:
 playerName  = PlayerPrefs.GetString( "PlayerName");
Il n'y a rien de plus à faire. Unity se charge automatiquement d'enregistrer dans un fichier les valeurs de PlayersPrefs lors de la fermeture du jeu, que ce soit sur Windows ou en mode Web. Par contre, il est possible de forcer l'enregistrement à l'aide de la fonction:
 PlayerPrefs.Save();
Passons à un exemple concret pour voir comment appliquer PlayerPrefs dans une application. Voici un simple cube avec un bouton qui change sa couleur aléatoirement:
Unity Web Player | WebPlayer
-->

Le bouton change la couleur du cube. Si vous rafraîchissez la fenêtre, le cube réapparaît avec la dernière couleur choisie. Voici le script utilisé:
 
using UnityEngine;
using System.Collections;

/**
 * Change the color of a cube and save the data using PlayerPrefs.
 *
 * @author Mentalogicus
 * @date 11-2011
 * 
 * Copyright (C) 2011, Mentalogicus
 * All rights reserved
 * 
 */
public class StatsMenu : MonoBehaviour 
{
 //The current color of the cube.
 Color _current = new Color(1,1,1,1);

 // Use this for initialization
 void Start () 
 { 
  //Load the saved color.
  Load();
  
  //Change the shader to transparent diffuse.
  this.renderer.material.shader = Shader.Find("Transparent/Diffuse");
  
  //Apply the current color to our cube.
  this.renderer.material.color = _current;
 }
 
 /**
  * Show a button to change the color and 4 labels to show
  * the color RGBA component.
  */
 void OnGUI ()
 {
  GUI.BeginGroup( new Rect(50,50, 200,150) );
  GUI.Box( new Rect(0,0, 200,150), "Change Color" );
   
  if ( GUI.Button( new Rect( 10,25,100, 20), "Change Color" ) )
  {
   ChangeColor();
   AutoSave();
  }
  
  ShowColor();
  
  GUI.EndGroup();
 }
 
 /**
  * Show the current color used on your cube.
  */
 void ShowColor()
 {
  GUI.Label( new Rect( 10, 50, 150,20), "Red: " + _current.r );
  GUI.Label( new Rect( 10, 75, 150,20), "Green: " + _current.g );
  GUI.Label( new Rect( 10, 100, 150,20), "Blue: " + _current.b );
  GUI.Label( new Rect( 10, 125, 150,20), "Alpha: " + _current.a );
 }
 
 /**
  * Change the color to a random one.
  */
 void ChangeColor()
 {
  _current = new Color( Random.value, Random.value, Random.value, Random.value );
   
  this.renderer.material.color = _current;
 }
 
 /**
  * Save the color with the PlayerPrefs class.
  */
 void AutoSave()
 {
  PlayerPrefs.SetFloat( "Color_Red", _current.r );
  PlayerPrefs.SetFloat( "Color_Green", _current.g);
  PlayerPrefs.SetFloat( "Color_Blue", _current.b );
  PlayerPrefs.SetFloat( "Color_Alpha", _current.a );
 }
 
 /**
  * Load the color with the PlayerPrefs class.
  */
 void Load()
 {
  if ( PlayerPrefs.HasKey("Color_Red") )
  {
   _current.r = PlayerPrefs.GetFloat( "Color_Red" );
  }
  
  if ( PlayerPrefs.HasKey("Color_Green") )
  {
   _current.g = PlayerPrefs.GetFloat( "Color_Green");
  }
  
  if ( PlayerPrefs.HasKey("Color_Blue") )
  {
   _current.b = PlayerPrefs.GetFloat( "Color_Blue" );
  }
  
  if ( PlayerPrefs.HasKey("Color_Alpha") )
  {
   _current.a = PlayerPrefs.GetFloat( "Color_Alpha" );
  }
 }
 
}

Ce script est appliqué sur le cube. La classe PlayerPrefs est limitée dans ces capacités. Heureusement, il existe une extension nommée PlayerPrefsX qui étend les capacités de PlayerPrefs. Ce script est à l'adresse suivante:
http://www.unifycommunity.com/wiki/index.php?title=ArrayPrefs#C.23_-_PlayerPrefsX.cs .

Bonne programmation!

lundi 14 novembre 2011

Polyhedron Shower

Après avoir créé le code pour l’instanciation d'un cube, je n'ai pas pu m'arrêter et j'ai continué à ajouter du code. Voici le résultat:
-->

  • RandomObjectCreator.cs: crée les polygones à partir d'un tableau de Transform, les places de manières aléatoires et leurs donnent une vitesse et une rotation aléatoire.
  • RandomColorMaterial.cs: change la couleur et la transparence du matériel. Les belles couleurs viennent de se simple script!
  • Timer.cs: C'est une classe utilitaire qui indique si le délai est écoulé en appelant la fonction trigger.
  • PointLightAtCenter.cs: ce script ajoute une lampe au centre de mes polyèdres. Ce sont ces petites lampes qui ajoutent l'ambiance et font ressortir les couleurs.
  • BounceBack.cs: ce script inverse la vitesse des polyèdres lorsqu'il dépasse une certaine distance du centre.
RandomObjectCreator.cs

using UnityEngine;
using System.Collections;

/**
 * Choose randomly a polyhedron and instantiate it at a random position with
 * a random rotation. After that, add a RigidBody and assign a random force and
 * a random torque to move and rotate the polyhedron.
 *
 * @author Mentalogicus
 * @date 11-2011
 * 
 * Copyright (C) 2011, Mentalogicus
 * All rights reserved
 * 
 */
public class RandomObjectCreator : MonoBehaviour 
{
 
 
 public Transform[] _prefab;
 public float _force = 10;
 public float _radius = 10;
 
 // Use this for initialization
 void Start () 
 {
  
 }
 
 // Update is called once per frame
 void Update () 
 {
  
  if ( Input.GetKey("space") )
  {
   //Create a random position.
   //The insideUnitSphere return a random position inside a sphere of radius 1.
   Vector3 rndPos = Random.insideUnitSphere * 10;
   
   //Create a random rotation.
   Quaternion rndRotation = Random.rotation;
   
   //Choose randomly between the array of object
   int choice = (int) Mathf.Floor(Random.Range( 0.0f, _prefab.Length -.0000001f ) );
   
   //Instantiate a new object at a random position with a random rotation.
   Transform newGameObj = Instantiate( _prefab[choice], rndPos, rndRotation) as Transform; 
   
   //Rename the game object.
   newGameObj.name = "Allo";
   
   //Add a rigid body to the object.
   newGameObj.gameObject.AddComponent();
   
   //Remove the gravity.
   newGameObj.gameObject.rigidbody.useGravity = false;
   
   //Change the mass of the object to 1.
   newGameObj.gameObject.rigidbody.mass = 1.0f;
   
   //Add a random impulse to the rigidbody.
   newGameObj.gameObject.rigidbody.AddForce(new Vector3( Random.Range(-_force,_force), 
                                                         Random.Range(-_force,_force), 
                                                         Random.Range(-_force,_force) ), 
                                                 ForceMode.Impulse);
   
   //We add a random torque to the rigidbody to make him rotate!!!
   newGameObj.gameObject.rigidbody.AddTorque(new Vector3( Random.Range(-_force,_force), 
                                                         Random.Range(-_force,_force), 
                                                         Random.Range(-_force,_force) ), 
                                                 ForceMode.Impulse);
  }
  else if ( Input.GetKey("q") )
  {
   Application.Quit();
  }
  else if ( Input.GetKeyDown("return") )
  {
   GameObject[] objs = GameObject.FindGameObjectsWithTag ("Block");
   foreach ( GameObject obj in objs)
   {
    Destroy(obj);
   }
  }
 }

}

Licence Creative Commons
RandomObjectCreator.cs de Mentalogicus est mis à disposition selon les termes de la licence Creative Commons Paternité - Pas de Modification 3.0 non transposé.  

RandomColorMaterial.cs

using UnityEngine;
using System.Collections;

/**
 * Randomly assign a color and an alpha to the material of the object.
 * 
 *
 * @author Mentalogicus
 * @date 11-2011
 * 
 * Copyright (C) 2011, Mentalogicus
 * All rights reserved
 * 
 */
public class RandomColorMaterial : MonoBehaviour
{

 
 // Use this for initialization
 void Start ()
 {
  
  Shader shader1 = Shader.Find("Transparent/Diffuse");
  
  this.renderer.material.shader = shader1;
  
  //Set the main color of the material
  this.renderer.material.color = CreateRandomColor();
  
 }
 
 private Color CreateRandomColor()
 {
  float r = Random.value;
  float g = Random.value;
  float b = Random.value;
  float a = Random.Range(.4f,1f);
  
  return new Color( r, g, b, a );
 }
}
Licence Creative Commons
RandomColorMaterial.cs de Mentalogicus est mis à disposition selon les termes de la licence Creative Commons Paternité - Pas de Modification 3.0 non transposé.

Timer.cs

using System;
using UnityEngine;

/**
 * Timer with a delay. When the delay is over by, the trigger properties will
 * return true.
 *
 * @author Mentalogicus
 * @date 11-2011
 * 
 * Copyright (C) 2011, Mentalogicus
 * All rights reserved
 * 
 */
namespace Utils
{
 public class Timer
 {
  private float _timer;
  private float _delay;
  
  
  public void Start(  )
  {
   this.Reset();
  }
  
  public void Start( float delay )
  {
   _delay = delay;
   this.Reset();
  }
  
  public float time
  {
   set { _timer = value; } 
  }
  
  public float delay
  {
   get { return _delay; }
   set { _delay = value; }
  }
  
  public void Reset()
  {
   _timer = Time.time; 
  }
  
  public bool overBy
  {
   get { return (Time.time - _timer) >= _delay; }
  }
  
  public bool underBy
  {
   get { return (Time.time - _timer) < _delay; }
  }
  
  /**
   * When called, this properties return if the timer is overBy or underBy and
   * reset the timer.
   */
  public bool trigger
  {
   get
   {
    if ( overBy )
    {
     Reset();
     return true; 
    }
    else
    {
     return false;
    }
   }
  }
  
 } //End class
} //End namespace


Licence Creative Commons
Timer.cs de Mentalogicus est mis à disposition selon les termes de la licence Creative Commons Paternité - Pas de Modification 3.0 non transposé.
 
PointLightAtCenter.cs

using UnityEngine;
using System.Collections;

/**
 * Add a point like in the center of an object.
 *
 * @author Mentalogicus
 * @date 11-2011
 * 
 * Copyright (C) 2011, Mentalogicus
 * All rights reserved
 * 
 */
public class PointLightAtCenter : MonoBehaviour
{
 public float _range = 5f;
 
 // Use this for initialization
 void Start ()
 {
  //Add a point light in the center of the object.
  Light spot = this.gameObject.AddComponent();
  spot.type = LightType.Point;
  spot.range = _range;
  spot.intensity = 2;
 }

}


Licence Creative Commons
PointLightAtCenter.cs de Mentalogicus est mis à disposition selon les termes de la licence Creative Commons Paternité - Pas de Modification 3.0 non transposé.
 
BounceBack.cs
 
using UnityEngine;
using System.Collections;
using Utils;

/**
 * Inverse the velocity of an object that is at a distance greater
 * than the specified radius.
 *
 * @author Mentalogicus
 * @date 11-2011
 * 
 * Copyright (C) 2011, Mentalogicus
 * All rights reserved
 * 
 */
public class BounceBack : MonoBehaviour 
{
 
 public float _radius = 50;
 
 private Timer _timeToReturnBack = new Timer( );
 
 void Start()
 {
  _timeToReturnBack.Start( .2f );
 }
 
 // Update is called once per frame
 void Update () 
 {
  if ( this.transform.position.x * this.transform.position.x +
       this.transform.position.y * this.transform.position.y +
       this.transform.position.z * this.transform.position.z > _radius * _radius &&
       _timeToReturnBack.trigger )
  {
   this.rigidbody.velocity = -this.rigidbody.velocity;
  }
 }
}

Licence Creative Commons
BounceBack.cs de Mentalogicus est mis à disposition selon les termes de la licence Creative Commons Paternité - Pas de Modification 3.0 non transposé.

Comment instancier des objets dans Unity 3D?

Unity 3D est un engin de jeux complets avec un éditeur. Si Unity vous est totalement inconnu, je vous recommande de visiter leur site: http://unity3d.com/. Ce tutoriel assume que vous avez déjà un peu joué avec Unity 3D et que vous êtes familier avec l'interface. Les scripts sont en C#. Le but du tutoriel est d'apprendre à instancier des objets durant l'exécution du jeu et non dans l'éditeur.
L'éditeur d'Unity.
La première étape consiste à créer un nouveau projet dans Unity. Je l'ai appelé "RandomObjectsCreator". À la création du projet, Unity crée les répertoires Assets, Library et Temp. Le répertoire Assets sert de librairie pour les objets que nous ajoutons aux jeux. C'est le seul des trois répertoires que nous allons utiliser.

L'instanciation d'objet dans Unity se fait à l'aide de prefabs. Prefab est la version raccourcie de Préfabriquée. Le prefab est l'équivalent d'un plan de construction. L'objet a telle forme, telle couleur et va réagir de telle et telle façon dans telles et telles conditions. Une fois le prefab créé, il est possible de créer des milliers de versions du même objet à l'intérieur du jeu et chaque objet aura la forme et le comportement spécifié dans le prefab.

Pour créer un prefab, aller dans l'onglet Projet->click droit->Create->Prefab. Renommer ce prefab "Cube".
Menu pour la création d'un prefab.
L'icône du prefab est une boîte blanche vide. Cette icône indique que le prefab est vide. Pour le remplir, nous allons ajouter un cube à la scène. Dans le menu supérieur: GameObject->Create Other->Cube.
Création d'un cube dans Unity.
Dans le menu "Hierarchy", sélectionnez Cube et glissez le sur le prefab Cube. L'icône du prefab devient une boîte bleue, indiquant que le prefab contient un objet. Vous pouvez maintenant effacer le Cube de la scène. Si vous glissez le prefab Cube sur la scène, un cube apparaît! Magika!
Ajout d'un objet au prefab.
Il est temps de créer notre script. Dans le tab "Project", click droit->Create->C# Script. Nommons-le: "RandomObjectsCreator". En double cliquant sur le script, l'éditeur par défaut de Unity ouvre le script. Dans mon cas, c'est MonoDevelop qui est ouvert. Unity a créé automatiquement une classe nommée RandomObjectsCreator avec la fonction Start et la function Update:

using UnityEngine;
using System.Collections;

public class RandomObjectsCreator : MonoBehaviour 
{

 // Use this for initialization
 void Start () 
 {
 
 }
 
 // Update is called once per frame
 void Update () 
 {
 
 }
}

La classe hérite de la classe générique MonoBehavior. Les scripts attachés sur des objets dans la scène doivent obligatoirement hériter de MonoBehavior pour fonctionner. La classe MonoBehavior permet d'accéder aux propriétés et aux composants de l'objet auquel est attaché le script.

Le code pour instancier un prefab est:
Instantiate( _prefab, position, rotation);
La fonction Instantiate va créer un clone du prefab contenu dans la variable _prefab, l'afficher dans la scène à la position "position" avec la rotation "rotation" et va retourner une référence de l'objet avec le type Object. Le type Object est le type de base en C#. Dans le précédent code, nous n'avons pas mis de variable pour récupérer la référence à l'objet. Pour ce faire, le code sera:
Transform newGameObj = 
     Instantiate( prefab, position, rotation) as Transform; 
Transform est un type générique d'Unity qui permet d'accéder à toutes les propriétés de l'objet de la scène. Le as Transform est un casting. Instantiate retourne une référence de type Object. Or, nous voulons une référence de type Transform. Nous indiquons la transformation de la référence de type Object en une référence de type Transform avec le as Transform. Il est à remarquer que cette notation est identique à la suivante:
Transform newGameObj = 
     (Transform)Instantiate( _prefab, position, rotation); 
Personnellement, je préfère le as, car c'est plus proche de l'anglais que l'opérateur de casting avec parenthèse.

Pour faire apparaître un cube, le joueur doit peser sur la touche espace. Le code est entré dans la fonction Update qui est appelée chaque fois que l'écran est rafraichi. La commande nécessaire est:
Input.GetKey("space");
Cette fonction retourne vrai si la touche espace est enfoncée et faux autrement. La position de notre cube sera choisi aléatoirement dans une sphère d'un rayon déterminé par la variable _radius:
Vector3 rndPos = Random.insideUnitSphere * _radius;
et avec une rotation aléatoire:
Quaternion rndRotation = Random.rotation;
Le script complet est le suivant:
using UnityEngine;
using System.Collections;

public class RandomObjectsCreator : MonoBehaviour 
{
 public Transform _prefab;
 public float _radius = 10;
 
 // Update is called once per frame
 void Update () 
 {
  if ( Input.GetKey("space") )
  {
   //Create a random position.
   //The insideUnitSphere return a random position inside a sphere of radius 1.
   Vector3 rndPos = Random.insideUnitSphere * _radius;
   
   //Create a random rotation.
   Quaternion rndRotation = Random.rotation;
   
   //Instantiate a new object at a random position with a random rotation.
   Transform newGameObj = Instantiate( _prefab, rndPos, rndRotation) as Transform; 
  }
 }
}

Ce script doit être attaché à un GameObject dans la scène pour fonctionner. Nous allons créer un GameObject vide. Dans le menu GameObject->Create Empty.Un objet nommé GameObject est crée. Renommons le ObjectsCreator. Sélectionner ObjectsCreator et glisser le script RandomObjectsCreator dans l'onglet Inspector. Le script contient deux variables prefab, radius. Glisser le prefab Cube sur le none à droite de la variable prefab. Le nom Cube apparaît avec une icône de manipulateur 3D.
Ajout d'un script et assignation de la variable prefab aux prefab Cube.
Appuyer sur Play et ensuite sur la touche "espace". Des cubes vont apparaître aléatoirement à l'écran. Je vous recommande d'ajouter une lampe directionnelle dans la scène pour embellir votre rendu.
-->

Comment insérer un jeu Unity dans Blogger?

Lorsque je pose cette question sur Internet, je me retrouve sur des sites qui proposent des Gadgets à ajouter à Blogger. J'ai essayé plein de combinaisons et rien ne marche. Au final, la solution est simple. Lorsque vous compilez votre jeu sous Unity pour le Web, Unity crée un fichier .unity3d et un fichier .html. Le fichier .html contient ceci:
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <title>Unity Web Player | WebPlayer</title>
  <script type="text/javascript" src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject.js"></script>
  <script type="text/javascript">
  <!--
  function GetUnity() {
   if (typeof unityObject != "undefined") {
    return unityObject.getObjectById("unityPlayer");
   }
   return null;
  }
  if (typeof unityObject != "undefined") {
   unityObject.embedUnity("unityPlayer", "WebPlayer.unity3d", 680, 550);
   
  }
  -->
  </script>
  <style type="text/css">
  <!--
  body {
   font-family: Helvetica, Verdana, Arial, sans-serif;
   background-color: white;
   color: black;
   text-align: center;
  }
  a:link, a:visited {
   color: #000;
  }
  a:active, a:hover {
   color: #666;
  }
  p.header {
   font-size: small;
  }
  p.header span {
   font-weight: bold;
  }
  p.footer {
   font-size: x-small;
  }
  div.content {
   margin: auto;
   width: 550px;
  }
  div.missing {
   margin: auto;
   position: relative;
   top: 50%;
   width: 193px;
  }
  div.missing a {
   height: 63px;
   position: relative;
   top: -31px;
  }
  div.missing img {
   border-width: 0px;
  }
  div#unityPlayer {
   cursor: default;
   height: 550px;
   width: 550px;
  }
  -->
  </style>
 </head>
 <body>
  <p class="header"><span>Unity Web Player | </span>WebPlayer</p>
  <div class="content">
   <div id="unityPlayer">
    <div class="missing">
     <a href="http://unity3d.com/webplayer/" title="Unity Web Player. Install now!">
      <img alt="Unity Web Player. Install now!" src="http://webplayer.unity3d.com/installation/getunity.png" width="193" height="63" />
     </a>
    </div>
   </div>
  </div>
  <p class="footer">« created with <a href="http://unity3d.com/unity/" title="Go to unity3d.com">Unity</a> »</p>
 </body>
</html> 
Effacer les styles css, ils vont bousiller la mise en page de votre page. Dans Blogger, ouvrer un nouveau message et aller dans Modifier le code HTML. Coller ce code HTML (sans les styles). Une icône de Unity va apparaître, mais pas le jeu. Dans le code HTML, à l'endroit où est écrit:
if (typeof unityObject != "undefined") {
     unityObject.embedUnity("unityPlayer", "WebPlayer.unity3d", 680, 550);
}
remplacez "WebPlayer.unity3d" avec le lien Web où est hébergé votre jeu. Bon, si vous êtes comme moi, vous n'avez pas vraiment d'hébergeur, alors quoi faire? J'utilise Google Sites pour ce faire. Je me suis créé une page Web nommée FractalGameLab. Je vais dans Google Sites, dans les outils de gestion et j'importe le .unity3d. Je copie ensuite le lien pour télécharger la ressource et je remplace WebPlayer.unity3d par ce lien. Voilà! Le tour est joué. Pour prouver que ça marche, voici une démo de jeu que j'ai fait avec le livre de "Développez des jeux 3D avec Unity" par Will Goldstone.
Unity Web Player | WebPlayer
-->
Unity Web Player | WebPlayer

mardi 9 août 2011

Quel logiciel utiliser pour faire un jeu sur le Web pour 0$?

Bon, il y a plusieurs façons de le faire. Je vous présente ici les alternatives que je connais qui ne requièrent pas l'achat de logiciel. La première alternative consiste à développer en ActionScript 3 avec FlashDevelop et le Flex SDK Open Source d'Adobe (voir billet sur Comment programmer en Flash pour 0$). La seconde alternative est d'utiliser la version gratuite d'Unity. Unity est un engin de jeux 3D complet avec un éditeur avancé qui permet d'essayer le jeu en cours de développement. Il y a deux types de scripts pour créer la logique du jeu: le UnityScript qui ressemble au Javascript et le C#, qui est un clone de Java par Microsoft. Pour être plus précis, il utilise Mono, qui est la version libre du C#. La syntaxe du langage reste la même. Voici un lien vers un jeu que j'ai fait à l'aide du livre Développez des jeux 3D avec Unity par Will Goldstone:
Unity Web Player | WebPlayer
-->
Si vous ne voyez rien, allez télécharger le Unity Web Player.
Bon, un jeu n'est pas que du code. Il faut ajouter des graphiques et du son. Pour les graphiques, il y a plusieurs alternatives. La plus simple est d'utiliser le logiciel Open Source GIMP. GIMP est un logiciel de modification d'images comme Photoshop qui fonctionne sous Windows et Linux. Et bien, presque comme Photoshop. Il y a une différence majeure: les boîtes à outils sont flottantes. Si vous voulez une expérience plus Photoshop, je vous recommande GIMPshop. C'est toujours GIMP, mais avec une disposition plus classique des outils. Personnellement, je préfère le GIMP classique.
10 Capture d'image
20 Éditer l'image dans GIMP
Goto 10

Un programme que j'ai découvert et que j'aime particulièrement est Inkscape. C'est un logiciel de dessin vectoriel Open Source qui fonctionne sous Windows, Linux et Mac. D'ailleurs, mon logo a été créé avec ce logiciel.
Fenêtre principale d'Inkscape.
L'avantage du dessin vectoriel est de permettre de redimensionner son image sans perdre de qualité. GIMP est un logiciel de dessin dit matriciel. Le logiciel joue avec les pixels de l'image. Une fois l'image crée, un redimensionnement va réduire la qualité de l'image. Ce problème ne survient pas avec le vectoriel.

Pour les modèles 3D et les animations, il y a le puissant Blender. Ce logiciel est probablement un des joyaux du monde Open Source. Encore une fois, il fonctionne sous Windows et Linux. Avec Blender, il est possible de créer n'importe quel objet 3D, de l'éclairer, de le texturer et de l'animer.
L'interface de Blender est sobre et sans prétention.
Le focus est sur le modèle à créer.
Voici un film fait avec Blender:
Blender a été conçu pour les professionnels de la 3D et est très difficile à apprendre. Personnellement, la première fois que j'ai essayé Blender, je n'ai réussi à rien faire. Je n'arrivais même pas à tourner le cube, ni à zoomer et à dézoomer. Les fonctions de Blender sont activées par des raccourcis clavier. L'apprentissage de ces raccourcis est essentiel pour naviguer dans Blender. La philosophie du logiciel est: une main sur le clavier, l'autre sur la souris, ce qui assure une grande efficacité pour les initiés. Je vous recommande de lire un livre sur Blender ou de faire les tutoriels de base avant d'essayer de modéliser. Vous allez sauver beaucoup de temps et de frustration.

Finalement, pour le son, je recommande le logiciel Open Source Audacity. Ce logiciel fonctionne sous Windows, Linux et Max. Audacity est un éditeur et enregistreur de son audio.
(Source: http://audacity.sourceforge.net)
Je vous souhaite bien du plaisir dans la création de vos jeux.