デスクトップが透過するアプリ・ライブ壁紙アプリを Unity で作る

背景が透過するアプリを作るライブラリを見つけたので、参考にちょっと弄ってみました。



<img src="https://www.dropbox.com/s/5usk36t6dnkebz6/Hero.gif?dl=1" /> 



概ね参考にしたライブラリ通りですが、透過ウインドウにはタイトルバーがないから動かせない、という状態を解消する為の機能（↑ `WindowGrabber` ↑）を追加したモノを GitHub にアップ。


- [App Window Utility](https://github.com/sator-imaging/AppWindowUtility)
- [ビルドしたサンプルアプリ](https://github.com/sator-imaging/AppWindowUtility/releases)


丁度いいサイズ感なので、後日 GitHub Packages のテストに使う予定。


<!--
https://qiita.com/sator_imaging/items/e1cb54861b17bbac36ff
-->



--


ライブ壁紙アプリを作れるところまで弄ったものの、一度ライブ壁紙にすると二度と触れない、タスクマネージャーからプロセス終了するしかない状態に。


Unity でタスクトレイ（System Tray）にアイコン表示するための機能も付けなきゃなー、とさらに大袈裟になりそうだったのでライブ壁紙モードは諦め。


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Unityアプリを透過ウインドウに＆ライブ壁紙アプリに<br>海外のストリーマーはライブ壁紙使ってる人いるけど　キャラクターがデスクトップで踊っててもゲーム中は見えないけどな　デスクトップ映った時の画面映えのためかな？ <a href="https://twitter.com/hashtag/madewithunity?src=hash&amp;ref_src=twsrc%5Etfw">#madewithunity</a> <a href="https://t.co/H1pXR4BKln">pic.twitter.com/H1pXR4BKln</a></p>&mdash; サトー (@sator_imaging) <a href="https://twitter.com/sator_imaging/status/1393223216668168202?ref_src=twsrc%5Etfw">May 14, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>





### もくじ


- [参考記事＆リポジトリ](#参考記事リポジトリ)
- [機能](#機能)
    - [透過ウインドウ](#透過ウインドウ)
    - [ウインドウの不透明度](#ウインドウの不透明度)
    - [`WindowGrabber` コンポーネント](#windowgrabber-コンポーネント)
    - [フルスクリーンモード](#フルスクリーンモード)
    - [常に手前に表示（Always on Top）](#常に手前に表示always-on-top)
    - [クリックスルーモード](#クリックスルーモード)
    - [ウインドウフレームの表示](#ウインドウフレームの表示)
    - [カラーキーイングウインドウ](#カラーキーイングウインドウ)
    - [加算合成モード](#加算合成モード)
- [注意点](#注意点)
    - [プレイヤー設定（Player Settings）](#プレイヤー設定player-settings)
    - [High-Definition Render Pipeline (HDRP) と同時に使用する場合](#high-definition-render-pipeline-hdrp-と同時に使用する場合)
    - [透過ウインドウとウィンドウフレームの表示](#透過ウインドウとウィンドウフレームの表示)




## 参考記事＆リポジトリ

いつもありがとうございます。


- [Unity+Windows APIで非矩形ウィンドウ](https://qiita.com/kirurobo/items/013cee3fa47a5332e186) @kiruroboさん
    - 透過部分はクリックスルーで不透明部分はクリック可能だったり macOS 対応だったり、諸々てんこ盛りのリポジトリ
        - ↓ ↓ `UniWindowController` ↓ ↓
        - [kirurobo/UniWindowController](https://github.com/kirurobo/uniwindowcontroller)

- [Unity で Windows の透過ウィンドウを作る（操作も透過）](https://qiita.com/wakagomo/items/6e83019481d7cd326e72) @wakagomoさん

- [VMC（バーチャルモーションキャプチャー）](https://github.com/sh-akira/VMCUnityWindowExtensions)




## 機能


Tested with Unity 2020.3 LTS and HDRP 10.3.2 on Windows 10 64-bit.


### 透過ウインドウ

`bool AppWindowUtility.Transparent { get; set; }`

アプリを透過ウインドウに設定します。ウインドウの後ろにある別のウインドウが透けて見えるようになります。

透明度は Unity のレンダリング結果に依存しているので、カメラの `Background` を **Solid Color** に設定してアルファをゼロにする必要があります。

> 注： High-Definition Render Pipeline (HDRP) やその他の Scriptable Render Pipeline (SRP) ベースのレンダラーを使っている場合、Color Frame Buffer をデフォルトの RGB 10bit から RGB 16bit（8bit があればそちらでも可）に設定する必要があります。

<img src="https://dl.dropbox.com/s/sntvylmfgrrfw9w/Transparent.gif?dl=1" />



### ウインドウの不透明度

`AppWindowUtility.SetWindowOpacity(byte opacity)`

ウインドウ全体の不透明度を設定します。透過ウインドウと組み合わせて使うこともできます。

<img src="https://dl.dropbox.com/s/clu72kycyq2isvn/Opacity.gif?dl=1" />



### `WindowGrabber` コンポーネント

透過ウインドウが有効になっているとタイトルバーが消えてしまうので、ウインドウを移動することが出来なくなってしまいます。

`WindowGrabber` を空の `GameObject` に追加することで、アプリのウインドウのどこかをドラッグすれば移動できるようになります。

<img src="https://dl.dropbox.com/s/oxcnjfdkdshogf0/MoveWindow_WindowGrabber.png?dl=1" />



※ `WindowGrabber` が有効な間も uGUI を使うことが出来ます。  
<img src="https://dl.dropbox.com/s/etmsd3zb0muhltd/MoveWindow.gif?dl=1" />



### フルスクリーンモード

`bool AppWindowUtility.FullScreen { get; set; }`

ウインドウをフルスクリーンに設定します。

> 注： Unity 標準の `UnityEngine.Screen.SetResolution(width, height, isFullScreen)` ではなくコチラを使った方が App Window Utility との相性が良いです。




### 常に手前に表示（Always on Top）

`bool AppWindowUtility.AlwaysOnTop { get; set; }`

ウインドウがフォーカスを失っても、常に最前面に表示されるようになります。

<img src="https://dl.dropbox.com/s/sip8uw1d91osdii/AlwaysOnTop.gif?dl=1" />



### クリックスルーモード

`bool AppWindowUtility.ClickThrough { get; set; }`

アプリケーションがマウスのクリックを受け付けなくなります。

> 注： マウスを使わずにこの機能をオフにする方法を実装する必要があります。実装しなかった場合、二度とアプリに触れなくなります。

<img src="https://dl.dropbox.com/s/o27h63u7g5tg9mm/ClickThru_B.gif?dl=1" />



### ウインドウフレームの表示

`bool AppWindowUtility.FrameVisibility { get; set; }`

ウインドウのフレームを表示・非表示に設定します。

※ 透過ウインドウに設定すると、同時にフレームの表示もオフに設定されます。



### カラーキーイングウインドウ

`AppWindowUtility.SetKeyingColor(byte red, byte green, byte blue)`

アプリのウインドウ全体に対して、特定の色を透過させる機能を有効にします。
かなり特殊なので、`AppWindowUtility.Transparent` を使った方が良いです。



### 加算合成モード

Windows の場合、`AppWindowUtility.SetKeyingColor(0, 0, 0)` を設定した後に `AppWindowUtility.Transparent = true` を設定すると、透過ウインドウが加算合成モードになります。

※注※ これは Windows のバグの可能性があります。

<img src="https://dl.dropbox.com/s/nt5mmncsz6cfvh6/AdditiveComposition.gif?dl=1" />



## 注意点


### プレイヤー設定（Player Settings）

正しく動作させるためには、**Use DXGI Flip Model Swapchain for D3D11** をオフに設定する必要があります。

※ App Window Utility が期待通りに動作しない場合、以下のプレイヤー設定を参考にしてください。

<img src="https://dl.dropbox.com/s/72ii6o5dj7yxqtt/Notes_PlayerSettings.png?dl=1" />



### High-Definition Render Pipeline (HDRP) と同時に使用する場合

**Color Buffer Format** は必ず RGB 16bit（またはホスト OS が対応しているフォーマット）に設定する必要があります。
Scriptable Render Pipeline (SRP) ベースのレンダラーは同様の設定が必要になります。

<img src="https://dl.dropbox.com/s/d1qieutmog4npbw/Notes_HDRP.png?dl=1" />



### 透過ウインドウとウィンドウフレームの表示

`Transparent = true` を設定した後に `FrameVisibility = true` を設定すると、アプリの背景が非表示になった状態でウインドウフレームが表示されます。結果としてウインドウ全体がフレームの色で塗りつぶされることになります。

<img src="https://dl.dropbox.com/s/sr55jdguin250ic/Notes_TransparentThenShowFrame.gif?dl=1" />



--


以上です。お疲れ様でした。