Unity 학습

유니티3D 문 열고/닫기 상호작용 만들기

리저브콜드브루 2025. 6. 19. 18:19
728x90
반응형

간단한 코드 예시와 함께 문 열고 닫는 상호작용을 만들어보려고 한다.

 

1. 인터페이스 정의

상호작용 대상에 붙일 인터페이스를 정의한다.

public interface IInteractable
{
    void Interact();
    string GetInteractText(); // UI 힌트용
}

 

2. Layer 지정

Door 오브젝트의 Layer를 지정해준다.

알맞은 Layer가 없다면 Add Layer 클릭 후 추가한다.

Door는 Collider 컴포넌트가 있어야 한다.

Interact Layer 추가 및 지정

 

3. 상호작용 Text 추가

Hierarchy >> UI  >> Text - TextMeshPro 추가

Canvas와 함께 Text가 자동생성된다.

Canvas 상에서 원하는 위치, 앵커, 글씨체 같은 것들을 수정한다.

Text 추가
Text 초기값 수정

 

4. Interaction 스크립트

플레이어의 카메라 Root를 기준으로 Cast를 발사해 Interact Layer를 가진 객체를 판별하는 스크립트를 작성한다.

public class InteractionController : MonoBehaviour
{
    public float interactionRange = 3f; // 감지 거리
    public float interactionRadius = 0.5f; // Sphere 반지름

    // 상호작용 대상 오브젝트가 포함된 레이어를 지정
    public LayerMask interactableLayer;

    // 상호작용 힌트를 보여주는 UI 텍스트 (예: "[E] 문 열기")
    public TextMeshProUGUI interactHint;

    // 카메라 트랜스폼 연결 필드 추가
    public Transform cameraTransform;
    private IInteractable currentInteractable = null;

    void Update()
    {
        // 카메라 기준으로 SphereCast 쏨
        Vector3 origin = cameraTransform.position;
        Vector3 direction = cameraTransform.forward;

        Ray ray = new Ray(origin, direction);
        RaycastHit hit;

        // SphereCast를 사용해 일정 범위의 오브젝트를 감지
        if (Physics.SphereCast(ray, interactionRadius, out hit, interactionRange, interactableLayer))
        {
            // 충돌한 콜라이더에 IInteractable 인터페이스가 구현된 컴포넌트를 찾음
            var interactable = hit.collider.GetComponent<IInteractable>();

            if (interactable != null)
            {
                currentInteractable = interactable;
                // 상호작용 UI 텍스트를 해당 오브젝트에서 제공하는 텍스트로 설정
                interactHint.text = $"[E] {interactable.GetInteractText()}";

                // UI 텍스트 활성화 (화면에 표시)
                interactHint.enabled = true;

                // 사용자가 E 키를 눌렀을 때 상호작용 함수 호출
                if (Input.GetKeyDown(KeyCode.E))
                {
                    interactable.Interact();
                }
                return; // 감지 성공했으므로 else 처리로 넘어가지 않음
            }
        }

        // 상호작용 가능한 대상이 없으면 UI 텍스트 비활성화
        currentInteractable = null;
        interactHint.enabled = false;
    }
}

 

스크립트는 플레이어 오브젝트에 컴포넌트로 추가해준 뒤

Text와 CameraTransform을 연결해준다.

판별할 Layer를 Interact로 지정한다.

Layer 설정 그리고 Interact Hint, Camera Transform 연결

 

5. Door 스크립트 추가

문의 열림/닫힘 상태를 판단하고 회전각도를 업데이트하는 스크립트를 작성한다.

각자 세팅한 값에 따라 문의 초기상태와 목표값은 다를 수 있다.

Coroutine을 사용해 비동기적으로 부드러운 애니메이션처럼 연출되도록 만들었다.

public class Door : MonoBehaviour, IInteractable
{
    private bool isOpen = true;
    private float closeAngle = -90f;
    private float rotateSpeed = 2f;

    private Quaternion openRotation;
    private Quaternion closeRotation;
    Coroutine curCoroutine;

    void Start()
    {
        openRotation = transform.rotation;
        closeRotation = Quaternion.Euler(new Vector3(0, closeAngle, 0));
    }


    public void Interact()
    {
        if (curCoroutine != null) StopCoroutine(curCoroutine);
        curCoroutine = StartCoroutine(ToggleDoor());
    }

    IEnumerator ToggleDoor()
    {
        Quaternion targetRotation = isOpen ? closeRotation : openRotation;
        isOpen = !isOpen;

        while (Quaternion.Angle(transform.rotation, targetRotation) > 0.01f)
        {
            transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime * rotateSpeed);
            yield return null;
        }
    }

    public string GetInteractText()
    {
        return isOpen ? "is Close" : "is Open";
    }
}

 

결과

결과

 

728x90
반응형