5.4 게임애니메이션샘플 1 [basic ground locomotion]

 

모션매칭 시스템을 사용해 보려함.

캐릭터BP 




  • Update Camera
그냥 카메라 셋팅. 에임 모드와 가운데정렬 로 두가지 모드를 지원함. 



Movement

  • UpdateMovement

여기서 게이트 값 업데이트


  • UpdateRotation
This function is called every tick, and is used to  update the character movement component’s rotation mode using the Wants to Strafe input condition. 

When the character is on the ground, this function sets the Rotation Rate to -1, which causes the character to rotate instantly. This technique allows us to treat the actor as the "target rotation", while we independently control the rotation of the root bone within the Animation Blueprint. This allows us to do things not currently supported in the character movement component, such as stick flicks (completely re-orienting the character when only tapping movement input), and gives us more control over the rotation behavior during actions like turn starts, pivots, and turning in place. This is still an experimental technique, and better rotation control should be coming with the new movement component in future engine releases.


번역기 돌려보니 "좋은거 암튼 좋은거 근데 아직 실험적인 기능, 업데이트 될꺼임"
이건 로코모션 구성에 크게 영향이 없어 그냥 똑같이 만들어 준다
모드에 따라 use controller desired rotation 키고 끄고 orient rot 키고 끄고 
rotation rate 설정해 주는건데 -1은 첨보네 암튼 엄청 빨리 돌려준다 뭐 그런거임.
그냥 똑같이 만들어 주면 됨



  • GetDesiredGait
이 함수는 현재 입력과 Wants to Walk 또는 Wants to Sprint 조건을 기반으로 캐릭터의 보행을 결정합니다. Movement Stick 모드는 스틱 편향을 통해 걷기 또는 달리기를 제어할 수 있는지 여부를 결정합니다(현재 이로 인해 모션 일치 선택에 문제가 발생할 수 있습니다. 가장 안전한 구현을 위해 지금은 고정 속도 - 단일 보행 옵션을 사용하십시오).

여기서 게이트Gait 값을 받아온다.
무브먼트 스틱 모드?
아날로그 무브먼트 라는 이름의 열거형 파일이 있고 스프린트 워크 런 이렇게 게이트를 만들어 줘야 하는거 같은데 아직 스프린트가 구현되어 있지 않아서 지금은  런과 워크만 리턴받는다.
나는  IA 월드스페이스를 사용하지 않을거라  그거는 빼고 필요한 부분들만 
만들어 준다.

첫번째와 마지막이 스프린트 자리인거 같다.
일단 5.5업데이트 대비로 일단 똑같이 만들어 둔다.






  • CalculateMaxSpeed

캐릭터 방향에 따라 속도변화를 주기위한 함수라고 한다.

0은 정면 1은 좌우 2는 역방향. Curve_StrafeSpeedMap 이름의 커브를 사용 

X축은 캐릭터의 현재 방향이다. 해당 각 안에 있으면 0,1,2를 출력한다.

(그래프상 0-30도 사이의 방향값일때는 정면으로 이동한다는 의미)



  3개 walk run sprint 요소를 가지는 enum Gait 생성,  스프린트는 5.5에 업데이트됨 현재는 사용하지 않음.

walk run sprint 3개의 벡터가 있음 각각 XYZ 값이 설정되어 있는데 정방향, 좌우, 역방향의 속도를 의미함.  그래서 여기서 최대 속도를 바꿔줌. 



  • GetMovementInputScaleValue
난 키보드만 쓸거라 이건 안함.
  • SetupInput

이건 그냥 인풋액션


traversal action 은 시간이 좀 걸릴꺼 같으니 여기까지 하고 

여기까지 해당하는 모션매칭 작업을 해 보도록 하자.


ABP 

스키마 부터 보면

4개로 나누어져 있다



디폴트에 move와 move start 그리고 idle 이 포함되는거 같다.

traversal은 나중에 할거니 일단 제외하고 3개를 만들어 준다.


언리얼 문서  참고


각각의 설정이 조금씩 다르다. 참고해서 똑같이 만들어 준다.



weight? 


두가지 키워드가 보인다

Dense 와 Sparse 검색을 해 보니 LOD에 따른 애니메이션 스케일링 을 위함이라 한다.

귀찮으니 LOD는 나중에 해보고  Dense만 만들어서 테스트 해 보자.


