前提・実現したいこと
メッシュにシェーダーを適応させて、自然な見た目の地形表現をしたい。
該当のソースコード
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class World : MonoBehaviour 6{ 7 public int width; 8 public int height; 9 10 public Tile[,] tiles; 11 12 public Material material; 13 14 Mesh mesh; 15 16 public string seed; 17 public bool randomSeed; 18 19 public float frequency; 20 public float amplitude; 21 22 public float lacunarity; 23 public float persistance; 24 25 public int octaves; 26 27 Noise noise; 28 29 public float seaLevel; 30 31 public float beachStartHeight; 32 public float beachEndHeight; 33 34 public float grassStartHeight; 35 public float grassEndHeight; 36 37 public float dirtStartHeight; 38 public float dirtEndHeight; 39 40 public float stoneStartHeight; 41 public float stoneEndHeight; 42 43 private void Awake() 44 { 45 if(randomSeed == true) 46 { 47 int value = Random.Range(-1000, 10000); 48 seed = value.ToString(); 49 } 50 51 noise = new Noise(seed.GetHashCode(), frequency, amplitude, lacunarity, persistance, octaves); 52 } 53 54 // Use this for initialization 55 void Start() 56 { 57 CreateTiles(); 58 GenerateMesh(); 59 } 60 61 // Update is called once per frame 62 void Update() 63 { 64 Graphics.DrawMesh(mesh, Vector3.zero, Quaternion.identity, material, 0); 65 } 66 67 void CreateTiles() 68 { 69 this.tiles = new Tile[this.width, this.height]; 70 71 float[,] noiseValues = this.noise.GetNoiseValues(this.width + 1, this.height + 1); 72 73 for (int i = 0; i < this.width; i++) 74 { 75 for (int j = 0; j < this.height; j++) 76 { 77 Vector4 weights = new Vector4(noiseValues[i, j], noiseValues[i + 1, j], noiseValues[i, j + 1], noiseValues[i + 1, j + 1]); 78 79 float currentHeight = noiseValues[i, j]; 80 81 if(currentHeight < seaLevel) 82 { 83 Tile.Type type = Tile.Type.Water; 84 this.tiles[i, j] = new Tile(type, Tile.Type.Sand, Tile.Type.Water, weights); 85 } 86 else if (currentHeight >= beachStartHeight && currentHeight <= beachEndHeight) 87 { 88 Tile.Type type = Tile.Type.Sand; 89 this.tiles[i, j] = new Tile(type, Tile.Type.Grass, Tile.Type.Sand, weights); 90 } 91 else if(currentHeight >= grassStartHeight && currentHeight <= grassEndHeight) 92 { 93 Tile.Type type = Tile.Type.Grass; 94 this.tiles[i, j] = new Tile(type, Tile.Type.Grass, Tile.Type.Sand, weights); 95 } 96 else if(currentHeight >= dirtStartHeight && currentHeight <= dirtEndHeight) 97 { 98 Tile.Type type = Tile.Type.Grass; 99 this.tiles[i, j] = new Tile(type, Tile.Type.Grass, Tile.Type.Sand, weights); 100 } 101 else if(currentHeight >= stoneStartHeight && currentHeight <= stoneEndHeight) 102 { 103 Tile.Type type = Tile.Type.Grass; 104 this.tiles[i, j] = new Tile(type, Tile.Type.Grass, Tile.Type.Grass, weights); 105 } 106 else 107 { 108 Tile.Type type = Tile.Type.Grass; 109 this.tiles[i, j] = new Tile(type, Tile.Type.Grass, Tile.Type.Sand, weights); 110 } 111 } 112 } 113 } 114 115 void GenerateMesh() 116 { 117 MeshData data = new MeshData(this.tiles); 118 this.mesh = new Mesh(); 119 120 this.mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 121 122 this.mesh.vertices = data.vertices.ToArray(); 123 this.mesh.triangles = data.triangles.ToArray(); 124 125 this.mesh.SetUVs(0, data.UVs); 126 127 this.mesh.colors = data.colors.ToArray(); 128 129 this.mesh.RecalculateNormals(); 130 this.mesh.RecalculateBounds(); 131 } 132}
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System.Linq; 5 6public class MeshData{ 7 8 public List<Vector3> vertices; 9 public List<int> triangles; 10 public List<Vector4> UVs; 11 public List<Color> colors; 12 13 public MeshData(Tile[,] data) 14 { 15 vertices = new List<Vector3>(); 16 triangles = new List<int>(); 17 UVs = new List<Vector4>(); 18 colors = new List<Color>(); 19 20 for (int i = 0; i < data.GetLength(0); i++) 21 { 22 for (int j = 0; j < data.GetLength(1); j++) 23 { 24 CreateSquare(data[i, j], i, j); 25 } 26 } 27 } 28 29 void CreateSquare(Tile tile, int x, int y) 30 { 31 vertices.Add(new Vector3(x + 0, y + 0)); 32 vertices.Add(new Vector3(x + 1, y + 0)); 33 vertices.Add(new Vector3(x + 0, y + 1)); 34 vertices.Add(new Vector3(x + 1, y + 1)); 35 36 triangles.Add(vertices.Count - 1); 37 triangles.Add(vertices.Count - 3); 38 triangles.Add(vertices.Count - 4); 39 40 triangles.Add(vertices.Count - 2); 41 triangles.Add(vertices.Count - 1); 42 triangles.Add(vertices.Count - 4); 43 44 Vector2[] foregroundUVs = SpriteLoader.instance.GetTileUVs(tile.foregroundType); 45 Vector2[] backgroundUVs = SpriteLoader.instance.GetTileUVs(tile.backgroundType); 46 UVs.AddRange(foregroundUVs.Zip(backgroundUVs, (f, b) => new Vector4(f.x, f.y, b.x, b.y))); 47 48 for (int i = 0; i < 4; i++) 49 { 50 colors.Add(new Color(0.0f, 0.0f, 0.0f, tile.blendWeights[i])); 51 } 52 } 53} 54
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Tile 6{ 7 8 public enum Type { Dirt, Grass,Water,Sand,Void } 9 public Type type; 10 public Type foregroundType; 11 public Type backgroundType; 12 public Vector4 blendWeights; 13 14 public Tile(Type type, Type foreground, Type background, Vector4 weights) 15 { 16 this.type = type; 17 this.foregroundType = foreground; 18 this.backgroundType = background; 19 this.blendWeights = weights; 20 } 21} 22
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Noise { 6 7 int seed; 8 9 float frequency; 10 float amplitude; 11 12 float lacunarity; 13 float persistance; 14 15 int octaves; 16 17 public Noise(int seed,float frequency,float amplitude,float lacunarity,float persistance,int octaves) 18 { 19 this.seed = seed; 20 this.frequency = frequency; 21 this.amplitude = amplitude; 22 this.lacunarity = lacunarity; 23 this.persistance = persistance; 24 this.octaves = octaves; 25 } 26 27 public float [,] GetNoiseValues(int width,int height) 28 { 29 float[,] noiseValues = new float[width, height]; 30 31 float max = 0f; 32 float min = float.MaxValue; 33 34 seed %= 1024; 35 36 for (int i = 0; i < width; i++) 37 { 38 for(int j =0; j < height; j++) 39 { 40 noiseValues[i, j] = 0f; 41 42 float tempA = amplitude; 43 float tempF = frequency; 44 45 for(int k = 0;k < octaves; k++) 46 { 47 noiseValues[i, j] += Mathf.PerlinNoise((i + seed) / (float)width * frequency, j / (float)height * frequency) * amplitude; 48 frequency *= lacunarity; 49 amplitude *= persistance; 50 } 51 52 amplitude = tempA; 53 frequency = tempF; 54 55 if(noiseValues[i,j] > max) 56 { 57 max = noiseValues[i, j]; 58 } 59 60 if(noiseValues[i,j] < min) 61 { 62 min = noiseValues[i, j]; 63 } 64 } 65 } 66 67 for (int i = 0; i < width; i++) 68 { 69 for (int j = 0; j < height; j++) 70 { 71 72 noiseValues[i, j] = Mathf.InverseLerp(max, min, noiseValues[i, j]); 73 } 74 } 75 76 return noiseValues; 77 } 78}
試したこと
前回アドバイスしていただいたコードを改造して、描画するタイルを増やしたのですが、綺麗な地形表現にはなりませんでした。前回の質問のコードを使い、二枚のタイルだけなら、上手くいきます。
前景と背景のグラフィックを混ぜ合わせて描画しているのですが、四角形のメッシュで生成しているので、隣合うグラフィックの問題で、地形のように見えなくなっているのだと自分は考えました。
具体的にはBeach Start HeightとBeach End Heidhtという変数を使い、浜辺のように見せようとしているのですが、四角形に描画されるため、浜辺には見えなくなっています。
増やした変数の値は以下です。
使用したタイル↓
文字数制限に引っ掛かるため、「SpriteLoader」というスクリプトは記載しませんでした。前回の質問に記載してあります。
どのようにすればいいでしょうか? 回答お願いします。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/04/16 13:22