๐ŸซงArt_006 Sine Grid [Game Object]

BamgasiJMยท2026๋…„ 3์›” 16์ผ

Unity GenArt

๋ชฉ๋ก ๋ณด๊ธฐ
17/41
post-thumbnail

๐Ÿ“„Art_006_Sine_Grid.cs

using UnityEngine;
using System.Collections.Generic;

public class Art_SineGrid : MonoBehaviour
{
    [Header("๊ทธ๋ฆฌ๋“œ ๊ตฌ์กฐ (๋ณ€๊ฒฝ ์‹œ ์˜ค๋ธŒ์ ํŠธ ์žฌ์ƒ์„ฑ)")]
    public int   gridSize  = 50;
    public float spacing   = 0.8f;
    public float cubeSize  = 0.35f;
    public int   colorSeed = 0;

    [Header("ํŒŒ๋™ ์„ค์ • (์‹ค์‹œ๊ฐ„ ๋ฐ˜์˜)")]
    public float waveHeight    = 2.0f;
    public float waveSpeed     = 1.5f;
    public float waveFrequency = 0.8f;

    [Header("์ƒ‰์ƒ ์„ค์ • (์‹ค์‹œ๊ฐ„ ๋ฐ˜์˜)")]
    [ColorUsage(false)] public Color colorStart = new Color(0.1f, 0.1f, 0.1f);
    [ColorUsage(false)] public Color colorEnd   = new Color(1.0f, 1.0f, 1.0f);
    public float emissionIntensity = 0.4f;

    [Header("์žฌ์งˆ ์„ค์ •")]
    public Material baseMaterial;

    // ---------------------------------------------------
    // ํ๋ธŒ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ฒด
    // ---------------------------------------------------
    struct CubeData
    {
        public Transform tr;
        public Material  mat;
        public Vector3   basePos;
        public float     colorFactor; // 0~1: colorStart ์™€ colorEnd ์‚ฌ์ด ๋ณด๊ฐ„ ๊ณ„์ˆ˜
    }

    List<CubeData> _cubes = new List<CubeData>();

    // ---------------------------------------------------
    // Unity ์ด๋ฒคํŠธ
    // ---------------------------------------------------

    void OnEnable()
    {
        // baseMaterial ์ด ์—†์œผ๋ฉด URP ๊ธฐ๋ณธ ๋จธํ‹ฐ๋ฆฌ์–ผ ์ž๋™ ์ƒ์„ฑ
        if (baseMaterial == null)
            baseMaterial = CreateURPMaterial();

        Generate();
    }

    void Update()
    {
        // ๊ฒŒ์ž„ ์‹คํ–‰ ์ค‘ ํ•ญ์ƒ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ (์—๋””ํ„ฐ ์ฒดํฌ ์ œ๊ฑฐ)
        ApplyAnimation(Time.time * waveSpeed);
    }

    void OnDisable()
    {
        Clear();  // ์ปดํฌ๋„ŒํŠธ ๋น„ํ™œ์„ฑํ™” ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ฆฌ
    }

    // ---------------------------------------------------
    // ๊ทธ๋ฆฌ๋“œ ์ƒ์„ฑ
    // ---------------------------------------------------

    void Generate()
    {
        Clear();
        Random.InitState(colorSeed);

        // ๊ทธ๋ฆฌ๋“œ ์ „์ฒด๋ฅผ ๋กœ์ปฌ ์›์  ๊ธฐ์ค€์œผ๋กœ ์ค‘์•™ ์ •๋ ฌ
        float offset = (gridSize - 1) * spacing * 0.5f;

        for (int x = 0; x < gridSize; x++)
        {
            for (int z = 0; z < gridSize; z++)
            {
                Vector3 pos = new Vector3(
                    x * spacing - offset,
                    0f,
                    z * spacing - offset
                );

                // ํ๋ธŒ๋งˆ๋‹ค ๊ทธ๋ผ๋””์–ธํŠธ ๊ณ„์ˆ˜๋ฅผ ๊ณ ์ • (์‹œ๋“œ ๊ธฐ๋ฐ˜ ๋ฌด์ž‘์œ„)
                float colorFactor = Random.value;

                SpawnCube(pos, colorFactor);
            }
        }

        ApplyAnimation(0f);
    }

