반응형
✔ Unity - 카메라 오브젝트 포커싱 (Object Focus)
부드럽게 이동시키기, 오브젝트 줌 인/아웃 하기
유니티의 하이어라키에서 오브젝트를 더블클릭하거나 Ctrl + F를 누르면 포커싱되는 기능이있다.
API로 제공해주면 참 좋겠지만 없는것 같아서 스크립트로 제작했다. ( API있거나 생기면 공유좀 ㅠ_ㅠ)
또한 혹시나 오브젝트를 줌인하기 전에 줌아웃해서 전체 맵을 보고 줌인해야하는 경우도 있기에 경유 기능도 추가하여 제작했다.
● 카메라 특정 오브젝트로 부드럽게 이동하기 - 경유지점 포함
◇ 사용법
1. 아래 스크립트를 아무 오브젝트에 AddComponent하고 camera에 MainCamera를 드래그하여 넣어준다.
2. 경유지점이 있으면 subTarget에 Transform을 드래그하여 넣어준다.
3. SetTarget 함수를 호출하면서 파라미터로 목표오브젝트를 넣어준다.
- SetTarget(GameObject 목표오브젝트)
- SetTarget(GameObject 목표오브젝트, bool isBounds)
: bounds의 크기 기준으로 타겟을 설정한다. bound는 Mesh 중심에서 Mesh 크기만큼의 사각형을 뜻한다.
4. 잘되는지 확인
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 이동 완료시 발생 이벤트
/// </summary>
public class MoveCompleteEventArgs
{
public GameObject targetObject;
public Vector3 position;
public Quaternion quaternion;
}
public class CameraMoveToObject : MonoBehaviour
{
public static event System.EventHandler<MoveCompleteEventArgs> EventHandler_CameraMoveTargtet;
/// <summary>
/// 카메라
/// </summary>
public GameObject camera;
/// <summary>
/// 줌인 대상 오브젝트
/// </summary>
private Transform targetObject;
/// <summary>
/// 경유 지점 위치
/// </summary>
public Transform subTarget;
/// <summary>
/// 부드럽게 이동될 감도
/// </summary>
public float smoothTime = 0.3f;
private Vector3 velocity = Vector3.zero;
/// <summary>
/// 카메라 타겟 줌인 상태 플래그
/// </summary>
public static bool IsActive = false;
/// <summary>
/// 줌인 정도 -가 클수록 줌아웃
/// </summary>
public float Zoomin = -5;
/// <summary>
/// 오브젝트 크기에 맞춰 줌기능 사용시 사용될 데이터
/// </summary>
private Bounds boundsData;
private bool isBounds = true;
/// <summary>
/// 경유지점 도착 후 진행 카운트
/// </summary>
private int PassCount = 0;
// Update is called once per frame
void Update()
{
if (IsActive)
{
Vector3 targetPosition;
//경유지점이 있다면 목표지점을 경유우선으로 지정한다
if (subTarget != null && PassCount == 0)
{
targetPosition = subTarget.transform.position;
smoothTime = 0.1f;
}
else
{
//경유지점이 없다면 bounds 체크 후 목표지점을 종착지로 설정한다
if (!isBounds)
targetPosition = targetObject.TransformPoint(new Vector3(0, 10, Zoomin));
else
targetPosition = new Vector3(boundsData.center.x, boundsData.center.y + boundsData.size.y, boundsData.center.z - boundsData.size.z + Zoomin);
}
//위에서 설정된 위치로 부드럽게 이동
camera.transform.position = Vector3.SmoothDamp(camera.transform.position, targetPosition, ref velocity, smoothTime);
camera.transform.LookAt(targetObject);
//목표지점 이내에 도착
if (Vector3.Distance(targetPosition, camera.transform.position) < 0.1f)
{
//경유지점이 있을 경우
if (subTarget != null)
{
//if(Vector3.Distance(targetPosition,subTarget.transform.position) < 0.1f)
if (targetPosition == subTarget.transform.position)
{
PassCount++;
//경유지점 도착 후 targetPosition을 최종 목표위치로 변경
if (!isBounds)
targetPosition = targetObject.TransformPoint(new Vector3(0, 10, Zoomin));
else
targetPosition = new Vector3(boundsData.center.x, boundsData.center.y + boundsData.size.y, boundsData.center.z - boundsData.size.z + Zoomin);
}
else
{
//경유하고 최종 목적지 도착했을때 이벤트 처리
MoveCompleteEventArgs args = new MoveCompleteEventArgs();
args.targetObject = targetObject.gameObject;
args.position = camera.transform.position;
args.quaternion = camera.transform.rotation;
EventHandler_CameraMoveTargtet(this, args);
Clear();
}
}
else
{
//경유 지점 없이 최종 목적지 도착했을때 이벤트 처리
MoveCompleteEventArgs args = new MoveCompleteEventArgs();
args.targetObject = targetObject.gameObject;
args.position = camera.transform.position;
args.quaternion = camera.transform.rotation;
EventHandler_CameraMoveTargtet(this, args);
Clear();
}
}
}
//if (Input.GetMouseButton(0) && IsActive || Input.GetMouseButton(1) && IsActive || Input.GetAxis("Mouse ScrollWheel") != 0 && IsActive)
//{
// Clear();
//}
}
/// <summary>
/// target 오브젝트로 시점을 이동하는 함수
/// </summary>
/// <param name="target">목표 오브젝트</param>
/// <param name="bounds">오브젝트 크기에 따라 줌인 여부</param>
public void SetTarget(GameObject target, bool bounds = true)
{
if (target == null)
return;
IsActive = true;
targetObject = target.transform;
//bounds가 true일경우 target의 bounds 데이터를 저장
if(bounds)
{
Bounds combinedBounds = new Bounds();
var renderers = target.GetComponentsInChildren<Renderer>();
foreach (var render in renderers)
{
combinedBounds.Encapsulate(render.bounds);
}
boundsData = combinedBounds;
isBounds = true;
}
else
{
boundsData = new Bounds();
isBounds = false;
}
}
public void Clear()
{
smoothTime = 0.3f;
IsActive = false;
targetObject = null;
PassCount = 0;
}
}
반응형
'Programming > Unity' 카테고리의 다른 글
[Unity] 유니티 개발시 에디터 필수 조작 편의 Tips (936) | 2022.04.06 |
---|---|
[Unity] 런타임에서 프로젝트 관리 기능을 만들기! (263) | 2022.03.25 |
[Unity] 빌드 후 해상도 고정하기 - 풀스크린, 창모드 (514) | 2022.03.08 |
[Unity] Polybrush - NullReferenceException [Solustion] (594) | 2022.03.02 |
[Unity3D] 유니티에서 Timer 구현하기 - IEnumerator, System.Timers (3) | 2022.01.11 |
댓글