程序化世界生成无法处理大地图



所以,我正在windws 10上使用c#制作一个类似地形的游戏,它已经按程序生成了tilemap,我将这个脚本附加到一个网格上:

using UnityEngine;
using AccidentalNoise;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
using System;
public class CompileTerrain : MonoBehaviour
{
public TileBase dirtTile;
public TileBase grassTile;
public TileBase stoneTile;
public List<GameObject> fractalLayers = new List<GameObject>();
public Tilemap grid;
public int width;
public int height;
public float seed;
public int caveSmoothness = 2;
void Start()
{
grid.ClearAllTiles();
int touchCount = 0;
Vector3Int newPos;
double nx, ny;
ModuleBase combinedTerrain = CavesAndMountains((uint)seed);
List<Vector3Int> terrainCoords = new List<Vector3Int>();
SMappingRanges ranges = new SMappingRanges();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
nx = (ranges.mapx0 + ((double)x / (double)width) * (ranges.mapx1 - ranges.mapx0)) * 3;
ny = (ranges.mapy0 + ((double)y / (double)height) * (ranges.mapy1 - ranges.mapy0)) * 3;
if (combinedTerrain.Get(nx, ny) > 0f)
{
terrainCoords.Add(new Vector3Int(x, height - y, 0));
}
}
}
List<Tuple<int, int>> neighbors = new List<Tuple<int, int>>() {Tuple.Create(1, 1), Tuple.Create(-1, -1),
 Tuple.Create(0, 1), Tuple.Create(1, 0),
 Tuple.Create(0, -1), Tuple.Create(-1, 0),
 Tuple.Create(-1, 1), Tuple.Create(1, -1)};
for (int index = 0; index < terrainCoords.Count; index++)
{
if (index == terrainCoords.Count)
{
break;
}
touchCount = 0;
for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(terrainCoords[index].x + neighbors[posAdd].Item1, terrainCoords[index].y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : 0;
}
if (touchCount < 2)
{
terrainCoords.Remove(terrainCoords[index]);
}
}
for (int j = 0; j < caveSmoothness; j++)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (!terrainCoords.Contains(new Vector3Int(x, y, 0)))
{
touchCount = 0;
for (int posAdd = 0; posAdd < neighbors.Count; posAdd++)
{
newPos = new Vector3Int(x + neighbors[posAdd].Item1, y + neighbors[posAdd].Item2, 0);
touchCount += terrainCoords.Contains(newPos) ? 1 : -1;
}
if (touchCount > 1)
{
terrainCoords.Add(new Vector3Int(x, y, 0));
}
}
}
}
}
foreach (Vector3Int blck in terrainCoords)
{
grid.SetTile(blck, stoneTile);
}
terrainCoords.Sort((x, y) => x.x == y.x ? x.y.CompareTo(y.y) : x.x.CompareTo(y.x));
terrainCoords.Reverse();
TileBase selectedTile;
int depth = 0;
int lastx = 0;
int lasty = terrainCoords[0].y + 1;
foreach (Vector3Int blck in terrainCoords)
{
depth = blck.x != lastx ? 0 : depth;
lasty = blck.x != lastx ? blck.y + 1 : lasty;
selectedTile = depth < 4 ? grassTile : stoneTile;
selectedTile = 3 < depth && depth < 30 ? dirtTile : selectedTile;
grid.SetTile(blck, selectedTile);
lastx = blck.x;
depth += lasty - blck.y;
lasty = blck.y;
}
int layerNum = 1;
List<Vector3Int> posList = new List<Vector3Int>();
foreach (GameObject layer in fractalLayers)
{
GetPerlinLayer component = layer.GetComponent<GetPerlinLayer>();
for (int k = 0; k < component.populateCount; k++)
{
layerNum++;
foreach (Vector3Int pos in component.GetFractalCoords(width, height, (uint)(seed * layerNum)))
if (grid.GetTile(pos) != null && grid.GetTile(pos) != grassTile)
{
grid.SetTile(pos, component.defaultTile);
}
}
}
}
public static ModuleBase CavesAndMountains(uint seed)
{
AccidentalNoise.Gradient ground_gradient = new AccidentalNoise.Gradient(0, 0, 0, 1);
// lowlands
Fractal lowland_shape_fractal = new Fractal(FractalType.BILLOW, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 2, 0.25, seed);
AutoCorrect lowland_autocorrect = new AutoCorrect(lowland_shape_fractal, 0, 1);
ScaleOffset lowland_scale = new ScaleOffset(0.125, -0.45, lowland_autocorrect);
ScaleDomain lowland_y_scale = new ScaleDomain(lowland_scale, null, 0);
TranslatedDomain lowland_terrain = new TranslatedDomain(ground_gradient, null, lowland_y_scale);
// highlands
Fractal highland_shape_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 4, 2, seed);
AutoCorrect highland_autocorrect = new AutoCorrect(highland_shape_fractal, -1, 1);
ScaleOffset highland_scale = new ScaleOffset(0.25, 0, highland_autocorrect);
ScaleDomain highland_y_scale = new ScaleDomain(highland_scale, null, 0);
TranslatedDomain highland_terrain = new TranslatedDomain(ground_gradient, null, highland_y_scale);
// mountains
Fractal mountain_shape_fractal = new Fractal(FractalType.RIDGEDMULTI, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 8, 1, seed);
AutoCorrect mountain_autocorrect = new AutoCorrect(mountain_shape_fractal, -1, 1);
ScaleOffset mountain_scale = new ScaleOffset(0.3, 0.15, mountain_autocorrect);
ScaleDomain mountain_y_scale = new ScaleDomain(mountain_scale, null, 0.15);
TranslatedDomain mountain_terrain = new TranslatedDomain(ground_gradient, null, mountain_y_scale);
// terrain
Fractal terrain_type_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 3, 0.125, seed);
AutoCorrect terrain_autocorrect = new AutoCorrect(terrain_type_fractal, 0, 1);
ScaleDomain terrain_type_y_scale = new ScaleDomain(terrain_autocorrect, null, 0);
AccidentalNoise.Cache terrain_type_cache = new AccidentalNoise.Cache(terrain_type_y_scale);
Select highland_mountain_select = new Select(terrain_type_cache, highland_terrain, mountain_terrain, 0.55, 0.2);
Select highland_lowland_select = new Select(terrain_type_cache, lowland_terrain, highland_mountain_select, 0.25, 0.15);
AccidentalNoise.Cache highland_lowland_select_cache = new AccidentalNoise.Cache(highland_lowland_select);
Select ground_select = new Select(highland_lowland_select_cache, 0, 1, 0.5, null);
// caves
Fractal cave_shape = new Fractal(FractalType.RIDGEDMULTI, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 1, 4, seed);
Bias cave_attenuate_bias = new Bias(highland_lowland_select_cache, 0.65);
Combiner cave_shape_attenuate = new Combiner(CombinerTypes.MULT, cave_shape, cave_attenuate_bias);
Fractal cave_perturb_fractal = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 6, 3, seed);
ScaleOffset cave_perturb_scale = new ScaleOffset(0.5, 0, cave_perturb_fractal);
TranslatedDomain cave_perturb = new TranslatedDomain(cave_shape_attenuate, cave_perturb_scale, null);
Select cave_select = new Select(cave_perturb, 1, 0, 0.75, 0);
return new Combiner(CombinerTypes.MULT, cave_select, ground_select) as ModuleBase;
}
}

