특정 캐릭터가 공격(Attack)이나 스킬(Skill)사용하고자 할 때 여러가지의 입력을 받을 수 있다. 공격하는 커맨드를 입력하고 대상을 마우스로 지정한다거나, 커맨드입력 없이 마우스 클릭만으로 공격을 명령할 수 있다.
마우스로만 공격을 지시한다고 할 때 클릭한 목적이 이동
인지 공격
인지 어떻게 구분할 수 있을까?
layerMask를 이용해 클릭한 대상의 Layer가
Monster
인지Ground
인지 확인하자!
공격하는 과정의 구현은 구현하고자 하는 내용에 따라 다를 수 있다.
어떤 대상을 공격할지에 대한 정보(GameObject)를 가지고 있어야 한다.
GameObject _lockTarget;
캐릭터의 상태(Die, Idle, Moving, Skill)에 따라 실행해야 할 애니메이션이 다르다. 이동하거나 스킬, 공격모션을 취할 때마다 특정 애니메이션을 실행하는 것이 아닌 캐릭터의 State를 변경함으로 State에 맞는 애니메이션을 실행하도록 한다.
Animator anim = GetComponent<Animator>();
switch(_state)
{
case PlayerState.Die:
break;
case PlayerState.Idle:
anim.CrossFade("WAIT", 0.1f);
break;
case PlayerState.Moving:
anim.CrossFade("RUN", 0.1f);
break;
case PlayerState.Skill:
anim.CrossFade("ATTACK", 0.1f, -1, 0);
break;
}
Animator Component는 특정 GameObject의 애니메이션을 제어하는데 사용되는 컴포넌트로 위 코드에는 다른 상태로의 부드러운 전환을 위해 CrossFade를 사용했다. 아래 3개의 기능 외에도 여러가지 기능이 존재한다.
마우스올 공격을 명령하면 공격대상이 있는 위치까지 이동할 필요가 있다. 이 과정은 다음과 같이 나타낼 수 있다.
Ground
라면 누른 지점을 캐릭터의 이동지점으로 바꾼다.Monster
라면우선, 마우스가 클릭될 때 가지고 있는 정보는 목표지점과 공격대상이다.
Vector3 _destPos;
GameObject _lockTarget;
마우스를 클릭할 때 LayerMask를 이용해 Monster
인지 판별한 뒤에 공격대상을 변경한다.
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
bool raycastHit = Physics.Raycast(ray, out hit, 100.0f, _mask);
case Define.MouseEvent.PointerDown:
{
if (raycastHit)
{
_destPos = hit.point;
State = PlayerState.Moving;
if (hit.collider.gameObject.layer == (int)Define.Layer.Monster)
_lockTarget = hit.collider.gameObject;
else
_lockTarget = null;
}
}
기존에 존재했던 캐릭터의 이동은 다음과 같은 단계로 나타낼 수 있으며 아래 단계는 매 프레임마다 적용된다.
위 단계에서, 공격대상이 존재한다면 공격상태로 전환되어야 하기 때문에 다음과 같은 단계를 추가한다.
if(_lockTarget != null)
{
float distance = (_destPos - transform.position).magnitude;
if (distance <= 1.7)
{
State = PlayerState.Skill;
return;
}
}
위 코드에서 1.7
이 공격 사정거리에 해당하는 값이다.
처음에 언급한 상황인 마우스를 누르고 있지만 공격대상이 움직이거나 마우스커서가 움직여 대상을 벗어날 때에 공격을 계속 진행하고자할 때 이에대한 처리가 필요하다.
기존의 방법은 공격이 한번 끝났을 때 Idle State로 전환하도록 하였는데
State = PlayerState.Idle;
마우스커서 구현을 위해 추가적인 Mouse Action을 State전환의 조건으로 두어야할 필요가 있다. 이를위해 _stopSkill이라는 bool변수를 두어 true일 때 Idle상태로 전환, 즉 공격을 중지한다.
bool _stopSkill = false;
if (_stopSkill)
{
State = PlayerState.Idle;
}
else
{
State = PlayerState.Skill;
}
_stopSkill이 false일 때는 공격을 계속 진행할 때이다. 즉, 처음 공격명령을 내리는 Raycasting과정에 _stopSkill을 false로 설정한다.
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
bool raycastHit = Physics.Raycast(ray, out hit, 100.0f, _mask);
case Define.MouseEvent.PointerDown:
{
if (raycastHit)
{
_destPos = hit.point;
State = PlayerState.Moving;
_stopSkill = false;
if (hit.collider.gameObject.layer == (int)Define.Layer.Monster)
_lockTarget = hit.collider.gameObject;
else
_lockTarget = null;
}
}
_stopSkill이 true가 될 때는 몬스터가 죽어 사라지거나 공격불능상태가 되었을 때와 같이 많은 상황이 있지만 현재 설정할 내용은 Mouse PointerUp
이다. Mouse PointerUp
이 발생하는 부분에 다음과 같은 코드를 작성함으로 구현할 수 있다.
case Define.MouseEvent.PointerUp:
_stopSkill = true;
break;
아주 유익한 내용이네요!