Un billet bien différent de d'habitude aujourd'hui mais je trouve que les tutos sur ce sujet sont beaucoup trop rares. Je dois expliquer à un ami comment faire un jeu jouable en ligne avec Unity3D donc tant qu'à faire, autant mettre ça à disposition de tout le monde.
Je précise que je suis loiiiiiiiin d'être un pro et que ce tuto n'est en rien une méthode optimale ou complète pour mettre son jeu en réseau, c'est plus à prendre comme une base pour se lancer. J'espère ne pas faire trop d'erreurs et ne pas vous donner de mauvais conseils, les commentaires sont là pour ça sinon ;)
Je pars du principe que vous savez déjà utiliser Unity et que vous êtes plus ou moins à l'aise avec ses concepts de base telles que les Collision Box, les GameObjects, etc. Je code en javascript, normalement vous ne devriez pas avoir de mal à passer le code en C# si besoin est, désolé de ne pas le fournir :S
Ce petit guide sera en plusieurs parties (probablement 3) puisque il prend pas mal de temps à écrire.
Trève de blabla, c'est parti....
Mise en place des prérequis
Pas vraiment de réseau en soi dans cette première partie mais il faut bien un début à tout
On va commencer par créer une scène de base pour nos tests.
Vous pouvez aussi commencer directement dans un projet existant si le coeur vous en dit mais si c'est la première fois que vous vous essayez au jeu en réseau je vous conseille de démarrer un nouveau projet. Contrairement à ce qu'il m'est arrivé de lire à gauche et à droite, le réseau n'est pas du tout un simple élément qu'on ajoute sur un jeu fini (pas en tant que débutant en tout cas^^). Ça demande toute une méthodologie et une manière de penser le rapport entre nos objets différente.
Vous êtes prêts? Bien
Joueur et terrain
- Créons d'abord un simple cube qu'on appellera "Player" (je code généralement en anglais puisque les noms de variables ne peuvent pas contenir d'accents).
- Ajoutez lui un RigidBody avec les options suivantes pour qu'il subisse la gravité sans rouler partout.
Vous l'avez deviné ce cube représentera notre joueur (son petit nom c'est Cuby), placez la caméra derrière lui et attachez là au cube afin qu'elle suive le joueur lors de ses déplacements.
- Créez un nouveau cube, nommez le "Gun" et attachez le à Cuby (votre cube-joueur donc).
- Positionnez et redimensionnez ce nouveau cube comme si c'était un bras de Cuby, ça représentera son arme.
- Supprimez le composant "Box Collider" de cette arme afin d'éviter que les munitions qu'on tirera plus tard ne "se cognent" contre l'arme au moment où elles sont tirées (on pourrait aussi leur dire d'ignorer les collisions avec cet objet en particulier si on a vraiment besoin d'une box sur l'arme mais je fais au plus simple).
- Ensuite on va créer un nouveau cube pour le terrain, on l'appellera "Terrain" parce que nous sommes des gens originaux. Je donne à mon terrain les dimensions 40x1x40. Je vous conseille de lui ajouter un material de couleur ou une texture pour qu'on voit clairement la scène. Ajoutez aussi une directional light afin d'éclairer le niveau.
Vous devriez obtenir quelque chose dans ce goût là.
Cliquez sur les images pour les voir en taille réelle
Bien, on a notre joueur et il est paré pour la guerre. il ne manque plus que...
Un peu d'action !
Il va falloir apprendre à Cuby à se déplacer s'il veut survivre sur le champs de bataille.
- Jusqu'ici il n'y a rien de propre au réseau donc contentez-vous d'attacher le script suivant à votre cube, il n'est pas très compliqué. Ce script s'appelle Cuby.js et contiendra quasiment tout le code gérant notre petit cube préféré (pour de plus gros projets, mieux vaut séparer le fonctionnement du perso en plusieurs scripts).
Cuby.js
var life : int = 3; //la vie de notre cube
private var vitesse : float = 0.05;
function Start () {
}
function Update ()
{
Deplacement();
}
function Deplacement()
{
if ( Input.GetKey(KeyCode.Z) || Input.GetKey(KeyCode.UpArrow) )
transform.Translate(Vector3.forward * vitesse);
else if ( Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) )
transform.Translate(Vector3.back * vitesse);
if ( Input.GetKey(KeyCode.Q) || Input.GetKey(KeyCode.LeftArrow) )
transform.Rotate(Vector3.left * 2);
else if ( Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow) )
transform.Rotate(Vector3.right * 2);
if ( Input.GetKeyDown(KeyCode.Space) ) //le saut
rigidbody.AddForce(Vector3.up * 350);
}
- Vérifiez que votre cube se déplace bien comme prévu (avec les touches fléchées ou ZSQD et espace pour sauter).
On va par contre déjà créer les balles qu'il tirera.
- Créez une nouvelle sphère et dimensionnez-là comme bon vous semble. Je donne une taille de 0.2 à la mienne. Je la nomme également "Bullet".
- Créez un nouveau dossier "Prefabs" dans votre projet et placez y votre balle (glissez-déposez de l'onglet Hierarchy vers Project). Une fois cela fait, vous pouvez supprimer la balle de la scène.
- Puisque chaque joueur devra instancier son propre Cuby, on va en faire un prefab, glissez-le à son tour dans le dossier Prefabs. Une fois cela fait supprimez le de votre scène.
Votre projet doit maintenant ressembler à ceci:
Sauvegardez si ce n'est pas déjà fait puis créez une nouvelle scène.
Il va nous falloir...
Un menu
Ça peut paraître gadget mais au début où je bossais sur Cold World, j'avais tout d'abord construit le premier level sans menu, on arrivais directement sur la map avec l'interface de connexion. L'ajout d'un menu a été un véritable enfer puisque plus rien ne marchait et que je ne comprenais alors rien de rien à la mise en réseau sous Unity. Autant s'éviter des complications plus tard et directement créer le menu principal du jeu.
Bref !
- Créez un nouveau script que nous appellerons "MainMenu". Attachez-le à la caméra normalement déjà présente dans la scène.
- Créez également un script nommé "StartNet". Ne touchez pas à StartNet pour l'instant.
- A l'intérieur de MainMenu, copiez ceci:
var networkMaster : GameObject; // Prefab
private var instantiatedMaster : GameObject; //Prefab instancié
private var scriptStartNet : StartNetwork;
private var serverIP : String = "127.0.0.1";
private var serverPort : int = 25000;
function OnGUI()
{
var menuSizeX : int = 460;
var menuSizeY : int = 115;
var menuPosX : float = 20;
var menuPosY : float = Screen.height/2 - menuSizeY/2;
var mainMenu = new Rect(menuPosX, menuPosY, menuSizeX, menuSizeY);
var sizeButtonX : int = 250;
var sizeButtonY : int = 30;
//Le menu de base
GUI.BeginGroup(mainMenu, "");
GUI.Box(Rect(0,0,menuSizeX, menuSizeY), "");
//La demande de champs d'ip pour rejoindre un serveur
serverIP = GUI.TextField(new Rect(sizeButtonX + 30, 60, 120, 30), serverIP, 40);
if ( GUI.Button(Rect(10, 20, sizeButtonX, sizeButtonY), "Créer serveur"))
{
//Création du serveur
instantiatedMaster = Instantiate(networkMaster, Vector3.zero, Quaternion.identity);
scriptStartNet = instantiatedMaster.GetComponent("StartNetwork");
scriptStartNet.server = false;
}
if ( GUI.Button(Rect(10, 60, sizeButtonX, sizeButtonY), "Rejoindre serveur"))
{
//Rejoindre serveur
instantiatedMaster = Instantiate(networkMaster, Vector3.zero, Quaternion.identity);
scriptStartNet = instantiatedMaster.GetComponent("StartNetwork");
scriptStartNet.server = false;
}
GUI.EndGroup();
}
Si vous lancez le script, vous devriez normalement voir ceci:
Ne paniquez pas s'il y a des erreurs et que rien ne se passe lorsque vous cliquez sur les boutons, c'est tout à fait normal à ce stade.
Bien. Je pense que tout est prêt ou presque. Dans la prochaine partie du guide, on va pouvoir s'attaquer à la partie réseau, oui oui, pour de vrai ! Ne vous en faites pas j'expliquerai rapidement les trucs propres au réseau du script que vous venez de copier.
A demain pour la suite ;)
PS: d'ici là j'essayerai de trouver un moyen d'afficher le code plus proprement sur le blog.