美文网首页
使用Unity制作一个Windows桌面宠物

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

作者: 全新的饭 | 来源:发表于2022-06-01 10:32 被阅读0次

    示意

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

    桌宠.gif

    思路

    主要是2点

    1. 让程序背景透明
      参考文章:Unity 制作萌系live2d桌宠:屏幕自适应+交互
      将TablePetBackSample.cs挂在一个GameObject上。
      将MainCamera的ClearFlags改为SolidColor,Background的颜色改为透明:000000
    using UnityEngine;
    using System;
    // 为了使用属性:DllImport
    using 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
        }
    }
    
    1. 关注鼠标的位置和点击
      将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制作一个Windows桌面宠物

          本文链接:https://www.haomeiwen.com/subject/mhhxmrtx.html