Unity-Demo游戲?qū)崿F(xiàn)桌面小寵物
看到網(wǎng)上有用Unity做的桌面小寵物,就自己搜了些資料自己做了一個(gè)小Demo。
核心功能實(shí)現(xiàn)
簡單說一下思路,有一個(gè)腳本跟一個(gè)Shader,通過腳本和Shader負(fù)責(zé)將Unity運(yùn)行時(shí)的背景調(diào)成透明色。這個(gè)是通過調(diào)顏色來進(jìn)行了。具體原理也不清楚,查了查資料大概是這樣
窗口透明化與無邊框
- 通過Windows API調(diào)用
SetWindowLong和DwmExtendFrameIntoClientArea實(shí)現(xiàn)透明背景和隱藏邊框,需在相機(jī)設(shè)置中將Clear Flags設(shè)為Solid Color且透明度為01。 - 注意:背景色需與模型邊緣顏色相近以避免毛邊(如0x00BGR格式的COLORREF值)2。
- 通過Windows API調(diào)用
交互邏輯
- 點(diǎn)擊穿透:通過檢測鼠標(biāo)坐標(biāo)與模型碰撞器實(shí)現(xiàn)交互(如點(diǎn)擊播放撓癢動(dòng)畫)15。
- 拖拽限制:動(dòng)態(tài)計(jì)算模型碰撞器與屏幕邊緣距離,使用
Mathf.Clamp限制移動(dòng)范圍2。
代碼部分
shader
Shader "Custom/MakeTransparent" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_TransparentColorKey ("Transparent Color Key", Color) = (0,1,0,1)
_TransparencyMargin ("Transparency Margin", Float) = 0.01
}
SubShader {
Pass {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma vertex VertexShaderFunction
#pragma fragment PixelShaderFunction
#include "UnityCG.cginc"
struct VertexData
{
float4 position : POSITION;
float2 uv : TEXCOORD0;
};
struct VertexToPixelData
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
};
VertexToPixelData VertexShaderFunction(VertexData input)
{
VertexToPixelData output;
output.position = UnityObjectToClipPos (input.position);
output.uv = input.uv;
return output;
}
sampler2D _MainTex;
float3 _TransparentColorKey;
float _TransparencyMargin;
float4 PixelShaderFunction(VertexToPixelData input) : SV_Target
{
float4 color = tex2D(_MainTex, input.uv);
float deltaR = abs(color.r - _TransparentColorKey.r);
float deltaG = abs(color.g - _TransparentColorKey.g);
float deltaB = abs(color.b - _TransparentColorKey.b);
if (deltaR < _TransparencyMargin && deltaG < _TransparencyMargin && deltaB < _TransparencyMargin)
{
return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
return color;
}
ENDCG
}
}
}
C#
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class TransparentWindow : MonoBehaviour
{
[SerializeField] private Material m_Material;
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("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int cx, int cy,
int uFlags);
[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")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
const int GWL_STYLE = -16;
const int GWL_EXSTYLE = -20;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const uint WS_EX_TOPMOST = 0x00000008;
const uint WS_EX_LAYERED = 0x00080000;
const uint WS_EX_TRANSPARENT = 0x00000020;
const int SWP_FRAMECHANGED = 0x0020;
const int SWP_SHOWWINDOW = 0x0040;
const int LWA_ALPHA = 2;
private IntPtr HWND_TOPMOST = new IntPtr(-1);
private IntPtr _hwnd;
void Start()
{
#if !UNITY_EDITOR
MARGINS margins = new MARGINS() { cxLeftWidth = -1 };
_hwnd = GetActiveWindow();
int fWidth = Screen.width;
int fHeight = Screen.height;
SetWindowLong(_hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
//SetWindowLong(_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT);//若想鼠標(biāo)穿透,則將這個(gè)注釋恢復(fù)即可
DwmExtendFrameIntoClientArea(_hwnd, ref margins);
SetWindowPos(_hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
ShowWindowAsync(_hwnd, 3); //Forces window to show in case of unresponsive app // SW_SHOWMAXIMIZED(3)
#endif
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}
}
具體步驟
1.新建一個(gè)material(材質(zhì)球),選擇剛建立的Shader:

2.將剛寫的C#腳本掛在攝像機(jī)上,攝像機(jī)的Clear Flags模式選擇Solod Color,并將剛建立的材質(zhì)球掛在腳本上。

3.攝像機(jī)的Background屬性要和材質(zhì)球的Transparent Color Key屬性一致:

4.這里要注意一個(gè)點(diǎn),unity19以上的版本需要設(shè)置一個(gè)東西。在playerSetting中將這個(gè)UseDXGIFlipModelSwapchainforD3D11取消勾選。

這樣就可以實(shí)現(xiàn)窗口透明了,然后在場景里加一個(gè)模型跟動(dòng)作就好啦
總結(jié)
到此這篇關(guān)于Unity-Demo游戲?qū)崿F(xiàn)桌面小寵物的文章就介紹到這了,更多相關(guān)Unity-Demo桌面小寵物內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#Url操作類封裝、仿Node.Js中的Url模塊實(shí)例
這篇文章主要介紹了C#Url操作類封裝、仿Node.Js中的Url模塊,實(shí)例分析了C#Url操作類封裝的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-10-10
C# KeyUp事件中MessageBox的回車(Enter)鍵回調(diào)問題解決方案
這篇文章主要介紹了C# KeyUp事件中MessageBox的回車(Enter)鍵回調(diào)問題解決方案,需要的朋友可以參考下2014-07-07
c# DataView.ToTable()方法 去除表的重復(fù)項(xiàng)問題
這篇文章主要介紹了c# DataView.ToTable()方法 去除表的重復(fù)項(xiàng)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Winform 實(shí)現(xiàn)進(jìn)度條彈窗和任務(wù)控制
這篇文章主要介紹了Winform 實(shí)現(xiàn)進(jìn)度條彈窗和任務(wù)控制的方法,幫助大家更好的利用c# winform進(jìn)行開發(fā),感興趣的朋友可以了解下2020-12-12
C#?實(shí)現(xiàn)Ping遠(yuǎn)程主機(jī)功能及代碼演示
這篇文章主要介紹了C#?實(shí)現(xiàn)Ping遠(yuǎn)程主機(jī)功能,本教程將演示1.0.2版本更新功能,以及實(shí)現(xiàn)的具體代碼演示,需要的朋友可以參考下2024-05-05
c#數(shù)據(jù)綁定之刪除datatable數(shù)據(jù)示例
這篇文章主要介紹了c#刪除datatable數(shù)據(jù)示例,需要的朋友可以參考下2014-04-04

