구르기 (회피)
몬스터의 공격이나 보스의 공격 패턴을 피하기 위해 구르기
를 추가했다.
연속 공격
처음에 연속 공격은 생각보다 구현이 헷갈려서 해맸지만 구현은 성공했다..!
[ 연속 공격이 되는 과정 ]
공격키 입력 -> 공격 진행 -> 공격 중에 공격키 입력하는지 계속 확인 -> 공격키를 누르면 다음 공격 진행 || 안누르면 Idle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
float _attackCloseTime = 0;
// State가 Attack면 UpateAttack 계속 호출
protected override void UpdateAttack()
{
_attackCloseTime += Time.deltaTime;
// 공격이 시간이 끝나면 종료 || 공격이 끝났는데 다른 애니메이션에 있다면 종료
if ((anim.GetCurrentAnimatorStateInfo(0).IsTag("Attack") == true &&
_attackCloseTime > 0.94f && _onComboAttack == false) ||
(anim.GetCurrentAnimatorStateInfo(0).IsTag("Attack") == false &&
_attackCloseTime > 0.99f && _onComboAttack == false))
{
StopAttack();
State = Define.State.Idle;
return;
}
dir = _destPos - transform.position;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 20f * Time.deltaTime);
}
bool _onAttack = false;
bool _onComboAttack = false;
int attackClipNumber = 0;
string[] _attackClipList = new string[] {"ATTACK1", "ATTACK2"};
// 공격키를 누르면 호출
void OnAttack()
{
// 콤보 체크
if (_onAttack &&
anim.GetCurrentAnimatorStateInfo(0).IsTag("Attack") &&
anim.GetCurrentAnimatorStateInfo(0).normalizedTime >= 0.3f)
{
_onComboAttack = true;
}
// 공격!
if (!_onAttack)
{
anim.CrossFade(_attackClipList[attackClipNumber], 0.1f, -1, 0);
State = Define.State.Attack;
_onAttack = true;
}
}
// [ Anim Event ] 공격 애니메이션이 끝나면 호출
public void ExitAttack()
{
// 공격 중에 공격 키를 눌렀나?
if (_onComboAttack == true)
{
if (attackClipNumber == 1)
attackClipNumber = 0;
else if (attackClipNumber == 0)
attackClipNumber = 1;
anim.CrossFade(_attackClipList[attackClipNumber], 0.1f, -1, 0);
_onComboAttack = false;
}
}
void StopAttack()
{
_onAttack = false;
_onComboAttack = false;
_stopAttack = true;
_attackCloseTime = 0;
attackClipNumber = 0;
}
💻 BaseController.cs
컨트롤이 필요한 캐릭터는 모두 BaseController.cs
를 상속받는다. (Player, Monster, NPC,…)
BaseController.cs
는 상태(State
)에 관련한 기본 기능을 가지고 있다.
애니메이션 코드
애니메이션을 코드로 관리하기 위해 CrossFade
를 사용했으며
애니메이션(CrossFade
)은 캐릭터의 상태(State
)가 바뀌면 호출되도록 구현했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int number = 1;
[SerializeField]
protected Define.State _state = Define.State.Idle;
public virtual Define.State State
{
get { return _state; }
set {
_state = value;
// anim.CrossFade(재생 클립 이름, 바뀌는데에 지연 시간, 레이어, 재생 시작 시점)
switch (_state)
{
case Define.State.Moving:
anim.CrossFade("RUN", 0.1f);
break;
case Define.State.Idle:
anim.CrossFade("WAIT", 0.4f);
break;
case Define.State.DiveRoll:
anim.CrossFade("DIVEROLL", 0.1f, -1, 0);
break;
case Define.State.Attack:
// 플레이어는 공격 상황이 바뀔 수 있으니 Monster만 사용
if (WorldObjectType == Define.WorldObject.Monster)
{
anim.CrossFade("ATTACK"+number, 0.1f, -1, 0);
// 기본 공격 방법은 두가지로 번갈아도록 함.
if (number == 1)
number = 2;
else if (number == 2)
number = 1;
}
break;
case Define.State.Hit:
{
anim.CrossFade("HIT", 0.1f, -1, 0);
}
break;
case Define.State.Die:
{
anim.CrossFade("DIE", 0.1f, -1, 0);
}
break;
}
}
}