找回密码
 立即注册
查看: 455|回复: 0

使用Unity制作一个Windows桌面宠物

[复制链接]
发表于 2022-6-1 12:48 | 显示全部楼层 |阅读模式
示意

如下图中的狐狸,鼠标左键按住可拖动,鼠标右键按住可调整大小,鼠标左键点击可随机播放一个动作。

桌宠.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;    }    [DllImport("user32.dll")]    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);    [DllImport("user32.dll")]    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);    [DllImport("user32.dll")]    static extern int GetWindowLong(IntPtr hWnd, int nIndex);    [DllImport("user32.dll")]    static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);    [DllImport("Dwmapi.dll")]    static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);    [DllImport("user32.dll")]    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{    [DllImport("user32.dll")]    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的是否是桌宠。 }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 09:53 , Processed in 0.088766 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表