

GameObject์ ๋ถ์ฌ์ ์ฌ์ฉ
using UnityEngine;
using System.Collections.Generic;
public class Art_RadialPulse : MonoBehaviour
{
[Header("๊ทธ๋ฆฌ๋ ๊ตฌ์กฐ (๋ณ๊ฒฝ ์ ์ค๋ธ์ ํธ ์ฌ์์ฑ)")]
public int ringCount = 15;
public int baseSegments = 6;
public float ringSpacing = 1.2f;
[Header("ํ๋ ์ค์ (์ค์๊ฐ ๋ฐ์)")]
public float waveHeight = 2.2f;
public float waveSpeed = 1.2f;
public float waveFrequency = 1.2f;
[Header("ํฌ๊ธฐ ์ค์ (์ค์๊ฐ ๋ฐ์)")]
public float scaleMin = 0.25f;
public float scaleMax = 0.85f;
[Header("์์ ์ค์ (์ค์๊ฐ ๋ฐ์)")]
[Range(0f, 1f)] public float hueBase = 0.55f;
[Range(0f, 1f)] public float hueRange = 0.35f;
public float emissionIntensity = 1.2f;
[Header("์ฌ์ง ์ค์ ")]
public Material baseMaterial;
// ---------------------------------------------------
// ํ๋ธ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ฒด
// ---------------------------------------------------
struct CubeData
{
public Transform tr;
public Material mat;
public float radius;
public Vector3 basePos;
}
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();
SpawnCube(Vector3.zero, 0f); // ์ค์ฌ ํ๋ธ ์์ฑ
// ๋์ฌ์ ๊ทธ๋ฆฌ๋ ์์ฑ
for (int ring = 1; ring <= ringCount; ring++)
{
float radius = ring * ringSpacing;
int segments = baseSegments * ring;
for (int s = 0; s < segments; s++)
{
float angle = (float)s / segments * Mathf.PI * 2f;
Vector3 pos = new Vector3(
Mathf.Cos(angle) * radius,
0f,
Mathf.Sin(angle) * radius
);
SpawnCube(pos, radius);
}
}
ApplyAnimation(0f);
}
void SpawnCube(Vector3 pos, float radius)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.SetParent(transform);
go.transform.localPosition = pos;
go.transform.localScale = Vector3.one * scaleMin;
// ๋จธํฐ๋ฆฌ์ผ ์ธ์คํด์คํ ๋ฐ ์ด๋ฏธ์๋ธ ์ค์
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,
radius = radius,
basePos = pos
});
}
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;
// ํ๋ ๊ณ์ฐ
float wave = Mathf.Sin(c.radius * waveFrequency - t) * waveHeight;
float normalized = (wave / waveHeight + 1f) * 0.5f;
// ์์น ์
๋ฐ์ดํธ (Y์ถ์ผ๋ก ํ๋)
Vector3 p = c.basePos;
p.y = wave;
c.tr.localPosition = p;
// ์ค์ผ์ผ ์
๋ฐ์ดํธ
c.tr.localScale = Vector3.one * Mathf.Lerp(scaleMin, scaleMax, normalized);
// ์์ ๊ณ์ฐ (HSV ๊ธฐ๋ฐ ๊ทธ๋ผ๋ฐ์ด์
)
float hue = (hueBase + normalized * hueRange) % 1f;
Color albedo = Color.HSVToRGB(hue, 0.7f, 1f);
Color emission = Color.HSVToRGB(hue, 1f, normalized) * 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_RadialPulse] URP ์
ฐ์ด๋๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. Inspector ์์ baseMaterial ์ ์ง์ ํ ๋นํด์ฃผ์ธ์.");
return new Material(Shader.Find("Diffuse"));
}
Material mat = new Material(urpShader);
mat.EnableKeyword("_EMISSION");
mat.globalIlluminationFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;
return mat;
}
}