리타겟팅된 애니메이션으로 Dense database를 만들어준다. 

나는 아직 점프도 구현 하지 않았으니 

이렇게 7개를 우선 만든다.

가장 기본 형태라고 생각된다.

7개로 우선 그라운드 로코모션을 만들어 본다.

여기서 시작.



ABP를 열어 살펴보면 우선 이니셜라이즈는 캐릭터캐스팅 함수화고,업데이트에서 3개의 함수가 보인다.


이벤트 그래프 카테고리의 4개의 함수다



  • SetReferences

캐릭터 캐스팅 해 오고 무브먼트 변수만들고, 특별한거 없음.



  • UpdateEssentialValues


캐릭터 Transform값을 가져온다.

a.animnode.offsetrootbone.enable CMD로 루트본의 오프셋 활성화 여부에 따라
루트 트렌스폼을 셋 해준다.

false일경우는 캐릭터 트렌스폼 값으로 설정

true일때는 캐릭터Bp에서 돌려준90도를 더해주고 루트 트렌스폼을 만들어준다.

인플레이스턴과 aim offset에서 해당 값을 사용한다.

일단 나는 offsetRoot 관련 함수가 없어서 분기하지 않고 캐릭터 트랜스폼으로 모두 사용

요렇게


현재 가속도와 최대 가속도 값으로 총량을 구해 0보다 크면 가속중임.
코멘트에 현재 사용하지 않으나 나중을 위해 만들어 뒀다고 써있음.

HasAcceleration는 정말 사용하지 않고 있음. 신기하네 


노드가 길어 두장.





프레임당 속도 Last Non zero velocity 랑 velocity last frame 두개는 같아 보이는데 왜 나눠뒀을까...명확한 역할을 지금은 잘 모르겠다. 변수가 어디에 어떻게 사용되는지 봐야 겠다.



LOD 값을 가져와서 Dense 랑 Sparse 를 바꿔준다는데 찍어봐도 LOD값이 바뀌지 않는다.

변수도 사용하지 않는다.

그리고 난 어차피 sparse 안만드니까 상관없다.




선택된 PSD의 테그값을 가져온다.


나중에 이쪽에서 어떤 tag인지 확인.




  • GenerateTrajectory

이 함수는 권장 캐릭터 이동 구성 요소로부터의 모션 모델을 사용하여 궤적 이력을 업데이트하고 미래 예측을 생성합니다. 사용자 정의 캐릭터 이동 구성 요소는 사용자 지정 궤적 생성 함수가 필요할 수 있습니다.

알려진 문제: 몽타주 루트 모션 및 와핑은 궤적 생성에 영향을 미치지 않습니다.











주로 공중에서 사용한다는 이 부분은 중력을 가하고 충돌을 예측한다고 한다.

문제는 잘못된 트레젝토리를 생성한다고 한다. 어쩔..





0.5초뒤 위치에서 0.4초뒤 위치를 빼주고 10을 곱해서 미래 위치를 예측한다.
10은 계산의 편의를 위해 그냥 곱해주는거 같다. 



  • UpdateStates

"이 기능은 캐릭터가 있는 모든 중요한 게임 플레이 관련 상태를 캐시할 뿐만 아니라 마지막 프레임의 값을 저장하여 값이 언제 변경되었는지 판단할 수 있도록 합니다. 편의상 Enums에 저장하여 모션 매칭 데이터베이스를 걸러내는 데 주로 사용되며, 현재 게임 플레이 상태의 모션만 선택할 수 있습니다."

이 함수에서 모션매칭을 선택하는거 같다. 4개중 가장 중요한 부분인거 같은 느낌적 느낌.

여기서 사용되는 Enum 




Gait 는 BP작업에서 만들어 뒀고 나머지 4개 만들어 준다.

E_MovementMode - OnGround /InAir 두가지 모드
E_RotationMode - OrientToMovement/Strafe 카메라 모드에 따른 캐릭터 로테이션 방식
E_MovementState - Idle/Moving
E_Stance -Stand/Crouch 현재버전에서 구현되어 있지 않음. 

모두 각각 라스트 프레임을 가지고 있다,이전 상태와 비교해 블랜드타임 등을 설정하기 위함이다.



쭉 보면 특별할게 없어 그냥 스샷 한장으로 마무리 한다.
중간에 불리언 함수 하나가 필요 한데, 다음에 정리할 내용이라 만들어주고 달아주도록 한다.





