[이전 편]

https://youcheachae.tistory.com/5#comment21549004

 

[Unity] 빌딩 시스템 만들기 #0. 구상

[시스템 구성 전]1. 한글로된 빌딩 snap 기능이 없어서 검색을 해보다가 connector를 사용하여  raycast를 사용한 빌딩 시스템을 발견.2. 현재 프로젝트에는 위의 방법으로 하는것은 어렵다고 판단.3. Sn

youcheachae.tistory.com

 


[Connector]

#0.구상 편에서 언급한 Connector에 대한 정보를 저장해야 합니다.

 

<ConnectorGroup>

[System.Serializable]
public enum ConnectorGroupType
{
    FloorConnectorGroup,
    CellingConnectorGroup,
    BasicWallConnectorGroup,
    RotatedWallConnnectorGroup,
    None
}

- 블럭 type에 따라 사용하는 커넥터를 나타내기 위한 enum입니다.

- type이 floor이라면 connectorGroup는 FloorConnectorGroup이고, celling또한 마찬가지 입니다.

- wall일때는 두가지로 나뉩니다. y가 90도로 회전이 되어있으면 connectorGroup은 rotatedWallConnectorGroup , 회전이 없다면 BasicWallConnectorGroup 입니다.

- 커넥터를 생성, 삭제하지 않는 블럭도 존재하니, None 멤버도 선언합니다.

 

<ConnectorType>

[System.Serializable]
public enum ConnectorType
{
    FloorConnector,
    CellingConnector,
    BasicWallConnector,
    RotatedWallConnector
}

 

- 커넥터를 설치 할 때 해당 커넥터의 회전, layermask를 설정하기 위한 enum입니다.

커넥터 오브젝트

- ConenctorType이 FloorConenctor : 회전값 : (90f, 0f, 0f) , LayerMask : FloorConnectorLayer

- ConenctorType이 CellingConnector : 회전값 : (90f, 0f, 0f) , LayerMask : CellingConnectorLayer

- ConenctorType이 BasicWallConnector : 회전값 : (0f,0f,0f) , LayerMask : WallConnectorLayer

- ConnectorType이 RotatedWallConnector : 회전값 : (0f, 90f, 0f) , LayerMask : WallConnector

 

(+) 참고 : building System에 사용하는 LayerMask 입니다.

 

<Connector 구조체>

// 커넥터 구조체 
[System.Serializable]
public struct Connector
{
    public string name;
    private List< Tuple<ConnectorType , Vector3 >> _connectorTypeList;         // 커넥터들의 타입 ,  위치 

    public List<Tuple<ConnectorType, Vector3>> connectorList => _connectorTypeList;   

    public void F_SetConector(List<Tuple<ConnectorType, Vector3>> v_typeList)
    {
        this._connectorTypeList = v_typeList;
    }

    public static readonly Connector Defalt = new Connector()
    {
        name = string.Empty,
        _connectorTypeList = new List<Tuple<ConnectorType, Vector3>>()
    };
}

- 커넥터 구조체를 선언합니다.

- ConnectorGroup별 사용하는 ConnectorType과 Vector3 위치값을 저장합니다.

보라색 : floor , 주황색 : wall , 파랑색 celling

1. Type이 Foor인 블럭이 가지는 커넥터 

 // 1. floor 데이터 지정 
 List<Tuple<ConnectorType, Vector3>> _connType1 = new List<Tuple<ConnectorType, Vector3>>
 {
      new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(-2.5f , 2.5f ,0) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, 2.5f , 2.5f)),
      new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(2.5f , 2.5f ,0) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, 2.5f , -2.5f)),
      new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(-2.5f , -2.5f ,0) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, -2.5f , 2.5f) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(2.5f , -2.5f ,0) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, -2.5f , -2.5f) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.FloorConnector, new Vector3(-5 , 0, 0) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.FloorConnector, new Vector3(0,0, 5) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.FloorConnector, new Vector3(5 ,0,0) ),
      new Tuple<ConnectorType, Vector3>( ConnectorType.FloorConnector, new Vector3(0,0, -5) )
 };

2. Type이 Celling인 블럭이 가지는 커넥터 

 

