포켓몬을 좋아하는 남자친구와 함께 기획한 개인 소장용 포켓몬 방치형 수집게임 개발일지!
📖 오늘의 학습 정리 📖
- 투명창 만들기
- 투명화 세팅
- 클릭 가능하도록
투명창 만들기
1. 투명화 세팅
1단계: 투명하게 그리기

Unity의 Main Camera 설정에서 Background의 Alpha(투명도)를 0으로 세팅하기
2단계: 투명한 캔버스 달라고 요청하기
▼ 전체 코드 (OverlayController.cs)
더보기
using UnityEngine;
using System;
using System.Runtime.InteropServices;
public class OverlayController : MonoBehaviour
{
[Header("창 설정")]
[SerializeField] private bool isAlwaysOnTop = true;
// 윈도우 설정
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
private const int SW_MINIMIZE = 6;
// 창의 확장 스타일 제어
const int GWL_EXSTYLE = -20;
const int WS_EX_LAYERED = 0x80000;
const int WS_EX_TRANSPARENT = 0x20;
// 창 스타일 제어
const int GWL_STYLE = -16;
const int WS_POPUP = unchecked((int)0x80000000);
const int WS_VISIBLE = 0x10000000;
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
const uint SWP_NOSIZE = 0x0001;
const uint SWP_NOMOVE = 0x0002;
private IntPtr hWnd;
private bool isClickThrough = false;
struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
private void Start()
{
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
hWnd = GetActiveWindow();
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED);
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
MARGINS margins = new MARGINS { cxLeftWidth = -1 };
DwmExtendFrameIntoClientArea(hWnd, ref margins);
SetAlwaysOnTop(isAlwaysOnTop);
#endif
}
private void Update()
{
// 왼쪽 Ctrl 키를 누르면 클릭 통과 모드 On/Off 토글
if (Input.GetKeyDown(KeyCode.LeftControl))
{
ToggleClickThrough();
}
}
/// <summary>
/// 클릭 통과 상태 설정/해제
/// </summary>
public void SetClickThrough(bool isTransparent)
{
isClickThrough = isTransparent;
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
int extendedStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
if (isTransparent)
{
SetWindowLong(hWnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
}
else
{
SetWindowLong(hWnd, GWL_EXSTYLE, extendedStyle & ~WS_EX_TRANSPARENT);
}
#endif
}
public void ToggleClickThrough()
{
SetClickThrough(!isClickThrough);
}
/// <summary>
/// '항상 위' 상태를 설정하거나 해제
/// </summary>
/// <param name="isTopmost">true이면 항상 위, false이면 해제</param>
public void SetAlwaysOnTop(bool isTopmost)
{
isAlwaysOnTop = isTopmost;
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
IntPtr flag = isTopmost ? HWND_TOPMOST : HWND_NOTOPMOST;
SetWindowPos(hWnd, flag, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
#endif
}
/// <summary>
/// 창 최소화
/// </summary>
public void MinimizeWindow()
{
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
ShowWindow(hWnd, SW_MINIMIZE);
#endif
}
}
- GetActiveWindow(): 먼저 Windows에게 우리가 제어하고 싶은 창이 무엇인지 알려줘야 한다. 이 함수로 우리 게임 창의 고유 ID(hWnd)를 얻어온다.
- SetWindowLong(..., WS_POPUP): 그 다음, "이 창의 기본 스타일을 바꿔줘" 라고 요청한다. WS_POPUP 스타일을 적용해서 제목 표시줄, 테두리 등 창의 기본 장식을 모두 제거한다.
- DwmExtendFrameIntoClientArea(...): 이 함수는 Windows의 '바탕 화면 창 관리자(DWM)'에게 명령을 내린다.
- 명령 내용: "이 창의 프레임(테두리) 부분을 창 내부 영역까지 전부 확장해줘!"
- MARGINS { cxLeftWidth = -1 }: 이 값은 "모든 방향으로 무한히 확장해줘" 라는 의미의 특별한 신호
계속 Build and Run을 통해서 확인해봤는데, Edit > Project Setting > Player에서 꼭 Use DXGI flip model swapchain for D3D11 체크박스를 꺼주어야 한다.

DXGI Flip Model 스왑체인(“Use DXGI flip model swapchain for D3D11”)을 켜면, Unity가 만드는 윈도우가 ‘레이어드(투명창) 방식’과 충돌해서 알파가 합성에 쓰이지 못하고 검정으로 떨어진다고 한다. Flip Model 방식은 DXGI가 버퍼를 뒤집어(DWM에 직접 넘겨) 합성하기 때문에 지연/전력/성능에 유리하고, 이 방식을 끄면 Blt Model 방식으로 간다는데.. 뭐라는지 모르겠고 아무튼 꺼야지 투명창이 된다.
2. 클릭 통과 구현
- GetWindowLong(..., GWL_EXSTYLE): Windows 창에는 기본 스타일 외에 '확장 스타일'이라는 추가 속성들이 있음. 먼저 이 함수로 "현재 이 창의 확장 스타일 목록을 전부 알려줘" 라고 요청함.
- WS_EX_TRANSPARENT: 이 스타일이 적용된 창은 모든 마우스 이벤트를 무시하고, 자기 바로 아래에 있는 창이나 바탕화면으로 그대로 전달함.
- SetWindowLong(...)으로 스타일 토글하기: Update() 함수에서 Ctrl 키를 감지하여, 이 WS_EX_TRANSPARENT flag를 제어하도록 설정함.
- 클릭 통과 켜기: 기존스타일 | WS_EX_TRANSPARENT
- | (OR) 연산은 기존 스타일 목록에 새로운 스타일을 추가하는 역할을 합니다.
- 클릭 통과 끄기: 기존스타일 & ~WS_EX_TRANSPARENT
- ~는 비트를 반전시키고 & (AND) 연산은 특정 스타일만 정확하게 제거하는 역할을 합니다.
- 클릭 통과 켜기: 기존스타일 | WS_EX_TRANSPARENT
🌱 내일 할 일 🌱
- 기본 AI 움직임 구현
'도토리도굴단 > Project: HoP 개발일지' 카테고리의 다른 글
| [🖥️Project: HoP] #5 무한 점프 시스템 (0) | 2025.12.13 |
|---|---|
| [🖥️Project: HoP] #4 Windows Low-Level Hook과 전역 입력 감지 (0) | 2025.12.11 |
| [🖥️Project: HoP] #3 애니메이션 시스템과 O(1) 최적화 (0) | 2025.12.08 |
| [🖥️Project: HoP] #2 위치 저장과 멀티 모니터 (0) | 2025.12.08 |
| [🖥️Project: HoP] #1 투명 윈도우와 위젯 시스템 구축 (0) | 2025.12.04 |