OldBlueWater/BlueWater/Assets/02.Scripts/Boids.cs

97 lines
3.5 KiB
C#
Raw Normal View History

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<MeshRenderer>();
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;
}
}
}