// 2. celling 데이터 지정 
List<Tuple<ConnectorType, Vector3>> _connType2 = new List<Tuple<ConnectorType, Vector3>>
 {
     new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(-2.5f , 2.5f ,0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, 2.5f , 2.5f)),
     new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(2.5f , 2.5f ,0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, 2.5f , -2.5f)),
     new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(-2.5f , -2.5f ,0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, -2.5f , 2.5f) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3(2.5f , -2.5f ,0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3(0, -2.5f , -2.5f) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3(-5 , 0, 0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3(0,0, 5) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3(5 ,0,0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3(0,0, -5) )
 };

3. Type이 Wall인 블럭이 가지는 커넥터 

 

// 3. wall 데이터 지정
List<Tuple<ConnectorType, Vector3>> _connType3 = new List<Tuple<ConnectorType, Vector3>>()
{
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3( 0, 5f , 0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3( 5f, 0 , 0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3( 0 , -5f ,0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.BasicWallConnector, new Vector3( -5f, 0, 0) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( 0f ,2.5f, -2.5f) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( 0f, 2.5f, 2.5f) ),
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( 0 , -2.5f ,2.5f) ),    
     new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( 0 , -2.5f, -2.5f) ),
 };

4. Type이 Rotated wall 인 블럭이 가지는 커넥터 

 

        // 4. rotated wall 데이터 지정
        List<Tuple<ConnectorType, Vector3>> _connTyp4 = new List<Tuple<ConnectorType, Vector3>>()
        {
             new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3( 0, 5f , 0) ),
             new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3( 0, 0 , 5f)  ),
             new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3( 0 , -5f ,0) ), 
             new Tuple<ConnectorType, Vector3>( ConnectorType.RotatedWallConnector, new Vector3( 0 , 0, -5f) ),
             new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( 2.5f , 2.5f, 0) ),
             new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3(-2.5f , 2.5f ,0) ),
             new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( -2.5f , -2.5f ,0) ),
             new Tuple<ConnectorType, Vector3>( ConnectorType.CellingConnector, new Vector3( 2.5f , -2.5f, 0) ),
        };

 

- 각 type에 해당하는 커넥터를 선언한 후 , Connector 타입의 배열에 담아줍니다.

- 이로써 블럭 type에 맞는 ConnectorGroup을 배열을 통해 쉽게 접근할 수 있습니다.

    [SerializeField] private Connector[] _connectorContainer;
    
    public void F_SetConnArr(Connector con1, Connector con2, Connector con3, Connector con4)
    {
        _connectorContainer = new Connector[System.Enum.GetValues(typeof(ConnectorGroupType)).Length];       // 커넥터 타입만큼 배열 생성

        _connectorContainer[ (int)ConnectorGroupType.FloorConnectorGroup ]        = con1;
        _connectorContainer[ (int)ConnectorGroupType.CellingConnectorGroup ]      = con2;
        _connectorContainer[ (int)ConnectorGroupType.BasicWallConnectorGroup ]    = con3;
        _connectorContainer[ (int)ConnectorGroupType.RotatedWallConnnectorGroup ] = con4;
        _connectorContainer[ (int)ConnectorGroupType.None ]                       = Connector.Defalt;
    }

 


[Block]

1. 각 블럭이 가지고 있어야할 데이터

 

<HousingBlock.cs>

    private int _blockTypeNum;                      // 블럭 type num
    private int _blockDetailNum;                    // 블럭 detail num
    private ConnectorGroupType _blockConnectorGroup;// 어떤 connector group을 사용하는지
    private Vector3 _blockRotation;                 // 'r' input시 얼마나 회전 할 것인지 
    private int _blockHp;                           // hp
    private int _blockMaxHp;                        // max hp
    private Sprite _blockSprite;                    // ui상 사용할 이미지
    private string _blockName;                      // ui상 사용할 block 이름
    private string _blockToopTip;                   // ui상 사용할 block 설명

 

2. 블럭 데이터는List에 [_blockTypeNum][_blcokDetailNum]으로 쉽게 접근하기 위해서 2차원 List로 저장되어 있습니다.

 

