public enum Type{None,
MainCenter, AtkBuilding, ResourceCenter,
EnemyMainCenter, EnemyAtkBuilding, EnemyResourceCenter}
public Type buildingType; //현재 노드 위 건물의 타입
public enum NodeType{Player, Enemy, None}
public NodeType nodeType; //현재 노드를 점령중인 타입
public List<List<GameObject>> adjNodeWay;
public int adjNodeIndex; //연결되어 있는 노드의 수
//public List<GameObject> nearWay; //연결되어 있는 길
public int nearWayIndex; //연결되어 있는 길의 수
public GameObject[] buildingObj; //건물 오브젝트가 담기는 배열
public Transform buildingArea; //건물이 지어질 구역
GameObject BuildOnArea; //건물
public SphereCollider detectArea; //공격을 감지할 범위
MeshRenderer mesh;
public float maxLifeScore; //현재 노드 최대값, 상황에 맞게 변함(ex 주변 노드 개수)
public float lifeScore; //현재 노드 수치
public float unitOutSpeed; //유닛 생산속도
public float recoverLifeScore; //노드 체력 회복 수치
public float recoverLifeTime; //노드 체력 회복 속도
public float attackScore; //노드의 공격력
public bool fightTrigger; //전투 트리거용(스위치, 추후삭제)
public bool buildMode; //건물을 선택하고 체크 (스위치)
public bool delNode; //삭제 트리거(스위치)
public bool underMaxLife; //체력회복 여부
public bool built; //건설여부, true일 경우 건물이 올라가 있다는 뜻
public bool playerArea; //플레이어의 영토인지 체크되는 boolean
public bool enemyArea; //적의 영토인지 체크되는 boolean
public bool neutralityArea; //영토가 중립상태인지 체크되는 boolean
지형은 진영(플레이어, 적)의 건물이 세워질 포인트로 위와 같은(일시:04.03) 변수를 가진다.
인접노드와 그와 연결된 간선은 이중리스트로 관리한다. 별개의 배열로 관리할 경우 순서에 변경이 생길때 오류가 생길 수 있기 때문이다. 리스트의 요소는 노드 : [ 0 ], 간선 : [ 1 ] 으로 정한다.
//건물이 지어져있는지 감지
void IsBuilt(){
if(buildingArea == buildingObj[0]){
built = false;
}
}
//건물을 짓는 함수
void Build(Type bType){
if(!buildMode){
return;
}
if(BuildOnArea){
Destroy(BuildOnArea);
}
switch(bType){
case Type.None :
BuildOnArea = Instantiate(buildingObj[0], buildingArea.position + Vector3.up, transform.rotation);
break;
case Type.MainCenter :
BuildOnArea = Instantiate(buildingObj[1], buildingArea.position + Vector3.up, transform.rotation);
break;
case Type.AtkBuilding :
BuildOnArea = Instantiate(buildingObj[2], buildingArea.position + Vector3.up, transform.rotation);
break;
case Type.ResourceCenter :
BuildOnArea = Instantiate(buildingObj[3], buildingArea.position + Vector3.up, transform.rotation);
break;
case Type.EnemyMainCenter :
BuildOnArea = Instantiate(buildingObj[4], buildingArea.position + Vector3.up, transform.rotation);
break;
case Type.EnemyAtkBuilding :
BuildOnArea = Instantiate(buildingObj[5], buildingArea.position + Vector3.up, transform.rotation);
break;
case Type.EnemyResourceCenter :
BuildOnArea = Instantiate(buildingObj[6], buildingArea.position + Vector3.up, transform.rotation);
break;
}
buildMode = false;
}
IsBuilt는 현재 건물이 지어져 있는지 아닌지를 판별하는 함수로 Update주기로 호출된다.
Build함수는 노드 위 건물을 생성하는 함수로 buildingObj배열에 있는 오브젝트를 상황에 맞게 생성한다. 위치는 노드보다 +y축이다.
buildingObj배열은 유니티의 Inspector창에서 설정한다.
buildingObj 배열
각 오브젝트들은 모두 prefab으로 구성된다.
public void LifeSensor(){ //현재 체력이 최대보다 적을 경우 bool타입 변수를 변경
if(lifeScore < maxLifeScore){
underMaxLife = true;
}else{
underMaxLife = false;
}
}
IEnumerator RecoverLife(){ //체력회복 코루틴, 발동조건은 위 함수를 따른다.
while(underMaxLife == true){
if(lifeScore < maxLifeScore){
lifeScore += recoverLifeScore;
if(lifeScore > maxLifeScore){
lifeScore = maxLifeScore;
}
}
yield return new WaitForSecondsRealtime(recoverLifeTime); //체력회복주기는 변수에 의존
}
}
public void Damaged(float _damage, NodeType _nodeType){ //공격을 받아 데미지를 입음
if(_nodeType != nodeType){ //공격한 노드가 현재 노드와 다른 타입일 경우
lifeScore -= _damage; //체력 감소
}else if(_nodeType == nodeType){//공격한 노드가 현재 노드와 같은 타입일 경우
lifeScore += _damage; //체력 증가
}
}
public void Attack(float _damage){ //체력을 감소시켜 공격한다
lifeScore -= _damage;
}
RecoverLife()함수에 의해서 주기적으로 노드의 체력이 회복된다.
그렇기때문에 노드의 체력이 한계치까지 회복되면 더이상 작동하지 않도록 LifeSensor()함수로 현재 체력을 감지한다.
Damaged는 노드간 상호작용 임시 오브젝트인 nodeInteraction에서 호출된다. 이때 대미지를 준 주체가 상대진영일경우 체력이 감소하지만 같은진영의 노드로부터 대미지를 받는다면 체력이 회복된다.
Attack은 설정된 공격력만큼 체력을 감소시켜 공격을 실행한다. 호출은 Damaged와 동일한 nodeInteraction으로부터 된다.
//현재 영토의 소속
void ActivateAreaStatus(int index){
if(index == 0){ //플레이어 영토 활성화
SetPlayerNode();
}else if(index == 1){ //적 영토 활성화
SetEnemyNode();
}
}
void SetPlayerNode(){
if(playerArea){
enemyArea = false;
neutralityArea = false;
mesh.material.color = Color.blue;
nodeType = NodeType.Player;
}
}
void SetEnemyNode(){
if(enemyArea){
playerArea = false;
neutralityArea = false;
mesh.material.color = Color.red;
nodeType = NodeType.Enemy;
}
}