
보는 대상이 될 Bench라는 Cube를 생성했습니다.
만들다보니 사물을 분간하기가 어려워져 오브젝트에Material을 적용시켰습니다.
구분하길 원하는 오브젝트에 원하는 색상으로 적용시키세요.
Create -> MaterialObjectObject에 드래그 앤 드롭오브젝트 감지용 스크립트, InteractionDetector을 생성합니다.
Player의 컴포넌트로 추가합시다.
Unity에서는 상대 감지를 위해 Ray, Raycast, RaycastHit 을 사용합니다.
아래 코드는 현재 바라보는 오브젝트의 태그가 Bench일 경우 로그를 띄우는 코드입니다.
using UnityEngine;
using UnityEngine.Experimental.GlobalIllumination;
public class InteractionDetector : MonoBehaviour
{
// Ray가 충돌한 오브젝트의 정보를 저장하는 변수
private RaycastHit hit;
private KeyCode InteractionKey = KeyCode.F;
void Update()
{
if (Input.GetKeyDown(InteractionKey))
{
CheckInteraction();
}
}
private void CheckInteraction()
{
// 화면 중앙 좌표를 구해서 Ray 생성 (크로스헤어 방식)
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2));
// Ray를 5미터 거리까지 쏘아서 충돌 감지
if (Physics.Raycast(ray, out hit, 5f))
{
// 충돌한 오브젝트의 태그가 "Bench"인지 확인
if (hit.collider.CompareTag("Bench"))
{
Debug.Log("Bench를 감지했습니다!");
}
}
}
}
Bench_Panel에 두 개의 Background, 그리고 Scroll View를 추가했습니다.
Bench_Panel
├── Background (Image)
├── Background2 (Image)
└── Scroll View (Scroll View)
Scroll View -> Viewport -> Content 컴포넌트에 Grid Layout Group과 Content Size Fitter을 추가합니다.
Content에 UI_Slot을 테스트 용으로 다수 집어 넣습니다. 나중에 스크립트에서 동적으로 할당하게끔 변경할 예정입니다.
Horizontal: 체크해제Vertical: 체크Scroll Sensitivity: 스크롤 속도Horizontal Fit: UnconstrainedVertical Fit: Preferred Size
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = true;
Bench를 바라본 채 F를 누르면 BenchPanel이 켜지고 꺼지는 코드입니다.
// UIManager.cs
public GameObject benchPanel;
private bool isBenchOpen = false;
public void ToggleBench()
{
if (!benchPanel) return;
isBenchOpen = !isBenchOpen;
benchPanel.SetActive(isBenchOpen);
SetMouseState();
}
// UI가 띄워져 있을 때는 마우스 커서 활성화
private void SetMouseSate()
{
if (isInventoryOpen || isBenchOpen)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
// InteractionDetector.cs
[SerializeField] private UIManager uiManager;
private void CheckInteraction()
{
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2));
if (Physics.Raycast(ray, out hit, 5f))
{
if (hit.collider.CompareTag("Bench"))
{
if (!uiManager) return;
uiManager.ToggleBench();
}
}
}
제작대 창이 켜지고 꺼지는 것을 확인할 수 있습니다.
1. 끄고 다시 열 때 스크롤이 원위치가 되어있지 않음
// UIManager.cs
private ScrollRect benchScrollRect;
void Start()
{
if (benchPanel != null)
{
benchScrollRect = benchPanel.GetComponentInChildren<ScrollRect>();
}
}
public void ToggleBench()
{
if (!benchPanel) return;
isBenchOpen = !isBenchOpen;
benchPanel.SetActive(isBenchOpen);
if (isBenchOpen && benchScrollRect != null)
{
benchScrollRect.verticalNormalizedPosition = 1f;
}
SetMouseSate();
}
2. Bench UI를 킨 채로 다른 곳을 보면 꺼지지 않음
Bench가 있어야 ToggleBench()가 실행하게 코딩되어 있다. UI가 띄워져 있는 동안은 이동 및 카메라 회전을 잠궈두자!// GameState.cs 스크립트 추가
using UnityEngine;
public class GameState : MonoBehaviour
{
public static bool IsUIOpen = false;
}
// UIManager.cs
private void SetMouseSate()
{
if (isInventoryOpen || isBenchOpen)
{
GameState.IsUIOpen = true;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
else
{
GameState.IsUIOpen = false;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
// PlayerController.cs
void Update()
{
if (!GameState.IsUIOpen)
{
HandleMouseLook();
HandleMovement();
HandleJump();
}
}
3. Bench 와 Inventory UI가 동시에 켜질 가능성이 있음
return되게 하자!// UIManager.cs
// 각 함수에 isBenchOpen 혹은 isInventoryOpen일 경우 return 한다는 조건을 추가함
private void ToggleInventory()
{
if (!inventoryPanel || isBenchOpen) return;
isInventoryOpen = !isInventoryOpen;
inventoryPanel.SetActive(isInventoryOpen);
SetMouseSate();
}
public void ToggleBench()
{
if (!benchPanel || isInventoryOpen) return;
isBenchOpen = !isBenchOpen;
benchPanel.SetActive(isBenchOpen);
if (isBenchOpen && benchScrollRect != null)
{
benchScrollRect.verticalNormalizedPosition = 1f;
}
SetMouseSate();
}
UI 완벽 제어 완료!!
Material 적용 및 생성다음 글에서는: