[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 5회차 미션 시작합니다.
무료 모델과 애니메이션을 사용하여 상태 머신을 구성하는 방법입니다.
STEP1. Mixamo - 모델링을 무료로 사용할 수 있는 사이트. (가입필요)
STEP2. Animator 구성하기 - Idle, Walk Animation을 다운로드 받아 Animator 상태 머신을 구성하고, 이를 플레이어 캐릭터와 연결하는 작업
STEP3. Animator 확장하기 - Animation State Machine Behavior를 구현하여 Animator의 구성을 확장.
+ Characters에서 'ybot' 검색하여 "Y Bot" - 다운로드 "FBX for Unity(.fbx)"를 내려받습니다.
+ Animations에서 'idle' 검색하여 아무 것이나 3개를 다운로드. Skin은 "With Skin"으로 내려받습니다. 애니메이션만 받으려는 경우에 "Without Skin"을 사용합니다.
+ Animations에서 'walk' 검색하여 마찬가지로 원하는 애니메이션 1개를 다운로드 합니다.
Unity에 Importing 하기.
Model 파일..
다운받은 파일들을 "Assets" 하위로 "FastCampus/Arts/Character/YBot/Models"에 임포팅합니다.
[Model]의 설정을 변경할 수 있지만 일단 기본으로 시작합니다.
[Rig]의 Animation Type을 "Humanoid"로 설정합니다. 사람 모양의 뼈대를 사용한다고 설정하는 것입니다. 사람 모양이 아닌 경우 "Generic"으로 설정하면 됩니다.
Skin Weights는 Vertex들이 주변 몇 개의 뼈들에 의해 영향을 받을 것인지 설정하는 것입니다. 예전에는 모바일에서 성능 향상을 위해 2개의 뼈 영향을 하기도 했지만, 요즘은 폰 성능의 향상으로 기본 4개로 설정하는 추세입니다.
[Animation] 설정은 모두 끄고, [Materials]도 기본 설정을 그대로 두겠습니다.
"Apply" 버튼 클릭하여 위에 설정한 값들을 적용합니다.
Animation 파일.
[Animation]에서 "Import Animation [v]"을 체크해주고 아래의 Root 옵션들은 일단 그대로 사용합니다.
ybot@idle_00, ybot@idle_01, ybot@idle_02 모두 동일하게 설정해 줍니다.
Scene에 설정하기
ybot 모델을 Hierarchy View에 가져다 놓고, 이름을 "ybot" -> "PlayerCharacter"로 설정합니다.
이 상태에서 Animator를 신규 추가해도 되고, idle_00 애니메이션을 드래그하여 "PlayerCharacter"에 가져다 놓으면 자동으로 "Animator" 컴포넌트가 생성되며 연결됩니다.
여기서 생성된 애니메이터(PlayerCharacter1)를 더블클릭하면 "Entry"에 추가된 "idle_00" 노드를 확인할 수 있습니다. 여기서 "idle_00" 노드를 더블클릭하면 위에서 설정한 애니메이션 설정값이 연동됩니다.
플레이를 해보면 캐릭터가 Idle 상태로 숨쉬듯이 조금씩 움직이는 모습을 볼 수 있습니다.
우리가 원하는 것은 "Idle" 상태일 때 3가지 정도로 Random하게 동작시킬 것이므로 아래와 같이 설정해 주어야 합니다.
"PlayerCharacter" - "Animator" - "Apply Root Motion [ ]"을 UnCheck합니다.
그리고 아래와 같이 Animator Node 설정에서 RMB "Create Sub-State Machine"을 선택하여 Sub-State 상태 머신을 생성합니다.
"New StateMachine" -> "Idle StateMachine"으로 변경하고 "Idle StateMachine"을 더블클릭하여 내부로 진입합니다.
여기서 idle_00, idle_01, idle_02 애니메이션을 드래그하여 가져다 놓습니다. idle_00은 "Base Layer"에서 설정되어 있었기에 자동으로 연결이 된 것으로 나옵니다.
이제 "Base Layer"에 있는 "idle_00"을 삭제하면 자동으로 "Entry" -> "Idle StateMachine"으로 연결됩니다.
다시 "Idle StateMachine"으로 진입해서 "idle_00" ~ "idle_02"가 랜덤하게 설정되도록 하기 위해 좌측의 "Parameters"를 설정합니다. "+"를 클릭하여 "Int"를 추가하고 변수이름은 "RandomIdle"로 지정합니다.
"idle_00" 위에서 우측클릭하여 "Make Transition"을 선택하고 "idle_01"로 연결합니다. 마찬가지로 "idle_00" -> "idle_02"로 연결해주고, "idle_01" -> "idle_00"과 "idle_02" -> "idle_00"도 추가해줍니다.
"idle_00" -> "idle_01"로 가는 화살표를 클릭하여 "Has Exit Time [ ]"을 UnCheck하고, Conditions에서 "RandomIdle", "Equals", "1"로 설정해주면 됩니다. "idle_00" -> "idle_02"로 추가해 줍니다.
Behavior
"Idle_00"에서 "Add Behavior"를 클릭하고, New Script에서 "IdleRandomStateMachineBehavior"로 추가합니다.
IdleRandomStateMachineBehavior.cs
변수를 추가합니다.
public int numberOfStates = 2; // 00은 기본이기에 추가된 01, 02에 대한 2개를 지정
public float minNormTime = 0f; // 최소 실행 시간
public float maxNormTime = 5f; // 최대 실행 시간
public float randomNormalTime;
readonly int hashRandomIdle = Animator.StringToHash("RandomIdle"); // string 비교의 오버헤드가 크기에 int로 hash 처리하여 비교.
override public void onStateEnter() // 기본 상태로 진입했을 때 호출됨 (idle_00 노드 진입시)
{
randomNormalTime = Random.Range(minNormTime, maxNormTime);
}
override public void OnStateUpdate() // 상태 진입후 업데이트 될때 발생.
{
// "Base Layer"에 있음을 의미
if (animator.IsInTransition(0) && animator.GetCurrentAnimatorStateInfo(0).fullPathHash == stateInfo.fullPathHash)
{
animator.SetInteger(hashRandomIdle, -1); // 아무 것도 하지 않음.
}
if (stateInfo.normalizedTime > randomNormalTime && !animator.IsInTransition(0))
{
animator.SetInteger(hashRandomIdle, Random.Range(0, numberOfStates));
}
}
Unity로 돌아와서 에러 없는지 확인후 플레이를 진행하면 Idle 상태가 넘어가는 것을 확인할 수 있습니다.
이로써 Idle 상태 Transition은 모두 완성이 되었습니다.
Walking Animation..
"Base Layer"에서 "Walking" 애니메이션을 드래그하여 추가합니다. Idle 상태에서 캐릭터 이동시 걸어가도록 할 것이므로 "Idle StateMachine"에서 "Make Transition"하여 "Walking" 노드로 연결해줍니다.
Idle에서 Walk 상태로의 변화를 체크하기 위해 "bool Move" 변수를 Parameter에 추가합니다.
Transition 화살표를 클릭하여 Conditions가 "Move", "true"일 때로 설정하면 됩니다.
마찬가지로 "Walk"에서 "Idle"로의 State Transition도 추가합니다.
"Ide StateMachine"의 탈출(Exit)을 설정하기 위해 아래와 같이 각 idle에서 Exit로 "Move == true" 조건을 설정해 줍니다.
플레이를 해보면 Idle 상태로 있다가, Move를 체크해주면 걷는 동작으로 바뀌는 것을 확인할 수 있습니다.
PlayerCharacter Script를 추가합니다.
"PlayerCharacter"의 Animator를 드래그하여 Script의 "Animator"에 연결합니다.
PlayerCharacter 스크립트를 더블클릭하여 Editor로 진입하고 필요한 변수와 함수를 작업합니다.
작업완료후 실행하면 아래와 같이 클릭하여 이동할 때 Walk State로 잘 변경되어 이동하는 것을 확인할 수 있습니다. 앞으로 공격 등의 애미메이션을 구현할 때 이와 같은 상태머신으로 작업을 하게 되는 것입니다.
3인칭 카메라 구현.
3인칭 TopDown 카메라를 구현하고 설정들을 에디터에서 확장하여 처리하는 방법입니다.
"Main Camera"에서 New Script "TopDownCamera"를 추가합니다
TopDownCamera.cs
변수추가.
public float height = 5f; //카메라 높이
public float distance = 10f; // 카메라와 타겟의 거리
public float angle = 45f; // 카메라 각도
public float lookAtHeight = 2f; // 타겟 높이
public float smoothSpeed = 0.5f; // 부드럽게 이동하기 위해 속도
private Vector3 refVelocity; // 내부 Velocity 계산용 변수
public Transform target; // 카메라의 타겟을 위한 변수
Start(), Update()는 모두 삭제하고 다음을 추가합니다.
private void LateUpdate()
{
HandleCamera();
}
private void HandleCamera()
{
if (!target)
{
return;
}
// 카메라 world position 계산
Vector3 worldPosition = (Vector3.forward * -distance) + (Vector3.up * height);
Debug.DrawLine(target.position, worldPosition, Color.red);
Vector3 rotatedVector = Quaternion.AngleAxis(angle, Vector3.up) * worldPosition;
Debug.DrawLine(target.position, rotatedVector, Color.green);
Vector3 finalTargetPosition = target.position;
finalTargetPosition.y += lookAtHeight;
Vector3 finalPosition = finalTargetPosition + rotatedVector;
Debug.DrawLine(target.position, finalPosition, Color.blue);
transform.position = Vector3.SmoothDamp(transform.position, finalPosition, ref refVelocity, smoothSpeed);
transform.LookAt(target.position); // 카메라가 타겟 바라보기
}
카메라가 바라보는 위치와 캐릭터가 바라보는 위치를 표시하여 보기위해서 디버그용 함수를 구현합니다.
OnDrawGizmos()
{
Gizmos.color = new Color(1f, 0f, 0f, 0.5f);
if (target)
{
Vector3 lookAtPosition = target.position;
lookAtPosition.y += lookAtHeight;
Gizmos.DrawLine(transform.position, lookAtPosition);
Gizmos.DrawSphere(lookAtPosition, 0.25f);
}
Gizmos.DrawSphere(transform.position, 0.25f);
}
Unity로 돌아와서.. "Main Camera"의 스크립트의 Target에 "PlayCharacter"를 드래그 하여 연결해 줍니다.
그리고 플레이하면 캐릭터를 따라다니는 카메라를 구현할 수 있습니다.
변수값들을 실시간 변경해 보면서 캐릭터와 TopDown 카메라의 관계를 확인할 수 있습니다.
휴우.. 유니티는 정말 어마무시하긴 하네요.. 예전에는 코드 레벨에서 하던 작업을 UI 상에서 구성하고 연결만 하면 사용할 수 있으니 코드는 최소한으로만 작성하고 유니티툴에서 잘 활용하면 되는 것이겠습니다. 굳이 단점이라면야 소스 코드를 잘 짜는 사람이더라도 유니티툴을 잘 다룰줄 알아야 한다는 것이겠지요.. 어디에 어떤 메뉴가 있고 어떤 시점에 연결해서 써야하는지 확인해야 하는지 등을 모두 알아야 하니까요.. 눈이 뱅글뱅글 돌아갑니다. @~@
패스트캠퍼스 - 올인원 패키지 : 유니티 포트폴리오 완성 bit.ly/2R561g0
'[컴퓨터] > 웹 | 앱 | 게임 개발' 카테고리의 다른 글
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 7회차 미션 (0) | 2020.10.25 |
---|---|
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 6회차 미션 (0) | 2020.10.24 |
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 4회차 미션 (0) | 2020.10.22 |
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 3회차 미션 (0) | 2020.10.21 |
[패스트캠퍼스 수강 후기] 올인원 패키지 : 유니티 포트폴리오 완성 100% 환급 챌린지 2회차 미션 (0) | 2020.10.20 |