<HousingDataManager.cs>

    [Header("Housing Block List ")]
    private List<List<HousingBlock>> _blockDataList;
    private List<HousingBlock> _Floor;        // 0. 바닥 
    private List<HousingBlock> _Celling;      // 1. 지붕
    private List<HousingBlock> _Wall;         // 2. 벽
    private List<HousingBlock> _Door;         // 3. 문
    private List<HousingBlock> _Window;       // 4. 창문
    private List<HousingBlock> _Repair;       // 5. 수리도구
    
    private void F_InitHousingBLockList() 
    {
        _Floor = new List<HousingBlock>();
        _Celling = new List<HousingBlock>();
        _Wall = new List<HousingBlock>();
        _Door = new List<HousingBlock>();
        _Window = new List<HousingBlock>();
        _Repair = new List<HousingBlock>();

        _blockDataList = new List<List<HousingBlock>>
        {
            _Floor,
            _Celling,
            _Wall,
            _Door,
            _Window,
            _Repair
        };
    }

 

3. CVS로 데이터 가져오기 (추후 포스팅 예정)

엑셀로 정리한 데이터 , 추후 cvs 파일로 가지고 있을예정


[ UI ]

1. 해당 slot는 type Num과 detail Num이 존재합니다.

typeNum , Detail Num 순서입니다.

 

2. <HousingSlot.cs>

: 마우스커서를 slot에 enter할 시 인덱스를 저장합니다 

public class HousingSlot : MonoBehaviour , IPointerEnterHandler 
{
    [SerializeField]
    private int _typeNum;
    [SerializeField]
    private int _detialNum;
    
    // 프로퍼티
    public int typeNum { get => _typeNum; set { _typeNum = value; } }
    public int detialNum { get => _detialNum; set { _detialNum = value; } }

    public void OnPointerEnter(PointerEventData eventData)
    {
        HousingUiManager.instance.F_SetBlockNum( _typeNum , _detialNum);
    }

}

 

3. <HousingManager.cs>

: 추후에 저장된 idx로 housingBlock 데이터와 하우징 프리팹 List에 접근합니다.

public class MyBuildManager : MonoBehaviour
{   
    [SerializeField] public List<List<GameObject>> _bundleBulingPrefab;
    [SerializeField] private List<GameObject> _floorList;
    [SerializeField] private List<GameObject> _cellingList;
    [SerializeField] private List<GameObject> _wallList;
    [SerializeField] private List<GameObject> _doorList;
    [SerializeField] private List<GameObject> _windowList;
    
    private void Awake()
    {
        // 1. 초기화                      
        _bundleBulingPrefab = new List<List<GameObject>> // 각 block 프리팹 List를 하나의 List로 묶기
        {
            _floorList,
            _cellingList,
            _wallList,
            _doorList,
            _windowList
        };
        
     }
}

: 하우징 프리팹 또한 [_blockTypeNum][_blcokDetailNum]으로 쉽게 접근하기 위해서 2차원 List로 저장되어 있습니다.

 

4. <HousingUiManager.cs>

우클릭 시 ui가 켜지고 , 블럭 선택 후 우클릭을 해제하면 building이 시작 됩니다.

    [SerializeField] GameObject _buildingBlockSelectUi;     // block 선택 ui 
    [SerializeField] int _typeIdx;			// 타입 인덱스
    [SerializeField] int _detailIdx;	        	// 디테일 인덱스
    
    // housing UI On Off 
    private void Update()
    {
        // 우클릭시 : Ui On
         if (Input.GetMouseButtonDown(1)) 
             _buildingBlockSelectUi.SetActive(true);
	
	// 우클릭 떼면 : Ui Off
     	else if(Input.GetMouseButtonUp(1))
        {
            // 1. Ui Off
            _buildingBlockSelectUi.SetActive(false);
            // 2. Ui off시 동작
            F_WhenHousingUiOff();
        }

    }
    
    private void F_WhenHousingUiOff() 
    {
	   // 1. index 검사
       // 1-1. 유효하지 않으면 return
        if (_nowOpenPanel < 0 || _nowOpenDetailSlot < 0)
            return;
        // 1-2. 유효하면 : building 시작
        else 
            HousingManager.Instance.F_BuildingMovement(_typeIdx , _detailIdx);
    }
    
    public void F_SetBlockNum(v_type , v_detail)
    {
    	this._typeIdx = v_type;
        this._detailIdx = v_detail;
    }

 



https://github.com/churush912837465

 

churush912837465 - Overview

churush912837465 has 4 repositories available. Follow their code on GitHub.

github.com

 

+ Recent posts