IGDC 입문 프로젝트입니다.
지난 글 마지막에서 발생한 에러 몇 가지를 정리했습니다. 추가로 몇 가지 에러가 더 발생할텐데요,
정리해보면,
- 건설 이후에 건물을 클릭해도 UI가 다시 뜨지 않습니다.
- 건물 부지를 클릭해 UI를 띄운 후, 다른 곳을 클릭하면 사라지지만, 다른 곳 대신 다른 부지를 클릭하면?
- 얼레? 갑자기 게임이 멈춰요 (하단 참조)
1번 문제 해결하기
1번 문제의 경우는 위 그림과 같이 Sphere Collider가 Box Collider를 아예 애워싸기에 정작 클릭을 감지할 BoxCollider가 감지하지 못하는 경우 같습니다.
원기둥 형태의 콜라이더를 사용하면 좋지만... Unity에서는 원기둥 형태의 콜라이더를 지원하지 않습니다. 물론 다른 방식을 통해 구현을 할 수는 있지만, 우리는 그냥 Sphere Collider를 Box Collider로 변경하여 마우스 클릭용 콜라이더를 애워싸지 않게 변경할 것입니다.
AttackTower Prefab의 콜라이더를 다음과 같이 수정해줍시다.
가로로 길쭉한 녹빛 사각형이 Sphere에서 Box로 변경된 콜라이더입니다.
유령이 땅바닥에 붙어있는 게 아닌지라 몬스터의 감지를 위해 콜라이더를 땅에서 올렸습니다. 올리되, 마우스 클릭 감지를 위한 콜라이더보다 위에 있지 않도록 합니다. 혹은 마우스용 콜라이더의 높이를 조금 키워도 됩니다.
sampleC 프리팹도 Sphere에서 Box로 변해줍시다.
2번 문제 해결하기 > 2번 문제는 10.5번 글에서 다룹니다.
조건절을 딱히 생각을 깊게 하지 않고 짰더니 이런 문제가 생기는군요...
원래는 이런 코드였습니다.
if (!Physics.Raycast(ray, out var hit) || !hit.collider.CompareTag("AllyTower")) {
Invoke(nameof(SetModalVisible), 0.1f);
}
레이캐스트를 쐈을 때, 부딪히지 않는다면 (땅바닥을 쐈다면) 버튼 UI를 안보이게 만듭니다.
혹은 레이캐스트가 부딪히더라도 AllyTower 태그의 오브젝트가 아니라면 안 보이게 바꾸는 식이었습니다.
이 경우, 다른 타워를 클릭했을 때, 버튼 그룹의 UI는 이동이 되지만 타워의 visible 값은 변경되지 않아 다시 MouseDown 함수가 호출될 때 if문 내부가 작동하지 않기에 버튼 UI의 위치가 수정되지 않습니다.
or 대신 else if문으로 분리하여 처리를 해줍니다.
// SiteClick.cs 중 수정된 Update 본문
if (!visible && Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// 변경된 코드
if (!Physics.Raycast(ray, out var hit)) {
Invoke(nameof(SetModalVisible), 0.1f); // 0.25초가 너무 길다 싶어서 0.1초로 변경
}
else if (hit.collider.gameObject != gameObject) {
visible = !visible;
}
// 여기까지가 변경된 코드입니다.
}
다음 코드로 변경하면, 땅바닥을 클릭하면 버튼 UI가 없어지지만 다른 타워를 클릭했을 때 visible 값을 변경시키도록 하였습니다. 어차피 버튼 UI는 클릭한 다른 타워에서 이동시키도록 처리하니까요.
3번 문제 해결하기
타워를 설치하여 테스트를 해보면 갑자기 게임이 멈추는 케이스가 발생합니다.
멈추면서 다음 에러 메시지를 뱉습니다. 읽어보니 First() 함수가 작동하였으나, 요소가 없어서 발생한 문제입니다.
AttackTower를 구현하면서 다음 코드를 작성했었습니다. (monsters 변수를 List와 Queue 방식 둘 다 설명했지만, 이후로는 List만 설명합니다)
monsters의 First를 받아왔는데, 받아온 GameObject가 이미 다른 타워의 공격으로 없어진 경우에는 공격대상을 찾을 수 없겠죠?
// AttackTower.cs 중 일부
var shoot = Instantiate(projectile, transform.position, Quaternion.identity);
shoot.GetComponent<Projectile>().target = monsters.First();
while문으로 target이 null인지 체크합니다. null이라면 First (0번째 인덱스이므로) 0번째를 제거합니다. 그 후, 다시 First를 대입해주는데, 혹여나 제거함으로써 길이가 0인데 First를 반환하는 경우를 방지하기 위해 if문으로 길이를 체크합니다.
var shoot = Instantiate(projectile, transform.position, Quaternion.identity);
var target = monsters.First();
while (target == null) {
monsters.RemoveAt(0);
// 변경된 코드
if (monsters.Count == 0) {
break;
}
target = monsters.First();
}
// 변경된 코드
if (target != null) {
shoot.GetComponent<Projectile>().target = target;
}
지금까지 3가지 에러를 수정해봤습니다.
'Unity > IGDC 입문 프로젝트' 카테고리의 다른 글
11. 타워 업그레이드 및 제거 기능 구현 (0) | 2023.11.07 |
---|---|
10.5 - 버튼 클릭 수정 (0) | 2023.11.07 |
9. 공격 타워 배치 및 Cost 기능 구현 (0) | 2023.09.03 |
8. 공격 타워 구현 (0) | 2023.09.03 |
7. GameOver 알림 (0) | 2023.09.02 |