여기까지






Movement Analysis

  1. IsMoving
  2. IsStarting
  3. IsPivoting
  4. ShouldTurnInPlace
  5. JustLanded_Light
  6. JustLanded_Heavy
  7. JustTraversed
  8. ShouldSpinTransition

8개 함수를 가지고 있다. 나는 일단 4번까지만 해도 될거 같다.

  • IsMoving




바로 위 함수 3번째 분기 조건에 위 함수를 달아준다 이거는 pure 함수다.


내용은 지금 속도 미래 속도 모두 0이 아니면 움직이는거다.


  • IsStarting

database tags를 아직 잘 모르겠다. 

 현재 Database 자산이 피벗 데이터베이스인 경우 이 함수는 항상 false를 반환합니다. 이는 피벗의 후반부가 시작과 매우 유사하기 때문에 모션 매칭 시스템이 피벗을 중단하는 것을 방지합니다.

리턴 벨류는 항상 false 라는 얘기다. 이부분이 이해가 잘 안간다. 왜 항상 false를 반환하는걸 이렇게 만들지? 왜지? chooser table 에서 사용되는거 같은데 만들때 다시 보자.

왜냐하면 방향이 전환중이라는건 아직 애니메이션이 출력중이니 
여기서 원하는건 아이들 상태에서 이동스타트 데이타베이스 출력이다.
아마 맞을꺼야...

  • IsPivoting


이 기능은 캐릭터의 미래 궤적이 캐릭터의 현재 궤적과 매우 다른 방향으로 움직이고 있는지 확인하여 캐릭터가 피벗하고 있는지 여부를 결정하는 데 사용됩니다. 
45도 피벗은 스트래핑 중에는 잘 작동하지만 오리엔트 투 무브먼트 중에는 필요하지 않으므로 회전 모드는 임계값이 다릅니다.

라고 한다 오리엔트 일경우 60도.





미래 위치 - 현재위치 그럼 예측각이 나온다. 좌우 상관없이 절대값으로 비교해줘서
(모드에 따라 다른 임계값) 불리언 반환.
아직도 잘 모르겠다  이 리턴값이 어디에 사용 되는지.


  • ShouldTurnInPlace

왜 라스트 스테이트가 무빙이어야 하지? 


해당 불리언 값은 참 거짓의 전환을 필요로 한다.
만약 저 노드를 빼고 has velocity를 달아도 같은 결과를 도출한다.
두 노드는 아주 순간적으로 일치하지 않는 타이밍이 있는데 단지 그걸 필요로 해서 만들어진 노드이다. 저렇게 만든 이유는 에임 모드에서는 자동으로 턴인플레이스를 구현 하기 위해서다.(이제 보니 내가 노드를 빼먹었네 어쩐지 이상 하다 했다..) 아래가 정상적인 노







"이 기능은 뿌리뼈 회전이 캐릭터의 캡슐 회전과 다른지 확인하여 캐릭터가 제자리에서 회전하고 있는지 확인하는 데 사용됩니다. 이 프로젝트의 경우 회전이 50도보다 크고 캐릭터가 현재 목표로 하고 있다면 캐릭터를 제자리에서 돌려야 합니다. 또한 캐릭터가 막 멈췄을 경우 재생할 수 있는 장소에서 턴 인을 허용하여 "스틱 플릭" 동작을 제공합니다.

조준 상태 동안의 턴 인 플레이스 동작은 여전히 WIP입니다. 캐릭터가 너무 뒤떨어지는 것을 방지하기 위해 스티어링 또는 루트 오프셋 노드에 추가 제한을 적용해야 합니다."

모르겠다 리턴 벨류가 어디서 쓰이는지 지금은 모르니 일단 넘어가자

이쯤에서 AnimGraph를 만들어 보자
필요한것들만 달아서 그라운드 로코모션 출력이 목표다.



우선 여기서 database 바인딩 하는 방법을 찾아야 한다

바인딩 함수가 추가 되어야 하고 블랜드 타임이랑 인터업 이라는 함수를 만들어야 한다.

  • Update MotionMatching


"이 Anim Node Function은 Motion Matching 노드가 업데이트될 때마다 호출됩니다. 현재 게임 플레이 컨텍스트를 기반으로 Pose Search Database 자산 배열을 반환하는 Chooser 자산을 평가합니다. 이를 통해 더 높은 수준의 필터링을 수행할 수 있어 모션 매칭 시스템이 선택할 수 있는 애니메이션이 무엇인지 더 많이 제어할 수 있습니다.