    void SpawnCube(Vector3 pos, float colorFactor)
    {
        GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
        go.transform.SetParent(transform);
        go.transform.localPosition = pos;
        go.transform.localScale    = Vector3.one * cubeSize;

        // ๋จธํ‹ฐ๋ฆฌ์–ผ ์ธ์Šคํ„ด์Šคํ™” ๋ฐ ์ด๋ฏธ์‹œ๋ธŒ ์„ค์ •
        Material mat = Instantiate(baseMaterial);
        mat.EnableKeyword("_EMISSION");
        mat.globalIlluminationFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;

        go.GetComponent<Renderer>().material = mat;

        _cubes.Add(new CubeData
        {
            tr          = go.transform,
            mat         = mat,
            basePos     = pos,
            colorFactor = colorFactor
        });
    }

    void Clear()
    {
        // ๋Ÿฐํƒ€์ž„ ์•ˆ์ „ํ•œ ๋ฐฉ์‹์œผ๋กœ ์˜ค๋ธŒ์ ํŠธ ๋ฐ ๋จธํ‹ฐ๋ฆฌ์–ผ ์ •๋ฆฌ
        foreach (var cube in _cubes)
        {
            if (cube.mat != null)
                Destroy(cube.mat);
            if (cube.tr != null)
                Destroy(cube.tr.gameObject);
        }
        _cubes.Clear();
    }

    // ---------------------------------------------------
    // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ
    // ---------------------------------------------------

    void ApplyAnimation(float t)
    {
        for (int i = 0; i < _cubes.Count; i++)
        {
            CubeData c = _cubes[i];
            if (c.tr == null || c.mat == null) continue;

            // (x + z) ํ•ฉ์‚ฐ โ†’ ๋Œ€๊ฐ์„  ๋ฐฉํ–ฅ ์‚ฌ์ธํŒŒ
            float wave = Mathf.Sin(
                (c.basePos.x + c.basePos.z) * waveFrequency + t
            ) * waveHeight;

            float normalized = (wave / waveHeight + 1f) * 0.5f; // 0~1

            // ์œ„์น˜ ์—…๋ฐ์ดํŠธ (Y์ถ•์œผ๋กœ ํŒŒ๋™)
            Vector3 p = c.basePos;
            p.y = wave;
            c.tr.localPosition = p;

            // ๊ทธ๋ผ๋””์–ธํŠธ ์ƒ‰์ƒ ๊ณ„์‚ฐ: colorFactor ๋กœ ์‹œ์ž‘/๋ ์ƒ‰์ƒ ๋ณด๊ฐ„
            Color baseColor = Color.Lerp(colorStart, colorEnd, c.colorFactor);
            
            // ํŒŒ๋™ ๋†’์ด์— ๋”ฐ๋ผ ๋ช…๋„๋ฅผ ๋ณ€์กฐํ•˜์—ฌ ์ž…์ฒด๊ฐ ๊ฐ•์กฐ
            float brightnessMod = Mathf.Lerp(0.4f, 1f, normalized);
            Color albedo   = baseColor * brightnessMod;
            Color emission = baseColor * (brightnessMod * emissionIntensity);

            // URP ์ „์šฉ ์…ฐ์ด๋” ํ”„๋กœํผํ‹ฐ ์ ์šฉ
            c.mat.SetColor("_BaseColor", albedo);
            c.mat.SetColor("_EmissionColor", emission);
        }
    }

    // ---------------------------------------------------
    // ์œ ํ‹ธ๋ฆฌํ‹ฐ: URP ์ „์šฉ ๋จธํ‹ฐ๋ฆฌ์–ผ ์ƒ์„ฑ
    // ---------------------------------------------------

    Material CreateURPMaterial()
    {
        Shader urpShader = Shader.Find("Universal Render Pipeline/Lit");
        if (urpShader == null)
        {
            Debug.LogWarning("[Art_SineGrid] URP ์…ฐ์ด๋”๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Inspector ์—์„œ baseMaterial ์„ ์ง์ ‘ ํ• ๋‹นํ•ด์ฃผ์„ธ์š”.");
            return new Material(Shader.Find("Diffuse"));
        }

        Material mat = new Material(urpShader);
        mat.EnableKeyword("_EMISSION");
        mat.globalIlluminationFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;
        return mat;
    }
}

profile
Coding Art with Blender / oF / Processing / p5.js / nannou

0๊ฐœ์˜ ๋Œ“๊ธ€