728x90
반응형
간단한 코드 예시와 함께 문 열고 닫는 상호작용을 만들어보려고 한다.
1. 인터페이스 정의
상호작용 대상에 붙일 인터페이스를 정의한다.
public interface IInteractable
{
void Interact();
string GetInteractText(); // UI 힌트용
}
2. Layer 지정
Door 오브젝트의 Layer를 지정해준다.
알맞은 Layer가 없다면 Add Layer 클릭 후 추가한다.
Door는 Collider 컴포넌트가 있어야 한다.
3. 상호작용 Text 추가
Hierarchy >> UI >> Text - TextMeshPro 추가
Canvas와 함께 Text가 자동생성된다.
Canvas 상에서 원하는 위치, 앵커, 글씨체 같은 것들을 수정한다.
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로 지정한다.
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
반응형
'Unity 학습' 카테고리의 다른 글
Unity MonoBehaviour 클래스의 Awake, Start, Update 메서드의 개념 (0) | 2025.07.15 |
---|---|
유니티 public vs SerializeField 차이점 정리 (0) | 2025.06.20 |
Unity 오브젝트 풀링(Object Pooling)과 프리팹(Prefab)의 개념정리 (0) | 2025.06.19 |
Unity ScriptableObject의 개념과 MonoBehaviour와의 차이점 (0) | 2025.06.16 |
유니티 Starter Assets 무료 에셋을 이용한 3인칭 카메라 추적 만들기 (0) | 2025.06.10 |