❌ Attack 애니메이션 실행 시 앞으로 조금씩 전진함 ;;
애니메이션 자체가 갖고 있는 움직임으로 이를 무시하려면 Animator의 Applay Root Motion을 해제한다.
💡 Animator anim = GetComponent<Animator>();
_state = = PlayerState.Moving;
을 계속 세트로 작성해줘야 하는 번거로움을 없애고자 코드 정리
public PlayerState State
{
get { return _state; }
set
{
_state = value;
Animator anim = GetComponent<Animator>();
switch (_state)
{
case PlayerState.Die:
anim.SetBool("attack", false);
break;
case PlayerState.Idle:
anim.SetFloat("speed", 0);
anim.SetBool("attack", false);
break;
case PlayerState.Moving:
anim.SetFloat("speed", _stat.MoveSpeed);
anim.SetBool("attack", false);
break;
case PlayerState.Skill:
anim.SetBool("attack", true);
break;
}
}
}
bool _stopSkill = false;
void OnMouseEvent(Define.MouseEvent evt)
{
switch (State)
{
case PlayerState.Die:
break;
case PlayerState.Idle:
OnMouseEvent_IdleRun(evt);
break;
case PlayerState.Moving:
OnMouseEvent_IdleRun(evt);
break;
case PlayerState.Skill:
{
if(evt == Define.MouseEvent.PointerUp)
_stopSkill = true;
}
break;
}
}
void OnMouseEvent_IdleRun(Define.MouseEvent evt)
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
bool raycastHit = Physics.Raycast(ray, out hit, 100.0f, _mask);
//Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f);
switch (evt)
{
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;
}
}
}
break;
case Define.MouseEvent.Press:
{
if (_lockTarget == null && raycastHit)
{
_destPos = hit.point;
}
}
break;
case Define.MouseEvent.PointerUp:
_stopSkill = true;
break;
}
}
void OnHitEvent()
{
Debug.Log("OnHitEvent");
if (_stopSkill)
{
State = PlayerState.Idle;
}
else
{
State = PlayerState.Skill;
}
}
private void UpdateSkill()
{
if(_lockTarget != null)
{
Vector3 dir = _lockTarget.transform.position - transform.position;
Quaternion quat = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Lerp(transform.rotation, quat, 20 * Time.deltaTime);
}
}
ㄴ 적을 바라보고 공격 시 player 위치 회전값 설정
❌ 마우스 PointerUp 상태가 되면 Attack 애니메이션에서 바로 Idle로 전환되지 않고, 잠깐 Run 애니메이션으로 전환됐다가 Idle이 실행된다.
ㄴ 현재 Attack - RUN이 우선순위에 있기 때문에 attack == false라는 동일 조건 하에서는 RUN으로 먼저 전환되는 로직이기 때문이다.
ㄴ 그렇다고 Animator에 또 파라미터를 추가해서 조건을 달아주는 것도 매우 번거롭다.
anim.Play("애니메이션명");
anim.Play("RUN");
이렇게 바로 애니메이션을 호출할 수 있다. 하지만 이렇게 되면 애니메이션 간의 전환이 단절되어보여서 부자연스럽다는 단점이 있다. 이를 보완하는 것이 'CrossFade()'메서드이다.
anim.CrossFade("WAIT", 0.1f);
public PlayerState State
{
get { return _state; }
set
{
_state = value;
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;
}
}
}
-> 즉, 애니메이션의 전환에 꼭 파라미터가 필요한 것은 아니다!
ㄴKnight의 sword를 프리팹화하여 유니티짱의 오른손에 위치시킴
📄참고자료
[인프런] c#과 유니티로 만드는 MMORPG 게임 개발 시리즈_3. 유니티 엔진
Unity Documentation_Animator.CrossFade