작성
·
100
답변 3
1
간단하게 만든다면 얘기하신대로 만드시면 될거 같구요, 좀 더 제대로 만든다고하면 SpecialCombo처럼 하드 코딩하는 것보다 Command Map을 만들어서 Check하는게 더 좋습니다.
[Serializable]
class Command
{
public string name;
public KeyCode Key;
public Command[] linkedCommand;
}
Q -> W -> E -> R // name: Special Combo
ㄴ E -> Q // name: Skill 1
ㄴ E // name: Skill 2
0
답변해주셔서 감사합니다
커맨드를 저장하는건 이런식으로
List<KeyCode> keyList = new List<KeyCode>();
void Update()
{
if (Input.anyKeyDown)
{
foreach (KeyCode key in System.Enum.GetValues(typeof(KeyCode)))
{
if (Input.GetKeyDown(key)) { keyList.Add(key); } }
}
}
리스트로 구현하고 공격 애니메이션이 끝날때마다 리스트를 초기화 해준 다음에
커멘더 콜렉터에 bool값을 만든 다음에 해당 리스트에서 특정 조합과 순서가 해당되는게 있다면 참으로 만든 다음에
애니메이션의 transition 넘어가는 조건으로 해당 bool값을 넣어주는 방식으로 구현도 괜찮을까요?
MakeTransition<AttackState, SpecialAttackState>( state => Owner.CommandController.SpecialAttackBool)
입력받은 키의 비교는 예를들어 qwer이 순서대로 눌려야 한다면
List<KeyCode> SpecailCombo = new List<KeyCode> { KeyCode.Q, KeyCode.W, KeyCode.E, KeyCode.R };
bool SpecialAttackBool()
{
for (int i = 0; i < SpecailCombo.Count; i++)
{
if (keyList[i] != SpecailCombo[i])
{
return false;
}
}
return true;
}
0
수강해주셔서 감사합니다.
격투 게임과 몬스터헌터의 경우 공격이 커맨드 방식(=약공, 강공 조합)인데요,
공격 시작 시에 커맨드 수집을 끄고, 애니메이션 이벤트를 통해서 원하는 타이밍에 다시 커맨드 수집을 시작하게 만들거나, State내에서 애니메이션의 플레이타임을 확인하여 애니메이션이 어느 정도 진행되면 다시 커맨드 수집을 시작하게 만들면 됩니다. 예시 코드는 다음과 같습니다.
애니메이션 이벤트를 사용
먼저 말로 정리하면 다음과 같습니다.
CommandCollector를 통해 Command를 수집함 -> AttackingState로 들어가서 Command에 따른 Animation(=강공, 약공) 실행 및 Command 수집을 막음 -> Animation Event를 통해 특정 Frame부터 다시 Command를 수집함 -> Command 입력이 있다면 AttackState로 재진입하여 Combo를 이어감
// PlayerEntity - CommandCollector.cs
// Player 입력에 따라 Command(=약공, 강공, 점프 등)를 수집함
void Update()
{
// Player의 Key 입력이 있을 시 Key에 맞는 Command를 찾아옴
LastCommand = commands.Select(x => x.key == Input.GetButtonDown());
}
void OnDisable()
{
LastCommand = default;
}
// EntityStateMachine.cs
public void MakeTransitions()
{
...
// 입력된 Command가 있고 Attack Type이라면 다음 Combo로 이어감
MakeTransition<AttackingState, AttackingState>(x => x.Entity.CommandCollector
.LastCommand.Type == CommandType.Attack);
}
// AttackingState.cs
// 공격 상태
void override void Enter()
{
...
// Animation을 통한 공격 수행
// name == "strongAttack" or "lightAttack"
Entity.Animator.SetTrigger(Entity.CommandCollector.LastCommand.name);
// Command 수집을 멈춤
Entity.CommandCollector.enable = false;
}
void override void Exit()
{
...
Entity.CommandCollector.enable = true;
}
// AnimationEvents.cs
// Animation Event로 등록하여 사용
public void ActivateCommandCollector()
{
GetComponent<CommandCollector>().enable = true;
}
애니메이션 플레이 타임을 이용하는 방법은 애니메이션 이벤트 대신 AttackingState에서 애니메이션 플레이 타임을 확인해주면 됩니다.
플레이 타임을 확인
// AttackingState.cs
public override Update()
{
// 현재 실행중인 Animation 정보를 가져옴
var animationInfo = Entity.Animator.GetCurrentAnimatorStateInfo(0);
// normailzedTime(=PlayTime) 0 ~ 1
// Animation이 85퍼 진행되면 Command를 다시 수집함
if (animationInfo.normalizedTime >= 0.85f)
Entity.CommandCollector.enable = true;
}
언제나 그렇듯 보여드린 예시 코드가 무조건적 정답은 아니구요, 강의 내용을 활용해서 이렇게 만들 수 있다 정도로 보시면 됩니다.
오버로딩 경고는 애니메이션 이벤트가 SendMessage 방식이라 이름이 같은 함수들이 있으면 그 함수들 중에서 무엇이 실행될지 알 수 없기 때문에 나오는 경고입니다. Fuction에 해당 함수들을 사용하지 않으면 괜찮구요, 해당 함수들을 사용해야할 경우 래핑 함수 하나를 만들어서 사용해주시면 됩니다.
ex.
Show라는 함수들이 여럿 있을 경우 Show 대신 사용하려는 Show 함수를 래핑한 ShowCallback 함수를 사용해줌
public void ShowCallback()
{
display.Show();
}
감사합니다.
답장해주셔서 감사합니다.