You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#中Perlin Noise函数为何始终出现对称性问题?

Perlin Noise 对称性问题排查与解决

问题现象

使用Perlin Noise生成地形时,始终出现异常对称性,尝试偏移调整等方法后仍无法消除。

问题代码

int verticesx = (cubeAmountX) + 1;
int verticesy = (cubeAmountY) + 1;
for(float x = ((chunkX) * (cubeAmountX/3)); x < verticesx + ((chunkX) * (cubeAmountX/3)); x++){
    for(float y = ((chunkY) * (cubeAmountY/3)); y < verticesy + ((chunkY)* (cubeAmountY/3)); y++){
        float perlinNoiseResult = Mathf.PerlinNoise((x + 0.1f) / 100 * scale + 132765, (y + 0.2f) / 100 * scale + 38789);
        perlinNoiseResult *= (Mathf.PerlinNoise((x + 0.3f) / 100 * scale * (x + 0.4f) / 100 * scale + 132765, (y + 0.5f) / 100 * scale * (y + 0.6f) / 100 * scale + 38789)) / 5 + 1;
        float biomeDecider = (Mathf.PerlinNoise(Mathf.Sqrt(Mathf.Abs(x + 0.7f) / 100 * scale) + 132765, Mathf.Sqrt(Mathf.Abs(y + 0.8f) / 100 * scale) + 38789));
        biomeDecider = 1/(1+Mathf.Pow(2,(-16*(biomeDecider - 0.5f))));
        perlinNoiseResult *= biomeDecider + 0.1f;
        
        vertices.Add(new Vector3(x * lengthBetweenVertices, perlinNoiseResult * maxheight - 10, y * lengthBetweenVertices));
        uv.Add(new Vector2(x/verticesx,y/verticesy));
        for(int ix = 0;ix < detail * lengthBetweenVertices;ix++){
            for(int iy = 0; iy < detail * lengthBetweenVertices;iy++){
                Color color = CalculateColor(Mathf.PerlinNoise((x + ix/detail/lengthBetweenVertices)/ 100 * scale, (y + iy/detail/lengthBetweenVertices) / 100 * scale) * biomeDecider * maxheight - 10, maxheight);
                texture.SetPixel((int)x * (int)detail * (int)lengthBetweenVertices + ix,(int)y * (int)detail * (int)lengthBetweenVertices + iy,color);
            }
        }
    }
}

问题根源

  1. 二次项乘法引入对称:第二个Mathf.PerlinNoise的x参数使用了(x+0.3f)/100*scale * (x+0.4f)/100*scale,这是x的二次函数,存在对称轴,会导致噪声在对称轴两侧呈现对称分布。
  2. 绝对值运算强制对称:biomeDecider中使用了Mathf.Abs(x + 0.7f),这会让x + 0.7f和-(x + 0.7f)得到相同的输入值,直接引入关于x = -0.7f的镜像对称,最终传递到地形高度计算中。

修正方案

  • 把第二个噪声的参数从二次乘法改成线性偏移,保持输入的连续性与非对称性:
    // 原代码
    Mathf.PerlinNoise((x + 0.3f) / 100 * scale * (x + 0.4f) / 100 * scale + 132765, ...)
    // 修正后
    Mathf.PerlinNoise((x + 0.3f) / 100 * scale + 0.4f + 132765, (y + 0.5f) / 100 * scale + 0.6f + 38789)
    
  • 移除biomeDecider中的Mathf.Abs,改用线性输入:
    // 原代码
    Mathf.PerlinNoise(Mathf.Sqrt(Mathf.Abs(x + 0.7f) / 100 * scale) + 132765, ...)
    // 修正后
    Mathf.PerlinNoise((x + 0.7f) / 100 * scale + 132765, (y + 0.8f) / 100 * scale + 38789)
    
  • 确保所有Perlin Noise的输入参数都是线性变换,避免使用平方、绝对值这类会产生对称的运算,保持噪声的自然随机性。

内容的提问来源于stack exchange,提问作者Jeffie The Turtle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:22:43