카메라가 캐릭터를 따라오게끔 만들겠다.
먼저 Camera Script를 만든다.
그리고 Player란 Tag를 만들고 Player에게 Tag를 달아주자.
using UnityEngine;
public class CameraScript : MonoBehaviour
{
private GameObject player;
[SerializeField]
private float OffsetX = 0;
[SerializeField]
private float OffsetY = 3;
[SerializeField]
private float OffsetZ = -3;
private void Start()
{
player = GameObject.FindGameObjectWithTag("Player");
}
private void LateUpdate()
{
if (player)
{
transform.position = player.transform.position + Vector3.right * OffsetX + Vector3.up * OffsetY + Vector3.forward * OffsetZ;
transform.LookAt(player.transform);
}
else
player = GameObject.FindGameObjectWithTag("Player");
}
}
먼저 LateUpdate는 모든 게임 오브젝트가 Update 함수 호출 후에 호출하는 함수이다.
이 함수를 사용한 이유는 Player의 위치 변경 Script와 Camera Script 중 어느 것이 먼저 실행될지 모르므로 서로 돌아가면서 실행되는 것을 방지하기 위해서 필요하다.
GameObject player를 LateUpdate에서 매번 찾아서 하는 것이 아닌 레퍼런스로 받아서 처리하는 이유는 GameObject를 찾는 것은 모든 GameObject를 하나하나 들려 Tag를 확인하는 것이기 때문에 최적화를 위해서 다음과 같이 작성하였다.
앞에서 배운 레이캐스팅을 응용해서 만약 카메라 앞에 벽이 있으면 벽 앞으로 카메라를 이동하게끔 해보자.
private void LateUpdate()
{
if (player)
{
RaycastHit rayInfo;
Vector3 posPlayer = player.transform.position + Vector3.up;
Vector3 posCamera = posPlayer + Vector3.right * OffsetX + Vector3.up * OffsetY + Vector3.forward * OffsetZ;
Vector3 vecCamera = posPlayer - posCamera;
Physics.Raycast(posCamera, vecCamera, out rayInfo);
Debug.DrawRay(posCamera, vecCamera,Color.red);
if (rayInfo.collider.gameObject.tag == "Player")
transform.position = posCamera;
else
transform.position = posPlayer + 0.8f * (posPlayer - rayInfo.point).magnitude * vecCamera.normalized * (-1);
transform.LookAt(posPlayer);
}
else
player = GameObject.FindGameObjectWithTag("Player");
}
posPlayer를 다음과 같이 설정한 이유는 캐릭터의 발바닥이 원점 좌표로 설정되어있어서 그렇다.