인터페이스 관련 내용의 활용을 복기하고자 이전에 사용했었던 내용을 가져왔습니다.
인터페이스를 활용할 때, IDamageable 인터페이스를 만들어서 피해를 받을수 있는 오브젝트를 구분해서 데미지를 줄 수 있습니다.
IDamageable 인터페이스와 이를 가지고있는 Enemy 클래스입니다.
public interface IDamageable
{
public void TakeDamage(float damage);
}
public class Enemy : MonoBehaviour, IDamageable
{
//데미지 입기
public void TakeDamage(float damage)
{
//데미지 계산
currentHealth -= damage;
//데미지 효과
//죽음 체크
if (currentHealth <= 0f && isDeath == false)
{
Die();
}
}
}
그리고 여기 플레이어가 총을 쏠때 호출되는 코루틴함수 입니다.
IEnumerator PistolFire()
{
isFire = true;
//앞 방향으로 레이를 쏘고 레이에 맞는 Enemy에게 데미지 주기
RaycastHit hit;
if(Physics.Raycast(firePoint.position, firePoint.forward, out hit, attackRange))
{
//hit info
GameObject impactEff = Instantiate(hitImpactPrefab, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactEff, 2f);
//
IDamageable damageable = hit.transform.GetComponent<IDamageable>();
if (damageable != null)
{
damageable.TakeDamage(attackDamage);
}
}
//발사 효과 이펙트
animator.SetTrigger(fireTrigger);
pistolShot.Play();
//fireTime초 지연 후에
yield return new WaitForSeconds(fireTime);
isFire = false;
}
레이캐스팅 부분을 넘기고 피격당한 대상에게 IDamageable를 컴포넌트로써 사용중인지 탐색하여 이를 저장합니다.
IDamageable damageable = hit.transform.GetComponent<IDamageable>();
if (damageable != null)
{
damageable.TakeDamage(attackDamage);
}
if(damageable != null) 을 사용하여 대상에게 IDamageable이 붙은 컴포넌트가 있다면 해당 컴포넌트를 작동합니다.
여기에 또다른 IDamageable을 사용하는 클래스, BreakObject 가 있습니다.
이 클래스는 자신의 변수인 isUnbreakable이 false일경우 TakeDamage를 통해 한번 공격받으면 부숴지도록 구현되어있습니다.
public class BreakObject : MonoBehaviour, IDamageable
{
public void TakeDamage(float damage)
{
if(isUnbreakable)
{
return;
}
health -= damage;
if(health < 0f && isDeath == false)
{
Die();
}
}
}
이 클래스 또한 IDamageable 을 통해 함수를 호출하기 때문에 위의 내용을 그대로 사용할 수 있습니다.
만약 이 두 클래스에 Damageable 클래스를 사용하지 않는다면 이렇게 구현하게 됩니다.
IEnumerator PistolFire()
{
isFire = true;
//앞 방향으로 레이를 쏘고 레이에 맞는 Enemy에게 데미지 주기
RaycastHit hit;
if(Physics.Raycast(firePoint.position, firePoint.forward, out hit, attackRange))
{
//hit info
GameObject impactEff = Instantiate(hitImpactPrefab, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactEff, 2f);
if (hit.transform.tag == enemyTag) //적을 맞추었다
{
Robot robot = hit.transform.GetComponent<Robot>();
if (robot)
{
robot.TakeDamage(attackDamage);
}
Zombie zombie = hit.transform.GetComponent<Zombie>();
if (zombie)
{
zombie.TakeDamage(attackRange);
}
}
else if(hit.transform.tag == "BreakObejct")
{
//깨지는 오브젝트 깨트리기
}
}
//발사 효과 이펙트
animator.SetTrigger(fireTrigger);
pistolShot.Play();
//fireTime초 지연 후에
yield return new WaitForSeconds(fireTime);
isFire = false;
}
EnemyTag의 내용은 Enemy 라는 클래스를 부모클래스로 가지고 있고, Enemy 클래스에 TakeDamage가 구현되어있으면 이 클래스를 통해 호출이 가능합니다.
하지만 파괴 가능한 오브젝트는 다릅니다. 이 클래스는 자신의 변수에 따라 행동이 달라지기때문에 Enemy 클래스의 자식으로 넣을수 없으며, 오버라이드 기능을 사용한다고 해도 파괴가능 오브젝트가 Enemy 클래스의 자식클래스인것은 뭔가 이상합니다.
if (hit.transform.tag == enemyTag) //적을 맞추었다
{
Robot robot = hit.transform.GetComponent<Robot>();
if (robot)
{
robot.TakeDamage(attackDamage);
}
Zombie zombie = hit.transform.GetComponent<Zombie>();
if (zombie)
{
zombie.TakeDamage(attackRange);
}
//......
}
else if(hit.transform.tag == "BreakObejct")
{
//깨지는 오브젝트 깨트리기
}
이러한 경우를 처리하는데 유용한것이 인터페이스입니다.
'내일배움캠프 > TIL' 카테고리의 다른 글
내일배움캠프 11일차 TIL - GC(가비지 컬렉터) (0) | 2024.09.27 |
---|---|
내일배움캠프 10일차 TIL - C# 싱글톤 (0) | 2024.09.26 |
내일배움캠프 8일차 TIL - 텍스트 파일을 읽을때 주의할 점 (0) | 2024.09.24 |
내일배움캠프 7일차 TIL - 개인 프로젝트 진행 상황 돌아보기 (0) | 2024.09.23 |
내일배움캠프 6일차 TIL - Null 값을 가질수 없는 struct (0) | 2024.09.20 |