使用Unity制作一个Windows桌面宠物
示意如下图中的狐狸,鼠标左键按住可拖动,鼠标右键按住可调整大小,鼠标左键点击可随机播放一个动作。
桌宠.gif
思路
主要是2点
[*]让程序背景透明
参考文章:Unity 制作萌系live2d桌宠:屏幕自适应+交互
将TablePetBackSample.cs挂在一个GameObject上。
将MainCamera的ClearFlags改为SolidColor,Background的颜色改为透明:000000
using UnityEngine;using System;// 为了使用属性:DllImportusing System.Runtime.InteropServices;public class TablePetBackSample : MonoBehaviour{ private int currentX; private int currentY; #region Win函数常量 private struct MARGINS { public int cxLeftWidth; public int cxRightWidth; public int cyTopHeight; public int cyBottomHeight; } static extern IntPtr FindWindow(string lpClassName, string lpWindowName); static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); static extern int GetWindowLong(IntPtr hWnd, int nIndex); static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags); static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins); private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong); private const int GWL_EXSTYLE = -20; private const int GWL_STYLE = -16; private const int WS_EX_LAYERED = 0x00080000; private const int WS_BORDER = 0x00800000; private const int WS_CAPTION = 0x00C00000; private const int SWP_SHOWWINDOW = 0x0040; private const int LWA_COLORKEY = 0x00000001; private const int LWA_ALPHA = 0x00000002; private const int WS_EX_TRANSPARENT = 0x20; #endregion private IntPtr hwnd; void Awake() { var productName = Application.productName;#if UNITY_EDITOR#else hwnd = FindWindow(null, productName); int intExTemp = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, intExTemp | WS_EX_TRANSPARENT | WS_EX_LAYERED); SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_BORDER & ~WS_CAPTION); currentX = 0; currentY = 0; SetWindowPos(hwnd, -1, currentX, currentY, Screen.currentResolution.width, Screen.currentResolution.height, SWP_SHOWWINDOW); var margins = new MARGINS() { cxLeftWidth = -1 }; DwmExtendFrameIntoClientArea(hwnd, ref margins); #endif }}
[*]关注鼠标的位置和点击
将MyMouse.cs挂在一个GameObject上。
using System;using System.Collections;using System.Collections.Generic;using System.Runtime.InteropServices;using UnityEngine;public class MyMouse : MonoBehaviour{ public static extern short GetAsyncKeyState(int vKey); private const int VK_LBUTTON = 0x01; //鼠标左键 private const int VK_RBUTTON = 0x02; //鼠标右键 private const int VK_MBUTTON = 0x04; //鼠标中键 private bool _isLeftDown; private bool _isRightDown; private bool _isMiddleDown; public event Action<MouseKey, Vector3> MouseKeyDownEvent; public event Action<MouseKey, Vector3> MouseKeyUpEvent; public event Action<MouseKey, Vector3> MouseDragEvent; public event Action<MouseKey> MouseKeyClickEvent; public Vector3 MousePos{ get; private set; } private bool _hasDragged; private Vector3 _leftDownPos; private Vector3 _rightDownPos; private Vector3 _middleDownPos; private void Start() { Init(); } private void Update() { // 按下左键 if (GetAsyncKeyState(VK_LBUTTON) != 0) { if (!_isLeftDown) { _isLeftDown = true; _leftDownPos = MouseKeyDown(MouseKey.Left); } else if (MousePos != Input.mousePosition) { MouseKeyDrag(MouseKey.Left); if (!_hasDragged) { _hasDragged = true; } } } // 按下右键 if (GetAsyncKeyState(VK_RBUTTON) != 0) { if (!_isRightDown) { _isRightDown = true; _rightDownPos = MouseKeyDown(MouseKey.Right); } else if(MousePos != Input.mousePosition) { MouseKeyDrag(MouseKey.Right); if (!_hasDragged) { _hasDragged = true; } } } // 按下中键 if (GetAsyncKeyState(VK_MBUTTON) != 0) { if (!_isMiddleDown) { _isMiddleDown = true; _middleDownPos = MouseKeyDown(MouseKey.Middle); } else if(MousePos != Input.mousePosition) { MouseKeyDrag(MouseKey.Middle); if (!_hasDragged) { _hasDragged = true; } } } // 抬起左键 if (GetAsyncKeyState(VK_LBUTTON) == 0 && _isLeftDown) { _isLeftDown = false; MouseKeyUp(MouseKey.Left); if (!_hasDragged && _leftDownPos == MousePos) { MouseKeyClick(MouseKey.Left); } _hasDragged = false; } // 抬起右键 if (GetAsyncKeyState(VK_RBUTTON) == 0 && _isRightDown) { _isRightDown = false; MouseKeyUp(MouseKey.Right); if (!_hasDragged && _rightDownPos == MousePos) { MouseKeyClick(MouseKey.Right); } _hasDragged = false; } // 抬起中键 if (GetAsyncKeyState(VK_MBUTTON) == 0 && _isMiddleDown) { _isMiddleDown = false; MouseKeyUp(MouseKey.Middle); if (!_hasDragged && _middleDownPos == MousePos) { MouseKeyClick(MouseKey.Middle); } _hasDragged = false; } } private void OnDestroy() { Destroy(); } public void Init() { _isLeftDown = false; _isRightDown = false; _isMiddleDown = false; _hasDragged = false; } public void Destroy() { } private Vector3 MouseKeyDown(MouseKey mouseKey) { RefreshMousePos(); MouseKeyDownEvent?.Invoke(mouseKey, MousePos); // Log.Instance.ShowLog(string.Format("按下:" + mouseKey + ""+MousePos)); return MousePos; } private Vector3 MouseKeyUp(MouseKey mouseKey) { RefreshMousePos(); MouseKeyUpEvent?.Invoke(mouseKey, MousePos); // Log.Instance.ShowLog(string.Format("抬起:" + mouseKey + "" + MousePos)); return MousePos; } private Vector3 MouseKeyDrag(MouseKey mouseKey) { RefreshMousePos(); MouseDragEvent?.Invoke(mouseKey, MousePos); // Log.Instance.ShowLog(string.Format("拖动:" + mouseKey + "" + MousePos)); return MousePos; } private void MouseKeyClick(MouseKey mouseKey) { MouseKeyClickEvent?.Invoke(mouseKey); // Log.Instance.ShowLog(string.Format("点击:" + mouseKey + "" + MousePos)); } private Vector3 RefreshMousePos() { MousePos = Input.mousePosition; return MousePos; } public Vector3 MousePosToWorldPos(Vector3 mousePos) { var screenInWorldPos = Camera.main.WorldToScreenPoint(mousePos); var refPos = new Vector3(mousePos.x, mousePos.y, screenInWorldPos.z); var pos = Camera.main.ScreenToWorldPoint(refPos); return pos; }}public enum MouseKey{ None, Left, Right, Middle}
如何确认是否点击到桌宠?
关注鼠标Down事件,发生时,获得当前鼠标位置mousePos
var ray = Camera.main.ScreenPointToRay(mousePos); if (Physics.Raycast(ray, out RaycastHit hit)) { // 判断hit的是否是桌宠。 }
页:
[1]