Unity 3D中的程序地形编程

use*_*907 6 c# procedural-generation unity-game-engine perlin-noise

我试图与程序生成相处,我绝对不是团结的专业人士,但我遵循这个指南:点击 并得到一些结果.现在我有两个问题,我有一些基本的想法如何解决它们,但我想听听其他一些意见.

(我已经在Unity答案中发布了这个问题,但是我根本没有回复,如果有一些遗漏的信息或者几句话无法解释,请告诉我或者提供一些如何查找这些信息的建议)

主要问题是:块之间的差距:

在此输入图像描述

如果我会变焦,它们有点消失,但纹理仍然不合适而且非常显着.

第二个,你可以看到我在地面上有红色问题(我真的不知道怎么称呼它).我曾尝试使用指南中的材料,但效果相同.

此外,Perlin Noise(我知道我可以使用Diamond square或simplex)是伪随机算法,所以它会为相同的输入参数返回相同的值,所以它是否意味着我的块总是相同的?

我的代码(我正在使用指南中的LibNoise库):

    void Awake()
    {
        var settings = new TerrainChunkSettings(129, 129, 100, 40, FlatTexture, SteepTexture, TerrainMaterial);
        var noiseProvider = new NoiseProvider();
        for (var i = 0; i < 4; i++)
            for (var j = 0; j < 4; j++)
                new TerrainChunk(settings, noiseProvider, i, j).CreateTerrain();
    }
public class TerrainChunkSettings
{
    public int HeightmapResolution { get; private set; }

    public int AlphamapResolution { get; private set; }

    public int Length { get; private set; }

    public int Height { get; private set; }

    public Texture2D FlatTexture { get; private set; }

    public Texture2D SteepTexture { get; private set; }

    public Material TerrainMaterial { get; private set; }

    public TerrainChunkSettings(int heightmapResolution, int alphamapResolution, int length, int height, Texture2D flatTexture, Texture2D steepTexture, Material terrainMaterial)
    {
        HeightmapResolution = heightmapResolution;
        AlphamapResolution = alphamapResolution;
        Length = length;
        Height = height;
        FlatTexture = flatTexture;
        SteepTexture = steepTexture;
        TerrainMaterial = terrainMaterial;
    }
}

public class TerrainChunk
{
    private Terrain Terrain { get; set; }

    private TerrainChunkSettings Settings { get; set; }

    private NoiseProvider NoiseProvider { get; set; }

    public int X { get; private set; }

    public int Z { get; private set; }

    private TerrainData Data { get; set; }

    private float[,] Heightmap { get; set; }
    public TerrainChunk(TerrainChunkSettings settings, NoiseProvider noiseProvider, int x, int z)
    {
        X = x;
        Z = z;
        Settings = settings;
        NoiseProvider = noiseProvider;
    }

    public void CreateTerrain()
    {
        var terrainData = new TerrainData();
        terrainData.heightmapResolution = Settings.HeightmapResolution;
        terrainData.alphamapResolution = Settings.AlphamapResolution;

        var heightmap = GetHeightmap();
        terrainData.SetHeights(0, 0, heightmap);
        ApplyTextures(terrainData);
        terrainData.size = new Vector3(Settings.Length, Settings.Height, Settings.Length);

        var newTerrainGameObject = Terrain.CreateTerrainGameObject(terrainData);
        newTerrainGameObject.transform.position = new Vector3(X * Settings.Length, 0, Z * Settings.Length);
        Terrain = newTerrainGameObject.GetComponent<Terrain>();
        Terrain.Flush();
    }

    private float[,] GetHeightmap()
    {
        var heightmap = new float[Settings.HeightmapResolution, Settings.HeightmapResolution];

        for (var zRes = 0; zRes < Settings.HeightmapResolution; zRes++)
        {
            for (var xRes = 0; xRes < Settings.HeightmapResolution; xRes++)
            {
                var xCoordinate = X + (float)xRes / (Settings.HeightmapResolution - 1);
                var zCoordinate = Z + (float)zRes / (Settings.HeightmapResolution - 1);

                heightmap[zRes, xRes] = NoiseProvider.GetValue(xCoordinate, zCoordinate);
            }
        }

        return heightmap;
    }

    private void ApplyTextures(TerrainData terrainData)
    {
        var flatSplat = new SplatPrototype();
        var steepSplat = new SplatPrototype();

        flatSplat.texture = Settings.FlatTexture;
        steepSplat.texture = Settings.SteepTexture;

        terrainData.splatPrototypes = new SplatPrototype[]
        {
            flatSplat,
            steepSplat
        };

        terrainData.RefreshPrototypes();

        var splatMap = new float[terrainData.alphamapResolution, terrainData.alphamapResolution, 2];

        for (var zRes = 0; zRes < terrainData.alphamapHeight; zRes++)
        {
            for (var xRes = 0; xRes < terrainData.alphamapWidth; xRes++)
            {
                var normalizedX = (float)xRes / (terrainData.alphamapWidth - 1);
                var normalizedZ = (float)zRes / (terrainData.alphamapHeight - 1);

                var steepness = terrainData.GetSteepness(normalizedX, normalizedZ);
                var steepnessNormalized = Mathf.Clamp(steepness / 1.5f, 0, 1f);

                splatMap[zRes, xRes, 0] = 1f - steepnessNormalized;
                splatMap[zRes, xRes, 1] = steepnessNormalized;
            }
        }

        terrainData.SetAlphamaps(0, 0, splatMap);
    }
}

public interface INoiseProvider
{
    float GetValue(float x, float z);
}
public class NoiseProvider : INoiseProvider
{
    private Perlin PerlinNoiseGenerator;

    public NoiseProvider()
    {
        PerlinNoiseGenerator = new Perlin();
    }

    public float GetValue(float x, float z)
    {
        return (float)(PerlinNoiseGenerator.GetValue(x, 0, z) / 2f) + 0.5f;
    }
}
Run Code Online (Sandbox Code Playgroud)

Lud*_*ltz 4

1)主要问题是:块之间的间隙

您可以将地形缝合在一起,以确保它们具有相同的 LODSetNeighbors(Terrain left, Terrain top, Terrain right, Terrain bottom);

文档中:

允许您设置相邻地形之间的连接。

这可确保 LOD 与邻近地形相匹配。请注意,仅在一个地形上调用此函数是不够的,您需要设置每个地形的邻居。

2)第二个:地上的红色痕迹

这个问题应该来自于您在地形对象中使用的纹理。