[Unity] 빌딩 시스템 만들기 #1. UI , Connector Data
[이전 편]
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 위치값을 저장합니다.
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로 데이터 가져오기 (추후 포스팅 예정)
[ UI ]
1. 해당 slot는 type Num과 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