본문 바로가기
개발/Unity

유니티 - 카메라와 오브젝트의 각도 구하기

by 피로물든딸기 2022. 4. 30.
반응형

Unity 전체 링크

 

심즈 게임을 보면, 집 안의 내부가 보이지만, 안으로 들어가면 벽이 다시 생긴다.

즉, 카메라와 오브젝트의 특정한 각도가 될 경우, 오브젝트가 안보이는 경우가 있다.

 

카메라와 오브젝트의 각도를 구해서 위의 경우를 구현해보자.

 

먼저 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:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글