我正在寻找一种制作Unity3D游戏的方法,当我不点击某些游戏内容(如按钮或带碰撞器的物体)时,使窗口透明并点击直播
这对我很有帮助。事实上,有一个答案可以在点击和非点击之间切换
这是我的问题。使用该脚本,当Im在具有碰撞器的对象上时,鼠标位置在x轴上反转: https://i.stack.imgur.com/70CdC.gif
我尽我所能,但我真的不懂Windows api,所以我无法修复它。
有人可以告诉我应该修复什么吗?
这是我正在使用的代码:
using System;
using System.Runtime.InteropServices;
using UnityEngine;
[RequireComponent (typeof (Camera))]
public class TransparentWindow : MonoBehaviour
{
[SerializeField]
private Material m_Material;
[SerializeField]
private Camera mainCamera;
private bool clickThrough = true;
private bool prevClickThrough = true;
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const int HWND_TOPMOST = -1;
int fWidth;
int fHeight;
IntPtr hwnd;
MARGINS margins;
void Start()
{
mainCamera = GetComponent<Camera> ();
#if !UNITY_EDITOR // You really don't want to enable this in the editor..
fWidth = Screen.width;
fHeight = Screen.height;
margins = new MARGINS() { cxLeftWidth = -1 };
hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
DwmExtendFrameIntoClientArea(hwnd, ref margins);
Application.runInBackground = true;
#endif
}
void Update ()
{
// If our mouse is overlapping an object
RaycastHit hit = new RaycastHit();
clickThrough = !Physics.Raycast (mainCamera.ScreenPointToRay (Input.mousePosition).origin,
mainCamera.ScreenPointToRay (Input.mousePosition).direction, out hit, 100,
Physics.DefaultRaycastLayers);
if (clickThrough != prevClickThrough) {
if (clickThrough) {
#if !UNITY_EDITOR
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowLong (hwnd, -20, (uint)524288 | (uint)32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetLayeredWindowAttributes (hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
#endif
} else {
#if !UNITY_EDITOR
SetWindowLong (hwnd, -20, ~((uint)524288) | ((uint)32));//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetLayeredWindowAttributes (hwnd, 0, 255, 2);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
#endif
}
prevClickThrough = clickThrough;
}
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}}
我希望有人能帮助我! :(谢谢!
答案 0 :(得分:0)
这对我有用。
首先,您只需要一次SetWindowLong调用 然后,使用(-20)而不是GS_STYLE作为声明的'else'一半。 像这样:
void Update ()
{
// Raycast stuff
if (clickThrough != prevClickThrough) {
if (clickThrough) {
#if !UNITY_EDITOR
SetWindowLong (hwnd, -20, (uint)524288 | (uint)32);
//other code
#endif
} else {
#if !UNITY_EDITOR
SetWindowLong(hwnd, -20, WS_POPUP | WS_VISIBLE);
//other code
#endif
}
prevClickThrough = clickThrough;
}
}