我很有礼貌地从那些偶然发出噪音的好人那里借来并修改了它,我制作了一个空的游戏对象,我把这个脚本附在上面:

using UnityEngine;
using AccidentalNoise;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
public class GetPerlinLayer : MonoBehaviour
{
public TileBase defaultTile;
public float threshold = 0.5f;
public int populateCount = 5;
public List<Vector3Int> GetFractalCoords(int width, int height, uint seed)
{
double nx, ny;
ModuleBase combinedTerrain = new Fractal(FractalType.FBM, BasisTypes.GRADIENT, InterpTypes.QUINTIC, 6, 2, seed);
List<Vector3Int> fractalCoords = new List<Vector3Int>();
SMappingRanges ranges = new SMappingRanges();
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
nx = (ranges.mapx0 + ((double)x / (double)width) * (ranges.mapx1 - ranges.mapx0)) * 3;
ny = (ranges.mapy0 + ((double)y / (double)height) * (ranges.mapy1 - ranges.mapy0)) * 3;
if (combinedTerrain.Get(nx, ny) > threshold)
{
fractalCoords.Add(new Vector3Int(x, height - y, 0));
}
}
}
return fractalCoords;
}
}

我为每个游戏对象附加了不同颜色的方形精灵,并将它们保存为预制。一旦我有了这个预制件,我就把它附加到我以前的脚本中的fractalLayers列表中,以生成矿石。尽管它在较低的范围内运行良好,但我无法在更大的范围内进行运行。既然没有办法让代码运行得更快(除了重构,我不知道该怎么做(,而且我可能从新手开始就可以让我的部分代码更高效,我真的希望专业人士能对如何让我的代码运行得更好有一些见解。我知道我没有解释我的项目的所有内容,但它实际上只是一个简单的项目,这些是它唯一的脚本和独特的部分,你可以推断我做了什么并填空。感谢您的帮助。如果你能给我额外的推动力和一些关于这个主题的信息,我很乐意推荐一些视频和你的见解来指导我完成这个过程,因为我更像是一个视觉学习者。谢谢

(作为参考,我花了大约4分钟来构建这个,这里显示了设置。(

所以显然我的单词生成方法很好,只是我用来平滑地形的循环花了太长时间。

相关内容

  • 没有找到相关文章

最新更新