You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
4.8 KiB
C#

using System.Collections;
using UnityEngine;
public class tree : MonoBehaviour
{
public GameObject branchPrefab;
public int maxDepth = 4;
public float branchAngle = 45f;
public float scaleReduction = 0.6f;
public float initialLength = 5f;
public int branchesPerLevel = 4;
[Header("Artistic Settings")]
public Color trunkColor = new Color(0.4f, 0.2f, 0f); // 나무 몸통 (갈색)
public Color leafColor = new Color(1f, 0.4f, 0.6f); // 가지 끝부분 (핑크/벚꽃 느낌)
[Range(0f, 1f)] public float lengthRandomness = 0.2f; // 길이 랜덤 (0~1)
[Range(0f, 45f)] public float angleRandomness = 20f; // 휘어짐 극대화를 위한 각도 랜덤
[Header("Animation & Wind")]
public float growthDelay = 0.1f; // 가지 생성 대기 시간 (애니메이션 효과)
[Range(0f, 5f)] public float windStrength = 1.5f; // 바람의 세기
private GameObject branchContainer;
void Start()
{
// Hierarchy 창을 깔끔하게 유지하기 위한 컨테이너 생성
branchContainer = new GameObject("TreeContainer");
branchContainer.transform.position = transform.position;
StartCoroutine(CreateBranchRoutine(transform.position, transform.rotation, initialLength, 0, branchContainer.transform));
}
IEnumerator CreateBranchRoutine(Vector3 pos, Quaternion rot, float length, int depth, Transform parentTransform)
{
if (depth >= maxDepth) yield break;
// 런타임에서 자라나는 모습을 보여주기 위한 대기 시간
yield return new WaitForSeconds(growthDelay);
// 바람에 흔들릴 때 관절이 끊어지지 않도록, 가지 시작점(pos)에 가상의 피벗(Pivot)을 생성
GameObject pivot = new GameObject("Pivot_Depth_" + depth);
pivot.transform.position = pos;
pivot.transform.rotation = rot;
pivot.transform.parent = parentTransform;
// 흔들림(Sway) 스크립트 추가
BranchSway sway = pivot.AddComponent<BranchSway>();
sway.Init(depth, windStrength);
// 중앙 피벗 큐브를 위한 중심 위치 계산
Vector3 centerPos = pos + rot * (Vector3.up * length * 0.5f);
// 나뭇가지를 생성하고 부모를 생성한 피벗으로 설정
GameObject branch = Instantiate(branchPrefab, centerPos, rot);
branch.transform.parent = pivot.transform;
// 아티스틱: 깊이에 따라 색상 자연스럽게 섞기 (Lerp)
Renderer rnd = branch.GetComponentInChildren<Renderer>();
if (rnd != null)
{
float colorT = maxDepth > 1 ? (float)depth / (maxDepth - 1) : 1f;
rnd.material.color = Color.Lerp(trunkColor, leafColor, colorT);
}
// 동적 크기 조절: 깊이에 따라 두께가 얇아짐
float thickness = 0.15f * (maxDepth - depth);
branch.transform.localScale = new Vector3(thickness, length, thickness);
// 가지의 끝 지점 계산
Vector3 endPoint = pos + rot * (Vector3.up * length);
// 길이 및 각도 세팅
float randomizedLengthMultiplier = Random.Range(1f - lengthRandomness, 1f + lengthRandomness);
float nextLength = length * scaleReduction * randomizedLengthMultiplier;
float angleStep = 360f / branchesPerLevel;
for (int i = 0; i < branchesPerLevel; i++)
{
float randTilt = Random.Range(-angleRandomness, angleRandomness);
float randSpin = Random.Range(-angleRandomness, angleRandomness);
Quaternion tilt = Quaternion.Euler(branchAngle + randTilt, 0, 0);
Quaternion spin = Quaternion.Euler(0, (i * angleStep) + (depth * 25f) + randSpin, 0);
Quaternion finalRot = rot * spin * tilt;
// 다음 가지 생성 코루틴 실행
StartCoroutine(CreateBranchRoutine(endPoint, finalRot, nextLength, depth + 1, pivot.transform));
}
}
}
// 바람에 흔들리는 효과를 담당하는 컴포넌트
public class BranchSway : MonoBehaviour
{
private Quaternion initialLocalRotation;
private float speed = 1f;
private float amount = 2f;
private float offset;
public void Init(int depth, float windStrength)
{
initialLocalRotation = transform.localRotation;
offset = Random.Range(0f, 100f);
speed = 1f + Random.Range(0f, 0.5f);
// 끝가지일수록, 그리고 windStrength가 강할수록 더 많이 흔들림. 잘 보이도록 수치를 키움
amount = 2.5f * (depth + 1) * windStrength;
}
void Update()
{
// 시간에 따라 부드럽게 흔들리도록 사인 곡선 적용
float angleX = Mathf.Sin(Time.time * speed + offset) * amount;
float angleZ = Mathf.Cos(Time.time * speed * 0.8f + offset) * amount;
transform.localRotation = initialLocalRotation * Quaternion.Euler(angleX, 0, angleZ);
}
}