TIL

유니티 오브젝트 리스폰 시키기

박민혁_kog 2023. 9. 27. 20:51

원리 

스포닝풀 방식

게임오브젝트[]배열 model에 프리팹들 (현재 나무)를넣어둠 나무1 나무2

카운트 갯수 =유니티 갯수 만큼 받음

게임오브젝트(나무) 를 큐에 넣고

코루틴으로

큐에갯수가 있다면 박스 콜라이더에 랜덤 위치 뿌림 

리소스 스크립트는 오브젝트가 삭제시 스포너스크립트의 큐에 다시넣음=

큐갯수가 0이아님 = 랜덤 위치에 또뿌림

 

 

스포너 스크립트

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
using static UnityEngine.InputSystem.LowLevel.InputStateHistory;
using UnityEngine.UI;
using System.Linq;

public class Spawner : MonoBehaviour
{
    public GameObject rangeObject;
    BoxCollider rangeCollider;
    public GameObject[] Model;
    public Queue<GameObject> T_queue;//이부분 static으로 했었는데 그게 버그였음
    public int count;

    [Serialize]private float spawnDleay=20;
    [Serialize] private float objectDleayCount;

    //public TreeSpawn Instance;

    private void Awake()
    {
        T_queue = new Queue<GameObject>();
        rangeCollider = rangeObject.GetComponent<BoxCollider>();
        //Instance= this;
    }

    void Start()
    {
        for (int i = 0; i < count; i++)
        {
            GameObject choiceModel = Model[Random.Range(0, Model.Count())];
            GameObject t_object = Instantiate(choiceModel, this.gameObject.transform);
            t_object.transform.Rotate(new Vector3(0, Random.Range(-180,180), 0));
            T_queue.Enqueue(t_object);
            t_object.SetActive(false);
        }

        StartCoroutine(TreeMaker());
    }

    public void InsertQueue(GameObject p_object)
    {
        T_queue.Enqueue(p_object);
        p_object.SetActive(false);
    }
    public Queue<GameObject> returnQueue() 
    {
        return T_queue;
    }

    public GameObject GetQueue()
    {
        GameObject t_object = T_queue.Dequeue();
        t_object.SetActive(true);

        return t_object;
    }


    IEnumerator TreeMaker()
    {
        float dealy = 0.01f;
        while (true)
        {
            if (T_queue.Count != 0)
            {
                
                GameObject t_object = GetQueue();
                t_object.transform.position = Return_RandomPosition();
                if (T_queue.Count <= 5)
                    dealy = spawnDleay;

            }
            yield return new WaitForSeconds(dealy);
        }
    }

    Vector3 Return_RandomPosition()
    {
        Vector3 originPosition = rangeObject.transform.position;
        // 콜라이더의 사이즈를 가져오는 bound.size 사용
        float range_X = rangeCollider.bounds.size.x;
        float range_Z = rangeCollider.bounds.size.z;

        range_X = Random.Range((range_X / 2) * -1, range_X / 2);
        range_Z = Random.Range((range_Z / 2) * -1, range_Z / 2);
        Vector3 RandomPostion = new Vector3(range_X, 0f, range_Z);

        Vector3 respawnPosition = originPosition + RandomPostion;
        return respawnPosition;
    }

}

리소스 스크립트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Resource : MonoBehaviour
{
    public Item[] dropItem;
    public int quantityPerHit = 1;
    public int capacity;
    public GameObject spawnOBJ;
    private Spawner spawn;
    private void Start()
    {
        spawn=spawnOBJ.GetComponent<Spawner>();
    }
    public void Gather(Vector3 hitPoint, Vector3 hitNormal) 
    {
        for (int i = 0; i < quantityPerHit; ++i) 
        {
            if (capacity <= 0) { break; }
            capacity -= 1;
            for (int j = 0; j < capacity; ++j) 
            {
                Instantiate(dropItem[j].itemPrefab, hitPoint + Vector3.up, Quaternion.LookRotation(hitNormal, Vector3.up));
            }

        }
        if (capacity <= 0) 
        {

            spawn.InsertQueue(gameObject);
            Destroy(gameObject);

        }
    }
}