2 minute read

개요

게임 개발에서 랜덤 좌표에 게임오브젝트를 생성해야될 때가 있습니다.(몬스터, 보스의 범위공격 등등) 기초적인 부분이지만 한번 짚고 가도록 하겠습니다.


순서

  1. 생성할 영역을 지정
  2. 좌표를 랜덤으로 지정
  3. 지정한 랜덤 좌표에 오브젝트를 생성(이미 생성되있는 오브젝트에 랜덤 좌표 입력)

예제


선언

    #region private
    [SerializeField] GameObject m_prefab;
    [SerializeField] BoxCollider m_area;
    [SerializeField] Button m_random_button;
    [SerializeField] Button m_init_button;
    [SerializeField] int m_count;

    bool m_isExist;
    List<GameObject> m_cubelist;

    #endregion

사용할 오브젝트, 전역변수, 지정영역을 선언
m_prefab : Prefab화한 게임오브젝트
m_area : 오브젝트를 생성할 지정영역
m_random_button : 좌표를 랜덤으로 생성하는 버튼
m_init_button : 초기화 버튼
m_count : 몇개의 오브젝트를 생성할것인지를 Editor상의 Component에서 정하기
m_isExist : 오브젝트가 생성되었는지 아닌지를 판단할 플래그
m_cubelist : 생성한 오브젝트를 관리할 리스트


영역 및 랜덤 좌표 지정 부분

    /// <summary>
    /// Calculate Random Pos
    /// </summary>
    /// <returns>Vector3 type Pos</returns>
    private Vector3 CalcRandomPos()
    {
        Vector3 _prefab_size = m_prefab.GetComponent<Transform>().localScale;
        Vector3 _size = m_area.size;

        float _pos_x = Random.Range(-20,20) + Random.Range(-_size.x/2f, _size.x/2f) + _prefab_size.x;
        float _pos_z = Random.Range(-20,20) + Random.Range(-_size.z/2f, _size.z/2f) + _prefab_size.z;

        return new Vector3(_pos_x, 1, _pos_z);
    }


Initialize및 오브젝트 생성 부분



    private void Initializa()
    {
        m_random_button.onClick.AddListener(OnPushRandomButton);
        m_init_button.onClick.AddListener(OnPushInitButton);

        m_cubelist = new List<GameObject>();
        m_isExist = false;
    }

    /// <summary>
    /// Activate When Press Random Button
    /// </summary>
    private void OnPushRandomButton()
    {
        var random_pos = Vector3.zero;
        GameObject _instance;

        // if already Instantiate Object, or not
        if (!m_isExist) {
            m_isExist = true;
            for (int count = 0; count < m_count; count++) {
                random_pos = CalcRandomPos();
                _instance = Instantiate(m_prefab, random_pos, Quaternion.identity);
                m_cubelist.Add(_instance);
            }
        } else {
            // if already Exist, change Pos
            for(int count = 0; count < m_count; count++) {
                m_cubelist[count].transform.position = CalcRandomPos();
            }
        }
    }

초기화함수에서 버튼을 누르면 실행할 함수를 지정하고 리스트 및 플래그등을 초기화
OnpushRandomButton()함수내에서 생성할때 아래의 지역변수 randonPos 를 선언하지 않고 CalcRandomPos()함수를 Instantiate에 바로 넣어도 상관은 없으나,
가독성의 문제로 지역변수를 선언-> Instantiate에 넣는 방식으로 하였습니다.

/// <summary>
    /// Activate When Press Random Button
    /// </summary>
    private void OnPushRandomButton()
    {
        var random_pos = Vector3.zero;
        GameObject _instance;

        // if already Instantiate Object, or not
        if (!m_isExist) {
            m_isExist = true;
            for (int count = 0; count < m_count; count++) {
                random_pos = CalcRandomPos();
                _instance = Instantiate(m_prefab, random_pos, Quaternion.identity);
                m_cubelist.Add(_instance);
            }
        } else {
            // if already Exist, change Pos
            for(int count = 0; count < m_count; count++) {
                m_cubelist[count].transform.position = CalcRandomPos();
            }
        }
    }

전체 코드



public class GameManager : MonoBehaviour
{
    #region private
    [SerializeField] GameObject m_prefab;
    [SerializeField] BoxCollider m_area;
    [SerializeField] Button m_random_button;
    [SerializeField] Button m_init_button;
    [SerializeField] int m_count;

    bool m_isExist;
    List<GameObject> m_cubelist;


    #endregion

    private void Awake()
    {
        Initializa();
    }

    private void Initializa()
    {
        m_random_button.onClick.AddListener(OnPushRandomButton);
        m_init_button.onClick.AddListener(OnPushInitButton);

        m_cubelist = new List<GameObject>();
        m_isExist = false;
    }

    /// <summary>
    /// Activate When Press Random Button
    /// </summary>
    private void OnPushRandomButton()
    {
        var random_pos = Vector3.zero;
        GameObject _instance;

        // if already Instantiate Object, or not
        if (!m_isExist) {
            m_isExist = true;
            for (int count = 0; count < m_count; count++) {
                random_pos = CalcRandomPos();
                _instance = Instantiate(m_prefab, random_pos, Quaternion.identity);
                m_cubelist.Add(_instance);
            }
        } else {
            // if already Exist, change Pos
            for(int count = 0; count < m_count; count++) {
                m_cubelist[count].transform.position = CalcRandomPos();
            }
        }
    }

    /// <summary>
    /// Calculate Random Pos
    /// </summary>
    /// <returns>Vector3 type Pos</returns>
    private Vector3 CalcRandomPos()
    {
        Vector3 _prefab_size = m_prefab.GetComponent<Transform>().localScale;
        Vector3 _size = m_area.size;

        float _pos_x = Random.Range(-20,20) + Random.Range(-_size.x/2f, _size.x/2f) + _prefab_size.x;
        float _pos_z = Random.Range(-20,20) + Random.Range(-_size.z/2f, _size.z/2f) + _prefab_size.z;

        return new Vector3(_pos_x, 1, _pos_z);
    }

    /// <summary>
    /// Activate When Press Initialize Button
    /// </summary>
    private void OnPushInitButton()
    {
        m_isExist = false;
        for(int count = 0; count < m_cubelist.Count; count ++)
        {
            Destroy(m_cubelist[count]);
        }
        m_cubelist.Clear();
    }
}


실행 영상



[초기화버튼 추가]


Top

Updated: