공격을 구현하기 위해 다음과 같은 점을 고려해야 한다.
위 두가지를 동시에 만족하기 위해 코루틴을 사용할 수 있다. yield return
을 이용해 공격모션동안 다른 작업을 할 수 있도록 할 수 있다.
void GetIdleInput()
{
if (Input.GetKey(KeyCode.Space))
{
State = CreatureState.Skill;
_coSkill = StartCoroutine("CoStartPunch");
}
}
IEnumerator CoStartPunch()
{
// 피격 판정
GameObject go = Managers.Object.Find(GetFrontCellPos());
if (go != null)
{
CreatureController cc = go.GetComponent<CreatureController>();
if (cc != null)
cc.OnDamaged();
}
// 대기 시간
_rangeSkill = false;
yield return new WaitForSeconds(0.5f);
State = CreatureState.Idle;
_coSkill = null;
}
공격의 피적판정은 공격을 맞는쪽에서 처리하는 것이 편하다. 피격판정을 공격하는쪽에서 처리한다면 공격개체가 많아질수록 코드를 복사해야하고 수정할 때 수정해야할 부분이 많이지기 때문이다.
공격을 맞을 수 있는 개체에 OnDamaged
함수를 넣어 공격을 받거나 죽을 때 처리되는 부분을 구현할 수 있다.
public override void OnDamaged()
{
GameObject effect = Managers.Resource.Instantiate("Effect/DieEffect");
effect.transform.position = transform.position;
effect.GetComponent<Animator>().Play("START");
GameObject.Destroy(effect, 0.5f);
Managers.Object.Remove(gameObject);
Managers.Resource.Destroy(gameObject);
}
소멸이펙트 또한 하나의 GameObject로 오직 소멸이펙트 Sprite를 가지는 GameObject로 표현할 수 있다. 소멸이 될 때 Object를 생성해 Sprite를 실행시킴으로 소멸이펙트를 구현할 수 있다. 소멸이기 때문에 이펙트용 GameObject와 해당 스크립트를 실행하는 GameObject에 대한 소멸과정이 포함되어야 한다.
근거리 공격은 바로 앞에 있는 물체에 피해를 주는 것이라면 원거리공격은 투사체를 만들어 특정방향으로 보내는 것이다. 투사체를 던지는 것이기 때문에 플레이어는 피격에 대한 처리를 하는 것이 아닌 투사체 생성과 방향설정만 해주면 된다.
원거리 공격은 근거리 공격과 마찬가지로 코루틴을 사용한다. 근거리 공격과 다른점은 피격처리를 하지 않고 Arrow GameObject를 생성 및 설정만 하고 코루틴을 종료한다.
IEnumerator CoStartArrow()
{
// 피격 판정
GameObject go = Managers.Resource.Instantiate("Creature/Arrow");
ArrowController ac = go.GetComponent<ArrowController>();
ac.Dir = _lastDir;
ac.CellPos = CellPos;
// 대기 시간
_rangeSkill = true;
yield return new WaitForSeconds(0.3f);
State = CreatureState.Idle;
_coSkill = null;
}
투사체는 설정된 방향으로 이동하면서 앞에 부딪히는 물체가 있는지 확인한다. 문장상으로는 투사체가 확인을 한다는 것이 이상하게 들릴 수 있지만 투사체는 하나의 GameObject이기 때문에 투사체의 Script에서 탐색과 처리를 해줄 수 있다.
GameObject go = Managers.Object.Find(destPos);
if (go == null)
{
CellPos = destPos;
}
else
{
CreatureController cc = go.GetComponent<CreatureController>();
if (cc != null)
cc.OnDamaged();
Managers.Resource.Destroy(gameObject);
}