private void ApplyMesh(ProceduralMeshUpdater updater, bool addProceduralNormals) { if (!updater.HasMeshData) { // No mesh was actually generated! if (this.mesh != null) { this.mesh.Clear(); } if (this.meshRenderer != null) { this.meshRenderer.sharedMaterials = EmptyArray <Material> .Instance; } return; } if (this.mesh == null) { this.mesh = new Mesh(); this.mesh.name = "RTS: Procedural Mesh"; this.meshFilter.sharedMesh = this.mesh; // Mesh might need to be persisted! this.mesh.hideFlags = this.persist ? 0 : HideFlags.DontSave; } bool optimizeAtRuntime = (Application.isPlaying && !this.chunk.TileSystem.MarkProceduralDynamic); if (optimizeAtRuntime) { this.mesh.MarkDynamic(); } if (this.hasNormals && !addProceduralNormals) { this.mesh.Clear(false); this.hasNormals = false; } updater.UpdateMesh(this.mesh, addProceduralNormals); this.hasNormals = addProceduralNormals; if (!this.meshRenderer.sharedMaterials.SequenceEqual(updater.Materials)) { this.meshRenderer.sharedMaterials = updater.Materials; } }
/// <summary> /// Update procedural mesh from tile data. /// </summary> /// <param name="persist">A value of <c>true</c> indicates that generated mesh /// should be persisted at design time; <c>false</c> should always be specified /// at runtime.</param> public void UpdateMesh(bool persist = false) { // Attempt to recover if chunk reference is missing... if (this.chunk == null) { this.chunk = transform.parent.GetComponent <Chunk>(); } if (this.chunk == null || this.chunk.tiles == null) { return; } this.chunk.ProceduralDirty = false; var tileSystem = this.chunk.TileSystem; if (tileSystem == null) { return; } this.InitializeMeshComponents(persist); this.updatedOnce = true; try { ProceduralMeshUpdater updater = ProceduralMeshUpdater.Instance; updater.Clear(); // Fetch frequently used properties from tile system. int chunkWidth = tileSystem.ChunkWidth; int chunkHeight = tileSystem.ChunkHeight; TileData tile; Vector3 cellSize = tileSystem.CellSize; Vector3 origin; for (int row = 0, ti = 0; row < chunkHeight; ++row) { for (int column = 0; column < chunkWidth; ++column, ++ti) { tile = this.chunk.tiles[ti]; if (tile == null || !tile.Procedural || tile.tileset == null) { continue; } // Calculate origin of first vertex of tile. origin = new Vector3( column * cellSize.x, row * -cellSize.y, 0f ); updater.AddFromTileIndex(origin, cellSize.x, cellSize.y, tile.tileset, tile); } } // Only generate normals the first time. this.ApplyMesh(updater, tileSystem.addProceduralNormals); updater.Clear(); } catch (IndexOutOfRangeException) { Debug.LogError(string.Format("Chunk size of '{0}' is too large for procedural mesh.", this.chunk.TileSystem.name), this.chunk.TileSystem); } }