-
[Unity] 유니티 빌드 배경 투명화개발일지 2026. 4. 9. 01:53
디스코드의 오버레이나 데스크탑 방치게임처럼 필요한 공간을 제외한 나머지 공간을 투명화 시키고 싶어서 만들었다.
투명한을 뜻하는 단어는 많지만 보통 이런건 Transprent 라고 불리는듯
따라서 인터넷에서 해당 기능을 더 자세히 알아보고 싶으면 Transparent window로 검색하면 된다.
투명화를 시키고싶으면 Window API를 불러와 필요한 함수를 호출해야한다.
[테스트 코드] Window API를 불러오고 함수 사용
using System; using System.Runtime.InteropServices;//외부에서 함수를 가져오겠다는 의미 using UnityEngine; public class TransparentWindow : MonoBehaviour { /*Windows API함수로 현재 활성화된 창의 핸들을 얻는데 사용 * 궁금해서 찾아봤는데 64비트에서도 user32.dll 밖에 없다함 */ [DllImport("user32.dll")]//user32.dll 파일을 가져와라 public static extern int MessageBox(IntPtr hwnd, string text, string caption, uint type); private void Start() { MessageBox(new IntPtr(0),"Hellow World!","hi world",0); } }using System.Runtime.InteropServices : 외부에서 함수를 가져옴
Dll import ["필요한 파일 명"]: 외부 api에서 해당 파일을 가져오게 함
IntPtr: 포인터나 핸들을 저장 하는 변수? //아직 잘 모르겠다
nint: 포인터 크기를 가진 숫자를 연산하는 느낌이 강하다고 한다. 잘모르겠음!!
Native Int == nint란 플랫폼에 따라 다른 크기를 갖는 정수를 말함.
예를들어 32비트 플랫폼은 32비트 정수가 되고 64비트 플랫폼에서는 64비트 정수가 된다한다.
해당 코드를 실행할 경우 아래와 같이 메시지 상자가 생성된 것을 확인할 수 있다.

표준 Windows 메시지 상자 [테스트 코드] 유니티 백그라운드 투명화
using System; using System.Runtime.InteropServices;//외부에서 함수를 가져오겠다는 의미 using UnityEngine; public class TransparentWindow : MonoBehaviour { /*Windows API함수로 현재 활성화된 창의 핸들을 얻는데 사용 * 궁금해서 찾아봤는데 64비트에서도 user32.dll 밖에 없다함 */ [DllImport("user32.dll")]//user32.dll 파일을 가져와라 public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type); [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); private struct MARGINS { public int cxLeftWidth; public int cxRightWidth; public int cyTopHeight; public int cyBottomHeight; } [DllImport("Dwmapi.dll")] //창 여백을 설정할 수 있게 해주는 함수 private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins); private void Start() { MessageBox(new IntPtr(0), "Hellow World!", "hi world", 0); IntPtr hWnd = GetActiveWindow(); MARGINS margins = new MARGINS { cxLeftWidth = -1 };//음수를 넣으면 유리판처럼 투명해진다. DwmExtendFrameIntoClientArea(hWnd, ref margins); } }[유니티 세팅부분]


FullScreen Mode = FullScreen Window
D3D11은 체크 해제할 것
[테스트 화면]

