공부중
[Unity] modelViewer - 캐릭터 이동 구현. 본문
모델은 형님이 만들어서 fbx로 export해서 유니티 씬에 띄워놓은 상태이고...
캐릭터가 밖으로 빠져나가지 못하게 대충 box collider 만 주변에 씌워주고
캐릭터에는 capsule collider를 씌워주었다..
여기서 적어놓을것은 캐릭터 이동에 관한 스크립트를 적어볼려고 한다.
일단 여기(애니메이션)에서는 간단하게 Idle 상태가 기본 상태이며 isWalk라는 bool 변수를 하나 두고 이 변수를 통해서 Walk로 전환을 담당해주고 있다.
캐릭터를 움직이는데 w a s d 키를 이용해서 상하좌우 움직이게 해주어야 한다.
총 구현 코드는 아래와 같다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMovement : MonoBehaviour
{
public float speed = 1.0f;
private Vector3 movement;
private Animator anim;
private Rigidbody modelRigidbody;
private void Start()
{
anim = GetComponent<Animator>();
modelRigidbody = GetComponent<Rigidbody>();
}
private void Update()
{
float x = Input.GetAxis("Horizontal") * -1.0f;
float z = Input.GetAxis("Vertical") * -1.0f;
movement = new Vector3(x, 0.0f, z).normalized * speed * Time.deltaTime;
}
private void FixedUpdate() { Move(); }
private void Move()
{
if (movement.magnitude < 0.01f)
{
anim.SetBool("isWalk", false);
return;
}
modelRigidbody.velocity = movement;
modelRigidbody.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(movement), 0.15f);
anim.SetBool("isWalk", true);
}
}
간단하다면 간단하고 길다면 긴... 아무튼 50줄 미만의 코드가 나왔다.
public float speed = 1.0f;
private Vector3 movement;
private Animator anim;
private Rigidbody modelRigidbody;
변수 선언부를 보면...
유니티 에디터에서 바로 수정해 적용할 수 있도록 하기 위해서 public으로 speed를 만들어 두었고
나머지 부분은 딱히 외부에서 일일히 수정할 것들이 아니므로 private로 두었다.
movement는 최종 이동할 방향과 거리를 나타낸다.
private void Start ()
{
anim = GetComponent<Animator>();
modelRigidbody = GetComponent<Rigidbody>();
}
Start에서는 GetComponent를 통해서 등록된 컴포넌트들을 받아오고 있다.
private void Update()
{
float x = Input.GetAxis("Horizontal") * -1.0f;
float z = Input.GetAxis("Vertical") * -1.0f;
movement = new Vector3(x, 0.0f, z).normalized * speed * Time.deltaTime;
}
Update에서는 수직(Vertical) 수평(Horizontal)의 기울기 값(키보드 입력은 -1, 0 1 이겠지만... 아무튼..)을 와서 x와 z에 넣어주고 있다
그리고 뒤에 각각 -1.0을 곱한 이유는..... 내가 씬에서 배치한것도 그렇고
아무튼 결과적으로 카메라 위치에서 보면...
캐릭터 기준으로 이동하는 방향(forward)과 카메라가 바라보는 방향이 다르기 때문에..
저 -1을 안곱해줬으면 w를 눌렀을떄 캐릭터는 카메라가 바라보는 기준으로 아래로 이동하게 된다. -_-;;
어찌되었든간에 카메라가 바라보는 기준으로 상하좌우 움직이게 하면 되는데
카메라는 일단 위치 고정이고 줌인 아웃만 할 예정이므로 저렇게 날(?) 코딩을 했다 -_-;;
(추후에 카메라가 바라보는 기준으로 상하좌우 이동하게끔 해야겠다... 크흑)
그리고 받아온 x,z의 값을 가지고 Vector3에 저장한 뒤에 normalized (단위벡터 - 크기가 1인 벡터)로 만들어 주고 (방향)
speed와 deltaTime을 통해서 (거리)
movement에 넣어주었다.
private void FixedUpdate()
{
Move();
}
private void Move()
{
if (movement.magnitude < 0.01f)
{
anim.SetBool("isWalk", false);
return;
}
modelRigidbody.velocity = movement;
modelRigidbody.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(movement), 0.15f);
anim.SetBool("isWalk", true);
}
Update에서는 입력받아서 어디 방향으로 얼마나 이동할지를 구하였고
FixedUpdate에서는 실제로 이동하는것이 구현되어 있다.
FixedUpdate에는 간단하게 Move() 만 호출하고 있고
Move에는 먼저 이동할 크기가 0.01이하면 정지하는것으로 처리하였고
0.01보다 크면 모델의 rigidbody에 속도(방향+이동크기)을 주고
(이동 방식을 가속방식이 아닌 바로 이동하게하기 위해서 velocity에 바로 값을 넣어주었다.)
회전은 이동하는 방향으로 넣어주는데...
조금 스무스하게 하기 위해서 Quaternion.Slerp를 이용하였다.
Quaternion.Slerp은 public static Quaternion Slerp(Quaternion a, Quaternion b, float t); 의 모습을 하고 있으며
유니티 문서에서도 살펴보면 이런 주석이 달려있다. - 문서 링크
// Interpolates rotation between the rotations "from" and "to"
// (Choose from and to not to be the same as
// the object you attach this script to)
위의 주석에서 a는 from이고 b는 to 이다.
a에서 b 사이를 보간한다는 내용이고 마지막 인자 t는 [0,1]의 범위이다..
( t의 값이 커질수록 from에서 to의 회전이 빠르게 전환한다고 보면 된다. )
아무튼 현재의 회전값에서 바라보는 회전값까지 보간을 해주면서 회전할 예정이기 때문에 위의 코드처럼 넣어주었고
임의로 값 0.15f 를 넣어주었다.
아래의 영상은 결과를 보여주고 있다.
음... 끝...
(유튜브로 바꿔야 하나... 고민을 해봐야 겠다...)