예를 들어, 우리는 캐릭터가 걷고 있을 때만 (플레이어의 입력을 통해 제어됨) 워크 데이터베이스에서 검색하여 캐릭터가 워킹하려고 할 때 모션 매칭이 런을 선택하지 못하도록 합니다."

우선 Chooser Table 을 하나 만들어준다.
난 Dense 만 사용하니 하나만 만들어 주면 된다.

테이블 셋팅

4개의 nested chooser 만들어 준다.
idle/walk/run/inair


nested chooser 에디팅에서 만들어둔 PSD 넣어주고 조건을 만들어 주는데
위에서 의문을 가지고 있던 리턴불리언 값은 여기서 사용된다.
근데 문제가 하나 생겼다. 
나는 프로퍼티 불리언만 나온다. 함수 불리언을 어떻게 불러 오는지 모르겠다...

에픽꺼

내꺼

나도 함수 있는데...
내 함수는 어떻게 불러오는건데????

와우..., 리턴노드 아웃풋 불리언 네이밍이 중요하다 ReturnValue 여야 한다.
(난 Return Value)여서 function binding에 나오지 않았다.



  • Get_MMInterruptMode
update_motionMatching에 필요한 함수




인터업은 데이터베이스를 골라주는 어쩌구 저쩌구라 한다.
"이 기능은 모션 매칭 노드의 인터업 모드를 제어합니다. 이것은 모션 매칭이 선택 가능한 데이터베이스가 변경된 경우 새로운 데이터베이스로 강제로 혼합될지, 아니면 현재 재생 중인 애니메이션보다 비용이 적게 드는 일치를 찾을 때까지 기다릴지 결정합니다. 기본적으로, 우리는 인터럽트를 하지 않습니다. 그러나 코어 상태가 변경될 때마다, 우리는 새로운 애니메이션을 재생하기를 시작하기를 원한다는 것을 알고 있으므로, 강제로 인터럽트를 실행합니다. 이것은 모션 매칭이 캐릭터가 움직이기 시작했다면 유휴 상태에 머무르지 않도록 하거나, 캐릭터가 멈추기를 원한다면 사이클 애니메이션에 머무르지 않도록 하는데, 이것은 "계속되는 포즈 바이어스" 튜닝에 기초하여 일어날 수 있습니다. 본질적으로, 이것은 코어 상태의 변화에 반응하는 모션 매칭을 계속합니다."

enum 상태를 모두 비교해서 변화가 있을때 반환한다.
반환하는 값이 E Pose Search 형인데 이건 또 어디서 나온걸까?
찾아보자.

E pose search enum 은 아무리 찾아도 안 나온다.
내가 찾은 해당 핀 노출 방법은 아래와 같다.


아 빡쳐...


  • Get_MMBlendTime

"이 기능은 현재 및 이전 상태를 기준으로 모션 매칭 노드의 블렌드 시간을 변경하는 데 사용됩니다. 향후에는 선택한 데이터베이스에서 블렌드 시간을 보다 직접적으로 설정할 수 있도록 할 계획입니다."




간단하다. 상태 변화에 따라 블랜드 타임을 조절 해 준다.

  • Update_MotionMatching_PostSelection

Tag 설정은 PSD에서 해 줘야 한다.



이러면 이제 이해가 조금 간다.

해당 테그로 현재 PSD를 검사해 상황에 맞게 사용 하는거다.

예를 들어 무빙스타트 함수에서는 현재 방향전환이 아닌 상태여야 스타트 database로 연결을 시킨다는 의미 이다.


마지막으로 Blend Stack 





움직이게만 구성 했다.
orientation warping에서 root offset 함수들이 사용된다.
우선 이부분을 이해해 봐야겠다.

stop database는 사용하지 않는거 같은데....체크해 봐야 겠다.



에픽꺼


내꺼





walk run stop는 아이들 nested chooser 에 있다.
문제는 Speed2d값을 가져오지 않는것이다.
일단 fallback에 아이들을 넣어서 speed2d 값과 무관하게 출력은 시켰고
이건 나중에 다시 보기로 하자 진짜 모르겠고 안될 이유도 없는데..




댓글