[ 트러블 슈팅 ]
적이 죽고 리스폰되지 않음
적을 구현할 때 오브젝트 풀을 이용해서 생성, 제거를 반복하지 않고 계속해서 가져다 쓰는 기능을 구현했다. 하지만 맨 처음 풀 사이즈만큼 적들이 생성되고 죽고 나면 다시 리스폰되지 않는 현상이 발생했다.
private IEnumerator DestroyAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
Destroy(gameObject); // 오브젝트 파괴
}
그 이유는 적이 죽고 오브젝트를 씬에서 삭제하는 코루틴에서 적 오브젝트 자체를 파괴해버려서 다시 큐에 들어가지 못했기 때문에 생성되지 않았다.
private IEnumerator DestroyAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
ObjectPoolManager.Instance.ReturnToPool(gameObject, "Enemy"); // 오브젝트 풀로 다시 넣음
}
그래서 오브젝트를 파괴하는 코드를 제거하고 오브젝트 풀로 다시 넣는 코드를 추가했다.
리스폰된 적들이 안 죽음
하지만 초기 생성 적들은 정상적으로 적에게 맞고 쓰러지며 머리카락이 없었는데, 리스폰 된 오브젝트들은 이미 죽은 상태였던 오브젝트가 생성됐다. 그래서 플레이어가 오브젝트는 추적하지만 아무리 공격해도 적들이 죽지 않았다.
그 이유는 다시 생성된 오브젝트들이 초기 값으로 설정되지 않은 채 생성되었기 때문이다.
private IEnumerator DestroyAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
// 오브젝트 풀로 다시 넣음
ObjectPoolManager.Instance.ReturnToPool(gameObject, "Enemy");
// 죽은 적들 초기화
enabled = true;
Controller.enabled = true;
hairActivate.SetActive(false);
Animator.ResetTrigger("Die");
Health.health = maxHealth;
Health.IsDie = false;
}
그래서 풀에 넣은 뒤 오브젝트 설정을 초기 값으로 바꿔주는 코드들을 추가한다. 그러면 오브젝트가 풀에서 나올 때 초기 설정 값으로 나오게 된다.
참조 변수 값이 제대로 할당되지 않음
public void TakeDamage(int damage)
{
if (health == 0) return;
health = Mathf.Max(health - damage, 0);
if(IsEnemy) // 에너미일 때
{
OnTakeDamage?.Invoke(); // 데미지 받을 때 깜빡깜빡
ShowHitText();
}
if (health == 0)
{
IsDie = true;
OnDie?.Invoke();
}
}
하지만 여전히 죽지는 않는 모습을 보였는데, 그 이유는 체력이 정상적으로 회복되지 않아서 애초에 체력이 0이었기 때문이다. 그래서 Die 이벤트가 호출되지 않고 그냥 return 돼서 추적만 되고 죽지 않았다.
public HealthSystem Health { get; private set; }
해결을 위해서는 체력을 100으로 초기화 해줘야 하는데, 현재 클래스에서 체력 데이터를 받아오는 변수를 프로퍼티를 이용해서 가져오고 있기 때문에 그냥 Health.health에 값을 할당하면 적용되지 않는다.
public void ResetHealth() // 적 재생성 시 체력 초기화
{
health = maxHealth;
}
그래서 실제 값을 바꿀 수 있도록 HealthSystem 클래스에서 체력을 다시 채워주는 메서드를 만들어서 호출한다.
private IEnumerator DestroyAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
// 오브젝트 풀로 다시 넣음
ObjectPoolManager.Instance.ReturnToPool(gameObject, "Enemy");
// 죽은 적들 초기화
enabled = true;
Controller.enabled = true;
hairActivate.SetActive(false);
Animator.ResetTrigger("Die");
Health.ResetHealth();
Health.IsDie = false;
}
위 문제점을 해결한 최종 코드와 실행 화면이다. 사용이 끝난 오브젝트를 파괴하지 않고 재사용하기 위해서 오브젝트 풀에 넣고, 그와 동시에 초기 값을 할당해서 맨 처음 생성된 오브젝트와 같은 상태로 만들어준다. 이 과정에서 프로퍼티로 가져온 변수를 사용할 때에는 값이 정상적으로 변하지 않을 수 있기 때문에, 필요한 변수가 있는 클래스에서 계산식을 메서드로 구현해 값을 리턴해오는 방향으로 해결할 수 있다.
[ 회고 ]
팀 작업을 하면서 적 이동 및 구현 기능을 담당하신 분이 작성하신 코드에 내가 만든 오브젝트 풀을 합치는 과정에서 다소 불필요한 로직이나 코드가 발생했었다. 왜냐하면 팀원분은 적 오브젝트가 이동하고 공격하고 죽는 기능 자체만 구현하면 됐기 때문이고, 나는 이 오브젝트들을 효율적으로 관리하기 위해 재생성까지 고려해야 했기 때문이다. 이 과정에서 팀원 분들의 코드를 파악하고 있는 것도 매우 중요하다고 느꼈고, 오브젝트의 상태가 바뀐다면 처음 상태를 원할 때 초기 값을 할당해 주는 것을 잊지 말아야 한다는 것을 깨달았다.
'Coding > Unity' 카테고리의 다른 글
[내일배움캠프 59일차 TIL] 수면 시스템 구현하기 (0) | 2024.07.09 |
---|---|
[내일배움캠프 55일차 TIL] 2D 하루 낮밤과 다음 날 구현하기 (0) | 2024.07.03 |
[내일배움캠프 48일차 TIL] 오브젝트 풀에서 큐의 동작 원리 (0) | 2024.06.24 |
[내일배움캠프 46일차 TIL] JSON 직렬화로 데이터 저장, 불러오기 (0) | 2024.06.20 |
[내일배움캠프 43일차 TIL] Input System C# 제너레이트 활용 (0) | 2024.06.18 |