Unity2D – Apprentissage part 2 – Génération procédurale d’un terrain plat en 2D!

Après avoir tester le très bon Rimworld, je prends le parti de partir vers du 2D. Pourquoi? Plusieurs raisons:

  • Developper un jeu en 3D, même un prototype, demande beaucoup d’investissement sur la recherche et l’intégration de model 3d qui ne seront de toutes façons pas visuellement compatibles à la fin sans une aide exterieur.
  • La gestion de la caméra en 3D est un peu plus complexe
  • Le rendu est vraiment limitée (et nuit au gameplay) si on ne fait pas un minimum d’effort – ce que je ne suis pas prêt à faire par manque de temps –

Mon but étant d’aller assez vite vers de la génération procédurale poussée, ainsi que la mise en place de behavior (que de belles choses en perspectives!) je mise donc sur une base en 2D. Je me suis servi à nouveau de la methode de création de Mesh présenté par Quill18:

Je vous donne plus bas le code tout prêt à utiliser, mais avant ça une petite présentation / vidéo du début de projet en 2D:

Je me suis basé sur le tutorial Unity3D du roguelike afin d’avoir des bonnes pratiques pour structurer le jeu (et récupérer le visuel du personnage dans un tout premier temps)

J’ai changé le mode de caméra (suit le player) ainsi que le mode de déplacement (à la souris) et non plus case par case au clavier. Ca donne ca:

Code pour générer le terrain (sans les textures):

public void BuildMesh(GameObject instance)
{
int numTiles = sizeX * sizeY;
int numTris = numTiles * 2;
 
int vsize_x = sizeX + 1;
int vsize_y = sizeY + 1;
int numVerts = vsize_x * vsize_y;
 
Vector3[] vertices = new Vector3[numVerts];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
 
int[] triangles = new int[numTris * 3];
 
int x, z;
for (z = 0; z < vsize_y; z++)
{
for (x = 0; x < vsize_x; x++)
{
vertices[z * vsize_x + x] = new Vector3(x * tileSize, 0, -z * tileSize);
normals[z * vsize_x + x] = Vector3.up;
uv[z * vsize_x + x] = new Vector2((float)x / sizeX, 1f - (float)z / sizeY);
}
}
 
for (z = 0; z < sizeY; z++)
{
for (x = 0; x < sizeX; x++)
{
int squareIndex = z * sizeX + x;
int triOffset = squareIndex * 6;
triangles[triOffset + 0] = z * vsize_x + x + 0;
triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0;
triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1;
 
triangles[triOffset + 3] = z * vsize_x + x + 0;
triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1;
triangles[triOffset + 4] = z * vsize_x + x + 1;
}
}
 
// Create a new Mesh and populate with the data
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
 
MeshFilter meshFilter = instance.GetComponent<MeshFilter>();
meshFilter.mesh = mesh;
}

Une vidéo très interessante à ce propos (avec des infos supplémentaires comme le debugging de mesh, ou encore des conseils d’optimisation):

Unity3D – Apprentissage part 1 – Génération procédurale d’un terrain plat!

J’ai commencé à jouer avec Unity3D ces dernières semaines.
Mon projet d’apprentissage étant une génération de map procédurale (quelle originalité!) avec en tête le fait de mettre de l’IA ensuite.

Une petite vidéo de l’état actuel:

Avec une map plus grande:

Je me sers de l’algorithme de bruit de perlin pour générer le coté random.
Je veux volontairement faire cela avec des tiles (et non pas utiliser le Terrain de Unity hyper simple à utiliser, mais hyper complexe dans les data générées)
Mon but étant d’avoir quelques niveaux d’élevation, bien distints, sur la map.

Ma première étape a été la génération du terrain plat, et la mise en place des textures. Ma premiere idée a été de mettre en place des blocs à la Minecraft mais j’ai lu que le nombre de bloc posait problème niveau performance, et puisque je ne souhaite pas « casser » le terrain dynamiquemenent, une seule mesh est préférable (quoique pas trivial à mettre en place, merci les tutoriaux youtube)

Mon deuxième (et actuel problème) est lié à la gestion des colliders. La vidéo ci dessus donne l’impression que tout fonctionne mais ca n’est en réalité pas parfait

Restaurer le focus en WPF

Si vous désirez sauver et restaurer le focus en WPF (en interagissant avec un third party par exemple) vous pouvez utiliser:

public void SetSelectedItem(object SelectedItem)
{
// Sauvegarde le focus actuel
IInputElement focusedElement = Keyboard.FocusedElement;
 
// Here, do the third party interaction, like in mvvm:
Items.Where(p=>p.Id == SelectedItem.Id).IsSelected = true; // changes the focus
 
// Restaure le focus sauvegardé
if (focusedElement != null && Keyboard.FocusedElement != focusedElement)
        Keyboard.Focus(focusedElement);
}

Problème [RESOLU] avec GTX770-DC2OC-2GD5

216273

Jai eu un problème assez pénible après l’installation de mon nouvel ordinateur:

[PROBLEME]

Mon ordinateur crashait aléatoirement. Mon écran devenait noir (tout en restant allumé, diode active) et je devais forcément reboot la machine pour débloquer la situation.
Ca se produisait souvent:

  • Entre 2 maps de BF4. Durant le chargement de la nouvelle map.
  • Après avoir joué à BF4, quand je tentais d’ouvrir un browser.
  • Après une phase de minage de cryptocoins (j’utilise CudaMiner) Encore une fois, pas durant le processus, mais juste après

Mes dump files mentionnaient:

System:

SYSTEM_SERVICE_EXCEPTION nvlddmkm.sys

[…]

Probably caused by : nvlddmkm.sys ( nvlddmkm+39be1c )

Application: the thread tried to read from the virtual address for which it does not have the appropriate access

J’ai essayé de supprimer/réinstaller plusieurs drivers différents de NVIDIA sans succès

[SOLUTION]
Allez sur le site suivant et installez le bios update (sous Drivers & Tools)
VBIOS update for GTX770-DC2OC-2GD5 & GTX770-DC2-2GD5
Improve stability

https://www.asus.com/Graphics_Cards/GTX770DC2OC2GD5/#support

Ca a marché pour moi!