펄린 노이즈

PerlinNoise는 Ken Perlin이 1980년대 영화 “Tron”을 제작하는 동안 컴퓨터 효과를 위한 그라데이션 텍스처를 만들기 위해 만들었습니다.

개발한 노이즈 기능입니다.

노이즈 함수는 Minecraft 및 Terrari와 같은 많은 분야에서 사용됩니다.

설정된 규칙에 따라 게임 내 콘텐츠 자동 생성 “프로그램 콘텐츠 생성” 사용하는 게임에 적용할 수 있습니다.

이 노이즈 함수는 Unity에서 Mathf.PerlinNoise() 메서드로 제공됩니다.

그런 다음 텍스처에 노이즈를 칠하고 눈으로 노이즈를 검사해 보겠습니다.

노이즈 텍스처

using UnityEngine;

public class PerlinNoise : MonoBehaviour
{
    public int width = 256;
    public int height = 256;

    public float scale = 20f;

    public float offsetX;
    public float offsetY;

    private void Start()
    {
        offsetX = Random.Range(0f, 99999f);
        offsetY = Random.Range(0f, 99999f);       
    }

    private void Update()
    {
        Renderer renderer = GetComponent<Renderer>();
        renderer.material.mainTexture = GenerateTexture();
    }

    Texture2D GenerateTexture()
    {
        Texture2D texture = new Texture2D(width, height);

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                Color color = CalculateColor(x, y);

                texture.SetPixel(x, y, color);
            }
        }

        texture.Apply();

        return texture;
    }

    Color CalculateColor(int x, int y)
    {
        float xCoord = (float)x / width * scale + offsetX;  
        float yCoord = (float)y / height * scale + offsetY; 

        float sample = Mathf.PerlinNoise(xCoord, yCoord);

        return new Color(sample, sample, sample);
    }
}


오브젝트를 생성하여 텍스처를 적용하면 위와 같이 노이즈를 확인할 수 있습니다.

이 노이즈 기능은 게임의 다양한 부분에 적용될 수 있습니다.

파도

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Wave : MonoBehaviour
{
    float scale;
    float heightScale;

    int planeSize;
    public GameObject cube;

    void Start()
    {
        scale = 0.2f;
        heightScale = 2f;

        planeSize = 25;

        for (int x = 0; x < planeSize; x++)
        {
            for (int z = 0; z < planeSize; z++)
            {
                var c = Instantiate(cube, new Vector3(x, 0, z), Quaternion.identity);
                c.transform.parent = transform;
            }
        }
    }

    void Update()
    {
        foreach (Transform child in transform)
        {
            child.transform.position = new Vector3(child.transform.position.x,
            heightScale * Mathf.PerlinNoise(Time.time + (child.transform.position.x * scale),
            Time.time + (child.transform.position.z * scale)),
            child.transform.position.z);
        }
    }
}


높이 지도

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PerlinColor : MonoBehaviour
{
    public int size;
    public GameObject cube;
    public float scale;
    public float m;
    bool move;
    float height;

    void Start()
    {
        move = true;

        for (int x = 0; x < size; x++)
        {
            for (int z = 0; z < size; z++)
            {
                var c = Instantiate(cube, new Vector3(x, 0, z), Quaternion.identity);

                c.transform.parent = transform;
            }
        }
    }

    void Update()
    {
        foreach (Transform child in transform)
        {
            height = Mathf.PerlinNoise(child.transform.position.x / scale, child.transform.position.z / scale);

            child.GetComponent<MeshRenderer>().material.color = new Color(height, height, height, height);
        }

        if (move)
        {
            foreach (Transform child in transform)
            {
                height = Mathf.PerlinNoise(child.transform.position.x / scale, child.transform.position.z / scale);
                child.transform.position = new Vector3(child.transform.position.x, Mathf.RoundToInt(height * m), child.transform.position.z);

                // Mathf.RoundToInt() : 매개변수로 받은 두 정수중 가까운 정수를 반환합니다.

} } } }


지역

using UnityEngine;

public class TerrainGenerator : MonoBehaviour
{
    public int depth = 20;

    public int width = 256;
    public int height = 256;

    public float scale = 20f;

    public float offsetX = 100f;
    public float offsetY = 100f;

    private void Start()
    {
        offsetX = Random.Range(0f, 99999f);
        offsetY = Random.Range(0f, 99999f);
    }

    private void Update()
    {
        Terrain terrain = GetComponent<Terrain>();
        terrain.terrainData = GenerateTerrain(terrain.terrainData);

        //offsetX += Time.deltaTime * 5f;
    }

    TerrainData GenerateTerrain(TerrainData terrainData)
    {
        terrainData.heightmapResolution = width + 1;

        terrainData.size = new Vector3(width, depth, height);
        terrainData.SetHeights(0, 0, GenerateHeights());

        return terrainData;
    }

    float(,) GenerateHeights()
    {
        float(,) heights = new float(width, height);

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                heights(x, y) = CalculateHeight(x, y);
            }
        }

        return heights;
    }

    float CalculateHeight(int x, int y)
    {
        float xCoord = (float)x / width * scale + offsetX;
        float yCoord = (float)y / height * scale + offsetY;

        return Mathf.PerlinNoise(xCoord, yCoord);
    }
}