[Unity Course 2] 04. 주인공 캐릭터 제작 : Level Of Detail 설정, Follow Camera 로직
위키북스 출판사 이재현 저자님의 '절대강좌! 유니티' 책을 참고하여 필기한 내용입니다.
Level Of Detail 설정
주인공의 캐릭터는 카메라와의 거리에 따라서 다른 폴리곤을 렌더링 하기 위해 3개의 모델이 합쳐진 상태이다.
LOD : 카메라로부터 멀리 떨어질수록 낮은 폴리곤을 변경하여 렌더링 부하를 줄여주는 기법



세가지의 메쉬의 디테일이 다른걸 확인할 수 있다.
LOD Group 컴포넌트
: 카메라와 피사체의 거리에 따라 렌더링할 메시를 결정하는 역할

플레이어 오브젝트에 LOD Group 컴포넌트 추가

주인공과 캐릭터는 대부분 카메라와의 거리가 고정됐기 때문에 굳이 LOD를 적용할 필요는 없지만 멀티플레이어 상황에서 상대방이 멀리 떨어져 있는 내 캐릭터를 봤을때 유용하게 적용될 수 있다.
모바일에서 최적화하기위해선 꼭 필요
Follow Camera 로직
스크립트 폴더에 FollowCam 스크립트를 생성하고 Main Camera 에 추가한다.
using UnityEngine;
public class FollowCam : MonoBehaviour
{
// 따라가야 할 대상을 연결할 변수
public Transform targetTr;
// Main Camera 자신의 Transform 컴포넌트
private Transform camTr;
// 따라갈 대상으로부터 떨어질 거리
[Range(2.0f, 20.0f)]
public float distance = 10.0f;
// Y축으로 이동할 높이
[Range(0.0f, 10.0f)]
public float height = 2.0f;
private void Start()
{
// Main Camera 자신의 Transform 컴포넌트 추출
camTr = GetComponent<Transform>();
}
private void LateUpdate()
{
// 추적해야 할 대상의 뒤쪽으로 distance만큼 이동
// 높이를 height만큼 이동
camTr.position = targetTr.position
+ (-targetTr.forward * distance)
+ (Vector3.up * height);
// Camera를 피벗 좌표를 향해 회전
camTr.LookAt(targetTr.position);
}
}
[Range(min, max)] 어트리뷰트를 사용하면 인스펙터 뷰에서 다음과 같이 슬라이드로 표현할 수 있다.
그리고 Target Tr 에 플레이어 오브젝트를 드래그 앤 드롭해서 저장한다.

LateUpdate()함수는 모든 Update가 실행되고 난 후 동작하는 함수로 플레이어의 이동 Update()함수가 끝나고 나면 카메라 이동이 동작하도록 설정한다. 이렇게 해야 문제없이 실행된다.
카메라의 위치 = 타깃의 위치
+ (타깃의 뒤쪽 방향 * 떨어질 거리)
+ (Y축 방향 * 높이);
Transform.LookAt()함수는 인자로 Vector3 좌표 또는 Transform 컴포넌트를 전달하면 해당 좌표로 회전시키는 기능을 갖고 있다.
이렇게 작성하면 잘 따라가기는 하지만 카메라가 부드럽지 못하다 그래서 아래의 기능을 사용
Vector3.Lerp, Vector3.Slerp
선형 보간(Linear Interpolation)과 구면 선형 보간(Spherical Linear Interpolation) 은 시작점과 끝 사이의 특정 위치의 값을 추정할 때 사용, 이러한 보간 함수는 현재 값을 목푯값을 ㅗ변경할 때 값자기 변경하지 않고 부드럽게 변경시키는 로직에 많이 활용
선형 보간은 균일한 속도로 이동시키거나 회전 시킬때 사용한다. 아래의 구조체에 사용가능
Vector3.Lerp(시작 좌표, 종료 좌표, t);
Mathf.Lerp(시작 값, 종료 값,t);
Quaternion.Lerp(시작 각도, 종료 각도, t);

구면 선형 보간은 직선의 형태가 아닌 구면 형태로 값을 추론, 구면을 따라서 값을 반환하기 때문에 시간 t가 증가할 때 시작점과 종료점은 느리게 증가, 중간 지점은 빠르게 이동하는 특성
** 구면 선형 보간은 주로 회전 로직에 사용됨
Vector3.Slerp(시작 좌표, 종료 좌표, t);
Quaternion.Slerp(시작 각도, 종료 각도, t);

