LoginSignup
5
4

UnrealEngine SVGのベクターアニメーションを使ってワンランク上のUI表現を

Posted at

環境:UE5.3、WebUI Plugin、Lottie 5.12.1

はじめに

こういうアニメーションをUE上で使ってみようという内容のお話です。

See the Pen Lottie Animation Example by deliciousbrains (@deliciousbrains) on CodePen.

ベクター画像とは?

ピクセルの集まりではなく、点や直線、曲線など数式の集まりで作られた画像の事です。
ベクター画像のメリットは

  • 拡大しても画質が落ちない
  • データサイズが小さい
  • 変形が用意

などがあります。
image.png
参照:http://www.persfreaks.jp/main/tool/conic/

SVGとは?

SVG(Scalable Vector Graphics)は画像フォーマットの一種です。
XMLで記述でき、Webに適したベクターファイル形式です。

例:単純な矩形を描画するSVG

See the Pen SVGBox by 癒系 (@hrcvjbtz-the-bashful) on CodePen.

Lottieとは?

さて、このSVGのHTMLを手でチクチク作っても良いのですがそんなの大変すぎるのでGUIのツールを使って作りたいですよね。そこで出てくるのがLottieファイルです。

Lottieは、JSONベースのアニメーション形式で、こんな感じのファイルです。
image.png

LottieはAfterEffectsというツールから出力でき、手軽にベクターアニメーションを作ることができます。
image.png
参照:https://zenn.dev/getgotgoto/articles/7db64306a93193

準備

WebUIプラグインをUE5.3にインストール

これを使うとHTMLの表示、Javascriptとのイベント通知などができるようになります。
ランチャーエンジンであればFreeTrial版で試せます。ソースコードがほしい場合でも15$で購入できます。

インストール方法はドキュメントを見てください。

image.png

サンプルプロジェクトがついているのでこれで確認していきましょう。
image.png
プレイしてUEのアイコンが上下にふわふわしていたらHTMLを表示できています。
FPS表示とPlay、QUITボタン、音量調整のつまみがありますので
このサンプルでBPとのイベント通知の仕組みが確認することができます。

jQuery(function()
{
    $("#playGame").click(function(e)
    {
        $("#logo").fadeOut(1000);
        $("#playGame").fadeOut(1000);
        $("#quitGame").fadeOut(1000);
        $("#volumeSlider").fadeOut(500);

        // executed in blueprints
        ue5("play");
    });

    $("#quitGame").click(function(e)
    {
        // executed in blueprints
        ue5("quit");
    });

    $("#volumeSlider").on("input", function(e)
    {
        // executed in blueprints
        ue5("volume", parseFloat($(this).val()));
    });

    // notify blueprint that browser is ready
    ue5("ready");

    // delay for 1 sec
    setTimeout(function()
    {
        // transmit data to the game
        ue5("print",
        {
            "browser": navigator.userAgent,
            "time": Date.now()
        });
    },
    1000);
});

image.png

Lottie Playerをインストール

ここの
build/playerフォルダを
Contents/HTML以下にコピーします。

playerじゃ分かりにくいのでlottieという名前に変更しました。
image.png

sample.htmlをちょちょっと改造します。

<html>
<head>
<script>
// create the global ue5(...) helper function
"object"!=typeof ue&&(ue={}),uuidv4=function(){return"10000000-1000-4000-8000-100000000000".replace(/[018]/g,function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)})},ue5=function(r){return"object"!=typeof ue.interface||"function"!=typeof ue.interface.broadcast?(ue.interface={},function(t,e,n,o){var u,i;"string"==typeof t&&("function"==typeof e&&(o=n,n=e,e=null),u=[t,"",r(n,o)],void 0!==e&&(u[1]=e),i=encodeURIComponent(JSON.stringify(u)),"object"==typeof history&&"function"==typeof history.pushState?(history.pushState({},"","#"+i),history.pushState({},"","#"+encodeURIComponent("[]"))):(document.location.hash=i,document.location.hash=encodeURIComponent("[]")))}):(i=ue.interface,ue.interface={},function(t,e,n,o){var u;"string"==typeof t&&("function"==typeof e&&(o=n,n=e,e=null),u=r(n,o),void 0!==e?i.broadcast(t,JSON.stringify(e),u):i.broadcast(t,"",u))});var i}(function(t,e){if("function"!=typeof t)return"";var n=uuidv4();return ue.interface[n]=t,setTimeout(function(){delete ue.interface[n]},1e3*Math.max(1,parseInt(e)||0)),n});
</script>
<style>
#fpsMeter{font-family:'Open Sans',Arial,Helvetica,Verdana,sans-serif}
#fpsMeter{position:absolute}
#fpsMeter{top:3vh;left:5vh;color:#fff;font-size:18px;text-shadow:0 0 .2vh rgba(0,0,0,.5),0 0 1vh rgba(0,0,0,.5)}
</style>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="lottie/lottie.min.js" type="text/javascript"></script>
<script>
// called in-game via blueprints
ue.interface.setFPS = function(fps)
{
    // set element text
    $("#fpsMeter").text(fps.toFixed(1) + " FPS");
};

// delay until browser is ready
jQuery(function()
{
    // notify blueprint that browser is ready
    ue5("ready");
});
</script>
</head>
<body style="background-color: transparent; -webkit-user-select: none;">
    <p id="fpsMeter">0 FPS</p>
<div style="width:100%;height:100%;background-color:#333;display:inline-block;" class="bodymovin" data-bm-path="data.json" data-bm-renderer="svg"></div>
</body>
</html>

ポイントは

<script src="lottie/lottie.min.js" type="text/javascript"></script>

ここでプレイヤーのjsを指定して

<div style="width:100%;height:100%;background-color:#333;display:inline-block;" class="bodymovin" data-bm-path="data.json" data-bm-renderer="svg"></div>

ここでjsonファイルを指定すると勝手に再生してくれます。

image.png

やったー!再生できました。

使い所

NowLoading

See the Pen NowLoading by 癒系 (@hrcvjbtz-the-bashful) on CodePen.

ボタン

画面遷移

画面遷移なんかをラスタ画像でやろうとするとテクスチャサイズがデカくなりがちですが
こういう全画面に表示する場合でも小さいサイズのデータできれいに表示できて良さそうです。

image.png
divタグのbackground-colorをtransparentにすれば背景透過もできました。

運用についての提案

UIを全部HTMLで作れるかもと検討してみたのですがHTMLでレイアウトを書くのは大変ですし、かといってホームページビルダーみたいなツールが吐く自動HTMLコードは保守が大変そうです。

ということで、基本はUMGで作ってボタンやカーソルなど部品として使うのがよさそうです。

処理負荷について

image.png

ちゃんと調べてないですがエディタで21個再生してこれくらいなのでボタンとか数個程度なら心配する必要はなさそうです。

まとめ

UMGのアニメーションやマテリアルで頑張ればやれるかもしれないですが
編集環境にAfterEffectsを使えるというのは強い気がします。
手軽にかっこいいアニメーションを作ってユーザーにいいね!
って思ってもらえるようなUIを作っていきたいですね。
自分はプログラマなのでデザインできないですが。

以上。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4