using System.Collections; using Sirenix.OdinInspector; using UnityEngine; using Random = UnityEngine.Random; // ReSharper disable once CheckNamespace namespace BlueWaterProject { public class Boids : MonoBehaviour { [Title("군집(떼) 설정")] [Tooltip("Boid 프리팹")] [SerializeField] private Boid boidPrefab; [Range(1, 1000)] [Tooltip("생성할 개체 수")] [SerializeField] private int boidCount = 5; [Range(5, 100)] [Tooltip("개체 생성 범위")] [SerializeField] private float spawnRange = 10; [field: Tooltip("개체의 랜덤 속도 값\nx == Min\ny == Max")] [field: SerializeField] public Vector2 RandomSpeedRange { get; private set; } = new(5, 10); [field: Range(0, 10)] [field: Tooltip("응집력(뭉치기) 가중치")] [field: SerializeField] public float CohesionWeight { get; private set; } = 1; [field: Range(0, 10)] [field: Tooltip("정렬(같은 방향) 가중치")] [field: SerializeField] public float AlignmentWeight { get; private set; } = 1; [field: Range(0, 10)] [field: Tooltip("분리(서로 회피) 가중치")] [field: SerializeField] public float SeparationWeight { get; private set; } = 1; [field: Range(0, 100)] [field: Tooltip("경계 범위 내 행동 가중치")] [field: SerializeField] public float BoundsWeight { get; private set; } = 1; [field: Range(0, 100)] [field: Tooltip("장애물 회피 가중치")] [field: SerializeField] public float ObstacleWeight { get; private set; } = 10; [field: Range(0, 10)] [field: Tooltip("자아(독립행동) 가중치")] [field: SerializeField] public float EgoWeight { get; private set; } = 1; [Title("옵션")] [Tooltip("경계 범위 On/Off")] [SerializeField] private bool showBounds; public MeshRenderer BoundMeshRenderer { get; private set; } private void OnValidate() { if (BoundMeshRenderer) { BoundMeshRenderer.enabled = showBounds; } } private void Start() { CreateBoids(); } private void CreateBoids() { BoundMeshRenderer = GetComponentInChildren(); BoundMeshRenderer.enabled = showBounds; var myTransform = transform; for (var i = 0; i < boidCount; i++) { var randomPos = Random.insideUnitSphere * spawnRange; var randomRotation = Quaternion.Euler(0, Random.Range(0, 360f), 0); var boid = Instantiate(boidPrefab, myTransform.position + randomPos, randomRotation, myTransform); boid.Init(this, Random.Range(RandomSpeedRange.x, RandomSpeedRange.y)); } } public void SetBoundPos(Vector3 value) => BoundMeshRenderer.transform.position = value; public void SetBoundPosLerp(Vector3 value, float time) => StartCoroutine(BoundPosLerpCoroutine(value, 1/time)); private IEnumerator BoundPosLerpCoroutine(Vector3 value, float time) { while (Vector3.Distance(transform.position, value) > 0.1f) { transform.position = Vector3.Lerp(transform.position, value, time * Time.deltaTime); yield return null; } transform.position = value; } } }