심즈 게임을 보면, 집 안의 내부가 보이지만, 안으로 들어가면 벽이 다시 생긴다.
즉, 카메라와 오브젝트의 특정한 각도가 될 경우, 오브젝트가 안보이는 경우가 있다.
카메라와 오브젝트의 각도를 구해서 위의 경우를 구현해보자.
먼저 OnDrawGizmos를 이용해서 오브젝트의 앞을 씬에 표시해두자.
public class Front : MonoBehaviour
{
private void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawRay(this.transform.position, this.transform.localRotation * Vector3.forward * 2.0f);
}
}
위의 스크립트를 오브젝트에 추가한다. 그러면 Scene 화면에서 아래와 같이 앞이 표시된다.
카메라의 스크립트의 Update에 아래의 코드를 추가해보자.
void Update()
{
Debug.DrawRay(this.transform.position,
this.transform.localRotation * Vector3.forward * 1000.0f, Color.blue);
Vector3 cameraToObj = gb.transform.position - this.transform.position;
Debug.DrawRay(this.transform.position, cameraToObj * 1000.0f, Color.red);
}
카메라가 바라보는 방향 = 카메라의 정면은 파란색이고, 카메라가 오브젝트로 향하는 것은 빨간색이다.
즉, 특정 각도에서 오브젝트를 안보이게 하려면, 카메라의 방향과 오브젝트 정면의 각도가 아니라,
카메라에서 오브젝트를 바라보는 시점과 오브젝트 정면의 각도를 계산해야 한다.
따라서 각도는 Vector3.Angle을 이용해 아래와 같이 구하게 된다.
Vector3 cameraToObj = gb.transform.position - this.transform.position;
float angle = Vector3.Angle(cameraToObj, gb.transform.forward);
angle을 Debug.Log로 출력하면, 아래와 같이 오브젝트를 정면으로 바라볼 때, 약 180º 가 되는 것을 알 수 있다.
(현재 OnDrawGizmos 함수에서 Green으로 오브젝트의 정면이 표시되고 있다.)
따라서 특정 각도에서 SetActive를 이용해 오브젝트를 꺼주거나 켜주면 된다.
위의 경우는 gb를 public으로 선언해서 Cube를 할당한 상태이다.
if (angle > 100.0) gb.SetActive(true);
else gb.SetActive(false);
아래와 같이 카메라와 오브젝트의 각도에 따라 오브젝트가 사라지거나 나타난다.
전체 코드는 RotateAround.cs의 코드와 위의 코드를 합쳤다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraObjectAngle : MonoBehaviour
{
public GameObject lookAtMe;
public float rotateSpeed = 500.0f;
public float scrollSpeed = 2000.0f;
private float xRotateMove, yRotateMove;
bool isAlt;
Vector2 clickPoint;
float dragSpeed = 30.0f;
public GameObject gb;
void Update()
{
Debug.DrawRay(this.transform.position,
this.transform.localRotation * Vector3.forward * 1000.0f, Color.blue);
Vector3 cameraToObj = gb.transform.position - this.transform.position;
float angle = Vector3.Angle(cameraToObj, gb.transform.forward);
//Debug.Log(angle);
if (angle > 100.0) gb.SetActive(true);
else gb.SetActive(false);
Debug.DrawRay(this.transform.position, cameraToObj * 1000.0f, Color.red);
if (Input.GetKeyDown(KeyCode.LeftAlt)) isAlt = true;
if (Input.GetKeyUp(KeyCode.LeftAlt)) isAlt = false;
if (Input.GetMouseButtonDown(0)) clickPoint = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
if (Input.GetMouseButton(0))
{
if (isAlt)
{
lookAtMe.transform.SetParent(this.transform);
Vector3 position
= Camera.main.ScreenToViewportPoint((Vector2)Input.mousePosition - clickPoint);
position.z = position.y;
position.y = .0f;
Vector3 move = position * (Time.deltaTime * dragSpeed);
float y = transform.position.y;
transform.Translate(move);
transform.position
= new Vector3(transform.position.x, y, transform.position.z);
}
else
{
xRotateMove = Input.GetAxis("Mouse X") * Time.deltaTime * rotateSpeed;
yRotateMove = Input.GetAxis("Mouse Y") * Time.deltaTime * rotateSpeed;
Vector3 pos = lookAtMe.transform.position;
transform.RotateAround(pos, Vector3.right, -yRotateMove);
transform.RotateAround(pos, Vector3.up, xRotateMove);
transform.LookAt(pos);
}
}
else
{
lookAtMe.transform.SetParent(null);
float scroollWheel = Input.GetAxis("Mouse ScrollWheel");
Vector3 cameraDirection = this.transform.localRotation * Vector3.forward;
this.transform.position += cameraDirection * Time.deltaTime * scroollWheel * scrollSpeed;
}
}
}
Unity Plus:
Unity Pro:
Unity 프리미엄 학습:
'개발 > Unity' 카테고리의 다른 글
(1) 중심 게이지 만들기 - 파이 메뉴(Pie / Radial Menu) 만들기 (1) | 2022.05.08 |
---|---|
유니티 - 스프라이트 자르기 (Slice Sprite) (0) | 2022.05.03 |
유니티 - 오브젝트를 선택된 상태로 만들기 : (3) Shader Outline (1) | 2022.04.29 |
유니티 GL로 화면에 그림 그리기 (0) | 2022.04.28 |
드래그로 카메라 회전 및 이동하기 (Camera Rotate and Move with Drag) (0) | 2022.04.27 |
댓글