게임클라이언트 프로그래밍/3D Project

무한으로 생성되는 오브잭트, Random.Range / System.Random

Game Client Lee Hwanguk 2023. 8. 5. 19:58

* 게임이 시작되면 player는 z축으로 이동한다. 이때 player가 무한으로 이동할 수 있는 지면을 생성해 주어야한다.

미리 생성해놓은 지면 오브잭트를 프리팹화 한 후 AreaSpawner 오브잭트에서 일정 조건이 일치하면 무한으로 생성해주고

이미 지나간 지면은 파괴하게 만들어봤다.

 

1. AreaSpawner

 * Instantiate, Destroy

지면으로 쓰일 오브잭트의 길이는 z=20f로 미리 만들어 놓았다. 지면 오브잭트는 Awake 메소드에서 3개를 미리 생성한 후 플레이어가 일정 지점에 도달하면 기존의 지면을 Destroy 한 후 새로운 지면을 생성하게 만들었다.

 

*Random.Range / System.Ramdom

프리팹으로 만들어 놓은 지면(Area)오브잭트들의 메테리얼을 모두 다르게 설정 후 랜덤성을 체크해 보았다.

유니티에서 제공하는  Random.Range는 랜덤성이 떨어져 보였다. system.Random을 사용하여 랜덤성을 높였다.

 

2. Area

*Player의 Transform 전달

Setup메서드를 만들어 AreaSpawner와 player의 Transform을 전달하였다.

플레이어의 위치에서 현재 위치의 지면의 값을 뺀 값이 destroyDistance 이하라면 오브잭트를 Destroy하였다.

 

3. Test

*Script

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class AreaSpawner : MonoBehaviour
{
    [SerializeField]
    private GameObject[] areaPrefabs;
    [SerializeField]
    private int spawnAreaCountAtStart = 3;
    [SerializeField]
    private float zDistance = 20;
    private int areaIndex = 0;

    [SerializeField]
    private Transform playerTrans;

    private System.Random random;

    private void Awake()
    {

        this.random = new System.Random();


        for (int i=0; i<this.spawnAreaCountAtStart; ++i)
        {
            if (i == 0)
            {
                this.SpawnArea(false);
            }
            else
            {
                this.SpawnArea();
            }
        }
    }

    public void SpawnArea(bool isRandom = true)
    {
        Debug.Log(isRandom);
        GameObject clone = null;

        if(isRandom == false)
        {
            clone = Instantiate(this.areaPrefabs[0]);
        }
        else
        {
            //int index = Random.Range(0, this.areaPrefabs.Length); //랜덤성이 떨어져보임 
            int index = isRandom ? random.Next(0, this.areaPrefabs.Length) : 0;

            clone = Instantiate(this.areaPrefabs[index]);
        }

        //area가 배치되는 위치 설정(z축 현재 구역 인덱스 *zDistance)
        clone.transform.position = new Vector3(0, 0, this.areaIndex * this.zDistance);

        //area가 삭제될때 새로운 area를 생성 할 수 있도록 this와 player의 transform 전달
        clone.GetComponent<Area>().Setup(this, playerTrans);
        this.areaIndex++;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Area : MonoBehaviour
{
    [SerializeField]
    private float destroyDistance = 15;
    private AreaSpawner areaSpawner;
    private Transform playerTrans;
    
    public void Setup(AreaSpawner areaSpawner, Transform playerTrans)
    {
        this.areaSpawner = areaSpawner;
        this.playerTrans = playerTrans;
    }

    void Update()
    {
        if(this.playerTrans.position.z - this.transform.position.z>=this.destroyDistance)
        {
            this.areaSpawner.SpawnArea();
            Destroy(gameObject);
        }
    }
}