<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>techartnomad</title>
    <link>https://techartnomad.tistory.com/</link>
    <description>메이즈라인 주식회사 대표 컨설턴트. 시그라프 상해쳅터 정회원
ex.넷이즈,바이트덴스,거인네트워크,신동네트워크,알레고리드믹 등에서 Technical Specialist.
협력 경험: NVIDIA + QUALCOMM

https://www.mazeline.tech/</description>
    <language>ko</language>
    <pubDate>Fri, 24 Jul 2026 16:35:08 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>jplee</managingEditor>
    <image>
      <title>techartnomad</title>
      <url>https://tistory1.daumcdn.net/tistory/6333236/attach/4ffab9c97956485d95e0d4632691b535</url>
      <link>https://techartnomad.tistory.com</link>
    </image>
    <item>
      <title>[Update] UnrealEngine 6 위클리 프리빌드</title>
      <link>https://techartnomad.tistory.com/805</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;애픽 리포지토리의 ue6-main 브렌치를 1일 단위로 자동 빌드하도록 데브옵스 서버컴에 셋팅을 해 놨는데요.&lt;br /&gt;대부분(거의 모든)의 언리얼엔진 5.8 플러그인은 동작하지 않습니다. &lt;span style=&quot;color: #141414;&quot;&gt;Build.cs에 UE6 호환 매크로도 다르고 일부 모듈들도 리펙토링 되어버렸기 때문이죠. 그 부분은 당분간 포기? 하시고 월 단위로다도 사용해 보고자 하는 얼리어뎁터 아티스트분들은 굳이 고생해서 빌드 하지 마시고 받아쓰시라고 올려놓게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5OdiC/dJMcag0rDiG/xGLFkvFSD3FoJSFl8KpzN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5OdiC/dJMcag0rDiG/xGLFkvFSD3FoJSFl8KpzN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5OdiC/dJMcag0rDiG/xGLFkvFSD3FoJSFl8KpzN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5OdiC%2FdJMcag0rDiG%2FxGLFkvFSD3FoJSFl8KpzN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;371&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;언리얼엔진6 위클리 프리빌드 버전&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ue6-main 브렌치에 애픽에서 아직 인스톨빌드 xml 에 verse 관련 된 내용을 추가하지 않았습니다. 제가 현재 임시 수정중이긴 합니다. 아무튼 그래서 인스톨빌드로 언리얼6 프로젝트 실행 후 verse 관련 플러그인을 활성화 했을 경우 verseNative 또는 솔라리스 관련 애러가 뜰겁니다.&lt;/blockquote&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;Engine.7z&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;&quot; data-og-host=&quot;drive.google.com&quot; data-og-source-url=&quot;https://drive.google.com/file/d/1ziaYXmP0fHV7VNrUBzvPlMY0_3hj-y-h/view?usp=sharing&quot; data-og-image=&quot;&quot; data-og-url=&quot;https://drive.google.com/file/d/1ziaYXmP0fHV7VNrUBzvPlMY0_3hj-y-h/view?usp=sharing&amp;amp;usp=embed_facebook&quot;&gt;&lt;a href=&quot;https://drive.google.com/file/d/1ziaYXmP0fHV7VNrUBzvPlMY0_3hj-y-h/view?usp=sharing&amp;amp;usp=embed_facebook&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://drive.google.com/file/d/1ziaYXmP0fHV7VNrUBzvPlMY0_3hj-y-h/view?usp=sharing&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('\'\'');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Engine.7z&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;drive.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 7월 24일(커밋해시 57fc49e27aefa11418ba4cb06beddb6585ff8174)&lt;br /&gt;&lt;s&gt;2026년 7월 22일(커밋해시 bea62601323c3dd32efffa1c84af80f0cdbc7b88)&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 21일(커밋해시 f189eea1002d2670e2cffd8659e6b3f7706d9c55)&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 20일(커밋해시 69f0d76d7eabb1171430f3d59dc444d847054d1d)&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 18일(커밋해시 7e8e9767f4f3b9685a4cfd317b14467533b874ea)&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 18일(커밋해시 50ceaa4b7bf2a439647bc8b8630a69d9cec948b1)&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 17일(커밋해시 13df8ae684526ae2c55fac283b86e76f10f27292)&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 16일(커밋해시 fdc4af80c6a4ae83053cf9b99388c6d1c70d1408) :&lt;/s&gt; 애픽에서 누락한 stale cli_filter 버그 직접 수정 한 버전&lt;br /&gt;&lt;s&gt;2026년 7월 15일(커밋해시 ad3ce764444dfec2f2d61a336b5b522f9dcafec3 )&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 14일(커밋해시 f037e60a3a64b27ac9944ceabda9fa1d804fc122 )&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 13일(커밋해시 aba4d87630151b2b63d551c96521076dc2d54499 )&lt;/s&gt;&lt;br /&gt;&lt;s&gt;2026년 7월 12일(커밋해시 22801911dcae9c22c575c613e0596c63c88b7e46)&lt;/s&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;해당 빌드로 프로토타입 개발 하면서 이슈들도 파악중.&lt;/h4&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=KmRwRRtNIT4&quot; data-video-thumbnail=&quot;https://blog.kakaocdn.net/dna/ib4uW/dJMb9cBUm5A/AAAAAAAAAAAAAAAAAAAAACwS0G0wpAsWptYhL8FL5-l_vT91yelL8xvQtohVPRKu/img.jpg?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&amp;amp;expires=1785509999&amp;amp;allow_ip=&amp;amp;allow_referer=&amp;amp;signature=m0fRoKudD3UD5By45BNiJGq7R60%3D&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;UnrealEngine6 - Play Prototype Dev-Diarly. 01&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/KmRwRRtNIT4&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>UNREAL ENGINE</category>
      <category>UE6</category>
      <category>언리얼 엔진</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/805</guid>
      <comments>https://techartnomad.tistory.com/805#entry805comment</comments>
      <pubDate>Fri, 24 Jul 2026 00:00:40 +0900</pubDate>
    </item>
    <item>
      <title>[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 점프</title>
      <link>https://techartnomad.tistory.com/821</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐라고? 점프 같은 간단한 것에 뭐 설명할 게 있냐고? 어어어, 잠깐 가지 마라. 점프 하나를 구현하는 건 쉽지만, 자연스럽고 진짜 같은 점프를 구현하는 건 결코 쉽지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 속 골격 애니메이션이든 일본 2D 손그림 애니메이션이든, 가장 중요한 것은 걷기, 달리기, 점프처럼 일상생활에서 어디서나 볼 수 있는 동작을 잘 처리하는 것이다. 이런 동작은 우리가 현실에서 너무 많이 봐왔기 때문에, 조금만 부자연스러워도 금방 뭔가 이상하다는 것을 알아차린다. (반대로 마법을 쓰거나 검극으로 싸우는 동작 같은 것은 현실에서 거의 본 적이 없으니 기준을 찾을 수 없고, 그래서 이런 동작에 대한 관용도는 더 높다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 한 게임의 애니메이션 수준은, 흔히 이런 가장 기초적이고 게임에서도 현실에서도 가장 많이 쓰이는 동작에서 드러난다. (일본 손그림 2D 애니메이션도 마찬가지다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 최종 완성 효과 이미지를 하나 올려 독자를 붙잡아보겠다. (급하게 이 글을 닫지 말고) 어떻게 만드는지 궁금하다면 같이 아래로 따라와 보면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHh9B7/dJMcabSwEDz/VANCSFh2UiJMK4dBjYgKG0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHh9B7/dJMcabSwEDz/VANCSFh2UiJMK4dBjYgKG0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHh9B7/dJMcabSwEDz/VANCSFh2UiJMK4dBjYgKG0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bHh9B7/dJMcabSwEDz/VANCSFh2UiJMK4dBjYgKG0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;270&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(다만 이 완성본도 아직 완벽하다고 할 수는 없다. 발 고정도 아직 하지 않았고, 관성화 처리도 아직 하지 않았다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설령 이 글이 정말 별로라고 느껴지거나 흥미가 생기지 않더라도, 떠나기 전에 좋아요 하나만 눌러주고 가주면 좋겠다. 부탁이다 &amp;ge;﹏&amp;le;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 쓴 기술 블로그는 예전에 많은 사람에게 도움이 된 적이 있다. 이제는 나도 여러분의 도움을 받고 싶다! (작은 좋아요 버튼 한 번만 누르면 된다!)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 모두가 쓰지만, 사실 쓰기 좋은 것은 아닌 구현방안&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 감히 모두가 써봤다고 장담할 수 있는 방안이 무엇이냐고? 그건 당연히&amp;hellip;&amp;hellip;!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언리얼 엔진의 템플릿 프로젝트다 = = 어쨌든 블루프린트를 배워본 사람이라면 엔진에 딸려오는 3인칭 템플릿 프로젝트는 반드시 써봤을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 3인칭 UE 템플릿 프로젝트를 하나 열고, 스켈레탈 메시를 따라 애니메이션 블루프린트를 찾아 들어가면, 이런 상태 머신을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태 머신은 매우 간단하고 이해하기 쉽다. Idle/Run은 캐릭터가 정상적으로 지면에 서 있을 때의 상태 집합을 대표한다. JumpStart는 기상, 즉 점프 시작이고, 점프 시작 애니메이션이 재생되면 공중 체공 애니메이션을 루프한다. 착지할 때는 착지 애니메이션을 재생하고, 재생이 끝나면 다시 지면 상태로 돌아간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqVc1R/dJMcacjAkYw/DwLpJXAnKXZdcRJQjPO920/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqVc1R/dJMcacjAkYw/DwLpJXAnKXZdcRJQjPO920/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqVc1R/dJMcacjAkYw/DwLpJXAnKXZdcRJQjPO920/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqVc1R%2FdJMcacjAkYw%2FDwLpJXAnKXZdcRJQjPO920%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;617&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;617&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식의 신뢰도는 간신히 합격선에는 도달했다고 볼 수 있다. CF 같은 게임에 쓰면, 모두가 익숙하게 보아와서 딱히 부자연스럽다고 느끼지는 않을 것이다. 하지만 ALSV4로 만든 효과와 비교하면 곧바로 초라해진다. 주요 문제는 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;기상 시 왼발이 앞인지 오른발이 앞인지 구분하지 않고&lt;/b&gt;, 하나의 점프 시작 애니메이션만 통일해서 사용한다. 캐릭터 이동 속도가 빠를 때는 그럭저럭 들키지 않지만, 속도가 느릴 때는 비교적 분명하게 드러난다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기상 시 캐릭터의 이동 속도에 따라 점프 시작 애니메이션을 구분하지 않는다.&lt;/b&gt; 속도 0의 제자리 점프와 전력 질주 중의 점프에 같은 애니메이션 세트를 사용한다. (생각해보라. 현실에서 제자리에서 수직으로 뛰는 것과, 한참 도움닫기를 해서 앞으로 뛰는 동작이 같을 수 있겠는가.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글 첫머리의 GIF는 걷기, 달리기, 전력 질주 세 상태에서의 점프 시작 동작을 보여준다. 아주 분명히, 동작 폭이 완전히 다르다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cf4d8u/dJMcai48WkS/aWi4t3w3QMQ1oFBADvo9Bk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cf4d8u/dJMcai48WkS/aWi4t3w3QMQ1oFBADvo9Bk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cf4d8u/dJMcai48WkS/aWi4t3w3QMQ1oFBADvo9Bk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cf4d8u/dJMcai48WkS/aWi4t3w3QMQ1oFBADvo9Bk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;270&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;점프 과정 중 무게중심이 변화하는 과정이 없다.&lt;/b&gt; 기상, 공중, 나아가 착지할 때까지, 우리의 무게중심은 몸의 균형을 유지하기 위해 변화한다. 구체적인 변화 과정은 일률적으로 말하기 어렵다. 예를 들어 제자리 멀리뛰기 착지 시 무게중심은 앞으로 이동할 수도 있고, 뒤로 이동할 수도 있다. 뒤로 이동하면 엉덩방아를 찧게 된다. 연속적인 달리기 점프의 무게중심 변화도 제자리 멀리뛰기의 무게중심 변화와 다르다. 여기서는 하나하나 길게 말하지 않겠다. ALSV4에서는 기본적으로 사람이 상승 단계에서는 무게중심이 앞으로 기울고, 하강 단계에서는 뒤로 기운다고 본다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;착지 시 낙하 속도에 따라 착지 애니메이션을 구분하지 않는다.&lt;/b&gt; 높은 곳에서 떨어지는 것과 작은 계단에서 살짝 뛰어내리는 것은 낙하 속도에 큰 차이가 있다. 우리는 캐릭터 무릎이 내려가며 완충하는 시간의 길고 짧음으로 낙하 속도의 빠르고 느림을 표현해야 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐릭터 착지 시의 이동 요구를 고려하지 않는다.&lt;/b&gt; 위의 상태 머신을 보면, 로직은 착지 애니메이션이 거의 재생 완료될 때에만 정상적인 지면 상태 집합으로 돌아간다. 그런데 만약 착지 애니메이션이 아직 끝나기 전에 이동을 시작하면, 우리는 착지 상태 노드 안에 머무른 채 캐릭터를 이동시키게 된다. 이때 아직 착지 상태 노드 안에 있고 정상적인 지면 상태 집합으로 돌아가지 않았으므로 캐릭터의 이동 동작을 처리할 수 없다. 그래서 딱딱한 &lt;b&gt;슬라이딩&lt;/b&gt; 현상이 나타난다. 말로 들으면 조금 복잡하고 이해하기 어려울 수 있으니, 아래 GIF를 보면 바로 알 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;v2-89cf937f653c8651c9ec7d40678119ba_b.webp&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mU06V/dJMcagff6DD/3p0xeK9b7WzA8BpwnP3KH0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mU06V/dJMcagff6DD/3p0xeK9b7WzA8BpwnP3KH0/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mU06V/dJMcagff6DD/3p0xeK9b7WzA8BpwnP3KH0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmU06V%2FdJMcagff6DD%2F3p0xeK9b7WzA8BpwnP3KH0%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;338&quot; data-filename=&quot;v2-89cf937f653c8651c9ec7d40678119ba_b.webp&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 세심한 독자는 이렇게 물을 것이다. &amp;ldquo;내가 3인칭 템플릿을 썼을 때는, 달리면서 점프해도 착지할 때 그렇게 뚜렷한 슬라이딩을 느끼지 못했던 것 같은데?&amp;rdquo; 이유는 언리얼 템플릿의 착지 애니메이션이 겨우 0.2초밖에 되지 않고, 착지 애니메이션과 지면 상태를 블렌드하는 시간도 0.2초이기 때문이다. 그래서 그 슬라이딩을 알아차리기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 0.2초는 너무 빠르다. 비교적 뚜렷한 착지 동작을 보여주기에는 부족하다. 그리고 착지 애니메이션이 조금만 길어져도 슬라이딩 문제는 곧바로 튀어나온다. 그러므로 UE 템플릿의 방법처럼 잔꾀로 게으름을 피우는 것은 장기적인 해법이 아니다. 착지 이동과 착지 정지를 구분하는 것이야말로 현명한 선택이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. ALSV4가 사용하는 점프&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1 데이터 준비&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;상태 머신은 우리가 언제 점프했는지 알아야 한다. 따라서 이를 표시할 변수가 필요하다. 템플릿 프로젝트에서는 이동 컴포넌트에 내장된 낙하 함수를 사용해 판단하는 것을 볼 수 있다. 물론 이렇게 해도 되지만, 좋은 선택은 아니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MzHzs/dJMcaaMT9z3/NxwY5o5OalqvSeupJJhNV0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MzHzs/dJMcaaMT9z3/NxwY5o5OalqvSeupJJhNV0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MzHzs/dJMcaaMT9z3/NxwY5o5OalqvSeupJJhNV0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMzHzs%2FdJMcaaMT9z3%2FNxwY5o5OalqvSeupJJhNV0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;305&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 상황을 생각해보자. 캐릭터 발밑의 바닥이 갑자기 무너졌다. 캐릭터가 물살을 이기지 못해 절벽 아래로 휩쓸려 내려갔다. 혹은 단순히 작은 계단 하나를 내려갔다&amp;hellip;&amp;hellip; 이런 상황에서도 마찬가지로 여기의 &amp;ldquo;Is in Air?&amp;rdquo;는 참이 된다. 하지만 이때 우리가 캐릭터에게 점프 동작을 하게 만들고 싶지는 않을 것이다. 그러므로 가능하면 구분해두는 것이 좋다. 캐릭터가 떨어지고 있는지를 판단 기준으로 삼는 것이 아니라, 캐릭터가 정말로 점프했다는 이벤트로 변수 변화를 트리거해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mXKRU/dJMb99UI4V8/eeBMSA8KmYSDumDygSiVkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mXKRU/dJMb99UI4V8/eeBMSA8KmYSDumDygSiVkk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mXKRU/dJMb99UI4V8/eeBMSA8KmYSDumDygSiVkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmXKRU%2FdJMb99UI4V8%2FeeBMSA8KmYSDumDygSiVkk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;835&quot; height=&quot;233&quot; data-origin-width=&quot;835&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;두 번째 변수는 낙하 속도다. 이것은 캐릭터 속도의 Z축 값에서 직접 얻어지므로, 그 양수/음수는 캐릭터가 현재 상승 중인지 하강 중인지를 표시할 수 있다. 그리고 절댓값은 일반 낙하 애니메이션과 빠른 낙하 애니메이션을 블렌드하거나, 가벼운 착지와 무거운 착지 애니메이션을 블렌드하는 데 사용할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci7kH1/dJMb99UI4Wb/u5qfM3pK42fmfquzQQJBgK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci7kH1/dJMb99UI4Wb/u5qfM3pK42fmfquzQQJBgK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci7kH1/dJMb99UI4Wb/u5qfM3pK42fmfquzQQJBgK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci7kH1%2FdJMb99UI4Wb%2Fu5qfM3pK42fmfquzQQJBgK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;555&quot; height=&quot;256&quot; data-origin-width=&quot;555&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;세 번째 변수는 캐릭터의 몸 기울기량이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 캐릭터 자신의 좌표계 안에서의 속도를 기준으로, 그것을 X/Y축 속도 성분으로 분해한다. 이 성분은 곧 기울기 각도량을 대표한다. 이 기울기량은 지면에서 걷고 있을 때든 공중에 있을 때든 모두 사용해야 한다. 캐릭터 무게중심 변화에 따른 몸 기울기를 표현하기 위해서다. 공중 기울기량은 캐릭터가 상승 상태인지 하강 상태인지에 따라 추가로 하나의 기울기 계수를 곱하기만 하면, 점프 시작부터 낙하까지 무게중심이 앞에서 뒤로 이동하는 과정을 표현할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z7SX8/dJMb99UI4Wa/xjY2y1TiKUP7whMmpRsehk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z7SX8/dJMb99UI4Wa/xjY2y1TiKUP7whMmpRsehk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z7SX8/dJMb99UI4Wa/xjY2y1TiKUP7whMmpRsehk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz7SX8%2FdJMb99UI4Wa%2FxjY2y1TiKUP7whMmpRsehk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;571&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공중에서 추가로 기울기 계수를 곱해야 한다고 말했으니, FallSpeed의 양수/음수와 값을 어떻게 사용해 한 번의 점프 과정을 반영하고, 각 시점에 필요한 기울기 계수를 계산할 수 있을까? ALSV4는 이런 커브 하나를 사용했다. FallSpeed 값을 입력하기만 하면, 적절한 기울기 계수가 얼마여야 하는지 알려준다. 원리는 그림과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;817&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QYvc0/dJMcaaMT9z4/jBnre70KzNYTIYkXpuQkyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QYvc0/dJMcaaMT9z4/jBnre70KzNYTIYkXpuQkyk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QYvc0/dJMcaaMT9z4/jBnre70KzNYTIYkXpuQkyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQYvc0%2FdJMcaaMT9z4%2FjBnre70KzNYTIYkXpuQkyk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1325&quot; height=&quot;817&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2 단점들을 하나씩 극복하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 기상 시 왼발이 앞인지 오른발이 앞인지 구분하지 않는다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 비교적 간단하다. (하지만 예전에는 이야기한 적이 없었던 것 같다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언제 오른발이 앞이고, 언제 왼발이 앞인지 누가 가장 잘 알까? 답은 당연히 애니메이션 자신이다. 애니메이션은 자기가 어느 위치까지 재생되었는지 알고 있다. 따라서 우리는 두 가지 방법을 사용할 수 있다. 하나는 애니메이션 노티파이, 다른 하나는 애니메이션 커브다. 둘 다 애니메이션이 시간에 따라 변화하는 어떤 정보를 외부에 알려줄 수 있다. ALSV4는 애니메이션 커브를 사용한다. 이유는 【1】에서 자세히 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림처럼 ALSV4는 걷기, 달리기 등의 애니메이션 안에 Feet_Position이라는 커브를 편집해두었다. 왼발과 오른발의 앞뒤가 바뀔 때마다 그 값을 바꾼다. -1은 왼발이 앞, 1은 오른발이 앞을 뜻한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uigc4/dJMcabSwERI/G5JELA6thQZ15kOjgful01/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uigc4/dJMcabSwERI/G5JELA6thQZ15kOjgful01/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uigc4/dJMcabSwERI/G5JELA6thQZ15kOjgful01/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuigc4%2FdJMcabSwERI%2FG5JELA6thQZ15kOjgful01%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1134&quot; height=&quot;721&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 우리는 점프 상태 머신을 하나 만들고, 점프 시작 시 Feet_Position 값을 한 번 가져와서 그것이 0보다 큰지 작은지만 보면 된다. (직접 1인지 -1인지 판단하면 안 된다. 애니메이션 블렌드가 &lt;a href=&quot;https://zhida.zhihu.com/search?content_id=207206701&amp;amp;content_type=Article&amp;amp;match_order=1&amp;amp;q=%E6%9B%B2%E7%BA%BF%E5%80%BC&amp;amp;zhida_source=entity&quot;&gt;커브 값&lt;/a&gt;도 함께 블렌드하므로 실제 값은 &amp;plusmn;0.x 정도가 될 수 있기 때문이다.) 그런 다음 그에 맞는 왼발 앞 점프 시작 애니메이션 또는 오른발 앞 점프 시작 애니메이션을 재생하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LiA0g/dJMb99UI4Wc/6PRi7ZSWnsgDCczNJvtZWK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LiA0g/dJMb99UI4Wc/6PRi7ZSWnsgDCczNJvtZWK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LiA0g/dJMb99UI4Wc/6PRi7ZSWnsgDCczNJvtZWK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLiA0g%2FdJMb99UI4Wc%2F6PRi7ZSWnsgDCczNJvtZWK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1045&quot; height=&quot;433&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 기상 시 캐릭터의 이동 속도에 따라 점프 시작 애니메이션을 구분하지 않는다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 더 간단하다. 동작 폭이 큰 빠른 달리기 점프 시작 애니메이션 하나와, 동작 폭이 작은 걷기 점프 애니메이션 하나만 준비한 뒤, 캐릭터의 실제 속도값에 따라 그것들을 블렌드하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;819&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XcuRz/dJMb99UI4V7/pdFrblfjNKz3exHEJRB6iK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XcuRz/dJMb99UI4V7/pdFrblfjNKz3exHEJRB6iK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XcuRz/dJMb99UI4V7/pdFrblfjNKz3exHEJRB6iK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXcuRz%2FdJMb99UI4V7%2FpdFrblfjNKz3exHEJRB6iK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;819&quot; height=&quot;494&quot; data-origin-width=&quot;819&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXjefY/dJMcagff6Et/GB0dkNJQQgaJvZqy23afk0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXjefY/dJMcagff6Et/GB0dkNJQQgaJvZqy23afk0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXjefY/dJMcagff6Et/GB0dkNJQQgaJvZqy23afk0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXjefY%2FdJMcagff6Et%2FGB0dkNJQQgaJvZqy23afk0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1339&quot; height=&quot;381&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 점프 과정 중 무게중심 변화 과정이 없다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 2.1절에서 캐릭터 몸 기울기량을 이야기할 때, 이미 &amp;ldquo;점프 과정에 따라 동적으로 변화하는 적절한 몸 기울기량&amp;rdquo;을 어떻게 계산하는지 설명했다. 이 계산 과정을 한 문장으로 요약하면 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터의 수평 속도를 사용해 기본 기울기량과 점프 방향을 계산하고, 캐릭터를 점프 방향(혹은 이동 방향)으로 기울이며, 캐릭터 Z축 속도가 반영하는 점프 과정을 통해 캐릭터의 전방 기울기량을 점차 후방 기울기로 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋다. 아직도 잘 이해되지 않는다면 五谷延年 선배의 튜토리얼을 참고하거나 ALSV4 프로젝트를 직접 뒤져보면 된다. 여기서는 더 길게 설명하지 않겠다. 이제 계산된 몸 기울기량을 어떻게 적용하는지 이야기해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ALSV4는 앞/뒤/좌/우로 기울어진 4개의 포즈를 만들고, 그것들을 로컬 스페이스 Additive 애니메이션으로 설정했다. (전신을 기울여야 하므로 메시 스페이스 Additive를 사용한 것이 아니다.) 그리고 2D 블렌드 스페이스를 만들어, 입력된 X/Y축 기울기량에 따라 대응하는 기울기 포즈를 출력하게 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dUD2wP/dJMcagzybgD/qNNHN02wH4VkfNka8wvI20/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dUD2wP/dJMcagzybgD/qNNHN02wH4VkfNka8wvI20/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dUD2wP/dJMcagzybgD/qNNHN02wH4VkfNka8wvI20/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdUD2wP%2FdJMcagzybgD%2FqNNHN02wH4VkfNka8wvI20%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;338&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 다음에 해야 할 일은 매우 분명하다. 기울기 정도 값을 이 블렌드 스페이스에 입력하고, 반환된 기울기 포즈를 Additive 형식으로 원래의 Jump 상태 머신 위에 더하면 된다. (원래 Jump 상태 머신 안에는 점프 시작과 체공 두 과정이 포함되어 있고, 두 과정 모두 몸 기울기가 필요하기 때문이다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lxDk7/dJMcad3QVHV/81jbTBL6yaI7Dx1XiScSsk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lxDk7/dJMcad3QVHV/81jbTBL6yaI7Dx1XiScSsk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lxDk7/dJMcad3QVHV/81jbTBL6yaI7Dx1XiScSsk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlxDk7%2FdJMcad3QVHV%2F81jbTBL6yaI7Dx1XiScSsk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;805&quot; height=&quot;398&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 착지 시 낙하 속도에 따라 낙하/착지 애니메이션을 구분하지 않는다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 낙하 애니메이션이다. 일반 속도 낙하와 빠른 낙하를 낙하 속도로 블렌드하면 된다. 더 말할 필요가 없다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GzxJu/dJMcad3QVHS/BcrfAJzqMkVeefeZ4Kb4Z0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GzxJu/dJMcad3QVHS/BcrfAJzqMkVeefeZ4Kb4Z0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GzxJu/dJMcad3QVHS/BcrfAJzqMkVeefeZ4Kb4Z0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGzxJu%2FdJMcad3QVHS%2FBcrfAJzqMkVeefeZ4Kb4Z0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;882&quot; height=&quot;341&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음은 착지 애니메이션이다. 이것도 마찬가지다. 가벼운 착지와 무거운 착지를 블렌드한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wf7cv/dJMcaaMT9B3/ZRFy0L9ezKqPsN3fn5tZlk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wf7cv/dJMcaaMT9B3/ZRFy0L9ezKqPsN3fn5tZlk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wf7cv/dJMcaaMT9B3/ZRFy0L9ezKqPsN3fn5tZlk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwf7cv%2FdJMcaaMT9B3%2FZRFy0L9ezKqPsN3fn5tZlk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;798&quot; height=&quot;502&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 캐릭터 착지 시의 이동 요구를 고려하지 않는다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 말했듯, 캐릭터는 착지하자마자 바로 이동을 시작하고 싶을 수 있다. 어떤 게임(예를 들어 세키로)에서는 캐릭터가 높은 곳에서 떨어져 착지할 때(무거운 착지), 일시적으로 캐릭터의 조작권을 빼앗고, 착지 완충 애니메이션이 끝난 뒤에야 이동하거나 다른 행동을 시작할 수 있게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 애니메이션이 끝나기 전에는 캐릭터가 움직이지 못하게 하는 것은 당연히 슬라이딩을 극복하는 방법 중 하나다. (애초에 움직일 수 없으니 슬라이딩이 어디서 오겠는가.) 하지만 무거운 착지에는 이렇게 할 수 있어도, 캐릭터가 작은 계단 하나에서 뛰어내렸을 뿐인데도 조작권을 빼앗을 수는 없다. 그렇게 하면 플레이어의 게임 경험에 심각한 부정적 영향을 줄 것이다. 그러니 이 방법으로 게으름을 피우려는 길은 막혀 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 캐릭터가 착지할 때도 어떻게 자연스럽게 이동할 수 있게 할지 생각해보자. 이 사고방식은 사실 캐릭터가 이동하면서 사격하는 것을 어떻게 만들지와 같은 사고방식이다. 모두 이동을 주 애니메이션으로 삼고, 이동하면서 하는 &amp;ldquo;다른 일&amp;rdquo;을 추가적인 Additive 애니메이션으로 처리하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 우리는 가벼운/무거운 착지 애니메이션을 메시 스페이스 Additive 애니메이션으로 설정할 수 있다【2】. 그런 다음 위의 4번에서 했던 것처럼 FallSpeed로 블렌드하고, 마지막으로 지면의 걷기/달리기/전력 질주를 총괄하는 상태 머신에 그것을 더하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pQflm/dJMcad3QVHU/QZXk8aVCtmBnVyBNeen3H0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pQflm/dJMcad3QVHU/QZXk8aVCtmBnVyBNeen3H0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pQflm/dJMcad3QVHU/QZXk8aVCtmBnVyBNeen3H0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpQflm%2FdJMcad3QVHU%2FQZXk8aVCtmBnVyBNeen3H0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1217&quot; height=&quot;494&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;【1】왼발/오른발 처리방안 선택 문제에 관하여:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 애니메이션 노티파이를 사용하는 것은 필자 &lt;b&gt;개인적으로는&lt;/b&gt; 적합하지 않다고 본다. 왜냐하면 우리는 항상 왼발/오른발의 선후 문제를 처리해야 하는 것이 아니기 때문이다. 걷던 상태에서 멈출 때, 지면에서 점프할 때 같은 소수의 경우에만 왼발/오른발의 선후에 따라 애니메이션 선택을 결정할 필요가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 애니메이션에만 이런 특수 처리를 해야 할까? 우리가 해야 할 것은 걷는 상태에서 점프로 전환하거나, 걷다가 갑자기 멈출 때만 왼발/오른발을 구분하는 것이다. 따라서 왼발/오른발 앞뒤 처리를 위한 커브나 노티파이를 만들어야 하는 것은 걷기, 달리기, 전력 질주, 웅크린 걷기 같은 애니메이션뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자가 적합하지 않다고 느끼는 데는 주로 두 가지 이유가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 이유는 대량의 IF 판단이 비교적 큰 비용을 유발할 수 있다는 점이다. 걷기/달리기 애니메이션은 평소 매 순간 사용된다. 애니메이션 노티파이를 사용하면 많은 시간 동안 노티파이가 트리거되고, 노티파이 안에서 &amp;ldquo;지금 멈추려 하는가?&amp;rdquo;, &amp;ldquo;지금 점프하려 하는가?&amp;rdquo;를 하나하나 판단해야 한다&amp;hellip;&amp;hellip; 이는 CPU 분기 예측에 그다지 우호적이지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 이유이자 가장 중요한 이유는, 왼발/오른발을 구분해야 하는 상황이 늘어나는 순간(새로운 요구가 생기는 순간), 예를 들어 갑자기 캐릭터가 뒤쪽 발로 발차기하는 동작을 추가하고 싶어졌다고 하자. 그러면 우리는 또 노티파이 안에서 &amp;ldquo;지금 발차기하려 하는가?&amp;rdquo;를 판단해야 하고, 노티파이 안에서 발차기 이벤트에 대응하는 처리를 해야 한다&amp;hellip;&amp;hellip;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 오래 가다 보면, 곧 대량의 로직이 고작 왼발/오른발 노티파이 하나 안에 밀집하게 된다. 원래는 각자의 상태 머신 안에 분산되어 처리될 수 있던 것들이 모두 이 노티파이 안에 결합되어버리는 것이다. 이후 그중 어느 하나를 수정하거나 새로운 기능을 추가하려면 전부 이 노티파이를 건드려야 한다&amp;hellip;&amp;hellip; 이는 개방-폐쇄 원칙을 위반한다. 여기까지 들으면 디자인 패턴을 배운 독자는 이미 혈압이 올라갔을 것이다. 그래서 이것이 필자가 애니메이션 노티파이보다 애니메이션 커브를 사용하는 것이 더 좋다고 생각하는 이유다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;【2】착지 애니메이션이 왜 로컬 스페이스 Additive가 아니라 메시 스페이스 Additive 애니메이션을 사용하는가에 관하여:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9VgqC/dJMcaaMT9B4/B0i9we2Qi9ZlbU4r6ns8f0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9VgqC/dJMcaaMT9B4/B0i9we2Qi9ZlbU4r6ns8f0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9VgqC/dJMcaaMT9B4/B0i9we2Qi9ZlbU4r6ns8f0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9VgqC%2FdJMcaaMT9B4%2FB0i9we2Qi9ZlbU4r6ns8f0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1061&quot; height=&quot;788&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 그림은 UE5 문서에서 온 것이다. 볼 수 있듯, 로컬 스페이스 Additive 애니메이션을 사용하면, 더해지는 애니메이션은 더해지기 전의 골격 위치에 영향을 받는다. 반면 메시 스페이스 Additive 애니메이션은 이 영향을 무시할 수 있다. 여기서 필자 개인적으로 추측하건대, ALSV4는 캐릭터가 언제나 수직으로 일어서게 만들고 싶었기 때문에 메시 스페이스 Additive 애니메이션을 사용한 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.3 백척간두에서 한 걸음 더 나아가기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 소절에서는 명백한 단점을 극복하려는 것이 아니라, 새로운 장점 하나를 추가하려 한다. 바로 착지 예측이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 캐릭터가 착지할 때 애니메이션을 &amp;ldquo;체공 애니메이션&amp;rdquo;에서 착지 애니메이션으로 순간적으로 블렌드해야 한다는 데서 온다. 만약 애니메이션이 세심하게 설계되어, 착지 애니메이션 자체가 체공 애니메이션의 마지막 프레임에서 착지 동작으로 자연스럽게 전환되도록 만들어져 있다면, 사실 이 절은 큰 쓸모가 없다. (UE의 3인칭 템플릿이 바로 이렇게 한다. 체공 애니메이션 마지막 프레임과 착지 애니메이션 첫 프레임이 완전히 같다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 착지 애니메이션과 체공 애니메이션의 연결이 아트의 손을 거쳐 자연스럽게 만들어져 있지 않다면, 극히 짧은 착지 과정에서 애니메이션 블렌드 시간이 너무 짧아 여러 가지 부자연스러움이 쉽게 나타난다. 이 문제를 개선하기 위해 우리는 하나의 가능성을 제안한다. &amp;ldquo;착지하기 1초 전부터 미리 착지 포즈 쪽으로 블렌드할 수는 없을까?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다. 공중에서 미리 블렌드하는 것이다. 이것은 착지 시 블렌드 시간이 너무 짧은 문제를 해결한다. &amp;ldquo;착지 전 1초&amp;rdquo;가 언제인지를 알기 위해 우리가 해야 하는 것이 바로 &lt;b&gt;착지 예측&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 사고방식은 대략 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터의 현재 캡슐 위치에, 캐릭터의 현재 속도를 더해, 캐릭터의 캡슐이 다음 1초에 이동할 가능성이 있는 위치를 계산한다. 그 위치에 캡슐을 하나 그려 충돌 결과를 검사한다. 만약 그려진 캡슐과 충돌한 것이 걸을 수 있는 지면이라면, 캐릭터가 다음 1초 안에 그 위치에 착지한다는 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시에 이 착지 예측은 매 프레임마다 한 번씩 계산되므로, 이전 프레임에 그린 캡슐은 막 지면에 닿았을 뿐인데, 뒤의 몇 프레임에서는 이미 땅속에 묻혀 있을 수 있다. 캡슐이 땅속에 더 많이 묻힐수록 현재 캐릭터가 지면에 더 가까워졌다는 뜻이다. 따라서 우리는 캡슐이 흙 속에 묻힌 부피의 비율을 체공 애니메이션과 착지 애니메이션 첫 프레임의 블렌드 값으로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캡슐 그리기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8t8b1/dJMcacKMdn5/C9STrTUKEuJjdhKkw2EsYk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8t8b1/dJMcacKMdn5/C9STrTUKEuJjdhKkw2EsYk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8t8b1/dJMcacKMdn5/C9STrTUKEuJjdhKkw2EsYk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8t8b1%2FdJMcacKMdn5%2FC9STrTUKEuJjdhKkw2EsYk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;638&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;638&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캡슐 그리기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;충돌 결과로부터 &amp;ldquo;흙에 묻힌 비율&amp;rdquo;을 얻고, 그 결과를 그대로 출력 블렌드 값으로 삼아도 된다. ALSV4가 마스크와 커브 매핑을 한 번 더 추가한 것은 더 부드럽고 안전하게 만들기 위해서일 뿐이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHgyrA/dJMcaaMT9B5/4ukyQujckdGgrLFyyYnKp1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHgyrA/dJMcaaMT9B5/4ukyQujckdGgrLFyyYnKp1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHgyrA/dJMcaaMT9B5/4ukyQujckdGgrLFyyYnKp1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHgyrA%2FdJMcaaMT9B5%2F4ukyQujckdGgrLFyyYnKp1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;594&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산 결과를 얻은 뒤에는, 점프 상태 머신과 착지 애니메이션 첫 프레임을 이 값으로 블렌드하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;699&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kT5Ul/dJMcaae5ve7/SNGCxIKml6RvU6fGR62pGk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kT5Ul/dJMcaae5ve7/SNGCxIKml6RvU6fGR62pGk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kT5Ul/dJMcaae5ve7/SNGCxIKml6RvU6fGR62pGk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkT5Ul%2FdJMcaae5ve7%2FSNGCxIKml6RvU6fGR62pGk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;699&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;699&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;맺음말(필자의 관례적인 잡담을 뜻함)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 사람은 어느 정도로 게으르냐면? 글을 쓸 때마다 시작과 맺음말조차 새로 쓰기 귀찮아하는 수준이다&amp;hellip;&amp;hellip; 살짝만 바꿔서 또 가져다 쓰는 것이다 www&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난번 ALSV4 제자리 회전 편 업데이트로부터 이미 1개월 16일이 지났다. 매달 부지런히 글을 업데이트하던 나로서는, 최근 한 달 넘게 게으름을 피워 글을 안 올렸는데도 知乎의 팔로우와 조회수가 나를 놀라게 할 속도로 오르고 있어서(조금 더, 더 세게!) 정말 부끄러워 몸 둘 바를 모르겠다 = =. 그래서 방학이 되어 매일 크게 늘어지고만 싶었지만, 필자는 데드셀을 하거나 애니를 보며 빈둥대고 싶은 충동을 참고 이 글을 업데이트했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 ALSV4의 &lt;b&gt;발 IK&lt;/b&gt;를 업데이트할 계획이다. (지난번에도 이렇게 말하긴 했지만&amp;hellip;&amp;hellip; 하지만 계획은 변화보다 빠를 수 없으니까! 응! 맞다, 바로 그런 것이다!) 또한 IK를 다 이야기한 뒤에는 &lt;b&gt;등반&lt;/b&gt; 시스템도 한번 이야기할 생각이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아, 여름방학이라니&amp;hellip;&amp;hellip; 내 인생의 마지막 여름방학이다&amp;hellip;&amp;hellip;! 3학년 여름방학에는 인턴을 가야 하고, 4학년에는 여름방학이 없다. 눈앞의 2학년 여름방학이 바로 내 마지막 좋은 날이다&amp;hellip;&amp;hellip; 빈둥대고 싶지만 완전히 빈둥댈 수도 없다. ALSV4 글도 아직 다 업데이트하지 못했고, 알고리즘 문제도 풀어야 한다&amp;hellip;&amp;hellip; 지금의 나는 빈둥댄 상태와 빈둥대지 않은 상태의 &lt;a href=&quot;https://zhida.zhihu.com/search?content_id=207206701&amp;amp;content_type=Article&amp;amp;match_order=1&amp;amp;q=%E9%87%8F%E5%AD%90%E5%8F%A0%E5%8A%A0&amp;amp;zhida_source=entity&quot;&gt;양자 중첩&lt;/a&gt; 상태에 있다. 사랑하는 어머니께서 내 방문을 여는 순간, 관찰자가 생기므로 &amp;ldquo;너 또 게임하니&amp;rdquo;와 &amp;ldquo;열심히 공부하고 있구나&amp;rdquo; 두 상태 중 하나로 붕괴될 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q7pOF/dJMcad3QVHT/WeBKyiWKmcuza0UMCYTdj0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q7pOF/dJMcad3QVHT/WeBKyiWKmcuza0UMCYTdj0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q7pOF/dJMcad3QVHT/WeBKyiWKmcuza0UMCYTdj0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq7pOF%2FdJMcad3QVHT%2FWeBKyiWKmcuza0UMCYTdj0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;498&quot; height=&quot;498&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막은 좋아요 구걸 시간이다! 여기까지 봤다면, 설령 이 글이 비루하고 얕다고 느껴지더라도, 필자가 글 쓰느라 고생했다는 점을 생각해 &lt;b&gt;좋아요&lt;/b&gt; 하나만 누르고 가주면 좋겠다. 부탁이다 &amp;ge;﹏&amp;le;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(요 며칠 컴퓨터 메인보드가 타버렸다&amp;hellip;&amp;hellip; 새 컴퓨터가 언제 올지도 모르겠다. 새 글은 아마 좀 더 기다려야 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레노버 샤오신 사지 마라&amp;hellip;&amp;hellip;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS: 덧붙여 여기서 필자가 막 만든 &lt;b&gt;UE 골격 애니메이션 교류방&lt;/b&gt;을 살짝 광고한다. &lt;b&gt;916274600&lt;/b&gt; 각위 대佬들의 매서운 지적을 환영합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Pp3dN/dJMcaaMT9B2/yYI3Xbp1VWWr0TRmLmbD01/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Pp3dN/dJMcaaMT9B2/yYI3Xbp1VWWr0TRmLmbD01/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Pp3dN/dJMcaaMT9B2/yYI3Xbp1VWWr0TRmLmbD01/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPp3dN%2FdJMcaaMT9B2%2FyYI3Xbp1VWWr0TRmLmbD01%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;377&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문&lt;br /&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/535829374&quot;&gt;(76 封私信 / 32 条消息) UE4 UE5 骨骼动画 高级运动系统 跳跃 - 知乎&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <category>Advanced</category>
      <category>engine</category>
      <category>Locomotion</category>
      <category>System</category>
      <category>technical animation</category>
      <category>unreal</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/821</guid>
      <comments>https://techartnomad.tistory.com/821#entry821comment</comments>
      <pubDate>Thu, 23 Jul 2026 15:44:37 +0900</pubDate>
    </item>
    <item>
      <title>UnrealEngine 5.8 Tonemap Master Plugin git.</title>
      <link>https://techartnomad.tistory.com/818</link>
      <description>&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=h58uRTdzmZA&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/57brY/dJMb87N93L9/ZBKfU8xn0FWd57y1KuKUKk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/drME1F/dJMb89yqRmn/zKqTKyuLauDqySNSvsBTZ0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/dFchQR/dJMb85v2fzR/qgYlZKKyHkeyyzx7N1JRw1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;ToneMap Master Plugin.&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/h58uRTdzmZA&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784658552521&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - Techartflowio/UnrealEngine-Agx-Plugin&quot; data-og-description=&quot;Contribute to Techartflowio/UnrealEngine-Agx-Plugin development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Techartflowio/UnrealEngine-Agx-Plugin&quot; data-og-url=&quot;https://github.com/Techartflowio/UnrealEngine-Agx-Plugin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhS524/dJMb8YXYTPm/NiZFOi9yfh41DcYgRxhie0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bQta2Y/dJMb8PGJi3g/bPtNTBbuF0cYzpWASJYNwk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Techartflowio/UnrealEngine-Agx-Plugin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Techartflowio/UnrealEngine-Agx-Plugin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhS524/dJMb8YXYTPm/NiZFOi9yfh41DcYgRxhie0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bQta2Y/dJMb8PGJi3g/bPtNTBbuF0cYzpWASJYNwk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - Techartflowio/UnrealEngine-Agx-Plugin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to Techartflowio/UnrealEngine-Agx-Plugin development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루 정도 서치를 했으나 Agx 계산이 이게 맞나 싶기도 합니다. 순정엔진에 셰이더패치 없이 사용할 수 있도록 구현되어있습니다.&lt;br /&gt;수정 해야 할 곳이 있다면 기여자로 참여해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026.7.23 - GT7 톤맵핑 추가.&lt;br /&gt;2026.7.21 - AGX 톤맵핑 추가. &lt;/p&gt;</description>
      <category>UNREAL ENGINE</category>
      <category>agx</category>
      <category>technical artist</category>
      <category>tonemapping</category>
      <category>Unreal Engine</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/818</guid>
      <comments>https://techartnomad.tistory.com/818#entry818comment</comments>
      <pubDate>Thu, 23 Jul 2026 02:30:54 +0900</pubDate>
    </item>
    <item>
      <title>[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 제자리 회전</title>
      <link>https://techartnomad.tistory.com/820</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;저자: DarkFlameMaster&lt;br&gt;최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한다.&lt;br&gt;제자리 회전이 쓸모를 발휘하는 경우는 주로 이렇다. 캐릭터가 계속 “네가 지정한 방향”을 바라보게 하고 싶고, 동시에 캐릭터가 그냥 Actor 자체가 제자리에서 휙 도는 것이 아니라 제대로 몸을 돌리는 애니메이션을 갖기를 원할 때다. 예를 들어 세키로에서 적을 록온한 상태라고 하자. 너는 제자리에 서 있고, 적이 네 주변을 빙빙 돈다. 이때 비교적 이상적인 표현은 당연히 네 캐릭터가 제자리에서 잔걸음을 밟으며 적을 따라 함께 도는 것이다. 이것이 바로 제자리 회전이 쓰이는 곳이다.&lt;br&gt;먼저 최종 완성 효과 이미지를 하나 올려 독자를 붙잡아보겠다. (급하게 이 글을 닫지 말고) 어떻게 만드는지 궁금하다면, 같이 아래로 따라와 보면 된다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpDbXU/dJMcacYebaA/CPGdG58FQ3XrYf0a8mvPaK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpDbXU/dJMcacYebaA/CPGdG58FQ3XrYf0a8mvPaK/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpDbXU/dJMcacYebaA/CPGdG58FQ3XrYf0a8mvPaK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bpDbXU/dJMcacYebaA/CPGdG58FQ3XrYf0a8mvPaK/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;336&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설령 이 글이 네 흥미를 끌지 못하더라도, 떠나기 전에 좋아요 하나만 눌러주고 가주면 좋겠다. 부탁이다 ≥﹏≤&lt;br&gt;내가 쓴 기술 블로그는 예전에 많은 사람에게 도움이 된 적이 있다. 이제는 나도 독자 여러분께 한번 도움을 부탁드리고 싶다! (작은 좋아요 버튼 한 번만 누르면 된다!)&lt;br&gt;ALS의 제자리 회전 관련 지식을 더 깊이 배우고 싶은 독자는 다음 글을 읽어도 좋다.&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 기본 지식&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;오늘의 주제가 회전인 이상, 캐릭터 블루프린트에서 제공하는 몇 가지 기본 회전 옵션을 반드시 이야기해야 한다. UE를 막 배우기 시작한 사람들(나 자신을 가리킨다) 중에는 처음에 이 옵션들에 대해 의문을 품었던 사람이 꽤 많을 것이라고 믿는다. 이 기회에 이 몇 가지 옵션을 한꺼번에 놓고 이야기해보자. (잠시 후 2절에서도 그중 일부를 써야 하기 때문이다.) 이미 이 내용이 머릿속에 훤히 들어 있는 독자라면 그냥 건너뛰어도 된다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;캐릭터 무브먼트 컴포넌트&lt;/b&gt;&lt;/h3&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kxbtm/dJMcaaznMWk/8k1hzT9EGUc1u3YMaLg010/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kxbtm/dJMcaaznMWk/8k1hzT9EGUc1u3YMaLg010/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kxbtm/dJMcaaznMWk/8k1hzT9EGUc1u3YMaLg010/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKxbtm%2FdJMcaaznMWk%2F8k1hzT9EGUc1u3YMaLg010%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;525&quot; height=&quot;186&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;“컨트롤러가 요구하는 회전 사용” 옵션의 효과는 캐릭터의 회전이 컨트롤러가 위치한 회전값으로 부드럽게 전이되도록 하는 것이다. 전이 속도는 “회전 속도”에서 조정한다. 즉 마우스를 회전하면 캐릭터가 약간의 지연을 두고 마우스 회전을 따라잡는다.&lt;br&gt;“회전을 이동 방향으로 향하게 하기” 옵션의 효과는 캐릭터의 회전 방향이 가속도에 의해 결정되도록 하는 것이다. 즉 일반적인 3인칭 게임에서 흔히 보이는 방식이다. 마우스를 돌려도 사람은 돌지 않지만, WASD 방향키를 눌러 이동하면 캐릭터가 새로운 이동 방향을 향해 돌아간다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Pawn 디테일 패널&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;그다음은 Pawn(또는 Character) 디테일 패널 안의 설정이다. 여기 있는 “컨트롤러 회전 P/Y/R 사용”은 위에서 설명한 “컨트롤러가 요구하는 회전 사용”과 비교적 비슷하다. 만약 “컨트롤러 회전 Yaw 사용”만 체크한다면, 효과는 “컨트롤러가 요구하는 회전 사용”과 거의 같다. 다만 회전 지연 효과가 빠져 있을 뿐이다. 나머지 두 개, “컨트롤러 회전 Pitch 사용”, “컨트롤러 회전 Roll 사용”은 인간형 캐릭터를 제어할 때 일반적으로 체크하지 않으므로 여기서는 설명하지 않는다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;235&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O118o/dJMcaaznMWj/nzoklzGuBV7sNEc3plGqdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O118o/dJMcaaznMWj/nzoklzGuBV7sNEc3plGqdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O118o/dJMcaaznMWj/nzoklzGuBV7sNEc3plGqdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO118o%2FdJMcaaznMWj%2FnzoklzGuBV7sNEc3plGqdK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;235&quot; height=&quot;166&quot; data-origin-width=&quot;235&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;카메라와 스프링 암 디테일 패널&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;카메라에는 “Pawn 컨트롤 회전 사용”이라는 설정이 있다. 이름만 들으면 의미가 마치 “자신의 회전을 Pawn과 같게 만들고, Pawn의 회전값을 자신에게 대입한다”처럼 들린다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;94&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VtaEA/dJMcadJvQfb/nNWow9jNqwoat2vjsffgy0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VtaEA/dJMcadJvQfb/nNWow9jNqwoat2vjsffgy0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VtaEA/dJMcadJvQfb/nNWow9jNqwoat2vjsffgy0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVtaEA%2FdJMcadJvQfb%2FnNWow9jNqwoat2vjsffgy0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;264&quot; height=&quot;94&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;94&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 그렇지 않다. 왜냐하면 그렇게 설명하면 모순되는 부분이 하나 생기기 때문이다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;262&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kFuaO/dJMcadJvQfa/fFGreIIk30BhwL7bAszZB1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kFuaO/dJMcadJvQfa/fFGreIIk30BhwL7bAszZB1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kFuaO/dJMcadJvQfa/fFGreIIk30BhwL7bAszZB1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkFuaO%2FdJMcadJvQfa%2FfFGreIIk30BhwL7bAszZB1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;262&quot; height=&quot;158&quot; data-origin-width=&quot;262&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pawn(또는 Character)의 디테일 패널에서는 이 세 옵션을 조정할 수 있다. 컨트롤러의 회전을 사용해 자기 자신을 회전시킬지 여부가 세 개의 성분으로 나뉘어 있다. 만약 이 세 옵션을 모두 False로 두면, 이론적으로 Pawn의 회전은 더 이상 컨트롤러의 제어를 받지 않아야 한다. 그러면 우리가 마우스를 회전해도 캐릭터를 돌릴 수 없어야 한다.&lt;br&gt;맞다. 만약 의존 관계가 우리가 위에서 말한 것처럼 카메라 → Pawn → 컨트롤러라면, Pawn이 돌지 못하니 카메라도 돌 수 없어야 한다. 하지만 독자가 실제 게임에서 이렇게 설정해보면, 실제 결과는 일반적인 3인칭 게임과 같다. 마우스를 움직이면 카메라는 돌고, 캐릭터는 돌지 않는다.&lt;br&gt;분명히 이때 카메라의 회전은 Pawn이 아니라 컨트롤러에 의존한다. 소스 코드에서도 이 점은 쉽게 검증할 수 있다.&lt;/p&gt;&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;cpp&quot;&amp;gt;//CameraComponent.h    //Pawn 컨트롤 회전을 사용하는 경우(이 소스 코드를 보고 나면 사실 이 변수 이름이 그다지 적절하지 않고 사람을 오해하게 만든다는 것을 알 수 있다)    if (bUsePawnControlRotation)
    {
        const APawn* OwningPawn = Cast&amp;lt;APawn&amp;gt;(GetOwner());
        const AController* OwningController = OwningPawn ? OwningPawn-&amp;gt;GetController() : nullptr;
        //유효성 판단        if (OwningController &amp;amp;&amp;amp; OwningController-&amp;gt;IsLocalPlayerController())
        {
            //자신을 소유한 Pawn 객체의 GetViewRotation 함수를 호출한다            const FRotator PawnViewRotation = OwningPawn-&amp;gt;GetViewRotation();
            if (!PawnViewRotation.Equals(GetComponentRotation()))
            {
                SetWorldRotation(PawnViewRotation);
            }
        }
    }
//Pawn.cppFRotator APawn::GetViewRotation() const
{
    if (Controller != nullptr)
    {
        //자신을 제어하는 컨트롤러로 전달해, 컨트롤러의 GetControlRotation 함수를 호출한다.        //이것이 바로 이때 카메라가 실제로 컨트롤러의 회전에 의존한다는 증거다.        return Controller-&amp;gt;GetControlRotation();
    }
&lt;/code&gt;&lt;/pre&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 간단하지만 실행 불가능한 구현 방안&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;아이구, 1절을 다 읽었으니 아마 여러분은 어떻게 하면 되는지 이미 마음속으로 다 알고 있을 것이다. 그러니 여기서 지면을 낭비하지 말고 바로 다음 절로 넘어가자.&lt;br&gt;……&lt;br&gt;……&lt;br&gt;……&lt;br&gt;농담, 농담이다. 그래도 언급은 해야 한다.&lt;br&gt;여기서 “컨트롤러가 요구하는 회전 사용”을 체크하고, “회전을 이동 방향으로 향하게 하기”의 체크를 해제한다. 그리고 캐릭터 디테일 패널의 Pawn 섹션에서 “컨트롤러 회전 Yaw 사용”을 해제한다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BxD5i/dJMcacYebaI/vOa1nK89JFBoR9ehbDI5WK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BxD5i/dJMcacYebaI/vOa1nK89JFBoR9ehbDI5WK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BxD5i/dJMcacYebaI/vOa1nK89JFBoR9ehbDI5WK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBxD5i%2FdJMcacYebaI%2FvOa1nK89JFBoR9ehbDI5WK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;525&quot; height=&quot;186&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 캐릭터가 마우스 회전에 따라 회전하게 만들 수 있다. 회전 지연 효과를 더 뚜렷하게 만들고 싶다면 회전 속도 안의 Z값을 조금 낮추면 된다. Z값이 200일 때의 효과는 다음과 같다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QtmSx/dJMcajiLmS9/KjDMWgNRBKPB7brYYnmv71/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QtmSx/dJMcajiLmS9/KjDMWgNRBKPB7brYYnmv71/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QtmSx/dJMcajiLmS9/KjDMWgNRBKPB7brYYnmv71/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/QtmSx/dJMcajiLmS9/KjDMWgNRBKPB7brYYnmv71/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;304&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이렇게 하는 문제는 매우 명확하다. 표현되는 효과는 캐릭터 모델 전체가 제자리에서 한 바퀴 돈다는 것이다. 마치 회전판 위에 올려진 피규어가 회전판을 따라 도는 것처럼 보인다. 어떤 애니메이션도 없고, 당연히 신뢰감 같은 것은 말할 것도 없다. 그러므로 이제부터는 신뢰할 수 있고 그럴듯한 제자리 회전 애니메이션을 만들기 시작해야 한다.&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. ALSV4의 제자리 회전&lt;/b&gt;&lt;/h2&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.1 통속적이고 이해하기 쉬운 사고 정리&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말했듯, 캐릭터가 회전할 때 아무 애니메이션도 없으면 좀 안 된다. 자연스러운 생각은 카메라 시점과 캐릭터 방향 사이의 각도가 일정 각도(예를 들어 45도)를 넘으면 회전 애니메이션을 재생하는 것이다.&lt;br&gt;매번 회전해야 하는 각도는 45~180도 사이의 어떤 값도 될 수 있다. 그렇다고 해서 서로 다른 회전 각도 크기의 애니메이션을 잔뜩 만드는 것은 명백히 매우 비경제적이다. (게임 안의 캐릭터가 많다면, 회전 애니메이션 애셋만으로도 상당한 공간을 차지할 것이다.)&lt;br&gt;따라서 회전 애니메이션을 “작은 회전”과 “큰 회전”, “좌회전”과 “우회전”으로 나눌 수 있다. 이렇게 하면 총 4개의 애니메이션 애셋만 있으면 된다.&lt;br&gt;작은 회전은 45~130도 범위의 회전을 담당하고, 큰 회전은 130~180도 회전을 담당하게 한다.&lt;br&gt;이때 어떤 독자는 이렇게 물을 것이다. “어? 방금 각도가 다른 회전을 표현하려고 애니메이션 애셋을 잔뜩 쓰는 것은 너무 비경제적이라 어렵다고 했잖아. 그런데 왜 이제는 이 4개 애니메이션만으로 된다는 거지? 46도 회전과 129도 회전을 같은 애니메이션으로 표현하고, 만약 그 애니메이션이 90도만 회전한다면, 80도나 100도 바깥쪽 각도에서는 육안으로도 꽤 뚜렷한 오차가 생기지 않나?”&lt;br&gt;맞다. 볼 수 있듯, 애니메이션을 많이 만들면 너무 비경제적이고, 애니메이션을 적게 만들면 표현이 지나치게 부정확해지는 문제를 마주하게 된다. 그렇다면 관점을 바꿔보자. 애니메이션으로 캐릭터의 회전을 제어하지 않는다면, 캐릭터의 회전을 제어할 수 있는 다른 방법은 무엇이 있을까?&lt;br&gt;……&lt;br&gt;답은 이미 입 밖으로 나오려 하고 있다. 바로 코드 로직을 사용해 제어하는 것이다. SetWorldRotation, AddActorWorldRotation 같은 함수로 캐릭터 회전을 제어하고, 애니메이션은 캐릭터가 발을 두어 번 움직여 “발을 옮겨 회전하는 중”처럼 보이게 만들면 된다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHu6Dn/dJMb99UIttq/zhBVVMYWrkmwuLp73AGnX1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHu6Dn/dJMb99UIttq/zhBVVMYWrkmwuLp73AGnX1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHu6Dn/dJMb99UIttq/zhBVVMYWrkmwuLp73AGnX1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dHu6Dn/dJMb99UIttq/zhBVVMYWrkmwuLp73AGnX1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;880&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 애니메이션의 현실감을 높이기 위해, 캐릭터가 제자리 회전할 때(이동 중 회전은 별도 이야기다) 마우스를 돌리자마자 캐릭터가 즉시 따라 도는 것은 그다지 적절하지 않다. 약간의 지연이 있는 편이 좋다. 우리가 마우스를 돌린 뒤, 캐릭터는 잠시 멈춰 있다가 그제야 따라오기 시작해야 한다. 이 글에서는 이것을 “&lt;b&gt;회전 지연 시작 시간&lt;/b&gt;”이라고 부르겠다.&lt;br&gt;주의해야 할 것은 이것을 &lt;b&gt;회전 래그&lt;/b&gt;와 구분해야 한다는 점이다. 달리기를 예로 들어보자. 회전 래그가 없다는 것은 출발점에서 종점으로 곧바로 순간이동한 것과 같다. 중간에 “달려가는” 과정이 없는 것이다. 중간에 달려가는 이 &lt;b&gt;과정&lt;/b&gt;이 바로 “&lt;b&gt;회전 래그&lt;/b&gt;”다. 반면 회전 지연 시작 시간이 없다는 것은 출발점에서 심판이 “준비”라고 말하자마자 바로 뛰쳐나간 것과 같다. 회전 지연 시작 시간이 있다는 것은 “&lt;b&gt;출발점에서 잠깐 머무는 것&lt;/b&gt;”이다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.2 간명하고 이해하기 쉬운 구체 구현&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 우리는 당연히 캐릭터의 현재 방향과 컨트롤러 사이의 각도를 얻어야 한다. 이 각도가 임계값보다 커야만 제자리 회전을 실행할 수 있다. 또한 제자리 회전인 이상, 이때 캐릭터는 움직이고 있으면 안 된다.&lt;br&gt;(PS: 아래 블루프린트 코드는 ALSV4를 써본 적 없는 독자도 막힘 없이 읽을 수 있도록, 가능한 한 가장 통속적이고 이해하기 쉬운 방식으로 보여주었다.)&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5ik5C/dJMcajbTW0A/hs8voKvWJ74D8ubW46GKs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5ik5C/dJMcajbTW0A/hs8voKvWJ74D8ubW46GKs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5ik5C/dJMcajbTW0A/hs8voKvWJ74D8ubW46GKs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5ik5C%2FdJMcajbTW0A%2Fhs8voKvWJ74D8ubW46GKs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;909&quot; height=&quot;335&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;335&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 속도가 150보다 크거나, 캐릭터가 움직이고 있을 뿐 아니라 플레이어에게도 이동 입력이 있다면(예를 들어 방향키를 눌렀다면) 조건에서 제외한다.&lt;br&gt;속도 크기만 직접 판단하지 않고, 이런 약간 복잡한 판단 로직을 사용한 것은, 캐릭터가 컨베이어 벨트에 실려 움직이지만 캐릭터 본인은 움직이지 않는 상황 같은 것을 고려했기 때문이다. 우리는 이런 경우 캐릭터도 정지 상태로 간주되기를 원한다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OjKt5/dJMcad3Qkh9/jz4X8HxJKzbXHrBU0bLyNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OjKt5/dJMcad3Qkh9/jz4X8HxJKzbXHrBU0bLyNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OjKt5/dJMcad3Qkh9/jz4X8HxJKzbXHrBU0bLyNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOjKt5%2FdJMcad3Qkh9%2Fjz4X8HxJKzbXHrBU0bLyNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;914&quot; height=&quot;450&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 조건을 만족하면, 이제 제자리 회전을 준비할 수 있다. 이때 우리가 해야 할 일은 이번 회전 지연 시작 시간이 얼마면 적절한지 계산하고, 시간이 흐르기를 조용히 기다리다가, 회전 지연 시작 시간 요구를 만족하면 실제로 애니메이션을 재생하고 캐릭터를 회전시키는 것이다.&lt;br&gt;(DeltaTimeX는 “Get World Delta Seconds” 노드가 반환하는 값, 즉 두 프레임 사이에 흐른 초 단위 시간이다.)&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1183&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bziRir/dJMcaccQlHr/UgPGj0tesGJi9fXIHy9k3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bziRir/dJMcaccQlHr/UgPGj0tesGJi9fXIHy9k3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bziRir/dJMcaccQlHr/UgPGj0tesGJi9fXIHy9k3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbziRir%2FdJMcaccQlHr%2FUgPGj0tesGJi9fXIHy9k3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1183&quot; height=&quot;671&quot; data-origin-width=&quot;1183&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 우리는 회전을 허용하는 최소 임계값을 45도로 가정했다. 또한 각도가 클수록 더 빨리 회전을 시작하기를 원한다. 이런 상황에서 너무 많은 회전 지연 시작 시간은 캐릭터 반응이 느려 보이게 만들고, 회전 각도가 작을 때에는 약간의 지연이 있는 편이 더 자연스럽다. 따라서 이번 회전 지연 시작 시간을 계산하는 방법은 45~180도의 목표 회전량을 0.75~0초의 회전 지연 시작 시간으로 매핑하는 것이다.&lt;br&gt;마지막으로 회전 애니메이션을 재생하기 전에, 이번에 사용할 회전 애니메이션이 무엇인지 결정해야 한다.&lt;br&gt;(TurnAngle이 이번 목표 회전량이다.)&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ozWif/dJMcaic9yTF/n36ie3pgNPojKy0dMDDcX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ozWif/dJMcaic9yTF/n36ie3pgNPojKy0dMDDcX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ozWif/dJMcaic9yTF/n36ie3pgNPojKy0dMDDcX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FozWif%2FdJMcaic9yTF%2Fn36ie3pgNPojKy0dMDDcX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;642&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 회전값이 45~130도 사이면 90도 회전(작은 회전 애니메이션)을 사용하고, 130~180도 사이면 180도 회전(큰 회전 애니메이션)을 사용하도록 설정한다. 또 양수/음수로 좌우를 판단하고, 보행 상태로 앉아서 도는지 서서 도는지를 판단한다. 총 8가지 경우가 있으며, ALSV4는 미리 설정해둔 8개의 애니메이션 리소스 중 상황에 맞는 하나를 이번에 재생할 애니메이션 애셋으로 선택한다.&lt;br&gt;애니메이션 재생을 시작한 뒤에는 곧바로 한 가지를 생각해야 한다. 애니메이션 재생 시간은 2초이고, 이제 우리는 캐릭터의 몸이 이 2초 안에 시작점에서 종점까지 회전하도록 해야 한다.&lt;br&gt;자연스럽게 보이게 하려면, 캐릭터의 회전 속도가 이 2초 안에서 균일한 선형 회전이 되어서는 안 된다. 시작점과 끝점 양쪽은 느리고, 중간은 빨라야 한다. 분명히 커브는 괜찮은 선택이다. 우리는 &lt;b&gt;커브 값이 곧바로 이 프레임에서 캐릭터의 회전량&lt;/b&gt;(회전 각도)을 대표하도록 만들 수 있다.&lt;br&gt;사용하는 커브는 애니메이션 시퀀스 안에서 편집해도 되고, 별도의 커브 애셋을 만들어도 된다. (왜 ALSV4가 후자를 쓰지 않았는지는 잘 모르겠다.)【1】&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1216&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKnWd9/dJMcahk0BJb/gjzerYt1lu2ufk86PGvqb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKnWd9/dJMcahk0BJb/gjzerYt1lu2ufk86PGvqb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKnWd9/dJMcahk0BJb/gjzerYt1lu2ufk86PGvqb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKnWd9%2FdJMcahk0BJb%2FgjzerYt1lu2ufk86PGvqb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1216&quot; height=&quot;862&quot; data-origin-width=&quot;1216&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이 오른쪽 90도 회전 커브에는 총 60개의 키프레임이 있고, 그것들의 총합은 정확히 90이 된다.&lt;br&gt;물론 우리는 실제로 90도를 도는 것이 아니다. 여기서 90도 회전은 단지 “작은 회전 애니메이션”의 별칭일 뿐이다. 우리는 이 커브 값을 실제 회전량에 따라 보정해야 한다. 따라서 &lt;b&gt;첫 번째 보정&lt;/b&gt;은 커브 값 / 90(또는 /180)을 한 뒤 실제 회전량을 곱하는 것이다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ow1Vs/dJMcagffv9Y/tVkniKXGPKkxYQ7iurtmgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ow1Vs/dJMcagffv9Y/tVkniKXGPKkxYQ7iurtmgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ow1Vs/dJMcagffv9Y/tVkniKXGPKkxYQ7iurtmgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fow1Vs%2FdJMcagffv9Y%2FtVkniKXGPKkxYQ7iurtmgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;607&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;607&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 번째 보정&lt;/b&gt;은 재생 속도를 곱하는 것이다. (그림의 RotationScale은 뒤에서 커브 값을 스케일링하는 데 사용된다.)&lt;br&gt;여기서 먼저 UE 애니메이션 시퀀스 재생 로직을 언급해야 한다. 애니메이션의 실제 재생 시간이 프레임레이트 변동의 영향을 받지 않도록 하기 위해, 애니메이션의 시간 단위는 프레임이 아니라 초다.&lt;br&gt;만약 프레임을 시간 단위로 삼는다면, 게임에서 1프레임이 지나면 애니메이션도 1프레임 재생된다. 애니메이션이 60프레임으로 만들어졌다고 가정하면, 60FPS에서는 애니메이션이 1초 만에 끝나지만, 30FPS에서는 2초가 걸린다. 이것은 분명히 안 된다.&lt;br&gt;애니메이션이 초를 시간 단위로 삼는다면, 게임에서 1프레임이 지날 때 애니메이션은 DeltaTime(두 프레임 사이의 시간 차)만큼 진행된다. 이렇게 하면 프레임레이트가 높을 때 DeltaTime은 낮아지고, 애니메이션의 한 번 진행량은 적지만 1초 안의 진행 횟수는 많아진다. 프레임레이트가 낮을 때는 DeltaTime이 커지고, 애니메이션의 한 번 진행량은 많지만 1초 안의 진행 횟수는 적어진다.&lt;br&gt;애니메이션을 2배속으로 재생하면, 애니메이션은 이 1프레임에서 DeltaTime * 2만큼 진행된다. 이것이 바로 배속 재생 애니메이션의 원리다.&lt;br&gt;우리는 캐릭터의 회전도 매 프레임 한 번씩 보정한다. (어쨌든 시작점에서 종점까지 회전하는 이 &lt;b&gt;과정&lt;/b&gt;을 표현해야 하기 때문이다.) 이는 곧 우리가 커브 값을 가져오는 것도 1프레임에 1번이라는 뜻이다.&lt;br&gt;조금 극단적인 상황을 상상해보자. 지금 게임 프레임레이트가 30FPS라고 가정한다. 애니메이션을 정상 속도로 재생하면, 게임이 1프레임 진행될 때 애니메이션도 정확히 1프레임 진행된다. 만약 애니메이션을 30배속으로 재생하면, 매번 진행되는 시간 길이가 바로 30배가 된다. 시작 시의 1프레임까지 계산해도, 게임은 총 3프레임 정도밖에 실행되지 않았는데 이 애니메이션은 이미 끝나버린다.&lt;br&gt;아래 그림과 같다. (ALSV4는 이 커브를 RotationAmount, 즉 회전량이라고 이름 붙였다.)&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LtkBa/dJMcadbFD61/k6iXGD4Q5CkK5jJL6gloVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LtkBa/dJMcadbFD61/k6iXGD4Q5CkK5jJL6gloVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LtkBa/dJMcadbFD61/k6iXGD4Q5CkK5jJL6gloVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLtkBa%2FdJMcadbFD61%2Fk6iXGD4Q5CkK5jJL6gloVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1135&quot; height=&quot;820&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임이 3프레임밖에 실행되지 않았다는 것은, 우리가 커브 값을 3번밖에 가져오지 않았고, 점도 3개만 샘플링했다는 뜻이다. 분명히 이 3개 점을 더해도 90에는 한참 못 미친다. (원래는 60개 점을 더해야 90이 되니까.) 그럼 어떻게 해야 할까? 비교적 거친 시뮬레이션 방법은 이 3개 점의 값을 각각 30배 하는 것이다.&lt;br&gt;어떤 독자는 곧바로 소리칠 것이다. “어? 이 오차 너무 심한 거 아니야? 이 세 프레임 값을 더한 뒤 30을 곱해도, 딱 봐도 90이 안 될 것 같은데!”&lt;br&gt;뭐, 이건 결국 30배속으로 애니메이션을 재생하는 극단적인 상황이다. 실제 적용에서는 3배속 재생도 거의 보기 어려울 수 있다. 따라서 이 시뮬레이션 효과로 생기는 오차는 사실 받아들일 수 있는 범위 안에 있다. 재생 속도가 2배를 넘지 않을 때에는 일반적으로 플레이어가 알아차리기 어렵다.【2】&lt;br&gt;&lt;b&gt;세 번째 보정&lt;/b&gt;은 게임 자체의 프레임레이트 변동이 가져오는 영향을 보정하는 것이다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zYxLQ/dJMcahecXGZ/TXoehcAbHDYVFe72bqrKpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zYxLQ/dJMcahecXGZ/TXoehcAbHDYVFe72bqrKpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zYxLQ/dJMcahecXGZ/TXoehcAbHDYVFe72bqrKpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzYxLQ%2FdJMcahecXGZ%2FTXoehcAbHDYVFe72bqrKpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1040&quot; height=&quot;587&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 배속 재생 원리와 비슷하게, 게임 프레임레이트가 높아지면 각 프레임에서 애니메이션의 진행 거리가 짧아진다. 프레임레이트가 너무 높아서 게임 프레임 델타(DeltaTime)가 애니메이션 프레임 델타보다 작아지면, 게임은 몇 프레임이나 진행됐는데 애니메이션은 아직 다음 프레임으로 넘어가지 않은 상황이 생긴다.&lt;br&gt;예를 들어 현재 게임이 60FPS이고, ALSV4 애니메이션의 기본 프레임레이트가 30FPS라고 하자. 즉 게임이 2프레임 진행되어야 애니메이션이 1프레임 진행된다. 그런데 우리는 애니메이션 커브 값을 가져와 캐릭터를 회전시키는 작업을 매 프레임 실행하므로, 애니메이션 커브 안의 같은 키프레임 값이 두 번 읽히게 된다. 캐릭터 회전량도 그 때문에 정확히 2배가 된다.&lt;br&gt;이 현상을 피하기 위해 우리는 커브 값 ÷ 게임 프레임레이트 × 기본 애니메이션 프레임레이트를 해야 한다. 위 그림에서는 커브 값 × 게임 프레임 델타 × 30으로 표현되어 있는데, 의미는 같다.&lt;br&gt;이렇게 하면 회전량이 2배가 될 수 있는 60FPS에서, 우리가 커브 값 × 30 ÷ 60, 즉 × 0.5를 해주기 때문에, 2배가 된 커브 값이 다시 보정된다. 마찬가지로, 이 보정은 재생 속도에 대한 보정과 마찬가지로 완전히 정확한 것은 아니다.【3】&lt;br&gt;&lt;b&gt;본문에 넣으면 글의 상세함과 흐름에 영향을 줄 수 있는 작은 여담:&lt;/b&gt;&lt;br&gt;【1】사용하는 커브는 애니메이션 시퀀스 안에서 편집해도 되고, 별도의 커브 애셋을 만들어도 된다. (왜 ALSV4가 후자를 쓰지 않았는지는 잘 모르겠다.)&lt;br&gt;필자 &lt;b&gt;개인적으로는&lt;/b&gt; 후자가 전자에 비해 가진 유일한 단점은 커브에 입력하는 시간값을 조금 신경 써야 한다는 점이라고 생각한다.&lt;br&gt;애니메이션은 배속 재생될 수 있으므로, 이때 실제 소요 시간이 꼭 2초라고 할 수 없다. 예를 들어 2배속 재생에서는 애니메이션 각 프레임의 진행 시간이 2 * DeltaTime이 된다. 그에 맞춰 우리가 커브에 입력하는 진행 시간도 2를 곱해야 한다. (그렇지 않으면 애니메이션은 이미 끝났는데 우리는 아직 애니메이션이 절반쯤 재생될 때 써야 하는 커브 값을 가져오고 있는 상황이 된다.) 반면 애니메이션 시퀀스 안의 커브는 그 자체가 애니메이션 안에 내장되어 있으므로, 커브 값을 얻는 위치가 애니메이션 재생 진행도에 직접 의존한다. 따라서 입력 시간 문제를 신경 쓸 필요가 없다.&lt;br&gt;후자를 사용하는 장점은 &lt;b&gt;여러 회전 애니메이션이 같은 커브를 재사용할 수 있다는 것&lt;/b&gt;이다. ALSV4는 좌우 회전, 90도 회전과 180도 회전을 구분하기 위해 총 4개의 회전 커브를 만들었다. 그런데 이 4개는 사실 대동소이하다. 90도와 180도 회전 커브의 차이는 각 키프레임 샘플링 포인트의 값이 2배 차이 나는 것뿐이고, 좌회전과 우회전은 값의 양수/음수 차이일 뿐이다. 그렇다면 커브 애셋 하나를 만들고, 위에서 이미 작성한 90 or 180, left or right 구분 로직에 따라 커브에 대응하는 곱셈 처리를 해주면 된다. 굳이 4개의 애니메이션 시퀀스마다 커브를 한 번씩 편집할 필요는 없다.&lt;br&gt;【2】애니메이션 감속 재생으로 생기는 커브 값 누적 오차는 가속 재생보다 작다. 이는 가속이 빨라질수록 샘플링 간격이 점점 커지고, 커브가 어떤 구간에서 급격히 변화한다면 샘플이 희소해져 눈에 띄는 오차가 생기기 때문이다. 감속 재생에서는 애니메이션 진행 시간 간격이 애니메이션 안의 두 프레임 사이 거리보다 작아져, 같은 키프레임이 여러 번 읽힌다. 그래서 모든 키프레임이 적어도 읽히게 보장되며, 커브 변화가 급격하더라도 점을 놓쳐 지나가는 일로 과도한 오차가 생기지는 않는다.&lt;br&gt;【3】게임 프레임레이트가 높아지는 결과는 애니메이션 감속 재생과 비슷하다. 따라서 게임 프레임레이트가 30보다 높을 때 애니메이션 재생에 생기는 오차는 매우 작다. 반대로 게임 프레임레이트가 30보다 낮을 때에는 애니메이션 배속 재생과 마찬가지로 비교적 큰 오차가 생긴다. (말이 나온 김에 말하자면, 게임 프레임레이트가 30프레임보다 낮아지면 이미 뚜렷한 끊김이 생기므로, 플레이어는 애니메이션의 신뢰감 하락까지 그다지 신경 쓰지 않을 것이다. ALSV4 애니메이션의 기본 프레임레이트를 30으로 설정한 것은 꽤 영리하다고 할 수 있다.)&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.3 블렌드 시간이 커브에 가져올 수 있는 영향&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;3.2절의 커브 설명을 보고 나면, 게임 프레임레이트 변동과 애니메이션 배속 재생이 오차를 일으키는 이유가 모두 애니메이션 커브의 샘플링 횟수가 변하기 때문이라는 것을 알 수 있다.&lt;br&gt;하지만 블렌드 시간도 사실 다른 방식으로 커브 샘플링에 오차를 가져온다. 블렌드 시간이 길수록 오차는 커진다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMziNv/dJMcaaznMZ9/V5pD7CH3lfaT0CWOkxOfgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMziNv/dJMcaaznMZ9/V5pD7CH3lfaT0CWOkxOfgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMziNv/dJMcaaznMZ9/V5pD7CH3lfaT0CWOkxOfgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMziNv%2FdJMcaaznMZ9%2FV5pD7CH3lfaT0CWOkxOfgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;488&quot; height=&quot;494&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제자리 회전 애니메이션에서는 RotationAmount 커브가 활성화되어 있지만, 제자리 대기 상태에서는 이 커브를 사용하지 않는다. (즉 값이 0이다.) 제자리 회전과 제자리 대기를 블렌드할 때, RotationAmount 값도 함께 블렌드된다.&lt;br&gt;다시 말해, 만약 블렌드 인 시간을 0.4초로 설정했다면, 커브상에서는 상당히 긴 구간의 커브 값이 제자리 대기 상태의 “0값”과 가중 평균 블렌드를 하면서 영향을 받게 된다. (값이 낮아진다.) &lt;b&gt;블렌드 인/아웃 시간이 길수록 커브 값이 영향을 받는 구간도 많아지고, 마지막에 표현되는 회전 효과도 더 부정확해진다.&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q1PBJ/dJMcagTSNUt/KzdqxdkgFaOzDNgm0JXCrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q1PBJ/dJMcagTSNUt/KzdqxdkgFaOzDNgm0JXCrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q1PBJ/dJMcagTSNUt/KzdqxdkgFaOzDNgm0JXCrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ1PBJ%2FdJMcagTSNUt%2FKzdqxdkgFaOzDNgm0JXCrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1131&quot; height=&quot;814&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;814&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 언급할 만한 점은, 애니메이션 배속 재생은 애니메이션의 총 재생 시간을 줄인다는 것이다. (가속 재생을 말한다.) 그러면 원래 0.4초였던 블렌드 시간이 전체 길이의 20%를 차지했더라도, 2배속 재생에서는 40%를 차지하는 것으로 변한다. (애니메이션 배속 재생은 블렌드 시간 길이까지 함께 스케일링하지 않는다.)&lt;br&gt;그러면 블렌드의 영향을 받는 커브 값의 “피해 구역”도 크게 늘어난다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;815&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MuJrN/dJMcaijQCpJ/x7tJyFTx9QX9Xmo2o8LYc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MuJrN/dJMcaijQCpJ/x7tJyFTx9QX9Xmo2o8LYc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MuJrN/dJMcaijQCpJ/x7tJyFTx9QX9Xmo2o8LYc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMuJrN%2FdJMcaijQCpJ%2Fx7tJyFTx9QX9Xmo2o8LYc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1138&quot; height=&quot;815&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;815&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 &lt;b&gt;배속 재생은 블렌드 시간이 가져오는 오차를 대폭 확대한다&lt;/b&gt;.&lt;br&gt;블렌드 시간을 높이면 물론 애니메이션 사이의 전환을 더 자연스럽고 매끄럽게 만들 수 있다. 하지만 커브 값이 블렌드에 의해 훼손되어, 애니메이션 신뢰감 요구가 높은 상황(예를 들어 이 글의 제자리 회전처럼, 오차가 10도를 넘으면 매우 뚜렷해지는 경우)에서는 더 큰 오차를 만들 수도 있다. 따라서 &lt;b&gt;맹목적으로 블렌드 시간을 늘리는 것은 현명한 선택이 아니다&lt;/b&gt;.&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;맺음말(필자의 관례적인 잡담을 뜻함)&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;지난번 ALSV4 &lt;b&gt;8방향 이동&lt;/b&gt; 편 업데이트로부터 이미 1개월 18일이 지났다. 매달 &lt;b&gt;부지런하고 성실하게 붓을 놓지 않고&lt;/b&gt; 글을 올리던 나로서는, 최근 한 달 넘게 게으름을 피우며 글을 올리지 않았는데도, 知乎의 팔로우와 조회수가 나를 놀라게 할 속도로 오르고 있어서 정말 부끄러워 몸 둘 바를 모르겠다 = =. 그래서 모레 이번 학기의 첫 기말고사를 맞이해야 하는 상황임에도, 필자는 야근하듯 이 글을 먼저 업데이트하고 나서 복습하러 가기로 했다.&lt;br&gt;다음 글은 ALSV4의 발 IK를 업데이트할 계획이다. 결국 애니메이션을 깊이 공부해본 적 없는 사람이라도, 8방향 이동과 IK는 들어봤거나(혹은 인터넷 튜토리얼을 따라 간단히 구현해보려 시도했거나) 했을 것이다. 5월 20일부터 6월 중순까지는 시험 주간이라, 다음 글 업데이트는 빨라도 6월은 되어야 나올 것 같다.&lt;br&gt;이번 절의 제목은 “제자리 회전”이지 “회전”이 아니다…… 왜냐하면 ALSV4 안의 회전을 한 번에 다 설명하려고 하면 이 글의 내용량이 너무 방대하고 뒤섞이기 때문이다. 이동 과정 중의 회전 같은 것은 많은 움직임 디테일을 포함한다. 예를 들어 자세(무게중심) 기울기, 카메라 변화, 보행 상태 제한과 전이 등등……&lt;br&gt;그리고 같은 창작자인 몇몇 선배들에게 감사드리고 싶다. @聆枫LingFeng, @小木子. 내가 며칠 전 블렌드 시간 때문에 생기는 여러 오차 현상으로 혼란스러워하고 있을 때, 그룹에서 인내심 있게 귀중한 조언을 제공해주었다. (특히 小木子 선배가 제공한 디버깅 조언 덕분에 정말 많은 우회로를 피할 수 있었다.)&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z4D5B/dJMcagsMMW7/jZBWbHymsfF7sOFpDk5GJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z4D5B/dJMcagsMMW7/jZBWbHymsfF7sOFpDk5GJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z4D5B/dJMcagsMMW7/jZBWbHymsfF7sOFpDk5GJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ4D5B%2FdJMcagsMMW7%2FjZBWbHymsfF7sOFpDk5GJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1205&quot; height=&quot;634&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마지막은 좋아요 구걸 시간이다&lt;/b&gt;! 여기까지 봤다면, 설령 이 글이 비루하고 얕다고 느껴지더라도, 필자가 글 쓰느라 고생했다는 점을 생각해 &lt;b&gt;좋아요&lt;/b&gt; 하나만 누르고 가주면 좋겠다. 부탁이다 ≥﹏≤&lt;br&gt;내가 쓴 기술 블로그는 예전에 많은 사람에게 도움이 된 적이 있다. 이제는 나도 여러분이 나에게 손을 내밀어주기를 간절히 부탁하고 싶다. (작은 좋아요 버튼 한 번만 누르면 된다!)&lt;br&gt;PS: 덧붙여 여기서 필자가 막 만든 &lt;b&gt;UE 골격 애니메이션 교류방&lt;/b&gt;을 살짝 광고한다. &lt;b&gt;916274600&lt;/b&gt; 각위 대佬들의 매서운 지적을 환영합니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/diaZbh/dJMcaalJ6fN/RkzCGKAIpeYvke4XAnGsdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/diaZbh/dJMcaalJ6fN/RkzCGKAIpeYvke4XAnGsdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/diaZbh/dJMcaalJ6fN/RkzCGKAIpeYvke4XAnGsdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdiaZbh%2FdJMcaalJ6fN%2FRkzCGKAIpeYvke4XAnGsdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;377&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고:&lt;br&gt;&lt;a href=&quot;https://www.bilibili.com/video/BV12f4y1r71N/?p=84&quot; target=&quot;_self&quot;&gt;&lt;span&gt;62 고급 로코모션 시스템 해체 - 제자리 회전_哔哩哔哩_bilibili&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <category>Advanced</category>
      <category>engine</category>
      <category>Locomotion</category>
      <category>System</category>
      <category>unreal</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/820</guid>
      <comments>https://techartnomad.tistory.com/820#entry820comment</comments>
      <pubDate>Thu, 23 Jul 2026 00:23:41 +0900</pubDate>
    </item>
    <item>
      <title>[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동</title>
      <link>https://techartnomad.tistory.com/817</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 간단한 소개와 사고 정리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8방향 이동이란, 캐릭터가 앞, 뒤, 좌, 우, 좌전방, 좌후방, 우전방, 우후방으로 이동하는 애니메이션을 갖는 것을 말한다. 캐릭터의 컨트롤러 회전(컨트롤러 회전은 특정 방향을 가리키는 단위 벡터라고 대략 이해해도 된다)과 캐릭터의 속도 벡터 사이에 일정한 크기의 각도가 생기면, 캐릭터의 애니메이션도 그에 맞춰 변화해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 두 개 들어보자. 하나는 속도 방향은 변하지 않고 컨트롤러 방향만 회전하는 경우다. 예를 들어 현재 캐릭터가 우리가 &amp;ldquo;W&amp;rdquo;를 누르고 있을 때 x축(월드 좌표계 기준)을 따라 직선으로 앞으로 달리고 있다고 하자. 이때 마우스를 회전시켜 컨트롤러가 오른쪽으로 돌아 y축(월드 좌표계 기준)을 향하게 만들면, 캐릭터는 오른쪽 앞방향으로 달리는 동작을 해야 자연스럽게 보인다. (이때 W는 계속 누르고 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너 뭘 봐?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;214&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://picx.zhimg.com/v2-c3050e820dd6d1f2c0617453ceaa2fcb_1440w.jpg&quot; data-phocus=&quot;https://picx.zhimg.com/v2-c3050e820dd6d1f2c0617453ceaa2fcb_1440w.jpg&quot;&gt;&lt;img src=&quot;https://picx.zhimg.com/v2-c3050e820dd6d1f2c0617453ceaa2fcb_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpicx.zhimg.com%2Fv2-c3050e820dd6d1f2c0617453ceaa2fcb_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;214&quot; height=&quot;331&quot; data-origin-width=&quot;214&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너 뭘 봐?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 예는 컨트롤러 방향은 변하지 않고 속도 방향이 바뀌는 경우다. 마찬가지로 현재 캐릭터가 우리가 &amp;ldquo;W&amp;rdquo;를 누르고 있을 때 x축(월드 좌표계 기준)을 따라 직선으로 앞으로 달리고 있다고 하자. 이때 &amp;ldquo;W&amp;rdquo;를 계속 누른 상태에서 &amp;ldquo;D&amp;rdquo;를 동시에 누르고, 마우스는 움직이지 않는다. 그러면 캐릭터 역시 오른쪽 앞방향으로 달리는 동작을 해야 자연스럽게 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 예시에서 캐릭터의 달리기 애니메이션이 정면에서 우전방으로 바뀌는 원인은 모두 같다. 컨트롤러와 속도 방향의 변화가 컨트롤러와 속도 사이 각도를 바꾸기 때문이다. 그래서 우리는 이 변화를 드러내기 위해 애니메이션을 변경해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 8방향 이동을 구현하려면 해야 할 일은 꽤 명확하다. 매 프레임마다 캐릭터 속도와 컨트롤러 회전 사이의 각도를 계산하고, 그것으로 애니메이션을 갱신하면 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 전통적인 방법과 그 문제점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 속도와 컨트롤러 회전 사이의 각도는 아래 노드로 계산할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UE, 정말 친절하다. 손잡고 애니메이션 만들라고 가르쳐주는 수준이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1255&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://pic2.zhimg.com/v2-3bdb57bdcfa0385c3a7e250dbd15fea5_1440w.jpg&quot; data-phocus=&quot;https://pic2.zhimg.com/v2-3bdb57bdcfa0385c3a7e250dbd15fea5_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic2.zhimg.com/v2-3bdb57bdcfa0385c3a7e250dbd15fea5_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic2.zhimg.com%2Fv2-3bdb57bdcfa0385c3a7e250dbd15fea5_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1255&quot; height=&quot;447&quot; data-origin-width=&quot;1255&quot; data-origin-height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UE, 정말 친절하다. 손잡고 애니메이션 만들라고 가르쳐주는 수준이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각도가 연속적으로 변화하는 문제이기 때문에, 자연스러운 생각은 블렌드 스페이스를 사용하는 것이다. 하나의 좌표축을 -180~180도로 설정하고, 그 안에 8방향 이동의 각 애니메이션을 배치하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Advanced Locomotion System 4에는 정우측과 정좌측 애니메이션이 별도로 제작되어 있지 않기 때문에, 여기서는 애니메이션 시퀀스 두 개를 덜 넣고 대충 맞춰두었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 말하면 ALS4에는 우전방과 좌전방 애니메이션이 제작되어 있지 않다. 우전방과 좌전방이라는 이름을 달고 있는 애니메이션 시퀀스 안에는 실제로 정우측과 정좌측 애니메이션이 들어 있다. 우전방과 좌전방 애니메이션 효과를 만들려면 직접 수동으로 블렌드해야 한다. 우후방과 좌후방도 보기에는 그냥 역재생한 결과처럼 보인다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1111&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kIXxt/dJMcaiqzhav/vcr97kWPLhAaR5SPeOsZ70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kIXxt/dJMcaiqzhav/vcr97kWPLhAaR5SPeOsZ70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kIXxt/dJMcaiqzhav/vcr97kWPLhAaR5SPeOsZ70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkIXxt%2FdJMcaiqzhav%2Fvcr97kWPLhAaR5SPeOsZ70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1111&quot; height=&quot;834&quot; data-origin-width=&quot;1111&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 말하면 ALS4에는 우전방과 좌전방 애니메이션이 제작되어 있지 않다. 우전방과 좌전방이라는 이름을 달고 있는 애니메이션 시퀀스 안에는 실제로 정우측과 정좌측 애니메이션이 들어 있다. 우전방과 좌전방 애니메이션 효과를 만들려면 직접 수동으로 블렌드해야 한다. 우후방과 좌후방도 보기에는 그냥 역재생한 결과처럼 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 생각은 매우 자연스럽다. 하지만 블렌드 스페이스 자체의 성질 때문에, 이方案은 실행할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 말하면 문제는 &amp;ldquo;점프&amp;rdquo;에 있다. 예를 들어 왼쪽에서 오른쪽으로 갈 때 값이 점프한다. (오른쪽에서 왼쪽으로 가도 마찬가지다.) 이 문제는 조금 작은 편이다. 이유는 180도만 점프하기 때문이다. 블렌드 시간을 조심스럽게 선택하면 억지로 해결할 수도 있다. 블렌드 시간이 짧으면 점프할 때 동작이 빠르게 전환되며 생기는 변형이 더 뚜렷해지고, 블렌드 시간이 길면 캐릭터가 좌우를 전환할 때 중간에 정면을 향해 &amp;ldquo;제자리걸음&amp;rdquo;하는 두 스텝이 나타난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 심각한 문제는 좌후방에서 우후방으로 갈 때의 점프다. (우후방에서 좌후방도 마찬가지로 점프한다.) 얼핏 보면 좌후방과 우후방 두 동작의 차이는 그렇게 크지 않아 보이고, 원래라면 블렌드해도 자연스러워야 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 블렌드 스페이스의 눈에는 좌후방과 우후방 두 동작을 블렌드하는 것이 아니다. 좌표축 맨 왼쪽 끝에 있는 애니메이션을 좌표축 맨 오른쪽 끝에 있는 애니메이션으로 블렌드하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블렌드 스페이스는 사용자가 정한 블렌드 시간 안에 좌표축 위의 애니메이션을 하나씩 차례로 섞어 지나간다. 그래서 최종적으로 실제 보이는 효과는, 캐릭터가 뒤로 이동할 때마다 마우스를 좌우로 조금만 움직여도 캐릭터가 한 번씩 경련하는 것처럼 보이는 것이다. 극도로 부자연스럽다. (축을 -180~180에서 0~360으로 바꿔도 소용없다. 그렇게 하면 떨림이 뒤로 걸을 때가 아니라 앞으로 걸을 때 생길 뿐이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블렌드 스페이스가 &amp;ldquo;원형&amp;rdquo; 수직선을 지원할 수 있다면 좋았을 것이다. 아쉽게도 현재는 지원하지 않고, 직선 축만 처리할 수 있다. 그래서 우리는 상태 머신을 사용해 점프 문제를 해결할 수밖에 없다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. ALS4가 애니메이션 상태 머신으로 8방향 이동을 구현하는 방식&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.1 이동 의도 계산&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적인 방법에서는 캐릭터 속도와 컨트롤러 사이의 각도가 얼마인지에 따라 그에 대응하는 이동 애니메이션을 사용한다. 하지만 애니메이션 상태 머신에서는 점프로 인한 부자연스러움을 극복해야 하므로, 이렇게 직접적인 방식을 사용할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 각도의 구간을 직접 &amp;ldquo;어느 애니메이션을 사용할지&amp;rdquo;로 대표시킬 수 없다. 이 각도는 오직 **&amp;ldquo;이동 의도&amp;rdquo;**를 표현하는 데만 쓰인다. 구체적으로 어떤 애니메이션 시퀀스를 사용할지는 이동 의도와 캐릭터가 현재 사용 중인 애니메이션 시퀀스를 종합해서 결정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이동 의도&lt;/b&gt;: 앞, 뒤, 왼쪽, 오른쪽 네 방향만 있다. 캐릭터의 속도 방향과 컨트롤러 회전 사이의 각도로 계산한다. 우리는 컨트롤러와 캐릭터 속도 방향의 각도가 -70~70도이면 앞, 70~110도이면 오른쪽, -70~-110도이면 왼쪽, 나머지는 뒤라고 규정한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-1e2b105b93114bba1d1e54bcdf07c94c_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-1e2b105b93114bba1d1e54bcdf07c94c_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-1e2b105b93114bba1d1e54bcdf07c94c_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-1e2b105b93114bba1d1e54bcdf07c94c_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;1080&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명히 이동 의도는 월드 좌표계와는 관계가 없고, 플레이어 자신의 좌표계와만 관련이 있다. 우리는 각도가 앞/뒤/좌/우 네 구간(혹은 사분면) 중 어디에 있는지 판단하는 함수를 작성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 핵심 내용의 스크린샷&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;777&quot;&gt;&lt;span data-url=&quot;https://picx.zhimg.com/v2-f6b87c2aed542cdaba3826bbde90a87d_1440w.jpg&quot; data-phocus=&quot;https://picx.zhimg.com/v2-f6b87c2aed542cdaba3826bbde90a87d_1440w.jpg&quot;&gt;&lt;img src=&quot;https://picx.zhimg.com/v2-f6b87c2aed542cdaba3826bbde90a87d_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpicx.zhimg.com%2Fv2-f6b87c2aed542cdaba3826bbde90a87d_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1258&quot; height=&quot;777&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;777&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 핵심 내용의 스크린샷&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버퍼라는 이 파라미터는 사분면의 범위를 동적으로 확대하거나 축소하는 데 사용된다. 캐릭터의 현재 이동 의도가 왼쪽 또는 오른쪽일 때에는 앞뒤 각도 구간을 확대하고, 좌우 사분면의 각도 구간을 축소한다. 반대로도 마찬가지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 컨트롤러와 캐릭터 속도의 각도를 계산해 사분면 함수에 넣으면, 캐릭터의 다음 이동 의도를 얻을 수 있다. 이 각도를 어떻게 계산하느냐에 대해서, ALS4에서는 이렇게 한다. (AimingRotation은 캐릭터 컨트롤러 회전을 저장한다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;781&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xXJGc/dJMcaiRF2ny/Z0xzxk9yxwBTaUNbjOguz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xXJGc/dJMcaiRF2ny/Z0xzxk9yxwBTaUNbjOguz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xXJGc/dJMcaiRF2ny/Z0xzxk9yxwBTaUNbjOguz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxXJGc%2FdJMcaiRF2ny%2FZ0xzxk9yxwBTaUNbjOguz0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;781&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;781&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 앞에서도 말했듯이, UE에는 편리한 내장 함수(방향 계산)가 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;693&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-2f364e39c81eb26353290870c4375c80_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-2f364e39c81eb26353290870c4375c80_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-2f364e39c81eb26353290870c4375c80_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-2f364e39c81eb26353290870c4375c80_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;693&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;693&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 방식의 효과는 동등하다. 독자는 직접 실험해서 검증해봐도 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.2 8방향 이동 애니메이션 상태 머신 제작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림에서 보듯, 모든 노란색 전이 조건은 &amp;ldquo;이동 의도 == 앞으로&amp;rdquo;, 초록색 전이 조건은 &amp;ldquo;이동 의도 == 뒤로&amp;rdquo;, 빨간색은 오른쪽, 파란색은 왼쪽이다. (같은 색을 가진 것은 공유 전이 규칙을 사용했기 때문이다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://pic1.zhimg.com/v2-60dc4d87fcd32b2f4c15c7999346e0e8_1440w.jpg&quot; data-phocus=&quot;https://pic1.zhimg.com/v2-60dc4d87fcd32b2f4c15c7999346e0e8_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic1.zhimg.com/v2-60dc4d87fcd32b2f4c15c7999346e0e8_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic1.zhimg.com%2Fv2-60dc4d87fcd32b2f4c15c7999346e0e8_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;963&quot; height=&quot;737&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태 머신은 전통적인 블렌드 스페이스 방법에서 발생하는 점프 문제를 해결한다. 이 상태 머신을 구성하는 사고방식을 간단히 말해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바깥쪽의 이 빨간 원은 이해하기 쉬울 것이다. W를 누르고, WD, D, SD, S라는 키 입력 순서로 가면, Move-F, Move-FR, Move-BR, Move-B 상태 노드로 이동할 수 있다. 만약 W를 누른 상태에서 바로 S를 누르는 상태로 바뀐다면, 가운데 빨간 지름을 따라 Move-F에서 Move-B로 바로 변한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;553&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;769&quot; height=&quot;553&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;553&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 중간의 두 주황색 전이 조건의 의도를 중점적으로 이야기해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블렌드 스페이스에서 우전방에서 좌후방으로 전환하려면, 180도 점프가 발생하기 때문에 좌표축 절반에 해당하는 애니메이션 시퀀스를 쭉 블렌드해서 지나가야 한다. (이 상태 머신에 놓고 보면 빨간 원주를 따라 반 바퀴 도는 것으로 나타난다.) 그러면 그다지 자연스럽지 않아 보인다. 그래서 우전방과 좌후방 애니메이션이 &amp;ldquo;원주를 반 바퀴 도는&amp;rdquo; 과정 없이 직접 블렌드될 수 있도록, 특별히 이 주황색 지름을 추가했다. 180도 점프가 발생할 때 목표 애니메이션과 직접 블렌드할 수 있게 한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세히 관찰하면, 이 상태 머신에는 총 세 개의 지름이 있다. 모두 180도 점프 시의 블렌드를 처리하기 위해 설계된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 360도 점프는? 애니메이션 상태 머신 안의 상태 노드는 고리 형태로 연결될 수 있기 때문에, 이 문제는 저절로 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 말할 만한 점은, &lt;b&gt;8&lt;/b&gt;방향 이동 애니메이션 상태 머신인데 상태 노드는 &lt;b&gt;6개&lt;/b&gt;밖에 없다는 것이다. 하지만 이것은 영향을 주지 않는다. 8개 상태 노드(실제로는 10개여야 한다. 정좌측과 정우측은 사실 정방향으로 걷는지 후방으로 걷는지, 혹은 가슴 방향과 이동 방향이 일치하는지에 따라 나눠야 한다)로 만드는 것도 가능하다. 다만 그러려면 이동 의도 계산에 더 많은 공을 들여야 한다. 이동 의도는 앞/뒤/좌/우 네 개의 열거값만으로는 부족하고, 실제로 확실한 8방향 열거값이 필요하다. 당연히 판단도 더 번거로워진다. 상태 머신 안의 전이 조건도 원래 4개 그룹에서 8개 그룹으로 나뉘게 된다. 연결 사고방식은 위와 비슷하니, 관심 있는 독자는 직접 한번 시도해봐도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 왜 이런 6개 상태 노드짜리 8방향 이동 상태 머신도 정상적으로 동작할 수 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 언급했듯, ALS 시스템의 우전방 애니메이션은 이름만 우전방일 뿐이다. 실제로 들어 있는 것은 가슴이 오른쪽을 향한, 정우측 이동 애니메이션이다. (캐릭터는 이때 정방향으로 걷고 있다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://pica.zhimg.com/v2-da2809edefd13d4249106e9f4a4250c0_1440w.jpg&quot; data-phocus=&quot;https://pica.zhimg.com/v2-da2809edefd13d4249106e9f4a4250c0_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pica.zhimg.com/v2-da2809edefd13d4249106e9f4a4250c0_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpica.zhimg.com%2Fv2-da2809edefd13d4249106e9f4a4250c0_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;402&quot; height=&quot;409&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 우후방 애니메이션은 등이 오른쪽을 향한, 정우측 이동 애니메이션이다. (맞다. 아무리 봐도 가슴이 왼쪽을 향한 좌측 이동 애니메이션을 역순 재생한 것처럼 보인다 = = 캐릭터는 이때 뒤로 걷고 있다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://picx.zhimg.com/v2-b81e9f382fe9b27c935398604ed5995d_1440w.jpg&quot; data-phocus=&quot;https://picx.zhimg.com/v2-b81e9f382fe9b27c935398604ed5995d_1440w.jpg&quot;&gt;&lt;img src=&quot;https://picx.zhimg.com/v2-b81e9f382fe9b27c935398604ed5995d_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpicx.zhimg.com%2Fv2-b81e9f382fe9b27c935398604ed5995d_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;475&quot; height=&quot;377&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ALS4의 관점에서 우전방은 &amp;ldquo;오른쪽 앞방향으로 이동&amp;rdquo;이 아니라, 가슴(몸의 앞면)이 오른쪽을 향한 채 오른쪽으로 이동하는 것이다. 마찬가지로 우후방도 등(몸의 뒷면)이 오른쪽을 향한 채 오른쪽으로 이동하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이 &lt;b&gt;6개&lt;/b&gt; 상태 노드짜리 상태 머신은, &lt;b&gt;겉으로 보기에는 &amp;ldquo;정좌측과 정우측&amp;rdquo;이 없는 것 같지만, 실제로는 오직 &amp;ldquo;정좌측과 정우측&amp;rdquo;만 있고 좌전방/좌후방/우전방/우후방이 없는 셈이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 W를 누르고, W를 놓은 뒤 A를 누르면 FL 노드에 도달한다. 이때는 &amp;ldquo;몸의 앞방향이 왼쪽&amp;rdquo;인 정좌측 이동 상태다. 여기서 다시 A를 놓고 D를 누르면, 주황색 지름을 따라 BR 노드로 가게 된다. 즉 &amp;ldquo;몸의 앞방향이 왼쪽&amp;rdquo;인 정우측 이동이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;553&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-1f2c1f782d915cd29eb0e3f2795d0208_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;769&quot; height=&quot;553&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;553&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 이런 설계의 장점 중 하나를 보여준다. 좌우 전환처럼 격렬한 180도 점프가 있을 때, &lt;b&gt;캐릭터의 가슴 방향은 변하지 않는다.&lt;/b&gt; 캐릭터 가슴이 180도 돌아버리는 상황이 발생하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 독자는 묻고 싶을 것이다. 그럼 약속했던 우전방/우후방, 좌전방/좌후방은 어디 갔는가? 답은 Move-F 또는 Move-B 노드 안에서 블렌드해서 얻는다는 것이다. 구체적으로 어떻게 블렌드하고, 사용되는 블렌드 값은 어떻게 계산해야 하는지는 다음 절에서 말하겠다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.3 속도 블렌드 값 계산&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이동 의도가 해결하는 문제는 상태 노드 사이의 전환이고, 속도 블렌드 값이 해결하는 문제는 상태 노드 내부의 애니메이션 블렌드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속도 블렌드 값을 계산할 때는 주로 캐릭터의 상대 속도를 사용한다. 이 개념은 이동 의도와 구분할 필요가 있다. 캐릭터의 상대 속도란 현재 시점에서 캐릭터 자신의 좌표계 기준 이동 방향을 뜻하고, 이동 의도는 캐릭터가 다음 시점에 향하려는 이동 방향을 뜻한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 이동 의도는 앞/뒤/좌/우 네 값으로만 나뉘기 때문에, 속도 블렌드 값이 요구하는 정밀한 블렌드를 구현할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속도 블렌드 값은 사실상 캐릭터의 상대 속도를 캐릭터 좌표계의 X/Y축에 직교 분해하여, 캐릭터 상대 속도가 X축과 Y축에서 가지는 성분을 얻는 것이다. 캐릭터 좌표계의 X/Y축은 실제로 앞/뒤/좌/우를 뜻하므로, 이 성분은 캐릭터가 현재 왼쪽(오른쪽)으로 이동하는 정도와 앞(뒤)으로 이동하는 정도를 나타낸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YQj8D/dJMcaaTCJTO/AuTTLBt0DUrATX6QhiOazk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YQj8D/dJMcaaTCJTO/AuTTLBt0DUrATX6QhiOazk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YQj8D/dJMcaaTCJTO/AuTTLBt0DUrATX6QhiOazk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYQj8D%2FdJMcaaTCJTO%2FAuTTLBt0DUrATX6QhiOazk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1040&quot; height=&quot;314&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상대 속도의 x 성분과 y 성분을 (x^2 + y^2)의 제곱근으로 나누어, 상대 X와 상대 Y에 할당한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;601&quot;&gt;&lt;span data-url=&quot;https://pic1.zhimg.com/v2-4b69e9b78754d54ee6a493565cfc886e_1440w.jpg&quot; data-phocus=&quot;https://pic1.zhimg.com/v2-4b69e9b78754d54ee6a493565cfc886e_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic1.zhimg.com/v2-4b69e9b78754d54ee6a493565cfc886e_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic1.zhimg.com%2Fv2-4b69e9b78754d54ee6a493565cfc886e_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1060&quot; height=&quot;601&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;601&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 속도 블렌드 값 계산은 완료된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 속도 블렌드 값에 보간을 적용하는 함수도 하나 더 작성해야 한다. 캐릭터 이동 상태가 변화할 때 부드럽게 전환되도록 하기 위해서다. 원본 속도 블렌드 값은 이전 프레임의 옛 데이터이고, 목표 속도 블렌드 값은 이번 프레임의 새 데이터다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 상태 노드 안에서의 활용이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터의 앞, 뒤, 좌전방, 우전방 애니메이션을 멀티 핀 블렌드한다. 여기서는 캐시 포즈를 사용해 애니메이션 시퀀스를 &amp;ldquo;변수&amp;rdquo;처럼 저장했다. 이렇게 하면 애니메이션 시퀀스를 교체할 때 애니메이션 상태 머신을 수정할 필요가 없다. 전달되는 포즈만 바꾸면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://pic4.zhimg.com/v2-88c7370b71b3b02827acbcf5f256ba21_1440w.jpg&quot; data-phocus=&quot;https://pic4.zhimg.com/v2-88c7370b71b3b02827acbcf5f256ba21_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic4.zhimg.com/v2-88c7370b71b3b02827acbcf5f256ba21_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic4.zhimg.com%2Fv2-88c7370b71b3b02827acbcf5f256ba21_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;674&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 FR 노드에서는 Left 방향의 애니메이션에 LF를 사용할 수 없고, LB를 사용해야 한다. 이유는 위에서 말한 것처럼, 좌우 180도 점프 시에는 가슴 방향이 변하지 않기를 원하기 때문이다. 따라서 LB 애니메이션(즉 뒤로 걷기, 가슴이 오른쪽을 향한 채 왼쪽으로 이동하는 애니메이션)을 사용해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlBxKL/dJMcac4XxTB/Drt0dGT9NLk4YlmnIkTKQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlBxKL/dJMcac4XxTB/Drt0dGT9NLk4YlmnIkTKQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlBxKL/dJMcac4XxTB/Drt0dGT9NLk4YlmnIkTKQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlBxKL%2FdJMcac4XxTB%2FDrt0dGT9NLk4YlmnIkTKQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1158&quot; height=&quot;554&quot; data-origin-width=&quot;1158&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 BL 노드에서도 위 그림과 완전히 똑같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FL과 BR 노드에서는 이런 모습이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBL3Bu/dJMcajpojak/Sa4IPfh3Q2pyfuKkrwycsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBL3Bu/dJMcajpojak/Sa4IPfh3Q2pyfuKkrwycsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBL3Bu/dJMcajpojak/Sa4IPfh3Q2pyfuKkrwycsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBL3Bu%2FdJMcajpojak%2FSa4IPfh3Q2pyfuKkrwycsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1107&quot; height=&quot;595&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Move-B 노드에서는 L과 R의 애니메이션 포즈에 LB와 RB를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FR 노드에서 BL 노드로 점프하는 예를 들어 이 상태 머신의 블렌드를 설명해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 이동 상태가 바뀌는 순간, 이동 의도는 즉시 변화하고 상태 머신은 FR 노드에서 BL 노드로 이동한다. 전이 조건은 자동으로 두 노드의 출력 포즈를 블렌드한다. 그런데 속도 블렌드에는 보간을 사용했기 때문에, 상태 머신은 이미 상태 노드 점프를 했더라도 속도 블렌드 자체는 아직 균일하게 변화하는 중이다. (이때 R은 아직 0으로 내려가지 않았고, L도 아직 1로 올라가지 않았다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FR 노드와 BL 노드에서 사용하는 포즈는 완전히 동일하며, 점프가 발생한 순간 속도 블렌드 값도 아직 크게 변하지 않았다. 그래서 이때 BL 노드의 출력 포즈는 사실 FR 노드와 별 차이가 없다. 바꿔 말하면, 전이 조건이 블렌드해야 하는 두 상태 노드의 출력 포즈가 매우 비슷하므로, 블렌드 결과도 비교적 자연스럽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 BL 노드 내부에서 속도 블렌드의 보간이 진행되면서, BL 노드의 출력 포즈도 점차 가슴이 오른쪽을 향한 우측 이동 애니메이션에서 가슴이 오른쪽을 향한 좌측 이동 애니메이션으로 전환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해서 한 번의 자연스럽고 균일한 동작 전환이 완료된다. (사실 이렇게 해도 아직 충분히 자연스럽지는 않고, 해야 할 다른 작업이 좀 더 있다. 하지만 일단 여기까지 업데이트하고, 남은 것은 나중에 다시 이야기하자 = =)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 위에서 말하지 않은 것은 캐시 포즈에 입력되는 포즈가 어떤 모습이어야 하는가다. 여기서 간단히 한마디 하자면, 애니메이션 시퀀스를 직접 사용해도 물론 가능하지만, 우리가 「UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초 - 知乎 (&lt;a href=&quot;http://zhihu.com/&quot;&gt;zhihu.com&lt;/a&gt;)」에서 언급한 방식을 사용하는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;677&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-8f0ab593a25dc53294be9d7bfd4ae026_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-8f0ab593a25dc53294be9d7bfd4ae026_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-8f0ab593a25dc53294be9d7bfd4ae026_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-8f0ab593a25dc53294be9d7bfd4ae026_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;522&quot; height=&quot;677&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;677&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관심 있는 독자는 한번 가서 읽어봐도 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;맺음말&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 필자가 &lt;a href=&quot;https://www.zhihu.com/people/6e0f0f37e048b0ec8bcb9d7d48fb5c02&quot;&gt;@五谷延年&lt;/a&gt; 선배가 B站（ 빌리 빌리를 말함 ）(그리고 冲呀 플랫폼)에 올린 고급 로코모션 시스템 튜토리얼을 공부하는 과정에서, 튜토리얼에 약간 부족한 점이 있다고 느꼈고, 그 때문에 공부할 때 적지 않은 혼란이 있었던 데서 출발했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 필자는 튜토리얼을 모든 면에서 빠짐없이 만들려면 마음도 힘도 많이 들 뿐 아니라 현실적으로 어렵다는 것을 잘 알고 있다. 필자는 五谷延年 선배가 UE 커뮤니티에 사심 없이 기여한 이 튜토리얼에 매우 감사하고 있으며, 무슨 불평을 하려는 것도 아니다. 그래서 이 글을 썼다. 어디까지나 五谷延年 선배 튜토리얼에 대한 아주 작은 보충이라고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 본 독자는 가능하다면 손 가는 김에 &lt;b&gt;좋아요와 즐겨찾기(그리고 가능하면 좋아요 버튼도 하나 더)를 눌러주면 좋겠다. 이건 나에게 정말 중요하다 = =&lt;/b&gt;! 앞으로도 골격 애니메이션 관련 튜토리얼과 생각 공유가 더 있을 예정이니, &lt;b&gt;팔로우&lt;/b&gt;해두면 업데이트를 놓치지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로, 중간고사와 수업 실험이 가까워지고 있어서, 최근에는 글을 업데이트할 시간이 아마 없을 것이다&amp;hellip;&amp;hellip; (&lt;b&gt;좋아요와 댓글로 업데이트를 재촉할 수는 있다&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 우리는, 다음에 또 만나자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덧붙여 여기서 필자가 막 만든 &lt;b&gt;UE 골격 애니메이션 교류방&lt;/b&gt;을 살짝 광고한다. &lt;b&gt;916274600&lt;/b&gt; 각위 大佬들의 매서운 지적을 환영합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-d08c89b10532761e25593556158ebb62_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-d08c89b10532761e25593556158ebb62_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-d08c89b10532761e25593556158ebb62_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-d08c89b10532761e25593556158ebb62_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;377&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://link.zhihu.com/?target=https%3A//www.bilibili.com/video/av80124207/&quot;&gt;&lt;b&gt;【초보자용】언리얼 4 ARPG 튜토리얼 - 리셋판 - 7화 - 활 사용 시 8방향 이동 상태_哔哩哔哩_bilibili&lt;/b&gt;www.bilibili.com/video/av80124207/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://pic4.zhimg.com/v2-f864b00c7d5e81573bf452cdb0e3caad_180x120.jpg&quot; data-phocus=&quot;https://pic4.zhimg.com/v2-f864b00c7d5e81573bf452cdb0e3caad_180x120.jpg&quot;&gt;&lt;img src=&quot;https://pic4.zhimg.com/v2-f864b00c7d5e81573bf452cdb0e3caad_180x120.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic4.zhimg.com%2Fv2-f864b00c7d5e81573bf452cdb0e3caad_180x120.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;300&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://link.zhihu.com/?target=https%3A//www.bilibili.com/video/BV12f4y1r71N&quot;&gt;&lt;b&gt;언리얼 4(UE4) 애니메이션 기술: 쉽게 깊이 들어가는 고급 로코모션 시스템_哔哩哔哩_bilibili&lt;/b&gt;www.bilibili.com/video/BV12f4y1r71N&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://picx.zhimg.com/v2-a3a25185faaf2edc974f78b21fd6682d_180x120.jpg&quot; data-phocus=&quot;https://picx.zhimg.com/v2-a3a25185faaf2edc974f78b21fd6682d_180x120.jpg&quot;&gt;&lt;img src=&quot;https://picx.zhimg.com/v2-a3a25185faaf2edc974f78b21fd6682d_180x120.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpicx.zhimg.com%2Fv2-a3a25185faaf2edc974f78b21fd6682d_180x120.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;300&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너와 처음 만났던 그날의 일&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://pic1.zhimg.com/v2-63ec1566e295581993162c6d140d70d0_1440w.jpg&quot; data-phocus=&quot;https://pic1.zhimg.com/v2-63ec1566e295581993162c6d140d70d0_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic1.zhimg.com/v2-63ec1566e295581993162c6d140d70d0_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic1.zhimg.com%2Fv2-63ec1566e295581993162c6d140d70d0_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://pic4.zhimg.com/v2-14e75ee6425034b3910663535aaec8b9_1440w.jpg&quot; data-phocus=&quot;https://pic4.zhimg.com/v2-14e75ee6425034b3910663535aaec8b9_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic4.zhimg.com/v2-14e75ee6425034b3910663535aaec8b9_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic4.zhimg.com%2Fv2-14e75ee6425034b3910663535aaec8b9_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이라, 나의 아이라 으흐흑&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://pic3.zhimg.com/v2-c54fa085a47ca4b92c3d37c6083d55d2_1440w.jpg&quot; data-phocus=&quot;https://pic3.zhimg.com/v2-c54fa085a47ca4b92c3d37c6083d55d2_1440w.jpg&quot;&gt;&lt;img src=&quot;https://pic3.zhimg.com/v2-c54fa085a47ca4b92c3d37c6083d55d2_1440w.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fpic3.zhimg.com%2Fv2-c54fa085a47ca4b92c3d37c6083d55d2_1440w.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이라, 나의 아이라 으흐흑&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <category>ALS</category>
      <category>movement</category>
      <category>technical animation</category>
      <category>로코모션</category>
      <category>무브먼트</category>
      <category>언리얼엔진</category>
      <category>테크니컬 애니메이션</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/817</guid>
      <comments>https://techartnomad.tistory.com/817#entry817comment</comments>
      <pubDate>Wed, 22 Jul 2026 00:51:35 +0900</pubDate>
    </item>
    <item>
      <title>[INDEX] ANIMATION SYSTEM</title>
      <link>https://techartnomad.tistory.com/816</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784789137464&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 점프&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/821&quot; data-og-url=&quot;https://techartnomad.tistory.com/821&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lRzFr/dJMb8WMCZxv/r9kFivK4YzanMKqgeDQE20/img.png?width=1440&amp;amp;height=617&amp;amp;face=0_0_1440_617&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/821&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/821&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lRzFr/dJMb8WMCZxv/r9kFivK4YzanMKqgeDQE20/img.png?width=1440&amp;amp;height=617&amp;amp;face=0_0_1440_617');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 점프&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784733867406&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 제자리 회전&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/820&quot; data-og-url=&quot;https://techartnomad.tistory.com/820&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnf7ti/dJMb8ZvOExc/XTGix0KhUNGqkIXNzXISrK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/b0kqO1/dJMb8SpVhFj/zR86lYfBpbdwmXElTykvIK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/cNwvqu/dJMb8WMCTHy/QgreXN5P3aO5x5eabWQB10/img.png?width=914&amp;amp;height=450&amp;amp;face=0_0_914_450&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/820&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/820&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnf7ti/dJMb8ZvOExc/XTGix0KhUNGqkIXNzXISrK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/b0kqO1/dJMb8SpVhFj/zR86lYfBpbdwmXElTykvIK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/cNwvqu/dJMb8WMCTHy/QgreXN5P3aO5x5eabWQB10/img.png?width=914&amp;amp;height=450&amp;amp;face=0_0_914_450');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 제자리 회전&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784649341418&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/817&quot; data-og-url=&quot;https://techartnomad.tistory.com/817&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ckWm7o/dJMb8QeziKC/SrlHwnstUBsFY2TBJTfTYk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ckep5o/dJMb8RkfeWg/BBVzE4kF0m2wnGOR4efRDk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bggOFH/dJMb8SXK13v/1QjMECkYayfZJ6M2uPLJ60/img.jpg?width=1440&amp;amp;height=1080&amp;amp;face=0_0_1440_1080&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/817&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/817&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ckWm7o/dJMb8QeziKC/SrlHwnstUBsFY2TBJTfTYk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ckep5o/dJMb8RkfeWg/BBVzE4kF0m2wnGOR4efRDk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bggOFH/dJMb8SXK13v/1QjMECkYayfZJ6M2uPLJ60/img.jpg?width=1440&amp;amp;height=1080&amp;amp;face=0_0_1440_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635363451&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역] UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/815&quot; data-og-url=&quot;https://techartnomad.tistory.com/815&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bCMpR6/dJMb9ia3170/ee9X9GAkJiEYDczcPJkmsK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/bh4muA/dJMb9iITMbO/QItoAkbk1462yxI4XtckrK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/yFeFD/dJMb87N9UeP/rQhpu0BJcv6Lgb3Zkjruy0/img.jpg?width=1057&amp;amp;height=856&amp;amp;face=0_0_1057_856&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/815&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/815&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bCMpR6/dJMb9ia3170/ee9X9GAkJiEYDczcPJkmsK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/bh4muA/dJMb9iITMbO/QItoAkbk1462yxI4XtckrK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/yFeFD/dJMb87N9UeP/rQhpu0BJcv6Lgb3Zkjruy0/img.jpg?width=1057&amp;amp;height=856&amp;amp;face=0_0_1057_856');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역] UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635312613&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템 (ALSV4)&quot; data-og-description=&quot;역자 남김: 맨날 렌더링쪽만 하다가 애니메이션쪽을 하려다보니 공부할 것들이 많은 것 같아서... ALS 와 GASP 둘 다 좀 파봐야겠나~ 싶어서 말이죠. 먼저 연구한 분들의 피가 되고 살이되는 포스팅&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/812&quot; data-og-url=&quot;https://techartnomad.tistory.com/812&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/8FwBi/dJMb9c9KOou/J4rrmpgntpXmhVE7gDZIk1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/exi8G/dJMb86oaGMP/5ewk6fnEIQ8nVSxbJYqszk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/8gkRs/dJMb9jgKmac/fkLJYdiSpKi6s7smUEM850/img.jpg?width=340&amp;amp;height=340&amp;amp;face=0_0_340_340&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/812&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/812&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/8FwBi/dJMb9c9KOou/J4rrmpgntpXmhVE7gDZIk1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/exi8G/dJMb86oaGMP/5ewk6fnEIQ8nVSxbJYqszk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/8gkRs/dJMb9jgKmac/fkLJYdiSpKi6s7smUEM850/img.jpg?width=340&amp;amp;height=340&amp;amp;face=0_0_340_340');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템 (ALSV4)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;역자 남김: 맨날 렌더링쪽만 하다가 애니메이션쪽을 하려다보니 공부할 것들이 많은 것 같아서... ALS 와 GASP 둘 다 좀 파봐야겠나~ 싶어서 말이죠. 먼저 연구한 분들의 피가 되고 살이되는 포스팅&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635221472&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역] PredictFootIK 구현&quot; data-og-description=&quot;예측 기반 Foot IK 구현하기들어가며개요&amp;quot;최종 결과는 문서 하단에서 확인하실 수 있습니다&amp;quot;이 글에서는 예측 기반 Foot IK를 구현하는 과정에서 마주한 기술적 도전과 해결 방법을 공유합니다.기&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/613&quot; data-og-url=&quot;https://techartnomad.tistory.com/613&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mJuzn/dJMb9efqXSh/GGE3NNR8Z5P2k4dmqW02g1/img.png?width=744&amp;amp;height=399&amp;amp;face=0_0_744_399,https://scrap.kakaocdn.net/dn/b2ZDXU/dJMb9eT2qSY/ytgTJK2UvlNZ2529daDBOK/img.png?width=744&amp;amp;height=399&amp;amp;face=0_0_744_399,https://scrap.kakaocdn.net/dn/YAPEB/dJMb8VNIRap/ckx1qZLc5Op2ENAZjTFZZ0/img.png?width=865&amp;amp;height=417&amp;amp;face=0_0_865_417&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/613&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/613&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mJuzn/dJMb9efqXSh/GGE3NNR8Z5P2k4dmqW02g1/img.png?width=744&amp;amp;height=399&amp;amp;face=0_0_744_399,https://scrap.kakaocdn.net/dn/b2ZDXU/dJMb9eT2qSY/ytgTJK2UvlNZ2529daDBOK/img.png?width=744&amp;amp;height=399&amp;amp;face=0_0_744_399,https://scrap.kakaocdn.net/dn/YAPEB/dJMb8VNIRap/ckx1qZLc5Op2ENAZjTFZZ0/img.png?width=865&amp;amp;height=417&amp;amp;face=0_0_865_417');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역] PredictFootIK 구현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;예측 기반 Foot IK 구현하기들어가며개요&quot;최종 결과는 문서 하단에서 확인하실 수 있습니다&quot;이 글에서는 예측 기반 Foot IK를 구현하는 과정에서 마주한 기술적 도전과 해결 방법을 공유합니다.기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635193276&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[번역][UE5] MotionMatching에서 MotionBrick으로&quot; data-og-description=&quot;역자의 말: 오랜 시간 렌더링과 최적화만 봐왔던 탓에 모션매칭이나 테크애니쪽으로는 아는게 별로 없는것 같습니다. 콘솔게임 개발도 많이 활성화 되가고 있고 최근에 붉은사막 플레이 영상들&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/761&quot; data-og-url=&quot;https://techartnomad.tistory.com/761&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/blxT52/dJMb9ia3182/K98AHT0PcrrA4N8ANaBGa0/img.gif?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/xundJ/dJMb82MQdOB/bTmFwdTNoBrGUYjmDbPjH0/img.gif?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/dmCKm0/dJMb89yqIdx/EvlMKxamkWWMkFO1vnWJBk/img.jpg?width=1440&amp;amp;height=794&amp;amp;face=0_0_1440_794&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/761&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/761&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/blxT52/dJMb9ia3182/K98AHT0PcrrA4N8ANaBGa0/img.gif?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/xundJ/dJMb82MQdOB/bTmFwdTNoBrGUYjmDbPjH0/img.gif?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/dmCKm0/dJMb89yqIdx/EvlMKxamkWWMkFO1vnWJBk/img.jpg?width=1440&amp;amp;height=794&amp;amp;face=0_0_1440_794');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[번역][UE5] MotionMatching에서 MotionBrick으로&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;역자의 말: 오랜 시간 렌더링과 최적화만 봐왔던 탓에 모션매칭이나 테크애니쪽으로는 아는게 별로 없는것 같습니다. 콘솔게임 개발도 많이 활성화 되가고 있고 최근에 붉은사막 플레이 영상들&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635292065&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Game Animation Technologies: Technical Comparison&quot; data-og-description=&quot;이 리서치 문서는 중국 테크 블로그 및 해외 테크 블로그 자료를 토대로 초안을 정리 하고 AI 를 사용하여 최종문서화 되었습니다.Motion Matching &amp;middot; MotionBricks &amp;middot; UE5 Pose Search본 문서는 현대 게임 애니&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/764&quot; data-og-url=&quot;https://techartnomad.tistory.com/764&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bmH6vT/dJMb8UH2ls5/QBQxEtDu2PKT2rx2qDMDs0/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/byJGDm/dJMb85v16zh/44rziHAjYWtQf912ZAQ8H1/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/N2YQz/dJMb8RR401P/HaZ5vI0oxiPHkr3ISSc511/img.png?width=1376&amp;amp;height=768&amp;amp;face=0_0_1376_768&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/764&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/764&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bmH6vT/dJMb8UH2ls5/QBQxEtDu2PKT2rx2qDMDs0/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/byJGDm/dJMb85v16zh/44rziHAjYWtQf912ZAQ8H1/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/N2YQz/dJMb8RR401P/HaZ5vI0oxiPHkr3ISSc511/img.png?width=1376&amp;amp;height=768&amp;amp;face=0_0_1376_768');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Game Animation Technologies: Technical Comparison&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 리서치 문서는 중국 테크 블로그 및 해외 테크 블로그 자료를 토대로 초안을 정리 하고 AI 를 사용하여 최종문서화 되었습니다.Motion Matching &amp;middot; MotionBricks &amp;middot; UE5 Pose Search본 문서는 현대 게임 애니&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635165320&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[공유] HONAMI ANIMATION SYSTEM for Unity.&quot; data-og-description=&quot;https://github.com/loyal-studio/Honami-Animation-System GitHub - loyal-studio/Honami-Animation-System: Honami Animation System is a complete, from-scratch alternative to Unity's built-Honami Animation System is a complete, from-scratch alternative to Unity&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/795&quot; data-og-url=&quot;https://techartnomad.tistory.com/795&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bh8rSp/dJMb8VNIRab/DkRrKLluYkAE47rt9qibi1/img.png?width=800&amp;amp;height=169&amp;amp;face=0_0_800_169,https://scrap.kakaocdn.net/dn/dhLmm2/dJMb8YXYSqO/IiaQ1cYRvzX9BfrWSOxRZK/img.png?width=800&amp;amp;height=169&amp;amp;face=0_0_800_169,https://scrap.kakaocdn.net/dn/gnySW/dJMb88Gh8Jo/3wV30FJtlRPyDjrYcg48jk/img.jpg?width=340&amp;amp;height=340&amp;amp;face=0_0_340_340&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/795&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/795&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bh8rSp/dJMb8VNIRab/DkRrKLluYkAE47rt9qibi1/img.png?width=800&amp;amp;height=169&amp;amp;face=0_0_800_169,https://scrap.kakaocdn.net/dn/dhLmm2/dJMb8YXYSqO/IiaQ1cYRvzX9BfrWSOxRZK/img.png?width=800&amp;amp;height=169&amp;amp;face=0_0_800_169,https://scrap.kakaocdn.net/dn/gnySW/dJMb88Gh8Jo/3wV30FJtlRPyDjrYcg48jk/img.jpg?width=340&amp;amp;height=340&amp;amp;face=0_0_340_340');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[공유] HONAMI ANIMATION SYSTEM for Unity.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://github.com/loyal-studio/Honami-Animation-System GitHub - loyal-studio/Honami-Animation-System: Honami Animation System is a complete, from-scratch alternative to Unity's built-Honami Animation System is a complete, from-scratch alternative to Unity&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1784635245231&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;&amp;quot;Advanced Horse IK Solution&amp;quot; related of tech for Study lists.&quot; data-og-description=&quot;Artist Shared Tutorial Series on Advanced Horse IK Solution in UE5Muhammad Kashif Ali shared a series of detailed learning videos covering the entire workflow.80.lv주로 엠엠오 알피지 개발에 오랫동안 참여한 탓인지 이런 구현을 해 &quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/609&quot; data-og-url=&quot;https://techartnomad.tistory.com/609&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vUkIV/dJMb83Sv5Lx/2xF57qRNX9JfH8ERmVsOk0/img.png?width=800&amp;amp;height=339&amp;amp;face=0_0_800_339,https://scrap.kakaocdn.net/dn/uMhDN/dJMb9lljZ2A/1uw49wLBmNsNJIq9GtKh61/img.png?width=800&amp;amp;height=339&amp;amp;face=0_0_800_339,https://scrap.kakaocdn.net/dn/b7kwSm/dJMb88fdNOs/nLWWCQ42KtkrtP8nmaZiv0/img.jpg?width=340&amp;amp;height=340&amp;amp;face=0_0_340_340&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/609&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://techartnomad.tistory.com/609&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vUkIV/dJMb83Sv5Lx/2xF57qRNX9JfH8ERmVsOk0/img.png?width=800&amp;amp;height=339&amp;amp;face=0_0_800_339,https://scrap.kakaocdn.net/dn/uMhDN/dJMb9lljZ2A/1uw49wLBmNsNJIq9GtKh61/img.png?width=800&amp;amp;height=339&amp;amp;face=0_0_800_339,https://scrap.kakaocdn.net/dn/b7kwSm/dJMb88fdNOs/nLWWCQ42KtkrtP8nmaZiv0/img.jpg?width=340&amp;amp;height=340&amp;amp;face=0_0_340_340');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;&quot;Advanced Horse IK Solution&quot; related of tech for Study lists.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Artist Shared Tutorial Series on Advanced Horse IK Solution in UE5Muhammad Kashif Ali shared a series of detailed learning videos covering the entire workflow.80.lv주로 엠엠오 알피지 개발에 오랫동안 참여한 탓인지 이런 구현을 해&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;techartnomad.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <category>ANIMATION</category>
      <category>Index</category>
      <category>System</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/816</guid>
      <comments>https://techartnomad.tistory.com/816#entry816comment</comments>
      <pubDate>Tue, 21 Jul 2026 21:04:26 +0900</pubDate>
    </item>
    <item>
      <title>[번역] UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초</title>
      <link>https://techartnomad.tistory.com/815</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 기본 개념&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 지금 걷기/달리기 블렌드 애니메이션을 만들려고 한다고 가정해보자. 만약 애니메이션 블루프린트, 블렌드 스페이스, 상태 머신을 아주 기본적으로만 배웠다면, 만들어지는 결과는 아마 대충 이런 모습일 가능성이 높다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kRMUu/dJMcag0xT0i/wkejWtC69tffrpDXKGLNA0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kRMUu/dJMcag0xT0i/wkejWtC69tffrpDXKGLNA0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kRMUu/dJMcag0xT0i/wkejWtC69tffrpDXKGLNA0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkRMUu%2FdJMcag0xT0i%2FwkejWtC69tffrpDXKGLNA0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;592&quot; height=&quot;246&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;246&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 플레이어의 이동 속도를 사용해서 걷기에서 달리기로 넘어가는 애니메이션 블렌드를 제어하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 완성도 있는 걷기/달리기 블렌드는 그렇게 단순하지 않다. 여기서는 Advanced Locomotion System 안의 걷기/달리기 블렌드를 예로 들어 간단히 이야기해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 몇 가지 개념을 명확히 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보행 상태(Gait)&lt;/b&gt;: 캐릭터가 현재 걷기, 조깅, 전력 질주 세 상태 중 어디에 있는지를 뜻한다. 캐릭터의 보행 상태는 플레이어의 키 입력 제어에만 의존해야 하며, 캐릭터의 현재 이동 속도에 의존해서는 안 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보폭(Stride)&lt;/b&gt;: 캐릭터가 현재 한 걸음을 내딛는 폭을 뜻한다. 같은 시간 안에서 캐릭터의 보폭이 클수록 이동 속도는 더 빨라진다. 반대로 말하면 속도가 빠를수록 보폭도 커져야 한다. 따라서 보폭은 애니메이션이 충분히 자연스럽게 보이도록 반드시 조정해야 하는 값이며, 플레이어의 속도와 연결되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;걸음 빈도/보행 주파수&lt;/b&gt;: 같은 시간 안에서 보폭이 동일하다면, 걸음 빈도가 높을수록 플레이어의 이동 속도는 더 빨라진다. 이 말은 누구나 아는 쓸데없는 소리처럼 보이지만, 사실 중요한 사실 하나를 드러낸다. 즉, 걷기와 달리기는 완전히 같은 속도에서도 서로 다른 보폭을 가질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 단순히 속도만으로 1차원 블렌드 스페이스의 걷기/달리기 블렌드를 제어하면 안 된다고 말하는가? 우선 걷기 애니메이션과 달리기 애니메이션을 직접 1D 블렌드하면 보폭 차이를 제대로 드러낼 수 없다. 걷기 애니메이션도 달리기 애니메이션과 같은 보폭을 가질 가능성이 충분히 있다. 설령 1차원 블렌드 스페이스 축 위에 세 애니메이션&amp;mdash;정지 자세, 걷기 애니메이션, 달리기 애니메이션&amp;mdash;을 올려둔다 해도, 속도가 걷기 속도를 넘지 않을 때에만 속도로 보폭을 제어할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 걸음 빈도도 정확히 제어되어야 한다. 우리는 재생 속도를 사용해 캐릭터의 걸음 빈도를 제어해야지, 걷기와 달리기 애니메이션의 블렌드로 제어해서는 안 된다. (걷기의 걸음 빈도는 달리기보다 느리다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 보폭과 걸음 빈도를 동시에 제어할 수 있는 걷기/달리기 블렌드 애니메이션을 원한다면, 블렌드 스페이스를 이런 식으로 만들어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6YH5B/dJMcaiKPPfW/H8HrdwHObhbSaUf72OctK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6YH5B/dJMcaiKPPfW/H8HrdwHObhbSaUf72OctK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6YH5B/dJMcaiKPPfW/H8HrdwHObhbSaUf72OctK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6YH5B%2FdJMcaiKPPfW%2FH8HrdwHObhbSaUf72OctK1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1057&quot; height=&quot;856&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2022.6.13 업데이트:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀장과 이야기한 뒤, 여기에는 세 가지 디테일이 있다는 것을 깨달았다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;ALS가 Idle &amp;rarr; Walk &amp;rarr; Run 형태의 1차원 블렌드 스페이스를 만들지 않은 이유는, 현실에서 50m 달리기를 할 때의 동작은 처음부터 달리기로 가속해야 하기 때문이다. 만약 먼저 정지에서 &amp;ldquo;걷기&amp;rdquo;로 가속하고, 다시 &amp;ldquo;걷기&amp;rdquo;에서 달리기로 가속한다면 매우 어색해 보인다. 그래서 2차원 블렌드 스페이스로 만들고, 걷기 시작과 달리기 시작을 위아래 두 경로로 나누어야 한다. 물론 걷기와 달리기를 각각 1차원 블렌드 스페이스로 만들고, 다시 Select로 고르는 방식도 가능하다.&lt;/li&gt;
&lt;li&gt;ALS가 블렌드 스페이스의 가장 왼쪽에 둔 것은 Idle 자세가 아니라, 설계된 정적인 자세이며 걷기와 달리기마다 서로 다르다. 이는 Idle에서 곧바로 걷기/달리기로 블렌드하면 약간 어색하고, ALS의 작가는 별도의 출발 애니메이션 리소스를 만들지 않았기 때문이다. 그래서 ALS는 가장 왼쪽 애니메이션을 &amp;ldquo;준비 자세&amp;rdquo;(달리기 전에 취하는 그 준비 자세)로 만들고, 이 준비 자세와 달리기 애니메이션을 보폭 기준으로 블렌드하여 &amp;ldquo;출발&amp;rdquo; 과정을 근사적으로 얻는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/29eS6/dJMcaic8wCm/y62nLHNKE2Kjh3AKZwtAE0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/29eS6/dJMcaic8wCm/y62nLHNKE2Kjh3AKZwtAE0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/29eS6/dJMcaic8wCm/y62nLHNKE2Kjh3AKZwtAE0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F29eS6%2FdJMcaic8wCm%2Fy62nLHNKE2Kjh3AKZwtAE0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;239&quot; height=&quot;483&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Walk/Run이라는 보행 상태 변수를 이용해 걷기-달리기 블렌드를 제어하고, 보폭(Stride)을 이용해 정지 자세-&lt;a href=&quot;https://zhida.zhihu.com/search?content_id=195408821&amp;amp;content_type=Article&amp;amp;match_order=1&amp;amp;q=%E8%BF%90%E5%8A%A8%E5%8A%A8%E7%94%BB&amp;amp;zhida_source=entity&quot;&gt;이동 애니메이션&lt;/a&gt;의 블렌드를 제어한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재생 속도는 블렌드 스페이스 플레이어 노드에서 핀으로 노출해야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5xDG3/dJMcag0xT0h/qTTpAkQafIAJy7dTvryoS1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5xDG3/dJMcag0xT0h/qTTpAkQafIAJy7dTvryoS1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5xDG3/dJMcag0xT0h/qTTpAkQafIAJy7dTvryoS1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5xDG3%2FdJMcag0xT0h%2FqTTpAkQafIAJy7dTvryoS1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1076&quot; height=&quot;413&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 변수에 기대면, 우리는 일단 비교적 자연스러운(최초의 원시적인 방식보다는 자연스럽다는 의미의) 걷기/달리기 블렌드 애니메이션을 만들 수 있다. (가속할 때의 무게중심 전방 기울기, 방향 전환 시 무게중심 이동, 8방향 이동 블렌드 등은 뒤에서 다시 이야기하자.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 이 세 값을 어떻게 계산할지만 생각하면 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 세 값의 계산&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1 WalkRunBlend(보행 상태)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 걷기/달리기 블렌드&amp;mdash;WalkRunBlend를 계산한다. 앞에서 말했듯이 보행 상태는 이동 속도가 아니라 플레이어의 키 입력 제어에만 의존해야 한다. 따라서 WalkRunBlend의 값이 0인지 1인지를 정하려면, 현재 플레이어의 키 입력이 내린 명령이 달리기인지 걷기인지 판단하기만 하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 캐릭터 블루프린트에 이런 코드를 작성할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vTuEo/dJMcaic8wCo/okGkC0kRUhMmYZnHNE9tW0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vTuEo/dJMcaic8wCo/okGkC0kRUhMmYZnHNE9tW0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vTuEo/dJMcaic8wCo/okGkC0kRUhMmYZnHNE9tW0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvTuEo%2FdJMcaic8wCo%2FokGkC0kRUhMmYZnHNE9tW0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;956&quot; height=&quot;570&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 애니메이션 블루프린트에서 Gait 값을 읽으면, 이때 플레이어가 내린 이동 명령을 판단할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyLxYH/dJMcaic8wCl/i77lXuweS0iXGWEPokbt5k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyLxYH/dJMcaic8wCl/i77lXuweS0iXGWEPokbt5k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyLxYH/dJMcaic8wCl/i77lXuweS0iXGWEPokbt5k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyLxYH%2FdJMcaic8wCl%2Fi77lXuweS0iXGWEPokbt5k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;839&quot; height=&quot;357&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리의 걷기/달리기 블렌드 스페이스에는 walk와 run 두 종류의 애니메이션만 사용되며, 전력 질주(Sprint) 애니메이션은 사용하지 않는다. 그래서 현재는 임시로 전력 질주와 달리기를 모두 run으로 보고 반환값을 1로 둔다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2 보폭&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터가 정지 상태에서 움직이기 시작할 때, 속도는 먼저 빨라졌다가 나중에 느려지는 식으로 변화한다. 예를 들어 정지 &amp;rarr; 걷기, 정지 &amp;rarr; 달리기가 그렇다. 속도가 점차 올라가는 과정에서 같은 보폭의 애니메이션만 사용하면 부자연스럽게 보인다. 앞에서 말했듯 같은 시간 안에서는 보폭이 클수록 이동 속도도 커져야 한다. 그런데 이렇게 가속하는 과정에서 속도는 변하는데 보폭은 변하지 않는다면, 당연히 자연스럽지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 속도의 상승에 따라 보폭도 함께 상승하는 함수를 설계해야 한다. 보폭이 속도 증가에 따라 선형적으로 증가하게 해도 되지만, ALSV4 시스템에서는 커브를 사용해 이를 묘사한다. 우리는 그냥 그 커브를 직접 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 그림은 달리기 보행 상태에서 속도 변화에 따른 보폭 커브다. (걷기 애니메이션과 달리기 애니메이션은 원래부터 기본 보폭과 보행 빈도가 다르기 때문에, 걷기 보행 상태의 보폭 커브와 달리기 보행 상태의 보폭 커브는 각각 따로 만들어야 한다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dLgeUe/dJMcag0xT0e/wnBrEqQ1NYcGJ1BQLttQVK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dLgeUe/dJMcag0xT0e/wnBrEqQ1NYcGJ1BQLttQVK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dLgeUe/dJMcag0xT0e/wnBrEqQ1NYcGJ1BQLttQVK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdLgeUe%2FdJMcag0xT0e%2FwnBrEqQ1NYcGJ1BQLttQVK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1350&quot; height=&quot;836&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 문제는 우리가 어느 보폭 커브를 사용할지 결정해야 한다는 점이다. 다시 말해 지금 캐릭터가 걷고 있는지 달리고 있는지를 판단해야 한다. 이 질문에 답하는 것은 아주 간단하다. 이전 절의 보행 상태(Gait) 변수를 이용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림처럼, 먼저 걷기/달리기 보폭 커브 리소스 인스턴스를 가져오고, 캐릭터의 구체적인 이동 속도에 따라 대응하는 보폭 크기를 얻은 뒤, 보행 상태가 걷기인지 달리기인지 전력 질주인지, 서 있는 상태가 서기인지 웅크리기인지에 따라 어느 보폭 커브를 사용할지 결정한다&amp;hellip;&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOYy1F/dJMcadCGpSs/cA1hJGbklZSosxRvcuLwM1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOYy1F/dJMcadCGpSs/cA1hJGbklZSosxRvcuLwM1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOYy1F/dJMcadCGpSs/cA1hJGbklZSosxRvcuLwM1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOYy1F%2FdJMcadCGpSs%2FcA1hJGbklZSosxRvcuLwM1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;745&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 가능한 방법이다. 하지만 이렇게 하면 유연성이 약간 부족하고, 또 한 가지 문제가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 우리의 로직은 이렇다. 키 입력 명령 &amp;rarr; 보행 상태 변수(Gait) &amp;rarr; 사용하는 애니메이션 시퀀스. 여기에는 작은 문제가 있다. 보행 상태 변수는 열거형 값이고, 상태가 몇 개뿐이다. 걷기 아니면 달리기다. 만약 보행 상태에 따라 사용할 보폭 커브가 걷기인지 달리기인지 결정한다면, 사실 별 문제는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 우리가 사용하는 것은 애니메이션 시퀀스가 아니라 블렌드 스페이스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 걷기 보폭 커브와 달리기 보폭 커브만으로는 충분하지 않다. 우리는 걷기와 달리기 사이에 놓인 중간 상태의 보폭 커브가 필요하다. 따라서 보행 상태(Gait)로 두 보폭 커브 중 하나를 직접 선택해서는 안 되고, 걷기 보폭 커브와 달리기 보폭 커브를 &lt;a href=&quot;https://zhida.zhihu.com/search?content_id=195408821&amp;amp;content_type=Article&amp;amp;match_order=1&amp;amp;q=%E6%8F%92%E5%80%BC&amp;amp;zhida_source=entity&quot;&gt;보간&lt;/a&gt;하여 중간 상태를 얻어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7r0GI/dJMcaic8wCn/zIyb8On1RghK6fZ3X8yO7K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7r0GI/dJMcaic8wCn/zIyb8On1RghK6fZ3X8yO7K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7r0GI/dJMcaic8wCn/zIyb8On1RghK6fZ3X8yO7K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7r0GI%2FdJMcaic8wCn%2FzIyb8On1RghK6fZ3X8yO7K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1288&quot; height=&quot;834&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 이제 문제는 이렇게 바뀐다. 캐릭터가 걷기/달리기 전환을 할 때, 애니메이션이 구체적으로 Walk/Run이라는 &lt;a href=&quot;https://zhida.zhihu.com/search?content_id=195408821&amp;amp;content_type=Article&amp;amp;match_order=1&amp;amp;q=%E5%9E%82%E7%9B%B4%E8%BD%B4&amp;amp;zhida_source=entity&quot;&gt;수직축&lt;/a&gt;의 어느 위치에 있는지를 우리는 어떻게 알 수 있는가? 이 값은 걷기 보폭 커브와 달리기 보폭 커브를 보간할 때 양쪽의 가중치를 직접 결정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답은 **【커브】**다. (애니메이션 시퀀스 안의 커브다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커브라는 것은 애니메이션 블루프린트에서 가져올 수 있다. (찾고자 하는 커브 이름만 알고 있다면.) 블렌드 스페이스는 기본적으로 애니메이션 안의 커브도 함께 블렌드한다. 따라서 걷기 애니메이션에 Weight_Gait라는 이름의 커브를 추가하고 그 값을 항상 1로 두며, 달리기 애니메이션에도 같은 이름의 Weight_Gait 커브를 추가하고 그 값을 항상 2로 두면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;665&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3RbiY/dJMcaic8wCq/aYziIN9THgumKbgI8A4QvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3RbiY/dJMcaic8wCq/aYziIN9THgumKbgI8A4QvK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3RbiY/dJMcaic8wCq/aYziIN9THgumKbgI8A4QvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3RbiY%2FdJMcaic8wCq%2FaYziIN9THgumKbgI8A4QvK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;665&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 걷기/달리기 전환 시 블렌드 스페이스의 녹색 애니메이션 포인터가 아래에서 위로 이동할 때, 이 커브 값도 블렌드에 의해 1에서 2로 변화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 블루프린트는 이렇게 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커브 값이 1에서 2로 변하므로, 여기서 1을 빼서 0에서 1로 변하는 값으로 바꾼다. 이 0~1 범위의 커브 값이 걷기 보폭 커브와 달리기 보폭 커브의 블렌드 정도를 결정할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGDj4j/dJMcaic8wCs/HKX0cKf3UjfPl92p2uumrK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGDj4j/dJMcaic8wCs/HKX0cKf3UjfPl92p2uumrK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGDj4j/dJMcaic8wCs/HKX0cKf3UjfPl92p2uumrK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGDj4j%2FdJMcaic8wCs%2FHKX0cKf3UjfPl92p2uumrK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1345&quot; height=&quot;774&quot; data-origin-width=&quot;1345&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;【블렌드 스페이스 기초에 대한 여담】어떤 독자는 이렇게 의문을 가질 수도 있다. &amp;ldquo;내가 달리기 키를 누르면 보행 상태가 바로 Gait == Run으로 바뀌는 것 아닌가? 그러면 내가 넘겨주는 Walk/Run 값은 1이어야 하는데, 어떻게 중간 상태가 생기지?&amp;rdquo; 답은, 블렌드 스페이스 안의 이 녹색 애니메이션 포인터는 가로축과 세로축 값이 바뀔 때 점프하듯 바로 이동하는 것이 아니라, 보간되어 이동한다는 것이다. 왼쪽 패널에서 가로축과 세로축의 보간 시간, 보간 방식을 모두 설정할 수 있다. 그래서 실제로 걷기/달리기 전환 시에는 &amp;ldquo;중간 상태&amp;rdquo;가 존재한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.3 보행 빈도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보행 빈도의 계산 방식은 아주 간단하다. 캐릭터의 현재 속도를, 현재 대응하는 보행 상태의 최고 속도로 나누면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, CurrentSpeed / CurrentMaxSpeed다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자연스럽게도 보행 빈도 계산 역시 보폭에서와 비슷한 문제를 만난다. 걷기/달리기 보행 상태가 전환되는 과정에서, 보행 빈도도 블렌드 스페이스의 걷기/달리기 보행 상태 블렌드처럼 함께 블렌드되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결 방법도 커브를 사용하는 것이다. 여기서는 커브에서 값을 얻고 0~1로 매핑하는 부분을 매크로로 만들어두었으므로, 자세히 설명하지 않겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;811&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IH1Mn/dJMcag0xT0j/wFSdaEoSSFlVk5dr3KAYX1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IH1Mn/dJMcag0xT0j/wFSdaEoSSFlVk5dr3KAYX1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IH1Mn/dJMcag0xT0j/wFSdaEoSSFlVk5dr3KAYX1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIH1Mn%2FdJMcag0xT0j%2FwFSdaEoSSFlVk5dr3KAYX1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1411&quot; height=&quot;811&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;811&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞부분은 걷기/달리기 블렌드 정도를 결정하는 데 사용하고, 뒷부분은 달리기와 전력 질주의 블렌드 정도를 결정하는 데 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 하면, 우리는 최초의 생각보다 조금 더 자연스러워 보이는 걷기/달리기 블렌드 애니메이션을 일단 만들 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/76ZIu/dJMcadCGpSq/6kuQMquN2cADRYwOvrz881/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/76ZIu/dJMcadCGpSq/6kuQMquN2cADRYwOvrz881/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/76ZIu/dJMcadCGpSq/6kuQMquN2cADRYwOvrz881/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F76ZIu%2FdJMcadCGpSq%2F6kuQMquN2cADRYwOvrz881%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;988&quot; height=&quot;370&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;맺음말&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 필자가 &lt;a href=&quot;https://www.zhihu.com/people/6e0f0f37e048b0ec8bcb9d7d48fb5c02&quot;&gt;@五谷延年&lt;/a&gt; 선배가 B站(그리고 冲呀 플랫폼)에 올린 고급 로코모션 시스템 튜토리얼을 공부하는 과정에서, 튜토리얼에 약간 부족한 점이 있다고 느낀 데서 출발했다. 예를 들어 36강의 걷기/달리기 블렌드 부분에서는, 이 노드들을 왜 이렇게 구성하는지에 대한 이념을 충분히 설명하지 못했고, 그래서 필자가 공부할 때 적지 않은 혼란이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 필자는 튜토리얼을 모든 면에서 빠짐없이 만들려면 마음도 힘도 많이 들 뿐 아니라 현실적으로 어렵다는 것을 잘 알고 있다. 필자는 五谷延年 선배가 UE 커뮤니티에 사심 없이 기여한 이 튜토리얼에 매우 감사하고 있으며, 무슨 불평을 하려는 것도 아니다. 그래서 이 글을 썼다. 어디까지나 五谷延年 선배 튜토리얼에 대한 아주 작은 보충이라고 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 본 독자는 가능하다면 손 가는 김에 &lt;b&gt;좋아요와 즐겨찾기(그리고 가능하면 좋아요 버튼도 하나 더)를 눌러주면 좋겠다. 이건 나에게 정말 중요하다 = =&lt;/b&gt;! 앞으로도 골격 애니메이션 관련 튜토리얼과 생각 공유가 더 있을 예정이니, &lt;b&gt;팔로우&lt;/b&gt;해두면 업데이트를 놓치지 않을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;955&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGObYD/dJMcaic8wCk/qKiGkI2A7OE1XCr7NR0Hvk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGObYD/dJMcaic8wCk/qKiGkI2A7OE1XCr7NR0Hvk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGObYD/dJMcaic8wCk/qKiGkI2A7OE1XCr7NR0Hvk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGObYD%2FdJMcaic8wCk%2FqKiGkI2A7OE1XCr7NR0Hvk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1347&quot; height=&quot;955&quot; data-origin-width=&quot;1347&quot; data-origin-height=&quot;955&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 골격 애니메이션에 관심 있는 독자라면, B站에서 五谷延年 선배의 무료 튜토리얼도 꼭 한번 공부해보기를 매우 환영한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.bilibili.com/video/BV12f4y1r71N/?p=53&amp;amp;spm_id_from=333.851.header_right.history_list.click&quot;&gt;36 고급 로코모션 시스템 해체 - 이동 보폭과 걷기/달리기 블렌드_哔哩哔哩_bilibili&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsYDS5/dJMcaiKPPfV/IkwD8aookoyxTwKxWWdVR1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsYDS5/dJMcaiKPPfV/IkwD8aookoyxTwKxWWdVR1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsYDS5/dJMcaiKPPfV/IkwD8aookoyxTwKxWWdVR1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsYDS5%2FdJMcaiKPPfV%2FIkwD8aookoyxTwKxWWdVR1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;300&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PS: 덧붙여 여기서 필자가 막 만든 &lt;b&gt;UE 골격 애니메이션 교류방&lt;/b&gt;을 살짝 광고한다. &lt;b&gt;916274600&lt;/b&gt; 각위 대佬들의 매서운 지적을 환영합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbJFeR/dJMcag0xT0f/K4Ky49eZbEkQHcVOeRIRD1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbJFeR/dJMcag0xT0f/K4Ky49eZbEkQHcVOeRIRD1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbJFeR/dJMcag0xT0f/K4Ky49eZbEkQHcVOeRIRD1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbJFeR%2FdJMcag0xT0f%2FK4Ky49eZbEkQHcVOeRIRD1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;326&quot; height=&quot;377&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차: &lt;a href=&quot;https://zhuanlan.zhihu.com/p/518724305&quot;&gt;UE4 UE5 골격 애니메이션 고급 로코모션 시스템(ALSV4) - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글: &lt;a href=&quot;https://zhuanlan.zhihu.com/p/489653380&quot;&gt;UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;사람이 꽤 많네&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eElJIz/dJMcaic8wCp/YAKqtumyzVdcNm3krvW2I1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eElJIz/dJMcaic8wCp/YAKqtumyzVdcNm3krvW2I1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eElJIz/dJMcaic8wCp/YAKqtumyzVdcNm3krvW2I1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeElJIz%2FdJMcaic8wCp%2FYAKqtumyzVdcNm3krvW2I1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8emYF/dJMcadCGpSr/yNtzXEyIetsKCI1W2Tqk0K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8emYF/dJMcadCGpSr/yNtzXEyIetsKCI1W2Tqk0K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8emYF/dJMcadCGpSr/yNtzXEyIetsKCI1W2Tqk0K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8emYF%2FdJMcadCGpSr%2FyNtzXEyIetsKCI1W2Tqk0K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnqEsG/dJMcaic8wCr/vWawWJD3UuGH67DKEPiJqk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnqEsG/dJMcaic8wCr/vWawWJD3UuGH67DKEPiJqk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnqEsG/dJMcaic8wCr/vWawWJD3UuGH67DKEPiJqk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnqEsG%2FdJMcaic8wCr%2FvWawWJD3UuGH67DKEPiJqk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s7D9q/dJMcag0xT0g/QTpNgOvQSKedo1HSt3mhf0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s7D9q/dJMcag0xT0g/QTpNgOvQSKedo1HSt3mhf0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s7D9q/dJMcag0xT0g/QTpNgOvQSKedo1HSt3mhf0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs7D9q%2FdJMcag0xT0g%2FQTpNgOvQSKedo1HSt3mhf0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타카기, 나한테 먹여줘! (간청)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bThTjq/dJMcaic8wCj/rcSNvQK3PHw8BdwQMes2Pk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bThTjq/dJMcaic8wCj/rcSNvQK3PHw8BdwQMes2Pk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bThTjq/dJMcaic8wCj/rcSNvQK3PHw8BdwQMes2Pk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbThTjq%2FdJMcaic8wCj%2FrcSNvQK3PHw8BdwQMes2Pk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;810&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타카기, 나한테 먹여줘! (간청)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문&lt;br /&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/482748722&quot;&gt;(77 封私信 / 85 条消息) UE4/UE5 骨骼动画 高级运动系统 走跑混合初步 - 知乎&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <category>ALS</category>
      <category>technical animation</category>
      <category>Unreal Engine</category>
      <category>v4</category>
      <category>로코모션</category>
      <category>언리얼엔진</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/815</guid>
      <comments>https://techartnomad.tistory.com/815#entry815comment</comments>
      <pubDate>Tue, 21 Jul 2026 20:57:39 +0900</pubDate>
    </item>
    <item>
      <title>[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템 (ALSV4)</title>
      <link>https://techartnomad.tistory.com/812</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;역자 남김: 맨날 렌더링쪽만 하다가 애니메이션쪽을 하려다보니 공부할 것들이 많은 것 같아서... ALS 와 GASP 둘 다 좀 파봐야겠나~ 싶어서 말이죠. 먼저 연구한 분들의 피가 되고 살이되는 포스팅 위주로 공부하면서 공유 하려고 합니다. 거의 20년을 렌더링만 해서... 아는게 없다는 말이죠. ㅎㅎㅎ&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;저자: DarkFlameMaster&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. ALSV4가 뭐냐?&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;고급 로코모션 시스템(Advanced Locomotion System, 줄여서 ALS)은 고품질 캐릭터 애니메이션과 반응성 있는 움직임에 초점을 맞춘, 꽤 선진적인 이족 보행 및 레이어링 시스템이다. 현재 4세대인 ALSV4는 언리얼 마켓플레이스에서 이미 무료로 풀려 있다.&lt;br&gt;사실 이 이미지를 글 표지로 쓰면 더 많은 사람이 보러 올 거라는 건 알지만, 그래도 참지 못하고 이차원풍 표지를 써버렸다 = =&lt;br&gt;&lt;br&gt;고급 로코모션 시스템은 걷기, 달리기, 전력 질주, 웅크리기, 구르기, 등반 등 여러 기본 동작 모드를 지원한다. 동시에 보폭과 보행 빈도, 이동 중 자세 기울기, 제자리 회전, 출발과 급정지, 달리는 중 예각 방향 전환, 카메라 팔로우 관리, 착지 시 다리 완충, 조준 오프셋, 다리와 손 IK 등 풍부하고 뛰어난 움직임 디테일도 갖추고 있다. 알아둘 것은, &lt;b&gt;일부 3A 액션 게임조차 이 정도로 풍부한 움직임 디테일을 갖추지 못한 경우가 있다&lt;/b&gt;는 점이다.&lt;br&gt;게다가 이것은 순수 블루프린트로 구현되어 있어서, 기획자라도 한번 배워보고 적용해볼 수 있다. (사실 ALS의 원작자 본인도 아트 출신이다.)&lt;br&gt;ALS 플러그인의 작가는 너무 강력했던 나머지 Epic에 스카우트되어 언리얼 5를 만들러 갔다. 최근 언리얼 5에서 제공하는 초심자용 프로젝트(하지만 실제 난이도는 전혀 초심자용이 아닌) Lyra의 애니메이션 파트도, 듣기로는 ALS 작가가 직접 나서서 만든 것 같다. 관심 있는 독자는 @quabqi 따로(大佬)의 새 글을 참고해도 좋다.&lt;br&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/517368184&quot; target=&quot;_self&quot;&gt;&lt;span&gt;UE5의 애니메이션 블루프린트(Lyra 프로젝트) - 知乎 (zhihu.com)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;blockquote data-ke-style=&quot;style3&quot;&gt;보통 중국에서 大佬(따라오) 라고 지칭하는건 큰늙은이 뜻은 아니고 경력있는 시니어 레벨 정도를 중국인들이 그들만의 느낌으로 지칭할 때 쓰는 말 중 하나임. 좀 더 존경하는 시니어의 경우 大神(da shen) 이렇게 큰 신으로 지칭하기도 한다.&lt;/blockquote&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 이 시리즈 글은 뭘 하려는 건가?&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;ALSV4가 무료가 되었다고는 해도, 이 플러그인의 복잡도는 여전히 상당히 높다. 작가가 플러그인 안에 주석을 많이 써두기는 했지만, 플러그인을 그대로 붙잡고 생으로 뜯어먹는 것은 여전히 난도가 좀 있다.&lt;br&gt;그렇다면 이 시리즈 글의 목적은 모두에게 ALSV4를 어떻게 쓰는지, 혹은 어떻게 배우는지를 가르치는 것인가?&lt;br&gt;아니다. 그렇지 않다.&lt;br&gt;지금에 와서는 인터넷에 ALS를 설명하는 글이나 영상 강좌가 이미 꽤 많이 나와 있다. 앞사람들이 이미 좋은 옥구슬을 깔아둔 상황에서, 필자는 식견도 얕고 능력도 부족하며, 또 굳이 같은 포지션의 튜토리얼을 하나 더 쓰고 싶은 생각도 없다.&lt;br&gt;이 시리즈 글의 의도는 ALSV4의 여러 방법이 “무엇인가”를 설명하는 데 있지 않고, &lt;b&gt;“왜 그렇게 하는가”를 설명하는 데 있다.&lt;/b&gt;&lt;br&gt;나중에 애니메이션을 만들 때, 우리는 당연히 ALSV4의 방식을 단순히 베껴 쓰기만 할 수는 없다. 프로젝트에서 ALSV4 플러그인을 사용한다 해도, 결국 그 위에서 수정하고 확장해야 한다. 그런데 이 부분은 왜 이렇게 했는지, 저 상태 노드는 왜 저기에 놓였는지, 이 전이 조건은 왜 이렇게 구성되었는지를 모른다면—수정하는 과정에서 자기도 모르게 ALSV4가 만들어낸 원래의 움직임 표현을 망가뜨리고, 결국 버그를 한 무더기 만들어내게 될 것이다.&lt;br&gt;여기서 필자는 다시 한번 @大钊 선배의 그 말을 인용하고 싶다.&lt;/p&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt; 
 &lt;p data-ke-size=&quot;size16&quot;&gt;필자는 늘 어떤 것을 제대로 설명하려면, 그 뒤에 있는 여러 개념을 더 많이 설명해야 한다고 생각한다. 그렇지 않고 소스 코드를 앞에 두고 각 클래스를 나열하고, 각 인터페이스의 역할을 말하고, 데이터가 서로 어떻게 참조되고 흐름이 어떻게 도는지만 설명하면, 너는 아주 빠르게 많은 정보를 알게 될 수 있다. 하지만 너는 What과 How만 알게 된 것이다. 그러면 다른 사람이 “왜?”라고 한마디 묻는 것을 막을 수 없다.&lt;/p&gt; 
&lt;/blockquote&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 “왜 ALS의 Locomotion States 상태 머신 안에 있는 Stop States 상태 머신에서는 반드시 ‘첫 업데이트 전이 건너뛰기’를 False로 설정해야 하는가?”라든가, “왜 8방향 이동 상태 머신의 각 노드 내부에서 또 하나의 멀티 핀 블렌드를 해야 하는가?” 같은 세부 처리는 일반적인 ALS 복각 튜토리얼에서는 거의 언급되지 않는다.&lt;br&gt;“왜”는 중요하다. 하지만 지면의 한계나 작가 본인의 소홀함 때문에, ALSV4 블루프린트 주석이나 인터넷의 여러 ALSV4 튜토리얼에서 이 “왜”가 항상 잘 설명되는 것은 아니다. 그래서 필자는 이 시리즈 글을 쓰게 되었다. 필자가 ALSV4에 대해 가진 우물 안 개구리 같은 견해를 나누는 과정에서, 독자 여러분과 함께 배우고 함께 진보할 수 있기를 바란다. 필자는 배운 지 오래되지 않았고 수준도 한정되어 있으므로, 글 안에 틀리거나 빠진 부분이 있는 것은 피하기 어렵다. 부디 여러 독자 대佬들께서 비판하고 지적해주시기를 바란다.&lt;br&gt;(첫 번째 문제의 답은, 그렇게 하지 않으면 Stop States 상태 머신 아래의 두 Plant Foot 상태로 전이할 때 떨림이 발생하기 때문이다. “첫 업데이트 전이 건너뛰기” 옵션은 상태 머신에 진입할 때 조건에 맞는 가장 먼 도달 가능 상태를 검사하고, 곧바로 그 상태를 100% 가중치로 상태 머신을 시작한다. 하지만 어떤 때에는 들어오자마자 바로 그 상태로 “순간이동”하기를 원하지 않고, 시작점에서부터 자연스럽게 전이되기를 원한다. 상태 머신 위쪽의 두 Lock Foot 상태가 떨리지 않는 이유는, 그것들 자체가 Moving 상태와 맞닿아 있고, 따라서 전이 시간이 0이기 때문이다.)&lt;br&gt;(두 번째 문제의 답은, 이 멀티 핀 블렌드가 8방향 이동 자체를 만드는 데에는 도움을 주는 것이 그렇게 분명하지 않지만, 우리가 W를 누른 채 마우스로 캐릭터를 빠르게 빙빙 돌릴 때 캐릭터 발에서 생기는 슬라이딩 현상을 효과적으로 줄여줄 수 있기 때문이다.)&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 목차&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;최신 업데이트:&lt;/b&gt;&lt;br&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/680719803&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://zhuanlan.zhihu.com/p/680719803&lt;/span&gt;&lt;/a&gt;&lt;br&gt;예전에 큰 구덩이를 파놓고 결국 글 하나만 쓰고 덮어버린 일이 있었기 때문에…… 이번에는 3편을 쓰고 나서야 감히 연재를 시작한다고 말하게 되었다 = =&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;[번역] UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/815&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bCMpR6/dJMb9ia3170/ee9X9GAkJiEYDczcPJkmsK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/bh4muA/dJMb9iITMbO/QItoAkbk1462yxI4XtckrK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/yFeFD/dJMb87N9UeP/rQhpu0BJcv6Lgb3Zkjruy0/img.jpg?width=1057&amp;amp;height=856&amp;amp;face=0_0_1057_856&quot; data-og-url=&quot;https://techartnomad.tistory.com/815&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/815&quot; target=&quot;_blank&quot; data-source-url=&quot;https://techartnomad.tistory.com/815&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bCMpR6/dJMb9ia3170/ee9X9GAkJiEYDczcPJkmsK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/bh4muA/dJMb9iITMbO/QItoAkbk1462yxI4XtckrK/img.jpg?width=800&amp;amp;height=518&amp;amp;face=0_0_800_518,https://scrap.kakaocdn.net/dn/yFeFD/dJMb87N9UeP/rQhpu0BJcv6Lgb3Zkjruy0/img.jpg?width=1057&amp;amp;height=856&amp;amp;face=0_0_1057_856')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;[번역] UE4/UE5 골격 애니메이션 고급 로코모션 시스템: 걷기/달리기 블렌드 기초&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;techartnomad.tistory.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/817&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ckWm7o/dJMb8QeziKC/SrlHwnstUBsFY2TBJTfTYk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ckep5o/dJMb8RkfeWg/BBVzE4kF0m2wnGOR4efRDk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bggOFH/dJMb8SXK13v/1QjMECkYayfZJ6M2uPLJ60/img.jpg?width=1440&amp;amp;height=1080&amp;amp;face=0_0_1440_1080&quot; data-og-url=&quot;https://techartnomad.tistory.com/817&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/817&quot; target=&quot;_blank&quot; data-source-url=&quot;https://techartnomad.tistory.com/817&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ckWm7o/dJMb8QeziKC/SrlHwnstUBsFY2TBJTfTYk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ckep5o/dJMb8RkfeWg/BBVzE4kF0m2wnGOR4efRDk/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bggOFH/dJMb8SXK13v/1QjMECkYayfZJ6M2uPLJ60/img.jpg?width=1440&amp;amp;height=1080&amp;amp;face=0_0_1440_1080')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 8방향 이동&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;techartnomad.tistory.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 제자리 회전&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/820&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnf7ti/dJMb8ZvOExc/XTGix0KhUNGqkIXNzXISrK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/b0kqO1/dJMb8SpVhFj/zR86lYfBpbdwmXElTykvIK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/cNwvqu/dJMb8WMCTHy/QgreXN5P3aO5x5eabWQB10/img.png?width=914&amp;amp;height=450&amp;amp;face=0_0_914_450&quot; data-og-url=&quot;https://techartnomad.tistory.com/820&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/820&quot; target=&quot;_blank&quot; data-source-url=&quot;https://techartnomad.tistory.com/820&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnf7ti/dJMb8ZvOExc/XTGix0KhUNGqkIXNzXISrK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/b0kqO1/dJMb8SpVhFj/zR86lYfBpbdwmXElTykvIK/img.gif?width=640&amp;amp;height=304&amp;amp;face=0_0_640_304,https://scrap.kakaocdn.net/dn/cNwvqu/dJMb8WMCTHy/QgreXN5P3aO5x5eabWQB10/img.png?width=914&amp;amp;height=450&amp;amp;face=0_0_914_450')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 제자리 회전&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;techartnomad.tistory.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 점프&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&quot; data-og-host=&quot;techartnomad.tistory.com&quot; data-og-source-url=&quot;https://techartnomad.tistory.com/821&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lRzFr/dJMb8WMCZxv/r9kFivK4YzanMKqgeDQE20/img.png?width=1440&amp;amp;height=617&amp;amp;face=0_0_1440_617&quot; data-og-url=&quot;https://techartnomad.tistory.com/821&quot;&gt;&lt;a href=&quot;https://techartnomad.tistory.com/821&quot; target=&quot;_blank&quot; data-source-url=&quot;https://techartnomad.tistory.com/821&quot;&gt;&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lRzFr/dJMb8WMCZxv/r9kFivK4YzanMKqgeDQE20/img.png?width=1440&amp;amp;height=617&amp;amp;face=0_0_1440_617')&quot;&gt; &lt;/div&gt;&lt;div class=&quot;og-text&quot;&gt;&lt;p class=&quot;og-title&quot;&gt;[번역] UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 점프&lt;/p&gt;&lt;p class=&quot;og-desc&quot;&gt;저자: DarkFlameMaster최근 언리얼 엔진의 골격 애니메이션 관련 지식을 공부하고 있다. 가르치면서 배우자는 생각으로, 여기서 애니메이션 관련 글을 좀 써서 방금 배운 것을 바로 팔아먹어보려 한&lt;/p&gt;&lt;p class=&quot;og-host&quot;&gt;techartnomad.tistory.com&lt;/p&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/547321935&quot; target=&quot;_self&quot;&gt;&lt;span&gt;UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 발 IK - 知乎 (zhihu.com)&lt;/span&gt;&lt;/a&gt;&lt;br&gt;[UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 카메라 관리 - 知乎 (&lt;a href=&quot;http://zhihu.com&quot; target=&quot;_self&quot;&gt;&lt;span&gt;zhihu.com&lt;/span&gt;&lt;/a&gt;)](&lt;a href=&quot;https://zhuanlan.zhihu.com/p/565763264?)&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://zhuanlan.zhihu.com/p/565763264?)&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/568124406&quot; target=&quot;_self&quot;&gt;&lt;span&gt;UE4 UE5 골격 애니메이션 고급 로코모션 시스템: 손 IK / 버추얼 본 - 知乎 (zhihu.com)&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/653171929&quot; target=&quot;_self&quot;&gt;&lt;span&gt;UE5 골격 애니메이션 정지 동작 방안 탐구 - 知乎 (zhihu.com)&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/680719803&quot; target=&quot;_self&quot;&gt;&lt;span&gt;UE4 UE5 고급 로코모션 시스템 ALS 회전 - 知乎 (zhihu.com)&lt;/span&gt;&lt;/a&gt;&lt;br&gt;ALSV4를 빌려 애니메이션에서 커브의 응용을 이야기하기 (아직 구상 중)&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 후기(감사와 잡담)&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 ALSV4의 작가가 이 플러그인을 무료로 공개하여 많은 개발자가 배울 수 있게 해준 것에 감사한다.&lt;br&gt;다음으로 @五谷延年 선배가 冲呀 플랫폼과 B站에 올린 시리즈 튜토리얼에도 감사드린다. (현재는 전부 무료가 되었으며, 여건이 되는 독자는 꼭 코인과 충전으로 응원해주시길 바란다.) 이 튜토리얼은 말하자면 나의 골격 애니메이션 입문 튜토리얼이었다. 과장 조금도 없이 말하자면, 五谷延年 선배의 이 튜토리얼이 없었다면 이 시리즈 글도 없었을 것이다.&lt;br&gt;&lt;a href=&quot;https://www.bilibili.com/video/BV12f4y1r71N/&quot; target=&quot;_self&quot;&gt;&lt;span&gt;虚幻4（UE4） 动画技术 深入浅出 高级运动系统_哔哩哔哩_bilibili&lt;/span&gt;&lt;/a&gt;&lt;br&gt;마지막으로 B站의 업主, 浅唱不会UE의 고급 로코모션 시스템 복각 튜토리얼도 함께 추천한다. 설명이 매우 성실하고 자세하다. 정말 보기 드문 좋은 튜토리얼이다.&lt;br&gt;&lt;a href=&quot;https://www.bilibili.com/video/BV1ja41197XQ/&quot; target=&quot;_self&quot;&gt;&lt;span&gt;关于高级运动系统复刻与解耦_哔哩哔哩_bilibili&lt;/span&gt;&lt;/a&gt;&lt;br&gt;창작자들에게 좋아요를 눌러주는 모든 분께 감사드린다.&lt;br&gt;후속 글은 제2절의 목차에 차례차례 업데이트할 예정이다. 관심이 있다면 팔로우하거나 이 글을 즐겨찾기해두면 된다. (물론 경험상 즐겨찾기한 뒤에는 보통 다시 열지 않는다는 것이 증명되긴 했지만.)&lt;br&gt;그럼 우리는, 다음에 또 만나자!&lt;br&gt;PS: 덧붙여 여기서 필자가 막 만든 &lt;b&gt;UE 골격 애니메이션 교류방&lt;/b&gt;을 살짝 광고한다. &lt;b&gt;916274600&lt;/b&gt; 각위 대佬들의 매서운 지적을 환영합니다.&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <category>ALS</category>
      <category>gasp</category>
      <category>Unreal Engine</category>
      <category>로코모션</category>
      <category>애니메이션 시스템</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/812</guid>
      <comments>https://techartnomad.tistory.com/812#entry812comment</comments>
      <pubDate>Tue, 21 Jul 2026 20:57:26 +0900</pubDate>
    </item>
    <item>
      <title>Systemic Shader Reduction: How We Cut Fortnite&amp;rsquo;s Shaders by 68% | Unreal Fest Chicago 2026</title>
      <link>https://techartnomad.tistory.com/814</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=wobQ8ZKQpbc&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/ddsenM/dJMb8QezbdY/eVSKkm0bNXeRlLTww1WAj1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/YYyTa/dJMb8Z3Et6K/CoyELYWxP3gq4Cc8YUgIk1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Systemic Shader Reduction: How We Cut Fortnite&amp;rsquo;s Shaders by 68% | Unreal Fest Chicago 2026&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/wobQ8ZKQpbc&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/814</guid>
      <comments>https://techartnomad.tistory.com/814#entry814comment</comments>
      <pubDate>Tue, 21 Jul 2026 04:25:46 +0900</pubDate>
    </item>
    <item>
      <title>A Deep Dive Intro Lore Version Control</title>
      <link>https://techartnomad.tistory.com/813</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2개월 전 쯤에 직접 Lore 빌드 해서 잠깐 사용해 봤는데 그 당시에는 계정 콘트롤도 애매하고 이래 저래 완성도 역시 많이 떨어지긴 했었는데요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언리얼패스트 시카고 2026 에서도 계속 소개하고 있으니 한번 보시죠.&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=ojJ4gqDUbbY&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cFvuQ7/dJMb8XSiSkv/DqiCLkAiDrG5GKL5MjozL0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/uDcRC/dJMb8QMpbKm/WAYZaBFGj4pktAyqtwSXA1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/Bjru2/dJMb8UH2fjI/jL7oB4JTpaVDKVPYHsVlS1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;A Deep Dive Into Lore: a Next-Generation Version Control System | Unreal Fest Chicago 2026&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/ojJ4gqDUbbY&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TECH.ART.FLOW.IO</category>
      <author>jplee</author>
      <guid isPermaLink="true">https://techartnomad.tistory.com/813</guid>
      <comments>https://techartnomad.tistory.com/813#entry813comment</comments>
      <pubDate>Tue, 21 Jul 2026 03:56:05 +0900</pubDate>
    </item>
  </channel>
</rss>