캐릭터 로드

This commit is contained in:
2026-08-26 03:39:36 +09:00
parent 8d1881749c
commit 7204afae54
31 changed files with 1750 additions and 41 deletions

View File

@@ -139,22 +139,10 @@ bool HitTest(out RaycastHit hit)
{
hit = default;
if (hitTestCamera == null) return false;
if (!Win32.GetCursorPos(out var pt)) return false;
if (!Win32.GetWindowRect(window.Hwnd, out var rc)) return false;
// 좌표 변환은 DesktopCursor 에 모아뒀다. 시선 추적도 같은 변환을 쓴다.
if (!DesktopCursor.TryGetScreenPosition(window.Hwnd, out Vector2 sp)) return false;
int w = rc.Width, h = rc.Height;
if (w <= 0 || h <= 0) return false;
// 창 기준 좌표 (좌상단 원점, Y 아래로)
int localX = pt.x - rc.left;
int localY = pt.y - rc.top;
if (localX < 0 || localY < 0 || localX >= w || localY >= h) return false;
// Unity 화면 좌표 (좌하단 원점, Y 위로)
float ux = localX * (Screen.width / (float)w);
float uy = (h - localY) * (Screen.height / (float)h);
var ray = hitTestCamera.ScreenPointToRay(new Vector3(ux, uy, 0f));
var ray = hitTestCamera.ScreenPointToRay(new Vector3(sp.x, sp.y, 0f));
return Physics.Raycast(ray, out hit, maxRayDistance, interactableLayers);
}

View File

@@ -0,0 +1,52 @@
using UnityEngine;
using UnityEngine.InputSystem;
/// <summary>
/// OS 커서 위치를 Unity 화면 좌표로 변환한다.
///
/// 우리 창은 WS_EX_NOACTIVATE 라 포커스를 받지 않으므로 Unity 의 Mouse.position 을
/// 신뢰할 수 없다. 또 창 밖 좌표는 Unity 가 아예 모른다. 그래서 GetCursorPos 로
/// OS 커서를 직접 읽고 창 사각형 기준으로 환산한다.
///
/// 히트테스트와 시선 추적이 같은 변환을 쓰므로 여기 한 곳에만 둔다.
/// </summary>
public static class DesktopCursor
{
/// <summary>
/// 커서의 Unity 화면 좌표(좌하단 원점)를 구한다. 커서가 창 밖이면 false.
/// </summary>
public static bool TryGetScreenPosition(System.IntPtr hwnd, out Vector2 screenPos)
{
screenPos = default;
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
if (hwnd == System.IntPtr.Zero) return false;
if (!Win32.GetCursorPos(out var pt)) return false;
if (!Win32.GetWindowRect(hwnd, out var rc)) return false;
int w = rc.Width, h = rc.Height;
if (w <= 0 || h <= 0) return false;
// 창 기준 좌표 (좌상단 원점, Y 아래로)
int localX = pt.x - rc.left;
int localY = pt.y - rc.top;
if (localX < 0 || localY < 0 || localX >= w || localY >= h) return false;
// Unity 화면 좌표로. 창 크기와 백버퍼 크기가 어긋날 경우를 대비해 비율 환산.
screenPos = new Vector2(
localX * (Screen.width / (float)w),
(h - localY) * (Screen.height / (float)h));
return true;
#else
// 에디터에서는 일반 마우스 입력으로 대체해 미리보기가 가능하게 한다.
var mouse = Mouse.current;
if (mouse == null) return false;
Vector2 p = mouse.position.ReadValue();
if (p.x < 0f || p.y < 0f || p.x >= Screen.width || p.y >= Screen.height) return false;
screenPos = p;
return true;
#endif
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b4fb0f7484cbf394fbdcc4d532b4ed07

View File

@@ -21,10 +21,7 @@ public class TransparentWindow : MonoBehaviour
[Tooltip("작업표시줄 / Alt+Tab 에서 숨김 (WS_EX_TOOLWINDOW)")]
[SerializeField] bool hideFromTaskbar = true;
[Header("검증용")]
[Tooltip("런타임 큐브 생성. 씬에 AlphaTestCube 가 있으면 그쪽이 우선한다")]
[SerializeField] bool spawnTestCube = false;
[Header("렌더링")]
[Tooltip("URP 포스트프로세싱 비활성화")]
[SerializeField] bool forceDisablePostProcessing = true;
@@ -32,7 +29,6 @@ public class TransparentWindow : MonoBehaviour
[SerializeField] bool quitOnEscape = true;
Camera cam;
Transform testCube;
/// <summary>플레이어 창 핸들. 준비되기 전에는 Zero.</summary>
public System.IntPtr Hwnd { get; private set; } = System.IntPtr.Zero;
@@ -55,11 +51,6 @@ void Awake()
}
Application.runInBackground = true;
// 씬에 큐브가 있으면 그것을 쓰고, 없을 때만 런타임 생성
var inScene = GameObject.Find("AlphaTestCube");
if (inScene != null) testCube = inScene.transform;
else if (spawnTestCube) CreateTestCube();
}
void Start()
@@ -73,8 +64,6 @@ void Start()
void Update()
{
if (testCube != null) testCube.Rotate(new Vector3(30f, 45f, 15f) * Time.deltaTime);
// 포커스가 있을 때만 동작하는 보조 탈출구
if (quitOnEscape)
{
@@ -83,14 +72,6 @@ void Update()
}
}
void CreateTestCube()
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = "AlphaTestCube";
cube.transform.position = transform.position + transform.forward * 5f;
testCube = cube.transform;
}
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
IEnumerator ApplyWindowStyle()
{