프로그램/유니티 스크립트 소스

[유니티 스크립트 소스] Fish Flock

코더 제로 2021. 2. 2. 04:18
728x90
반응형

1. 설정

1.1 게임오브젝트 생성

 

 ① Flock.cs가 들어 갈 빈 게임오브젝트 생성(Main Camera을 대신 사용해도 됨).

 ② 물고기(Fish)들이 들어 갈 부모 게임오브젝트 생성

 

 

1.2 프리팹 생성

 

 물고기 프리팹 모델을 프리팹으로 만든 뒤 FishController.cs 소스를 컴포넌트에 넣음.

 

2. 소스

2.1 Flock.cs

using UnityEngine;

public class Flock : MonoBehaviour
{
    public GameObject m_Prfbfish;
    public GameObject m_PrntFish;
    public int m_Fish = 30;
    public static int m_Boundary = 7;
    public static GameObject[] m_Fishes;
    public static Vector3 m_TargetPosition = Vector3.zero;

    void Start()
    {
        m_Fishes = new GameObject[m_Fish];

        for (int i = 0; i < m_Fish; i++)
        {
            Vector3 position = new Vector3(
                Random.Range(-m_Boundary, m_Boundary),
                Random.Range(-m_Boundary, m_Boundary),
                Random.Range(-m_Boundary, m_Boundary)
            );

            GameObject fish = (GameObject)Instantiate(m_Prfbfish, position, Quaternion.identity);

            fish.transform.parent = m_PrntFish.transform;
            m_Fishes[i] = fish;
        }
    }
    
    void Update()
    {
        GetTargetPosition();
    }

    void GetTargetPosition()
    {
        if (Random.Range(1, 10000) < 50)
        {
            m_TargetPosition = new Vector3(
                Random.Range(-m_Boundary, m_Boundary),
                Random.Range(-m_Boundary, m_Boundary),
                Random.Range(-m_Boundary, m_Boundary)
            );
        }
    }
}

 

2.2 FishController.cs

using UnityEngine;

public class FishController : MonoBehaviour 
{
	public float m_MaxSpeed = 2.0f;
	public float m_MaxTurnSpeed = 0.5f;
	private float m_Speed;
	private float m_NeighborDistance = 3.0f;
	private bool m_IsTurning = false;
		
	void Start () 
	{
		m_Speed = Random.Range (0.5f, m_MaxSpeed);
	}
		
	void Update () 
	{
		GetIsTurning ();

		if(m_IsTurning) 
		{
			Vector3 direction = Vector3.zero - transform.position;
			transform.rotation = Quaternion.Slerp (transform.rotation,
				Quaternion.LookRotation (direction),
				TurnSpeed () * Time.deltaTime);
			m_Speed = Random.Range (0.5f, m_MaxSpeed);
		} 
		
		else
		{
			if (Random.Range (0, 5) < 1)
				SetRotation ();
		}

		transform.Translate (0, 0, Time.deltaTime * m_Speed);
	}

	void GetIsTurning() 
	{
		if(Vector3.Distance(transform.position, Vector3.zero) >= Flock.m_Boundary) 
		{
			m_IsTurning = true;
		}
		
		else 
		{
			m_IsTurning = false;
		}
	}

	void SetRotation()
	{
		GameObject[] fishes;
		fishes = Flock.m_Fishes;

		Vector3 center = Vector3.zero;
		Vector3 avoid = Vector3.zero;
		float speed = 0.1f;

		Vector3 targetPosition = Flock.m_TargetPosition;

		float distance;
		int groupSize = 0;

		for (int i = 0; i < fishes.Length; i++)
		{
			if (fishes[i] != gameObject)
			{
				distance = Vector3.Distance(fishes[i].transform.position, transform.position);

				if (distance <= m_NeighborDistance)
				{
					center += fishes[i].transform.position;
					groupSize++;

					if (distance < 0.75f)
					{
						avoid += (transform.position - fishes[i].transform.position);
					}

					FishController anotherFish = fishes[i].GetComponent<FishController>();
					speed += anotherFish.m_Speed;
				}
			}
		}

		if (groupSize > 0) 
		{
			center = center / groupSize + (targetPosition - transform.position);
			m_Speed = speed / groupSize;

			Vector3 direction = (center + avoid) - transform.position;
			if (direction != Vector3.zero) {
				transform.rotation = Quaternion.Slerp (transform.rotation,
					Quaternion.LookRotation (direction),
					TurnSpeed () * Time.deltaTime);
			}
		}
 	}

	float TurnSpeed()
	{
		return Random.Range (0.2f, m_MaxTurnSpeed);
	}
 }

 

728x90
반응형