it编程 > 游戏开发 > 游戏引擎

Unity-Demo游戏实现桌面小宠物

16人参与 2025-08-17 游戏引擎

看到网上有用unity做的桌面小宠物,就自己搜了些资料自己做了一个小demo。

核心功能实现

简单说一下思路,有一个脚本跟一个shader,通过脚本和shader负责将unity运行时的背景调成透明色。这个是通过调颜色来进行了。具体原理也不清楚,查了查资料大概是这样

代码部分

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);//若想鼠标穿透,则将这个注释恢复即可
        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.新建一个material(材质球),选择刚建立的shader:

2.将刚写的c#脚本挂在摄像机上,摄像机的clear flags模式选择solod color,并将刚建立的材质球挂在脚本上。

3.摄像机的background属性要和材质球的transparent color key属性一致:

4.这里要注意一个点,unity19以上的版本需要设置一个东西。在playersetting中将这个usedxgiflipmodelswapchainford3d11取消勾选。

这样就可以实现窗口透明了,然后在场景里加一个模型跟动作就好啦

总结

到此这篇关于unity-demo游戏实现桌面小宠物的文章就介绍到这了,更多相关unity-demo桌面小宠物内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

285H处理器有多强? 零刻 GTi15 Ultra给迷你主机游戏性能测评

08-16

抠门装机! 高性价比AI装机配置推荐

08-11

2000价位经典对位战! 锐龙7 9700X和酷睿i7-14700K游戏性能对比测评

08-11

电脑提示dao360.dll丢失怎么办? dao360.dll缺失或安装错误修复指南

08-09

移动端RTX/桌面端RTX 5060差别大吗? 实际游戏体验对比评测

08-09

高阶游戏电脑必备! zalman思民ALPHA2 DS A36水冷散热器测评

07-31

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论