Unity의 3인칭 카메라
3인칭 카메라는 플레이어 뒤에 배치되는 카메라 유형으로, 일반적으로 약간 옆으로 이동하여 게임 레벨과 플레이어 자체를 시각적으로 표현합니다.
Unity에서 3인칭 슈터(TPS) 카메라를 만들기 위해 일반 플레이어 움직임과 3인칭 시점의 조합을 사용합니다.
1단계: 플레이어 컨트롤러 생성
먼저 회전과 이동을 처리하는 플레이어 컨트롤러를 만듭니다.
- 새 게임 개체를 만들고(Game Object -> Create Blank) 이름을 지정합니다. "Player"
- 새 캡슐(게임 개체 -> 3D 개체 -> 캡슐)을 만들고 "Player" 개체 내부로 옮깁니다.
- Capsule에서 Capsule Collider 구성 요소를 제거하고 위치를 (0, 1, 0)으로 변경합니다.
- 새 GameObject를 생성하고 이름을 "CameraParent"로 지정한 다음 "Player" Object 내부로 이동하고 위치를 (0, 1.64, 0)으로 변경합니다.
- 메인 카메라를 "CameraParent" 개체 내부로 이동하고 플레이어 뒤로 이동합니다. (제 경우에는 이 위치로 이동했습니다: (0.5, 0.6, -2.9))
- 새 스크립트를 만들고 SC_TPSController라고 부르고 그 안에 아래 코드를 붙여넣습니다.
SC_TPSController.cs
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class SC_TPSController : MonoBehaviour
{
public float speed = 7.5f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
public Transform playerCameraParent;
public float lookSpeed = 2.0f;
public float lookXLimit = 60.0f;
CharacterController characterController;
Vector3 moveDirection = Vector3.zero;
Vector2 rotation = Vector2.zero;
[HideInInspector]
public bool canMove = true;
void Start()
{
characterController = GetComponent<CharacterController>();
rotation.y = transform.eulerAngles.y;
}
void Update()
{
if (characterController.isGrounded)
{
// We are grounded, so recalculate move direction based on axes
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 right = transform.TransformDirection(Vector3.right);
float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
moveDirection = (forward * curSpeedX) + (right * curSpeedY);
if (Input.GetButton("Jump") && canMove)
{
moveDirection.y = jumpSpeed;
}
}
// Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
// when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
// as an acceleration (ms^-2)
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
characterController.Move(moveDirection * Time.deltaTime);
// Player and Camera rotation
if (canMove)
{
rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
transform.eulerAngles = new Vector2(0, rotation.y);
}
}
}
- SC_TPSController 스크립트를 "Player" 개체에 연결합니다. (Character Controller라는 또 다른 구성 요소도 추가되었음을 알 수 있습니다. 중심 값을 (0, 1, 0)으로 변경합니다.)
- "CameraParent" 개체를 "Player Camera Parent" 변수에 할당
2단계: 카메라 충돌 감지 추가
Camera 충돌 감지는 카메라와 플레이어 사이에 아무것도 없는지 확인하고 자동으로 카메라를 더 가까이 이동하여 카메라가 개체를 통과하는 것을 방지하는 스크립트로 구성됩니다.
- 새 스크립트를 만들고 이름을 SC_CameraCollision으로 지정한 다음 그 안에 아래 코드를 붙여넣습니다.
SC_CameraCollision.cs
using UnityEngine;
public class SC_CameraCollision : MonoBehaviour
{
public Transform referenceTransform;
public float collisionOffset = 0.3f; //To prevent Camera from clipping through Objects
public float cameraSpeed = 15f; //How fast the Camera should snap into position if there are no obstacles
Vector3 defaultPos;
Vector3 directionNormalized;
Transform parentTransform;
float defaultDistance;
// Start is called before the first frame update
void Start()
{
defaultPos = transform.localPosition;
directionNormalized = defaultPos.normalized;
parentTransform = transform.parent;
defaultDistance = Vector3.Distance(defaultPos, Vector3.zero);
//Lock cursor
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// LateUpdate is called after Update
void LateUpdate()
{
Vector3 currentPos = defaultPos;
RaycastHit hit;
Vector3 dirTmp = parentTransform.TransformPoint(defaultPos) - referenceTransform.position;
if (Physics.SphereCast(referenceTransform.position, collisionOffset, dirTmp, out hit, defaultDistance))
{
currentPos = (directionNormalized * (hit.distance - collisionOffset));
transform.localPosition = currentPos;
}
else
{
transform.localPosition = Vector3.Lerp(transform.localPosition, currentPos, Time.deltaTime * cameraSpeed);
}
}
}
- SC_CameraCollision 스크립트를 메인 카메라에 연결
- "CameraParent" 개체를 "Reference Transform" 변수에 할당합니다.
- 카메라가 벽을 통과할 경우를 대비해 "Collision Offset" 및 "Camera Speed" 값을 조정하세요.
이제 TPS 카메라가 준비되었습니다. 재생을 눌러 테스트해 보세요.