빌드를 실행하고서 테스트를 위해 대충 박아놓은 하얀 정사각형이 잘 보이는것을 확인할 수 있다.
더보기1. DXD11 껐는지 확인 (대략 유니티 2019 이후 버전만 해당)
2. 메인카메라의 컬러값이 모두 0 0 0 0인지 확인
3. 이전에 SetWindowLong 또는 SetWindowLongPtr을 사용해 투명화 뒷배경 상호작용을 테스트 한 적이 있는지?(불확실함)
나 같은 경우 코드를 작성하기전 다른 사람이 만든 투명화 코드로 테스트한 적이 있었는데
스페이스를 눌러서 백그라운드 상호작용을 껐다 킬수 있게 만든 코드였다.
그런데 이때 상호작용으로 변경된 윈도우 화면 설정이 리셋되지 않고 어디에 저장되었는지 나중에 투명화 코드를 사용할 때 투명화되지않고 검은화면으로 보이거나 흰색 바탕화면으로 보이는 문제가 있었다. (해당 Unity 2022.3.17f1)
가장 좋은 해결 방법은 그전에 쓴 코드를 복붙해서 원상태로 돌리는것이고
아닐시 이거 스타트문에 있는 SetWidowLong 구문을 한줄씩 Awake나 Start에 박아보자. 근데 원인이 이거 아닐수도 있다.
const long WS_EX_LAYERED = 0x00080000L; const long WS_EX_TRANSTPARENT = 0x00000020L; const int GWL_EXSTYLE = -20; [DllImport("user32.dll")] public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hwnd, int nIndes, uint dwNewLong); void Start() { hWnd = GetActiveWindow(); SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED); SetWindowLong(hWnd, GWL_EXSTYLE, (WS_EX_LAYERED | WS_EX_TRANSPARENT)); SetWindowLongPtr(hWnd, GWL_EXSTYLE, (IntPtr)WS_EX_LAYERED); SetWindowLongPtr(hWnd, GWL_EXSTYLE, (IntPtr)(WS_EX_LAYERED | WS_EX_TRANSTPARENT)); }이 코드 그대로 사용시 뒷 배경을 클릭하면 움직이는 유니티의 오브젝트가 멈추는 문제가 있는데 코드나 에디터 설정으로
해결이 가능하다.
Application.runInBackground = true;
[최종코드]
using System; using System.Runtime.InteropServices;//외부에서 함수를 가져오겠다는 의미 using UnityEngine; public class TransparentWindow : MonoBehaviour { /*Windows API함수로 현재 활성화된 창의 핸들을 얻는데 사용 * 궁금해서 찾아봤는데 64비트에서도 user32.dll 밖에 없다함 */ [DllImport("user32.dll")]//user32.dll 파일을 가져와라 public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type); [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hwnd, int nIndes, uint dwNewLong); [DllImport("user32.dll")]//오브젝트 상호작용 가능화 static extern int SetLayeredWindowAttributes(IntPtr hWnd, uint crkey, byte bAlpha, uint dwFlages); private struct MARGINS { public int cxLeftWidth; public int cxRightWidth; public int cyTopHeight; public int cyBottomHeight; } [DllImport("Dwmapi.dll")] //창 여백을 설정할 수 있게 해주는 함수 private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins); //변경할 윈도우 모드 const int GWL_EXSTYLE = -20; const uint WS_EX_LAYERED = 0x00080000; const uint WS_EX_TRANSPARENT = 0x00000020; const uint LWA_COLORKEY = 0x00000001; private void Start() { //0포인터 전달, 텍스트, 캡션 MessageBox(new IntPtr(0), "Hellow World!", "hi world", 0); IntPtr hWnd = GetActiveWindow(); MARGINS margins = new MARGINS { cxLeftWidth = -1 };//음수를 넣으면 유리판처럼 투명해진대 DwmExtendFrameIntoClientArea(hWnd, ref margins); //백그라운드 상호작용 가능 여부 //SetWindowLong(hWnd,GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT);//이코드를 넣은채로 editor에서 실행하면 유니티가 망가짐. SetWindowLong(hWnd,GWL_EXSTYLE, WS_EX_LAYERED);//이코드를 넣은채로 editor에서 실행하면 유니티가 망가짐. 에디터 if 처리를 하던가 빌드안할 시 주석처리 SetLayeredWindowAttributes(hWnd, 0, 0, LWA_COLORKEY);//알파값이0인 완전한 검은색은 클릭이 불가능하게 만듬 Application.runInBackground = true; } }SetLayeredWindowAttributes 백그라운드가 상호작용 되있어도 유니티에 깔아둔 오브젝트와 상호작용 가능하게 해주는 함수
나중에 응용할때 사용할 듯
다른 WindowApi를 정리해둔 위키
pinvoke.net: the interop wiki!
Type a page name and press Enter. You'll jump to the page if it exists, or you can create it if it doesn't. To create a page in a module other than misc, prefix the name with the module name and a period. What is PInvoke.net? A wiki for developers PInvoke.
pinvoke.net
참고영상
https://www.youtube.com/watch?v=RqgsGaMPZTw