using UnityEngine;
public class FollowCam : MonoBehaviour
{
// 따라가야 할 대상을 연결할 변수
public Transform targetTr;
// Main Camera 자신의 Transform 컴포넌트
private Transform camTr;
// 따라갈 대상으로부터 떨어질 거리
[Range(2.0f, 20.0f)]
public float distance = 10.0f;
// Y축으로 이동할 높이
[Range(0.0f, 10.0f)]
public float height = 2.0f;
// 반응 속도
public float damping = 10.0f;
private void Start()
{
// Main Camera 자신의 Transform 컴포넌트 추출
camTr = GetComponent<Transform>();
}
private void LateUpdate()
{
// 추적해야 할 대상의 뒤쪽으로 distance만큼 이동
// 높이를 height만큼 이동
Vector3 pos = targetTr.position
+ (-targetTr.forward * distance)
+ (Vector3.up * height);
//구면 선형 보간 함수를 사용해 부드럽게 위치를 변경
camTr.position = Vector3.Slerp(camTr.position,
pos,
Time.deltaTime * damping);
// Camera를 피벗 좌표를 향해 회전
camTr.LookAt(targetTr.position);
}
}
코드를 위와 같이 변경
Vector3.SmoothDamp
: 보통 카메라의 Follow로직에 많이 사용됨
Vector3.SmoothDamp(Vector3 current,
Vector3 target,
ref Vector3 currentVelocity,
flaot smoothTime,
float maxSpeed,
float deltaTime);
| 매개 변수 | 설명 |
| current | 시작 위치 |
| target | 목표 위치 |
| currentVelocity | 현재 속도 |
| smoothTime | 목표 위치까지의 도달 시간 |
| maxSpeed | 최대 속력 제한 값 (기본 값 무한대),생략가능 |
| deltaTime | 프레임 보정을 위한 델타 타임(기본값 Time.deltaTime) 생략가능 |
using UnityEngine;
public class FollowCam : MonoBehaviour
{
// 따라가야 할 대상을 연결할 변수
public Transform targetTr;
// Main Camera 자신의 Transform 컴포넌트
private Transform camTr;
// 따라갈 대상으로부터 떨어질 거리
[Range(2.0f, 20.0f)]
public float distance = 10.0f;
// Y축으로 이동할 높이
[Range(0.0f, 10.0f)]
public float height = 2.0f;
// 반응 속도
public float damping = 10.0f;
// SmoothDamp에서 사용할 변수
private Vector3 velocity = Vector3.zero;
private void Start()
{
// Main Camera 자신의 Transform 컴포넌트 추출
camTr = GetComponent<Transform>();
}
private void LateUpdate()
{
// 추적해야 할 대상의 뒤쪽으로 distance만큼 이동
// 높이를 height만큼 이동
Vector3 pos = targetTr.position
+ (-targetTr.forward * distance)
+ (Vector3.up * height);
//구면 선형 보간 함수를 사용해 부드럽게 위치를 변경
//camTr.position = Vector3.Slerp(camTr.position,
// pos,
// Time.deltaTime * damping);
// SmoothDamp을 이용한 위치 보간
camTr.position = Vector3.SmoothDamp(camTr.position, // 시작 위치
pos, // 목표 위치
ref velocity, // 현재 속도
damping); // 시간 t
// Camera를 피벗 좌표를 향해 회전
camTr.LookAt(targetTr.position);
}
}
damping 을 0.1로 설정 후 테스트
Target Offset 적용
지금까지의 코딩은 캐릭터가 화면 중앙에 위치해 전반 시야가 매우 좁다.
LookAt처리를 해서 피벗 좌표를 바라보기 때문이다 따라서 LookAt 좌표를 조정하여 전방 시야를 확보
using UnityEngine;
public class FollowCam : MonoBehaviour
{
// 따라가야 할 대상을 연결할 변수
public Transform targetTr;
// Main Camera 자신의 Transform 컴포넌트
private Transform camTr;
// 따라갈 대상으로부터 떨어질 거리
[Range(2.0f, 20.0f)]
public float distance = 10.0f;
// Y축으로 이동할 높이
[Range(0.0f, 10.0f)]
public float height = 2.0f;
// 반응 속도
public float damping = 10.0f;
// 카메라 LookAt 의 Offset 값
public float targetOffset = 2.0f;
// SmoothDamp에서 사용할 변수
private Vector3 velocity = Vector3.zero;
private void Start()
{
// Main Camera 자신의 Transform 컴포넌트 추출
camTr = GetComponent<Transform>();
}
private void LateUpdate()
{
// 추적해야 할 대상의 뒤쪽으로 distance만큼 이동
// 높이를 height만큼 이동
Vector3 pos = targetTr.position
+ (-targetTr.forward * distance)
+ (Vector3.up * height);
//구면 선형 보간 함수를 사용해 부드럽게 위치를 변경
//camTr.position = Vector3.Slerp(camTr.position,
// pos,
// Time.deltaTime * damping);
// SmoothDamp을 이용한 위치 보간
camTr.position = Vector3.SmoothDamp(camTr.position, // 시작 위치
pos, // 목표 위치
ref velocity, // 현재 속도
damping); // 시간 t
// Camera를 피벗 좌표를 향해 회전
camTr.LookAt(targetTr.position + (targetTr.up * targetOffset));
}
}