[Basic] CharacterController 컴포넌트
in Unity
characterController
characterController 컴포넌트에 대해 알아보자.
characterController는 기본적으로 3D 게임에서 사람 형태의 캐릭터 움직임과 관련된 제어를 위해 사용하며 캡슐 모양의 콜라이더가 포함되어 있다.
Slope Limit : 올라갈 수 있는 경사 한계 각
Step Offset : 설정값보다 낮은 높이의 계단(그 외 오브젝트)을 오를 수 있다.
Center : 캡슐 콜라이더 범위의 중심점
Radius : 캡슐 콜라이더 범위의 반지름 (x,z)
Height : 캡슐 콜라이더 범위의 높이(y)
이제 스크립트를 이용하여 플레이어 캐릭터의 이동을 구현해보자
우선 characterController 클래스의 메소드에서 움직임과 관련된 함수를 봐보자
Move(이동방향 x 속도 x Time.deltaTime); : 매개변수로 이동방향,속도,Time.deltaTime등의 세부적인 이동 방법을 설정하면 이동을 수행한다.
SimpleMove(Vector3 speed); : 매개변수로 이동 속도를 넣어 호출 하면 된다.
우선 플레이어 캐릭터의 움직임을 담당할 스크립트를 하나 만든다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement3D : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5.0f; //이동 속도
private Vector3 moveDir; //이동 방향
private CharacterController characterController;
void Awake()
{
characterController=GetComponent<CharacterController>();
}
void Update()
{
characterController.Move(moveDir*moveSpeed*Time.deltaTime);
}
//PlayerController에서 호출하기 위해 public 설정
public void MoveTo(Vector3 dir)
{
moveDir=dir;
}
}
그리고 플레이어를 제어 할 스크립트를 하나 만든다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Movement3D movement3D;
void Start()
{
movement3D=GetComponent<Movement3D>();
}
void Update()
{
float hAxis = Input.GetAxisRaw("Horizontal");
float vAxis = Input.GetAxisRaw("Vertical");
movement3D.MoveTo(new Vector3(hAxis, 0 ,vAxis));
}
}
이제 저장하고 프로젝트로 돌아가 Player오브젝트에 두 스크립트들을 추가해준다. 그러면 우리가 입력한대로 플레이어 오브젝트가 움직이는걸 확인 할 수 있다.
하지만 현재까지 작업한걸로는 중력이 적용되지 않는다. 그래서 스크립트에 중력을 적용하는 코드를 넣어줘야한다. Movement3D 스크립트를 다음과 같이 변경하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement3D : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5.0f; //이동 속도
private float gravity = -9.81f; //중력 계수
private Vector3 moveDir; //이동 방향
private CharacterController characterController;
void Awake()
{
characterController=GetComponent<CharacterController>();
}
void Update()
{
//characterController.isGrounded
//발 위치의 충돌을 체크해 충돌이 되면 true,충돌이 되지 않으면 false값을 나타내는 변수.
if (characterController.isGrounded == false)
{
moveDir.y += gravity * Time.deltaTime;
}
characterController.Move(moveDir*moveSpeed*Time.deltaTime);
}
//PlayerController에서 호출하기 위해 public 설정
public void MoveTo(Vector3 dir)
{
//앞, 뒤, 좌, 우 움직임은 매개변수로 넘어온 값을 사용하고
//아래방향은 Update에서 계속 계산 되는 moveDir.y를 사용한다.
moveDir = new Vector3(dir.x, moveDir.y, dir.z);
}
}
이제 저장하고 게임 플레이를 해보면 플레이어 오브젝트가 높은 곳에 있다가 발판이 없으면 떨어지는걸 확인할 수 있다.
이제 플레이어 점프를 구현해보자 Movement3D 스크립트를 다음과 같이 변경해주자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement3D : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5.0f; //이동 속도
[SerializeField]
private float jumpForce = 3.0f; //점프하는 힘
private float gravity = -9.81f; //중력 계수
private Vector3 moveDir; //이동 방향
private CharacterController characterController;
void Awake()
{
characterController=GetComponent<CharacterController>();
}
void Update()
{
//characterController.isGrounded
//발 위치의 충돌을 체크해 충돌이 되면 true,충돌이 되지 않으면 false값을 나타내는 변수.
if (characterController.isGrounded == false)
{
moveDir.y += gravity * Time.deltaTime;
}
characterController.Move(moveDir*moveSpeed*Time.deltaTime);
}
//PlayerController에서 호출하기 위해 public 설정
public void MoveTo(Vector3 dir)
{
//앞, 뒤, 좌, 우 움직임은 매개변수로 넘어온 값을 사용하고
//아래방향은 Update에서 계속 계산 되는 moveDir.y를 사용한다.
moveDir = new Vector3(dir.x, moveDir.y, dir.z);
}
//PlayerController에서 호출하기 위해 public 설정
public void JumpTo()
{
if(characterController.isGrounded == true)//플레이어가 바닥에 붙어있으면
{
moveDir.y = jumpForce;
}
}
}
그리고 PlayerController스크립트도 다음과 같이 수정하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Movement3D movement3D;
void Awake()
{
movement3D=GetComponent<Movement3D>();
}
void Update()
{
float hAxis = Input.GetAxisRaw("Horizontal");
float vAxis = Input.GetAxisRaw("Vertical");
Debug.Log(Input.GetAxisRaw("Horizontal"));
movement3D.MoveTo(new Vector3(hAxis, 0 ,vAxis));
if (Input.GetKeyDown(KeyCode.Space))
{
movement3D.JumpTo();
}
}
}
이제 게임 실행을 해보면 스페이스바를 누르면 플레이어가 점프하는걸 볼 수 있다.
이제 경사면 이동과 계단 이동에 대해 살펴보자.
우선 characterController 컴포넌트에 Slope Limit 프로퍼티의 값을 보면 45로 되어있다. 그렇기 때문에 플레이어는 45도가 넘는 경사면을 오를 수 없다.
30도인 곳은 올라가지만 50도인곳은 걸어서 올라갈 수 없다.
그리고 CharacterController컴포넌트에서 Step Offset의 값을 보면 0.3이라고 되어 있는데 이건 계단 사이에 높이 차이가 0.3이하여야지 플레이어가 올라갈 수 있다는 뜻이다. 현재 우리 프로젝트의 계단 사이에 높이는 0.4이기 때문에 플레이어가 올라갈 수 없다.