본문 바로가기

Unity

How to completely make 'Minecraft'(마인크래프트를 통째로 만드는 방법)을 따라해보며 유니티(Unity)를 연구하자 : 06-(응용)다이아몬드블럭을 설정한 갯수만큼 랜덤위치에 심어보기

유튜브(Youtube) Vagabond Developer(방랑개발자)님의 How to completely make 'Minecraft'(마인크래프트를 통째로 만드는 방법)을 따라하면서 유니티(Unity)를 알아가고 있습니다.  그 정리입니다.

 

https://www.youtube.com/watch?v=xNozfY_Iah8

응용으로 지난번까지 만든 지형에 다이아몬드블럭을 설정한 갯수만큼 랜덤위치에 심어봅니다.

 

06-(응용)다이아몬드블럭을 설정한 갯수만큼 랜덤위치에 심어보기

 

구현방법

1)랜덤으로 심을 다이아몬드갯수를 설정받음

2)다이아몬드갯수만큼 지형내의 좌표를 랜덤하게 생성

3)지형작성시 다이아몬드 좌표이면 다이아몬드를 심음

 

이미지를 준비해 텍스처작성 / 큐브(Cube)를 추가하고 머티리얼(Material)입히기 / 프리팹(Prefab) 작성

구글(Google) 이미지검색에서 diamond를 아이콘사이즈로 검색해서 Diamond으로 저장, 팝업메뉴의 (Import New Asset...)로 임포트(Import)하거나 드래그해서 Textures폴더에 넣음

WorldGenerator스크립트(Script) 코딩

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

public class WorldGenerator : MonoBehaviour
{
    public GameObject player;

    public int sizeX;
    public int sizeZ;

    public int groundHeight;
    public float terDetail;
    public float terHeight;
    int seed;

    public GameObject[] blocks;

    //다이아몬드블럭
    public int diamondCount;   //다이아몬드블럭갯수
    List<Vector3> diamonds = new List<Vector3>(); //다이아몬드블럭의 좌표저장용
    bool diamondConflict; //다이아몬드블럭의 좌표인가?
    //다이아몬드블럭

    // Start is called before the first frame update
    void Start()
    {
        seed = Random.Range(100000,999999);
        GenerateTerrain();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void GenerateTerrain()
    {
        //다이아몬드블럭
        while (diamonds.Count<diamondCount)
        {
            int x = Random.Range(0, sizeX - 1); //지형사이즈내에서의 랜덤X좌표
            int z = Random.Range(0, sizeZ - 1); //지형사이즈내에서의 랜덤z좌표
            int y = Random.Range(1, groundHeight - 1); //지형사이즈내에서의 랜덤y좌표

            diamondConflict = false;
            //이미 다이아몬드블럭의 좌표로 설정되어있는가?
            for (int i = 0; i < diamonds.Count ; i++)
            {
                if(diamonds[i]==new Vector3(x,y,z))
                {
                    diamondConflict = true;
                    break;
                }
            }
            //다이아몬드블럭의 좌표가 아니라면 랜덤으로 얻은 좌료를 다이아몬드블럭의 좌표로 추가
            if(diamondConflict == false)
            {
                diamonds.Add(new Vector3(x, y, z));
            }
        }
        //다이아몬드블럭


        for (int x = 0; x < sizeX; x++)
        {
            for (int z = 0; z < sizeZ; z++)
            {
                int maxY = (int)(Mathf.PerlinNoise((x / 2 + seed) / terDetail, (z / 2 + seed) / terDetail) * terHeight);
                maxY += groundHeight;

                GameObject grass = Instantiate(blocks[0], new Vector3(x, maxY, z), Quaternion.identity) as GameObject;
                grass.transform.SetParent(GameObject.FindGameObjectWithTag("Environment").transform,false);


                for (int y = 0; y < maxY; y++)
                {
                    //다이아몬드블럭
                    diamondConflict = false;
                    //다이아몬드블럭의 좌표인가?
                    for (int i = 0; i < diamonds.Count; i++)
                    {
                        if (diamonds[i] == new Vector3(x, y, z))
                        {
                            diamondConflict = true; //다이아몬드블럭좌표임
                            break;
                        }
                    }
                    if (diamondConflict == false) //다이아몬드블럭좌표가아니면 기존블럭심기
                    {
                        int dirtLayers = Random.Range(1, 5);
                        if (y >= maxY - dirtLayers)
                        {
                            GameObject dirt = Instantiate(blocks[2], new Vector3(x, y, z), Quaternion.identity) as GameObject;
                            dirt.transform.SetParent(GameObject.FindGameObjectWithTag("Environment").transform, false);
                        }
                        else
                        {
                            GameObject stone = Instantiate(blocks[1], new Vector3(x, y, z), Quaternion.identity) as GameObject;
                            stone.transform.SetParent(GameObject.FindGameObjectWithTag("Environment").transform, false);
                        }
                    }
                    else  //다이아몬드블럭좌표이면 다이아몬드블럭심기
                    {
                        Instantiate(blocks[3], new Vector3(x, y, z), Quaternion.identity);
                    }
                    //다이아몬드블럭
                }

                if (x == (int)(sizeX / 2) && z == (int)(sizeZ / 2))
                {
                    Instantiate(player, new Vector3(x, maxY + 3, z), Quaternion.identity);
                }
            }
        }
    }
}

Environment오브젝트(Object)의 Blocks에 DiamondBlock프리팹(Prefab)설정

Blocks의 사이즈를 4로 변경 

추가로 표시되는 Element 3에 DiamondBlock프리팹(Prefab)을 설정(드래그 앤 드롭 또는 선택)

다이아몬드블럭 갯수 설정

DiamondCoun를 설정

실행

땅속에서 다이아몬드블럭 발견!

 

지형생성처리부분의 변경없이 기존블럭좌표위에 다이아몬드블럭을 심으면 다이아몬드블럭이 표시될 줄 알았는데 생각처럼 작동되지 않았습니다. 그래서 다이아몬드블럭좌표의 기존블럭을 삭제하고 다이아몬드블럭을 심으려했는데 해당 좌표의 블럭(게임오브젝트(GameObject))을 얻어오는 것에 성공하지 못했습니다.

결국은 지형생성처리부분을 변경해서 다이아몬드블럭의 좌표이면 다이아몬드블럭을, 그렇지 않으면 기존 블록을 표시하는 방법으로 처리했습니다.

반응형