[Unity] Charactor Controller
Version 2019.3.6f1
GameWorld
Gameworld를 Import 합니다.
Prefabs의 GameWorld를 Scene에 올립니다.
Camera를 선택하고 위치를 조절합니다.
Character Controller
Capsule을 추가하고
Player라고 이름 바꿉니다.
Material을 추가하고 Player로 이름 바꾸고 색깔은 빨간색으로 합니다.
Player를 선택하고 Material > Element를 Player Material을 연결합니다.
Player에서 Character Controller를 추가하고
Capsule Collider는 삭제합니다.
Mesh Render를 끄면 충돌범위를 확인 할 수 있습니다.
Script 작성
Movement3D 스크립트를 생성합니다.
PlayerController 스크립트도 생성합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement3D : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5.0f;
private Vector3 moveDirector;
private CharacterController characterController;
private void Awake()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
characterController.Move(moveDirector * moveSpeed * Time.deltaTime);
}
public void MoveTo(Vector3 director)
{
moveDirector = director;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Movement3D movement3D;
private void Awake()
{
movement3D = GetComponent<Movement3D>();
}
private void Update()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
movement3D.MoveTo(new Vector3(x, 0, z));
}
}
Player를 선택하고 Movement3D와 CharacterController 스크립트를 넣어 줍니다.
Play해서 키보드 방향키로 이동해봅니다.
중력추가
중력을 위해서 스크립트를 수정합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement3D : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 5.0f;
private float gravity = -9.8f; // 충력계수
private Vector3 moveDirector;
private CharacterController characterController;
private void Awake()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
if ( characterController.isGrounded == false )
{
moveDirector.y += gravity * Time.deltaTime;
}
characterController.Move(moveDirector * moveSpeed * Time.deltaTime);
}
public void MoveTo(Vector3 direction)
{
//moveDirector = direction;
moveDirector = new Vector3(direction.x, moveDirector.y, direction.z);
}
}
Play 해서 y축을 변경해보면 중력이 작동합니다.
Jump 구현
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.8f; // 충력계수
private Vector3 moveDirector;
private CharacterController characterController;
private void Awake()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
if ( characterController.isGrounded == false )
{
moveDirector.y += gravity * Time.deltaTime;
}
characterController.Move(moveDirector * moveSpeed * Time.deltaTime);
}
public void MoveTo(Vector3 direction)
{
//moveDirector = direction;
moveDirector = new Vector3(direction.x, moveDirector.y, direction.z);
}
public void JumpTo()
{
if ( characterController.isGrounded == true )
{
moveDirector.y = jumpForce;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private KeyCode jumpKeyCode = KeyCode.Space;
private Movement3D movement3D;
private void Awake()
{
movement3D = GetComponent<Movement3D>();
}
private void Update()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
movement3D.MoveTo(new Vector3(x, 0, z));
if ( Input.GetKeyDown(jumpKeyCode) )
{
movement3D.JumpTo();
}
}
}
게임을 Play해서 Space키로 점프 해봅니다.
경사면 오르기
Character Controller의 Slope Limit 이 45도로 되어 있습니다.
경사면 30도는 오를 수 있습니다.
경사면 50도는 오르지 못합니다.
계단오르기
Step Offset이 0.3 입니다.
두 계단 간 Offset이 0.4 입니다.
계단을 오르지 못합니다.
StepOffset을 0.4로 변경합니다.
계단을 오릅니다.
1인칭 카메라 시점 구현
Main Camera를 Player 자식으로 넣어주고
Camera Position을 reset하고 Y를 0.6으로 설정합니다.
카메라가 Player의 눈 정도에 위치합니다.
CameraController 스크립트를 생성합니다.
using UnityEngine;
public class CameraController : MonoBehaviour
{
private float rotateSpeedX = 3;
private float rotateSpeedY = 5;
private float limitMinX = -80;
private float limitMaxX = 50;
private float eulerAngleX;
private float eulerAngleY;
public void RotateTo(float mouseX, float mouseY)
{
eulerAngleY += mouseX * rotateSpeedX;
eulerAngleY -= mouseY * rotateSpeedY;
eulerAngleX = ClampAngle(eulerAngleX, limitMinX, limitMaxX);
transform.rotation = Quaternion.Euler(eulerAngleX, eulerAngleY, 0);
}
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private KeyCode jumpKeyCode = KeyCode.Space;
[SerializeField]
private CameraController cameraController;
private Movement3D movement3D;
private void Awake()
{
movement3D = GetComponent<Movement3D>();
}
private void Update()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
movement3D.MoveTo(new Vector3(x, 0, z));
if ( Input.GetKeyDown(jumpKeyCode) )
{
movement3D.JumpTo();
}
float mouseX = Input.GetAxis("Mouse X");
float mouseY = Input.GetAxis("Mouse Y");
cameraController.RotateTo(mouseX, mouseX);
}
}
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.8f; // 충력계수
private Vector3 moveDirector;
[SerializeField]
private Transform cameraTransform;
private CharacterController characterController;
private void Awake()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
if ( characterController.isGrounded == false )
{
moveDirector.y += gravity * Time.deltaTime;
}
characterController.Move(moveDirector * moveSpeed * Time.deltaTime);
}
public void MoveTo(Vector3 direction)
{
//moveDirector = direction;
//moveDirector = new Vector3(direction.x, moveDirector.y, direction.z);
Vector3 movedis = cameraTransform.rotation * direction;
moveDirector = new Vector3(movedis.x, moveDirector.y, movedis.z);
}
public void JumpTo()
{
if ( characterController.isGrounded == true )
{
moveDirector.y = jumpForce;
}
}
}
MainCamera를 선택하고 CameraController 스크립트를 넣어줍니다.
Player > Movement 3D와 Player Controller에 각각 MainCamera를 연결해 줍니다.
게임을 Play 하고 마우스로 회전하고, 방향키로 이동 할 수 있습니다.