Meshes faits par les scripts
Un script fabrique un mesh avec new Mesh(), comme dans Unity, le remplit de sommets et d'indices, et le donne à un MeshFilter pour qu'on le voie et à un MeshCollider pour qu'on puisse le toucher. Un script peut aussi modifier un mesh de la scène. L'API est celle de Unity : SetVertices, SetNormals, SetTangents, SetColors, SetUVs (canaux 0 à 7), SetTriangles et SetIndices par sous-mesh, subMeshCount, indexFormat, RecalculateNormals, RecalculateTangents, RecalculateBounds, Clear, MarkDynamic, et les mêmes données en lecture (vertices, GetVertices, GetIndices…).
Les meshes n'existent que sur les appareils des joueurs : le serveur n'a ni rendu ni physique, et un script qui y fabrique un mesh reçoit une erreur.
Fabriquer un mesh
using NodeWorld.Flux;
public class Ramp : FluxScript
{
protected override void Start()
{
var mesh = new Mesh();
mesh.SetVertices(new[] { new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0.5f, 1), new Vector3(1, 0.5f, 1) });
mesh.SetUVs(0, new[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1) });
mesh.SetTriangles(new[] { 0, 2, 1, 2, 3, 1 }, 0);
mesh.RecalculateNormals();
GetComponent<MeshFilter>().sharedMesh = mesh; // visible
var collider = GetComponent<MeshCollider>();
collider.sharedMesh = mesh; // touchable : la physique prend sa forme tout de suite
}
}MeshFilter.sharedMeshdonne le mesh au filter.MeshFilter.meshdonne le mesh propre au filter : la première lecture fait une copie de son mesh partagé pour ce filter seul, comme dans Unity.MeshCollider.sharedMeshdonne la forme au collider. Metsconvex = truepour un mesh collider sur un rigidbody qui bouge, ou qui doit toucher un autre mesh collider.- Mets
indexFormat = IndexFormat.UInt32avant de donner plus de 65 535 sommets.
Le modifier à chaque frame
Les tableaux que tu donnes restent dans la mémoire du monde : le jeu les lit là, sans copie, et les passe à Unity. Garde tes tableaux, modifie-les et redonne-les :
protected override void Update()
{
for (var i = 0; i < _vertices.Length; i++)
_vertices[i].y = 0.2f * Mathf.Sin(_vertices[i].x * 2f + Time.time);
_mesh.SetVertices(_vertices);
_mesh.RecalculateNormals();
_mesh.RecalculateBounds();
}Appelle MarkDynamic() une fois sur un mesh qui change souvent. Un thread de ton script (Parallel.For, Task.Run) peut remplir les tableaux ; les appels qui modifient le mesh (SetVertices…) se font sur le thread principal.
Vertex buffer et index buffer
Pour une disposition à toi (plusieurs attributs dans un même flux, des flottants 16 bits…), utilise l'API avancée de Unity : SetVertexBufferParams avec des VertexAttributeDescriptor, SetVertexBufferData avec un tableau de ta structure de sommet, SetIndexBufferParams, SetIndexBufferData et SetSubMesh avec un SubMeshDescriptor. Le jeu pose un NativeArray sur tes tableaux et le passe à Mesh.SetVertexBufferData et Mesh.SetIndexBufferData.
Durée de vie
Un mesh fabriqué par un script appartient à son monde : il est détruit quand le monde se décharge, ou avant avec Object.Destroy(mesh). Un mesh de la scène modifié par un script change pour tous les renderers du monde qui l'utilisent.
