[Unity]uGUIでAfterEffectっぽいモーショングラフィック

# uGUIでオシャレなアニメーションを作りたい

　株式会社グレンジのクライアントエンジニア、flankidsです。

　突然ですが**オシャレなUIアニメーションをササッと作りたい**です。というのも、経歴的にゲームのモックアップを作っていた時期が長いのですが、モックアップは基本少人数開発なので、エンジニアも簡単なアニメーションを作れたほうが何かと都合が良いなと感じることが多いからです。
　とはいえ、モックアップ制作はスピード感が大事。そこばかりに時間を割くわけにもいかないので、結局は拡大・縮小やフェードイン・アウトを使う程度の簡素なものしか作って来れませんでした。

# そこで着目したのがAfterEffectのモーショングラフィック

　なんかいいのないかな〜と思ってたところ、偶然 [AfterEffectのチュートリアル動画](https://youtu.be/vmjPC31WvZU) を目にしました。
　おお、この幾何学的な動きはプログラムで作りやすいし、機能として使い勝手が良さそう！uGUIでこれに近い機能を作れば今後何かの役に立つかもしれない！なんならデザイナーさんにも役立ててもらえるかもしれない！

　ということで実際に作ってみました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">uGUIでAfterEffectっぽいモーショングラフィック <a href="https://t.co/3rwKweAPIB">pic.twitter.com/3rwKweAPIB</a></p>&mdash; バーガーが如く (@flankids) <a href="https://twitter.com/flankids/status/1339312249932894208?ref_src=twsrc%5Etfw">December 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

どうでしょう？それなりに凝ったアニメーションにはできたかも！

# 作った機能の概要

　↑で見てもらったグラフィックは、下記の３つの機能で構成されています。

* 自由に太さを変えられる、端が丸い線（RoundedLineView）
* 指定した図形の輪郭を切り出し、自由にサイズと輪郭の太さを変えられる機能（ThickableShapeView）
* 自由に太さを変えられる、端が丸い**円状**の線（CircleLineView）

**これらの機能をまとめたものを「uGUIMotionGraphics」と名付けてGitHabで公開しています！**

本記事ではこの **uGUIMotionGraphics** を使うための準備と使い方を中心に解説し、実装については補足的な感じで書いていきます。

#### 動作確認環境

* MacOS Catalina（バージョン 10.15.5）
* Unity 2020.1.6f1

# uGUIMotionGraphics導入手順

1. **uGUIMotionGraphics** をGitHubからダウンロード＆プロジェクトにインポート
2. **UnmaskForUGUI** をGitHubからダウンロード＆プロジェクトにインポート
3. **DOTween** をAssetStoreから取得＆インポート

### 1. uGUIMotionGraphics をGitHubからダウンロード＆プロジェクトにインポート

**【GitHub】uGUIMotionGraphics**
https://github.com/fluncle/uGUIMotionGraphics

![github_uGUIMotionGraphics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/f0f2f13b-1593-095a-8d5d-e622371ead47.png)

GitHubからダウンロードしてきて、

![スクリーンショット 2020-12-17 13.12.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/1c95ffaa-68ea-241b-0ec1-d02d6a68b459.png)　![スクリーンショット 2020-12-17 13.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/5f8da176-2cd7-4359-361b-00b4dc66ed5b.png)

uGUIMotionGraphics-○○というディレクトリをProjectにドラック＆ドロップ。
※この時点では後述２つのアセットが不足しているためエラーが出ます。

### 2. UnmaskForUGUI をGitHubからダウンロード＆プロジェクトにインポート

**【GitHub】UnmaskForUGUI**
https://github.com/mob-sakai/UnmaskForUGUI

![スクリーンショット 2020-12-17 13.24.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/29cac9f4-a3ae-d07c-5dd7-53c2c6396747.png)

GitHubからダウンロードしてきて、

![スクリーンショット 2020-12-17 13.29.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/b8ad3bf4-8f20-68fb-6f12-a05cc9d21efe.png)　![スクリーンショット 2020-12-17 13.28.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/0a5ba2cf-e720-9a90-2a1f-f1b2c269c43a.png)

UnmaskForUGUI-○○というディレクトリをProjectにドラック＆ドロップ。

### 3. DOTween をAssetStoreから取得＆インポート

**【AssetStore】DOTween (HOTween v2)**
https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676

![DOTween.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/46c6c846-d5f1-d351-c961-f2efe6356b45.jpeg)

　DOTweenは、uGUIMotionGraphicsのSampleフォルダ内のサンプルシーン動作に使用しているアセットです。
　**サンプルシーンは 16:9 のアス比でいい感じに見えるように作ってある**ので、ご覧いただく際はGameビューの解像度設定を是非！

　ちなみに、**サンプルが不要であればDOTweenのインポートは必要ありません**。（uGUIMotionGraphics/Sampleフォルダを削除お願いします）

# 自由に太さを変えられる、端が丸い線

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">自由に太さを変えられる、端が丸い線 <a href="https://t.co/gz4woHmDSw">pic.twitter.com/gz4woHmDSw</a></p>&mdash; バーガーが如く (@flankids) <a href="https://twitter.com/flankids/status/1339319100854583296?ref_src=twsrc%5Etfw">December 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

※Assets/uGUIMotionGraphics/Samples 内の RoundedLineScene で動作が確認できます
　
　こんな感じで、太さや長さを変えても**端の丸みのアス比が崩れず**、全体の長さに加えて**左右からも長さを変更できる**グラフィックです。

![RoundedLineView構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/4b1295c8-348c-9cc0-8d61-ff36e0bd22b0.png)

　上図のように、4つのパーツを組み合わせて構成しています。ポイントは、

* 端に線の太さと同じ大きさの円を置いていること
* 同じ画像を使ったMaskコンポーネント付きオブジェクトで表示Imageをマスクして**左右からFillAmountできるようにしている**こと

の2点です。

　線の太さが変わらなければ、SpriteEditorでSlicedに対応したSpriteを伸ばすだけで良いのですが、太さを変えるには9Sliceで対応できなかった（端の丸のアス比が破綻する）ため、この設計としています。

### 使い方

Assets/uGUIMotionGraphics/Prefabs 内の RoundedLineView をInspector上のCanvas内に配置してください。

![スクリーンショット 2020-12-17 13.44.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/dd7a8e75-f7dc-4fca-d522-71c8f2d73c01.png)

上図の赤枠内のパラメータがビューを変化させる変数です。

|パラメータ名  |概要  |
|---|---|
|Length  |線の長さ  |
|Thickness  |線の太さ  |
|Color  |線の色  |
|RightFillAmount  |線を右側から縮めるための値。0に近づくほど短くなる  |
|LeftFillAmount  |線を左側から縮めるための値。0に近づくほど短くなる  |

サンプルシーンでは、これらの変数をDOTweenで変化させて演出を作っています。以降で解説するモーショングラフィックも同様です。
変数に値を入れさえすれば良いので、Animationなどでも演出を作ることができます。

# 図形の輪郭を切り出し、サイズと輪郭の太さを変えられる機能

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">図形の輪郭を切り出し、サイズと輪郭の太さを変えられる機能 <a href="https://t.co/3hnPUjGvSL">pic.twitter.com/3hnPUjGvSL</a></p>&mdash; バーガーが如く (@flankids) <a href="https://twitter.com/flankids/status/1339331874410221568?ref_src=twsrc%5Etfw">December 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

※Assets/uGUIMotionGraphics/Samples 内の ThickableShapeScene で動作が確認できます

![スクリーンショット 2020-12-17 14.19.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/8b59b840-8c88-ca95-b01a-0f3d78cc3039.png)

　上図のように、2つのパーツを組み合わせて構成しています。ポイントは、

* **UnmaskForUGUI**を使ってImageに逆マスクをかけ、中をくり抜いている
* 表示Imageと逆マスクImageのSizeを使い、**図形の大きさ・輪郭線の太さを調整しているように見せている**

の2点です。

　ベクタ形式の図形を使っているような調整が可能ですが、実際にはラスタ形式の画像の大きさを変えてるに過ぎないので、**極端に大きなサイズにすると縁がボヤけやすい**ことに注意が必要です！

### 使い方

Assets/uGUIMotionGraphics/Prefabs 内の ThickableShapeView をInspector上のCanvas内に配置してください。

![スクリーンショット 2020-12-17 14.11.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/26e0d9f9-4f43-fc45-297f-008c1491ae79.png)

上図の赤枠内のパラメータがビューを変化させる変数です。

|パラメータ名  |概要  |
|---|---|
|SourceImage  |ベースにする図形  |
|Size  |図形の大きさ  |
|Thickness  |輪郭線の太さ。Sizeの半分の値で図形が完全に塗り潰される  |
|Color  |輪郭線の色  |

**SourceImageを変えることで丸以外の形にも対応できます**。
例えば、Assets/uGUIMotionGraphics/Sprites 内の square にすると四角形の図形で輪郭線を自由に変えるグラフィックが扱えます。


# 自由に太さを変えられる、端が丸い円状の線

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">自由に太さを変えられる、端が丸い円状の線 <a href="https://t.co/UNhXO87g9m">pic.twitter.com/UNhXO87g9m</a></p>&mdash; バーガーが如く (@flankids) <a href="https://twitter.com/flankids/status/1339332787510206464?ref_src=twsrc%5Etfw">December 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

※Assets/uGUIMotionGraphics/Samples 内の CircleLineScene で動作が確認できます

![スクリーンショット 2020-12-17 18.40.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/00f7ff52-322a-5d9a-e2e8-245c9cb40914.png)

　上図のように、5つのパーツを組み合わせて構成しています。ポイントは、

* **ThickableShapeView**の仕組みで円のImageに逆マスクをかけ、太さを制御している
* 表示ImageとマスクImageは回転形式（Radial 360）のFilledTypeで、それぞれ時計回り・反時計周りで円を欠けさせることができる
* **RoundedLineView**と同じような仕組みで、縁に線の太さと同じ大きさの円をくっつけて、丸い縁を実現している

の3点です。つまり合わせ技です！

### 使い方

Assets/uGUIMotionGraphics/Prefabs 内の CircleLineView をInspector上のCanvas内に配置してください。

![スクリーンショット 2020-12-17 14.27.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184294/7bf405b5-c304-ca4f-aa25-e311ce74da0a.png)

上図の赤枠内のパラメータがビューを変化させる変数です。

|パラメータ名  |概要  |
|---|---|
|Size  |図形の大きさ  |
|Thickness  |線の太さ。Sizeの半分の値で図形が完全に塗り潰される  |
|Color  |線の色  |
|RightFillAmount  |円を時計周りで欠けさせるための値。0に近づくほど小さくなる  |
|LeftFillAmount  |円を逆時計周りで欠けさせるための値。0に近づくほど小さくなる  |

# まとめ

　解説は以上です！AfterEffectの機能をUnityに無理やり移植したような形になりました（汗）。シェーダーを上手く使えばもっと賢く意図した図形を作れるのかもですが、ひとまず自分が今できる手段でやりたいことが実現できて満足です。
　実績のあるAfterEffectから機能を移植すればアニメーションのネタも輸入しやすいので、いろいろ潰しが効きそうだなと思います。他にいい機能が見つかったらまたUnityへの移植方法を考えてみたいです（テキスト周りのモーショングラフィックは需要高そう）。

　読んでいただきありがとうございました！ **よろしければ LGTM(いいね)・ストック して頂けると励みになります！** 良いお年を！

# 参考記事

* [(:3[kanのメモ帳] uGUIの画像(Image)の内側を切り抜いて(逆マスクで)表示](https://kan-kikuchi.hatenablog.com/entry/UnmaskForUGUI)
* [[Youtube] トランジション2 AfterEffects チュートリアル](https://youtu.be/vmjPC31WvZU)