-
[UE5] 시퀀스 이밸류에이터에 대해언리얼엔진/그 외 2023. 8. 19. 17:25
시퀀스 이밸류에이터의 기본 외형 애니메이션 블루프린트에는 시퀀스 이밸류에이터라는 노드가 있다.
노드의 설명은 "지정된 애니메이션의 지정된 단일 프레임을 구합니다." 라고 적혀있다.
언리얼 엔진 5의 라이라 샘플이나 공식 문서의 디스턴스 매칭을 보면 시퀀스 이밸류에이터를 사용한 예제를 볼 수 있다.
https://docs.unrealengine.com/5.2/ko/distance-matching-in-unreal-engine/
디스턴스 매칭
예시 워크플로 구현을 통해 언리얼 엔진의 디스턴스 매칭에 대해 자세히 알아봅니다.
docs.unrealengine.com
시퀀스 이밸류에이터와 가장 비슷한 노드로는 시퀀스 플레이어가 있다.
시퀀스 플레이어의 기본 외형 둘 다 지정된 애니메이션 시퀀스의 포즈를 출력하는 기본적인 기능을 하는데, 두 노드의 차이점을 굳이 비교하면
- 시퀀스 플레이어: 플레이어라는 이름에 맞게 시퀀스가 재생이 되고, 포즈들이 순서대로 출력된다.
- 시퀀스 이밸류에이터: 시퀀스에서 특정한 시간의 포즈를 출력한다.
제대로 비교한 것인지는 모르겠다.
더 설명을 하면 시퀀스 이밸류에이터는 애니메이션 시퀀스의 포즈 중에서 지정한 시간의 포즈가 출력된다.
만약 시퀀스 이밸류에이터를 사용중인데 출력되는 포즈를 변경시키고싶다면, 지정하는 시간을 계속 변경시켜줘야 한다.
지정할 시간을
DeltaTime
만큼 계속 누적시킨다면 애니메이션 시퀀스를 재생하는것이 된다.대신에 시퀀스 플레이어와는 다르게 시퀀스의 특정 시간대로 건너 뛰는것이 가능하다.
시퀀스 플레이어로는 시퀀스의 시작 위치를 지정하거나, 재생속도를 빠르게 해서 특정 위치로 빨리 이동할 수는 있지만, 그 중간의 과정을 모두 거치게 된다.
그래서 건너뛰는 구간에 애님 노티파이가 있다면 그 노티파이는 트리거된다.
하지만 시퀀스 이밸류에이터는 "명시적 시간으로 텔레포트"가 가능해서 중간 과정을 건너뛰어 애님 노티파이가 트리거되지 않게 할 수 있고, 시퀀스의 앞 부분으로 되돌아가는것도 가능하다.
시퀀스 이밸류에이터를 사용하려면 디테일의 세팅을 먼저 상황에 맞게 설정해야한다.
시퀀스 이밸류에이터 세팅 시퀀스 이밸류에이터로 시퀀스의 원하는 시간대의 포즈를 출력하려면 "명시적 시간"을 다이내믹 값으로 변경해야 시간을 동적으로 변경할 수 있다.
디테일 창의 세팅에서 "명시적 시간"의 오른쪽 드롭다운을 눌러서 다이내믹 값을 체크하면 된다.
핀으로 노출은 원하는대로 설정하면 된다.
그리고 "루프 여부" 옵션도 있는데 이것은 아직 확인해보진 못했다.
루프를 사용하려면 "명시적 시간으로 텔레포트"를 꺼야하고, SyncGroup을 사용해야한다.
개인적인 생각으로는 사용 조건도 있고, 애니메이션 루프가 필요한경우 시퀀스 플레이어를 쓰는게 더 낫다고 생각하기 때문에 이 옵션은 사용하지 않는다.
시퀀스 이밸류에이터로 애니메이션을 재생시키는 방법
시퀀스 이밸류에이터로 시퀀스를 재생시키려면 애니메이션 시퀀스와 함수를 지정해줘야 한다.
1. 애니메이션 시퀀스
애니메이션 시퀀스는 노드의 디테일에서 설정해서 바인드로 지정해줄 수도 있고, 다이내믹 값으로 설정해서 동적으로 지정할 수도 있다.
만약 다이내믹 값을 선택한 경우 아래의 함수를 통해 지정해줘야 한다.
2. 함수
함수의 경우에는 노드의 디테일에서 설정할 수 있다.
3개의 함수를 설명하자면,
일단 연관성이 있다는 것은 이 노드에서 포즈를 출력중인 상황이라고 보면 된다.
그렇기에 "연관성이 생길 시"는 이 노드가 연관성이 없었다가 연관성이 생기기 시작한 시점에 한번 호출된다.
"업데이트 시"는 포즈를 출력중일 때마다 호출되는 함수다.
"초기 업데이트 시"는 처음으로 연관성이 생길 때에만 호출된다. 그러므로 두번 이상 호출될 일은 없다.
간단한 예제로 Idle상태의 애니메이션을 시퀀스 이벨류에이터로 재생되게 만들어보겠다.
기본 제공 템플릿인 3인칭 프로젝트에서 시작하고, 거기에 포함된 SKM_Manny 스켈레탈 메시, 라이라 샘플에서 제공되는 애니메이션들을 사용한다.
Idle상태에서 재생되는 애니메이션이지만 시각적으로 확실하게 확인하기 위해 다른 용도로 제작된 애니메이션을 지정하겠다.
먼저 시퀀스 이밸류에이터는 이렇게 세팅한다.
1. 시퀀스 이밸류에이터 세팅
시퀀스: 다이내믹 값
명시적 시간: 다이내믹 값, 핀으로 노출 했지만 사용되지 않음
루프 여부: 체크 해제
2. 함수
함수를 두개 생성해서 하나는 노드가 처음 작동할 때, 다른 하나는 업데이트될 때를 담당하는 역할을 지정한다.
함수를 생성할 때에는 함수 드롭다운을 누르면 나오는 "바인딩 생성" 기능을 사용하면 함수의 입력값 세팅을 자동으로 해줘서 편하다.
"연관성이 생길 시"에는
IdleAnim_Setup
함수를 지정했고, "업데이트 시"에는IdleAnim_Update
함수를 지정했다.IdleAnim_Setup
에서는 업데이트 시에 사용될 변수를 초기화하고,IdleAnim_Update
에서는 애니메이션 시퀀스를 재생하게 만들 변수의 값을 업데이트한다.그 다음으로는 블루프린트에 변수를 추가한다.
하나는 시퀀스 이밸류에이터에 지정할 시간을 담당하는 float(플로트) 타입 변수다.
여기에서는 변수 이름을
SequenceExplicitTime
이라고 하겠다.그 외에는 사용될 애니메이션 시퀀스의 레퍼런스를 저장할 변수가 필요하다.
정확히는
Anim Sequence(애님 시퀀스)
의오브젝트 레퍼런스
타입이다.여기에서는 변수 이름을
IdleAnim
이라고 하고, 애니메이션이 재생되는걸 직관적으로 확인하기 위해 총기를 재장전하는 애니메이션을 사용하겠다.함수 구현은 다음과 같이 한다.
1. IdleAnim_Setup
일단 시간 지정에 사용될 float타입 변수인
SequenceExplicitTime
변수를 0으로 초기화하고, 그 값을 이용해서 시퀀스 이밸류에이터가 가지고있는ExplicitTime
의 값을 설정한다.이렇게 해서 시퀀스 이밸류에이터는 애니메이션 시퀀스의 0초를 가리키게 된다.
0초가 아니어도 상관 없다.
애니메이션 시퀀스의 시작 위치를 다른 시간으로 설정하고 싶다면 상황에 맞게 다른 값을 지정하면 된다.
그리고
IdleAnim
변수를 가져와서 시퀀스 이밸류에이터에 애니메이션 시퀀스를 지정한다.이 예제에서 애니메이션 시퀀스를 함수 내부에서 지정하는 이유는 시퀀스 이밸류에이터의 시퀀스를 "다이내믹 값"으로 지정했기 때문에 그러한 방법을 활용한 것이다.
"다이내믹 값"이 아니면 함수 외부에서 직접 지정해줘도 된다.
추가로 "연관성이 생길 시" 뿐만 아니라 "업데이트 시"에서도 애니메이션 시퀀스를 지정해줘도 된다.
이런 경우에는 업데이트 되는 상황에 따라 애니메이션을 중간에 변경할 수도 있다.
이 부분은 나중에 다시 설명하겠다.
참고로 노드를 추가할 때, 헷갈릴 수 있는 부분이 있다.
위 이미지처럼
Convert to Sequence Evaluator
노드가 두개 있고,Convert to Sequence Player
라는 노드도 있다.이 예제에서는 시퀀스 이밸류에이터를 사용중이므로
Convert to Sequence Evaluator
를 사용해야한다.만약 시퀀스 플레이어에 함수를 바인딩 해서 구현하는 경우에는
Convert to Sequence Player
를 사용하면 된다.그리고 같은 이름의 함수가 두개 있는데 둘중 하나는 Pure함수고, 다른 하나는 Pure가 아니다.
어차피 둘 다 같은 역할을 하기 때문에 상황에 맞게 고르면 된다.
이 노드를 간단하게 설명하면, 이 함수가 바인딩 된 노드를 입력값으로 받아서 그 노드를 시퀀스 이밸류에이터로 변환하는 것이다.
캐스팅과 비슷하다고 생각하면 되지 않을까 싶다.
그리고
SetExplicitTime
노드와 유사한SetAccumulatedTime
이라는 노드가 있다.이 노드도 위의 경우와 동일하게 시퀀스 플레이어에 사용되는 노드다.
시퀀스 이밸류에이터는
ExplicitTime
, 시퀀스 플레이어는AccumulatedTime
을 사용한다.애니메이션 시퀀스를 지정하는
SetSequence
노드에도 시퀀스 이밸류에이터에 사용되는 노드와 시퀀스 플레이어에 사용되는 노드가 구분되어있지만 이름은 같으므로 맞는 노드인지 확인한 뒤에 사용해야한다.2. IdleAnim_Update
업데이트 함수에서는
SequenceExplicitTime
을DeltaTime
만큼 누적시키면 된다.함수의 입력 값인
Context(AnimUpdateContext)
를 이용해서 각 틱의DeltaTime
을 가져와서 누적시킨다.그리고 그 값을 다시 시퀀스 이밸류에이터의
ExplicitTime
에 설정하면 끝이다.실행해보면 애니메이션이 재생되는걸 확인할 수 있다.
이렇게 까지만 구현하면 애니메이션이 루프되지 않는다.
만약 애니메이션 시퀀스가 루프되길 원한다면 애니메이션 시퀀스의 길이를 가져온다음
SequenceExplicitTime
이 애니메이션 시퀀스의 길이를 초과한다면SequenceExplicitTime
을 0으로 초기화시키면 된다.애니메이션 시퀀스가 루프되게 하는 방법 시퀀스 이밸류에이터에 지정된 애니메이션 시퀀스를 가져와서 애니메이션 시퀀스의 길이와 비교하면 된다.
그러면 다음과 같이 애니메이션이 루프된다.
만약 위에서 언급했던 중간에 다른 애니메이션 시퀀스로 변경하는것을 구현하고 싶다면 "업데이트 시"에서 구현하면 된다.
특정한 입력을 받으면 다른 애니메이션으로 변경되도록 구현해보겠다.
입력을 받는것은 간단하게 캐릭터 블루프린트에서 구현해 보겠다.
캐릭터의 블루프린트에 bool타입의
Input
이라는 변수를 추가했다.그리고 이벤트 그래프에 간단하게 마우스 왼쪽 버튼을 누르면
Input
이라는 변수를 true로, 떼면 false로 설정한다.그 다음 애니메이션 블루프린트에도 동일하게
Input
이라는 변수를 추가하고,BlueprintUpdateAnimation
이벤트에 캐릭터 블루프린트의Input
변수의 값을 가져와 그대로 설정하겠다.그리고
IdleAnim_Update
함수는 다음과 같이 구현한다.기존의 것에
SetSequence
노드가 추가된 것이다.OtherAnim
이라는 애님 시퀀스 오브젝트 레퍼런스 변수를 추가했고, 이 변수에 총기를 발사하는 애니메이션을 지정했다.그러므로 최종 결과물은 마우스 왼쪽 버튼을 누르고 있는 동안에는 총기를 발사하는 애니메이션이 루프되고, 버튼을 떼면 재장전하는 애니메이션이 루프된다.
굳이 애니메이션 노드 하나만 사용하기를 또는 스테이트가 변경되지 않기를 원한다면 이렇게 구현해도 된다.
물론 시퀀스 플레이어를 사용해도 가능하고, 대부분의 경우에는 시퀀스 플레이어가 더 편할 수도 있다.
하지만 애니메이션 시퀀스를 프레임 단위로 직접 관리할 수 있기 때문에 다양하게 응용이 가능할듯 하다.
마지막으로 정리하면 시퀀스 이밸류에이터는 시퀀스 플레이어와 큰 차이가 없어보이지만 애니메이션을 출력하는 방식이 다르다.
시퀀스 플레이어는 항상 재생되므로 시간을 옮기면 현재 시간에서 지정한 시간까지 훑고가는 느낌으로 중간에 있는 노티파이를 트리거하지만,
시퀀스 이밸류에이터는 특정 시간의 포즈를 출력한다.
그런데 그 시간을 지속적으로 증가시키면 시퀀스 플레이어처럼 애니메이션을 재생하는 목적으로도 사용할 수 있다.
애니메이션 스테이트 중간에 애니메이션이 동적으로 변경되는데 바뀐 애니메이션을 처음부터 재생하는게 아니라 이전 애니메이션의 시간에 이어서 재생되게하거나,
하나의 애니메이션이 경우에 따라 재생과 역재생을 반복해야하는 경우에는 시퀀스 플레이어보다는 시퀀스 이밸류에이터가 조금 더 어울리지 않을까 싶다.
'언리얼엔진 > 그 외' 카테고리의 다른 글
[UE5] C++로 애니메이션 시퀀스 변경, 커브 추가 (0) 2024.07.03 [UE5] 캐릭터 무브먼트 컴포넌트 작동 순서 정리 (0) 2024.06.13 [UE5] USTRUCT의 NetSerialize (1) 2024.03.12 [UE5] 블렌더로 루트 모션 애니메이션 만드는 방법 (4) 2024.01.25 [UE5] Enhanced Input Binding with Gameplay Tags C++ (0) 2024.01.21