爆発風エフェクトを作ってみた

前書き

一昔前のロボットたちが遠目でいっぱい爆発するときのエフェクトを作ってみました。
https://user-images.githubusercontent.com/10098082/128212844-aeedffcb-9b72-4747-83b9-a98b60f55279.png


サンプルはGitHubに上げています。
github.com


環境

Unity 2020.3.14f1
High Definition RP 10.5.1


実装方法

VFX Graphでパーティクルを生成

Projectビューを右クリック -> Create -> Vidual Effects -> Visual Effect Graph でグラフを生成できます。
最終的なVFX Graphの全体像です。(画像がデカいです)

Spawn

ConstantSpawnRateブロックを使用し、生成量を外部から変えられるようにしています。

Initialize Particle

パーティクル数のキャパシティ、座標、生存時間、スケールを設定しています。
スケールはすべて同じ大きさだと味がなかったので0.5~1.0倍の割合でバラつかせるようにしてます。

Update Particle

Set Color over Lifeブロックを使用し、生成から破棄までの色の変化を設定しています。

Set Color over Lifeブロックの中はHDRで、アルファをなくし、白→黄→赤に変化させています。

Output Particle Quad

ShaderGraphVFX Shader Graphを設定することで独自のシェーダーを適用できます。

BlendModeAdditiveに設定していますが、見栄えが良ければ何でも良いです。
Tex0は円形のテクスチャを設定しています。くり抜かれる前の円になります。
ColorGet Attribute: color (Current)ノードを使うことで、VFXGraph内で設定した色をShaderGraphに渡すことができます。
Thresholdは0~1の間でくり抜きを制御しています。1になるほどくり抜きが大きくなり、円→三日月→消滅のようになります。
Center Adjustはくり抜きを行う位置を設定します。X,Y方向をランダムにすることにより、三日月状で消えたりします。*1
Smooth Edgeはくり抜きの速度に使っているSmoothstepのEdge1のパラメータになります。


ShaderGraphで円をくり抜く

Projectビューを右クリック -> Create -> Shader -> VFX Shader Graphでグラフを生成できます。
最終的なVFX Shader Graphの全体像です。

くり抜く円を作る

distance(uv, float2(0.5, 0.5))でテクスチャの幅いっぱいの円が表現ができるので、それをShaderGraphで書きました。
CenterAdjustは円の中心をずらすパラメータです。

Stepノードを使うことで円の大きさを変えることができます。
また、Smoothstepノードを使い、円を大きくするスピードを制御しています。


Stepノードの値は内側が1なのでOne Minusノードを使用し、出力を反転することでAlpha値が0の円にします。
そして、円形のテクスチャをサンプルし、反転した値とかけることでくり抜きを行います。

これで円がくり抜かれる、爆風のようなアニメーションが出来上がりました。


色味を変更する

出来上がったものを見ても少し味気ないように思います。爆発したらもう少し光ってほしいです。
そういうことでPostProcessingを使って加工します。

ブルームを使う

Hierarchyビューを右クリック -> Volume-> Global Volumeを選択するとオブジェクトが生成されます
生成されたオブジェクトにVolumeコンポーネントがあり、Profileという項目にNEWと書かれたボタンがあるので押します。
するとAdd Overrideと書かれたボタンが出現します。

Add Overrideを押し、Post-processing -> Bloomを選択します。
Bloomの項目が出るのでIntensity0.4前後に設定します。

すると、いい感じに光るようになりました。



最後に

VFX GraphVFX Shader Graphを使うことで幅広い表現ができるパーティクルが作られました。


スペシャルサンクス

UGDGのかもそばさんVFX Graphで現在の色を取得するノードを教えていただきました。
ありがとうございます!

*1:x:0.0, y:0.0になることもあるので必ず三日月形になるわけではないです

URPで歪みシェーダーの実装

前書き

URPで背景のバッファの取得とその使用方法をまとめました。

サンプルはGitHubに上げています。
github.com


環境

Unity2020.3.14f1
Universal RP 10.5.1 (ForwardRenderer)
Shader Graph 10.5.1


実装方法

描画されたバッファを取得する

Universal Render Pipeline AssetOpaque Textureにチェックを入れます。

ShaderGraphではSceneColorノードでOpaqueTextureを取得できます。
入力はUV、出力はColorです。

歪ませる

歪みはテクスチャをサンプリングする際のUVをずらすことで表現できます。
サンプルではGradient Noiseノードを使用してUVをずらしています。

出力結果

おまけ:ノイズテクスチャをUVに適用する

ノイズテクスチャをスクロール

タイリングやオフセットは専用のTiling And Offsetノードがあり、OffsetTimeノードのTimeを入れると時間経過でスクロールします。

ノイズをUVに加算する

ノイズテクスチャは白黒で表現されており、値としては0~1になっています。
このまま使っても良いのですが、UVが全体的にずれることになり、実物と見える位置が大きく異なります。
そこで使うのがRemapノードです。
このノードは与えられた数値を指定した数値範囲にマッピングしてくれる優れものです。
今回では0~1-0.01~0.01の範囲にリマッピングしています。

あとは出力された値をScreenPositionと足し合わせることでUVがずれ、歪みとして表現されます。


最後に

URPではGUIでチェックを入れ、ShaderGraphでテクスチャが取得ができるので非常に簡単でした。


参考文献

すでに作ったUnityプロジェクトをGithubに追加するバッチを作ってみた

前書き

Unityでいろいろ試した後にGithubに追加したいけど、フォルダ名がリポジトリ名と被ってしまいリネームして中身を移動させてプッシュするのが手間でした。
なので、ドラッグ&ドロップしたらGithubリポジトリを作って、コミットまでしてくれるバッチファイルを作りました。
フォルダ名がリポジトリ名になります。

バッチファイルのサンプルはGithubにも上げています。



環境


Github CLIをインストールする

対応したOSのものをインストールします。
github.com


Github CLIをセットアップする

コマンドプロンプトgh auth loginと打ち、認証を行います。

どのアカウントでログインするか聞かれます。
Github.comGithub Enterpise Serverの選択肢があります。
今回はGithub.comを選びます。

次にGithubとやりとりをするプロトコルの選択肢が出ます。
今回はHTTPSを選びます。

Githubの認証情報でGitを認証するか聞かれます。
今回はYesを選びます。

どのように認証するか聞かれます。
今回はブラウザでしたいのでLogin with a web browserを選びます。

Enterを押すとブラウザにワンタイムパスを打ち込むページが表示するので、コマンドプロンプトに表示されているワンタイムパスを入力します。

入力したら認証画面が出るので、Authorize githubを押して、認証します。

コマンドプロンプトに戻るとAuthentication complete. Press Enter to continue...と表示されるので、Enterキーを押して終わらせます。

これで認証は終わりです。


バッチを作る

.batファイル作成し、以下のサンプルを張り付けて保存します。
サンプルではRider用に.gitignoreを追記してるので、注意してください。

:: 設定
set GITHUB_ID=eorfeorf
set REPO_TYPE=public
set IGNORE=Unity
set LICENSE=MIT
set DESCRIPTION=""
set ISSUES=false
set WIKI=false

::@echo off
setlocal
popd %~dp0

:: フォルダ名を取得.
:: なぜか末尾が消えるので\をつけ足してる.
set THIS_PATH=%1\
echo %THIS_PATH%
for %%1 in ("%THIS_PATH:~0,-1%") do set REPO_NAME=%%~nx1
echo %REPO_NAME%

:: ローカルを初期化.
pushd "./%REPO_NAME%"
git init -b main
popd

:: Githubのリポジトリを作成.
gh repo create %REPO_NAME% --%REPO_TYPE% -g="%IGNORE%" --license="%LICENSE%" -d=%DESCRIPTION% --enable-issues=%ISSUES% --enable-wiki=%WIKI% -y

:: リモートを追加.
set REPO_URL=https://github.com/%GITHUB_ID%/%REPO_NAME%.git

pushd "./%REPO_NAME%"

:: 生成されたファイルをローカルに.
git remote add origin %REPO_URL%
git pull origin main

:: Rider用に.gitignoreを修正.
echo # Rider>>.gitignore
echo .idea/>>.gitignore

:: 全部をプッシュ.
git add .
git commit -m "First commit"
git push -u origin HEAD:main

基本いじりたい設定を上に持ってきました。
GITHUB_ID

REPO_TYPE

  • リポジトリの公開範囲です。
  • publicとprivateがあります。

IGNORE

  • .gitignoreの種類です。

LICENSE

  • ライセンス設定です。

DESCRIPTION

  • リポジトリのDescriptionです。バッチの都合上、改行が入れられません。

ISSUES

  • issueを有効にするか指定。

WIKI

  • wikiを有効にするか指定。


使い方

リポジトリにしたいフォルダをこのバッチにドラッグ&ドロップします。
Unityの場合はプロジェクトのフォルダになります。


お願い

バッチで現在のフォルダ名を取得する際におまじないみたいなことをしているので、上手く解決できる方はご一報いただけると助かります。


最後に

欲しかった。


URPのShader変数_Timeの実装について

追記

2021/06/30:Time.realtimeSinceStartupの説明を変更しました。
2021/07/01:HDRPの定義を追加
2021/09/10:ShaderGraphのTimeの参考資料と説明を追加

前書き

Built-in Render PipelineUniversal Render PipelineでShaderで使用できる_Timeの実装が違うらしいので調べてみました。


注意点

今回HDRPの_Timeの実装は見ていません。
追記しました。


環境

Unity 2020.3.12f1
Universal RP 10.5.0
High Definition RP 10.5.0


Built-in Render Pipelineの_Time

ドキュメントを見てみると、ステージ(レベル)のロードからの時間と書かれています。
ここで言うステージはたぶんシーンのことを指すと思うので、シーンをロードすると毎回0から始まるようです。
docs.unity3d.com


Universal Render Pipelineの_Time

ここに自動生成される際の実装コードのサンプルがあるでこちらを見たほうが早いです。
docs.unity3d.com

URPで_Timeを設定している箇所はRuntime/ScriptableRender.csSetShaderTimeValues関数で行っており、呼び出し元はExecute関数です。
そこに設定するためのtime変数の定義があります。
github.com
定義は以下の通りです。

#if UNITY_EDITOR
    float time = Application.isPlaying ? Time.time : Time.realtimeSinceStartup;
#else
    float time = Time.time;
#endif
    float deltaTime = Time.deltaTime;
    float smoothDeltaTime = Time.smoothDeltaTime;
    ...
    SetShaderTimeValues(cmd, time, deltaTime, smoothDeltaTime);

コードを見ると、エディタ上ではプレイ中だとTime.time、非プレイ中だとTime.realtimeSinceStartupを入れています。
エディタ上でない場合はTime.timeを入れています。

確かに_Timeの実装が異なっているが確認できます。

おまけ:Time.realtimeSinceStartupって何?

名前の通りですが、アプリケーションを起動してからの時間です。
Time.timeScaleに影響しないのでゲーム中に一時停止に時間を計りたい、アニメーションさせたい場合は良さそうかもしれません。
ただ、プラットフォームやハードウェア依存なので気を付ける必要がありそうです。
docs.unity3d.com


High Definition Render Pipelineの_Time

HDRPはRuntime/RenderPipeline/Camera/HDCamera.csUpdate関数で定義されています。
github.com
定義は以下の通りです。

#if UNITY_EDITOR
    newTime = Application.isPlaying ? Time.time : Time.realtimeSinceStartup;
    deltaTime = Application.isPlaying ? Time.deltaTime : 0.033f;
#else
    newTime = Time.time;
    deltaTime = Time.deltaTime;
#endif
    time = newTime;
    lastTime = newTime - deltaTime;

time変数が_Timeに代入されている値です。
実装自体はURPと変わらないようです。


最後に

実装が異なっていましたが、あまり影響はなさそう雰囲気でした。

ProjectTinyを眺めてみる その1

前書き

アドカレ用に書こうと思います。
https://qiita.com/advent-calendar/2020/botti-unityqiita.com



注意点

DOTSなので今後もAPI等が変わる可能性が十分にあります。



環境



プロジェクトを開く

今回はProjectTinySamples/Tiny3Dを開きます。



眺める

プロジェクト自体は風車がくるくる回るだけのようです。
このシーンで用意されているスクリプトは2つあります。

Assets/Scripts/Components/Rotate.cs

回転に必要な要素を持つコンポーネントです。

using UnityEngine;
using Unity.Entities;

namespace Tiny3D
{
    [GenerateAuthoringComponent]
    public struct Rotate : IComponentData
    {
        public float speedX;
        public float speedY;
        public float speedZ;
    }
}
GenerateAuthoringComponent属性

これはGameObjectをEntityに自動で変換してくれるものです。
今までIConvertGameObjectToEntityを継承したクラスを作り、EntityManagerにコンポーネントをセットする必要がありました。

IComponentData

汎用コンポーネントを作るにはこのインターフェイスを継承する必要があります。

Assets/Scripts/Systems/RotationSystem.cs

using System;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Tiny;
using UnityEngine;

namespace Tiny3D
{
    public class RotationSystem : SystemBase
    {
        protected override void OnUpdate()
        {
            float time = (float)Time.ElapsedTime;
            Entities.ForEach((ref Rotate rotate, ref Rotation rotation) =>
            {
                quaternion qx = quaternion.RotateX(time * rotate.speedX);
                quaternion qy = quaternion.RotateY(time * rotate.speedY);
                quaternion qz = quaternion.RotateZ(time * rotate.speedZ);
                rotation.Value = math.normalize(math.mul(qz, math.mul(qy, qx)));
            }).ScheduleParallel();
        }
    }
}
SystemBase

Systemを実装するのに必要なクラスになります。一連のライフサイクルイベントが定義されおり、全てメインスレッドで動作します。

  • OnCreate()
    • GameObjectのAwake関数にあたります。
  • OnStartRunning()
    • GameObjectのOnEnable関数にあたります。
  • OnUpdate()
    • GameObjectのUpdate関数にあたります。
  • OnStopRunning()
    • GameObjectのOnDisable関数にあたります。
  • OnDestroy()
    • GameObjectのOnDestroy関数にあたります。
Entities.ForEach

ラムダ式の引数にコンポーネントを指定すると、含んでいるEntityを取得し処理します。
引数にrefを指定すると書き込み専用、inを指定すると読み取り専用になり、ジョブが最適化されます。
ジョブを実行するのに、Schedule()ScheduleParallel()を使います。前者は1スレッド、後者は複数スレッドでジョブを実行します。
また、Run()を使用すると、メインスレッド上で直ちにジョブが実行します。



最後に

今回は一番シンプルなシーンになっています。ECSの必要最低限の機能を紹介しました。
次回はこのシーンで使われているTiny用の汎用スクリプトを見ていきます。



ProjectTinyを眺めてみる その0

前書き

アドカレ用に書こうと思います。
https://qiita.com/advent-calendar/2020/botti-unityqiita.com



注意点

DOTSなので今後もAPI等が変わる可能性が十分にあります。



環境



準備

ProjectTinyを手に入れる

GitHubにあるProjectTinyをPullします。
github.com



フォルダ構成

  • RuntimeGeometry3D
    • 動的メッシュを作成するサンプル
  • Tiny2D
    • シンプルな2Dサンプル
  • Tiny3D
    • シンプルな3Dサンプル
  • TinyAquarium
  • TinyFactory
    • コードなしのアニメーションのサンプル
  • TinyGems
    • 2Dのゲーム
  • TinyKitchen
    • 高度なオーサリングフローを使用しているゲーム
  • TinyPhysics
    • 入力とPhysicsを組み合わせたサンプル
  • TinyRacing
    • ゲームに必要な機能が揃っているレースゲーム
  • TinySpaceship
    • 2Dのゲーム
  • TinyTime
    • テキスト・スキンメッシュレンダリングとライティングを動的に変更するサンプル



最後に

サンプルがしっかりあるのでDOTSを知るには良さそうでした。

3DVTuberになるためのツールまとめ

前書き

VTuberなりてえ~!!!となって雑にまとめました。
ある程度知っている人向けです。使い方はまとめていません。


[更新履歴]

2020/08/29:VMagicMirrorを追加。
2020/09/01:VMagicMirrorのリンクを追加。


ツールの組み合わせ

VMC

VRMモデルを全身動かしたいだけれあればこれ単体でできる。トラッカーがない場合は足などがIKで動く。

VMC + LIV

VMCで読み込んだモデルをゲーム内に反映させたい場合はこれ。

VMC + EVMC4U + CineSwitcher

VMCで読み込んだモデルをVR空間で物を持たせたりなどのシステムを組みたい場合はこれ。
CineSwitcherがなくても実現できるが、カメラワークが欲しくなるためセットであると良い。

VMC + waidayo

VMCで読み込んだモデルに表情を反映させたい場合はこれ。
ただし、顔認証機能のついたiPhoneiPadが必要。

Luppet + LeapMotion

VRMモデルをバストアップで動かしたい場合はこれ。WebカメラとLeapMotionを使うので頭、目パチ、手、指がトラッキングできる。

VMagicMirror

キーボードの操作やマウス操作がメインならこれ。頭トラッキングリップシンク、簡易ハンドトラッキングができる。Webカメラとマイクがあればすぐ始められるので非常にお手軽。


各ツール説明

OBS

配信ツール。グリーンバックなどで透過できます。割愛。
Open Broadcaster Software | OBS

VMC(VirtualMotionCapture)

VRMを読み込み、VR機器のトラッカーでトラッキングして、自分の動きをモデルに反映してくれる便利ツール。背景色を変えられるのでそのままOBSに流すだけで簡単に使える。
EVMC4Uなど他ツールにVMCの情報を送信するには、有料版を購入するか、GitHubにあるソースコードを自前でビルドする必要がある。
sh-akira.github.io

EVMC4U(EasyVirtualMotionCaptureForUnity)

VMCと連携してトラッキングしたモデルをUnity上に表示できる。コメントに合わせてギミックを出したりとUnity上で動かす必要があるため凝ったことをしたいなら必須。
VMCが情報を送信する必要があるので、VMCは有料版もしくは自前ビルドが必要。
github.com

CineSwitcher

カメラ制御を便利にするUnityのプラグイン。カメラ切り替えや追従を簡単にできる。Youtube Liveのコメントでカメラを切り替えることも可能。
booth.pm

waidayo

表情のキャプチャができるツール。舌、ほっぺ、眉などのブレンドシェイプができる。VMCに対応しており、キャプチャ情報を送ることでVMC上のモデルに反映できる。
ただし、顔認証機能のついたiPhoneもしくはiPadが必要。
github.com

Luppet

WebカメラとLeapMotionでトラッキングしてVRMモデルに反映させるツール。頭、目パチ、手、指のトラッキングができ、バストアップに特化している。
Webカメラ、LeapMotion、Luppetの3つだけなので値段が高くてVR機器に手が出せない人にオススメ。個人だと5000円のライセンスなので、他機材と合わせても2万円前後から始められる。また、顔や指の細かい動きを表現したい人にもオススメ。
luppet.appspot.com

VMagicMirror

Webカメラとマイクがあれば頭トラッキングリップシンクができる。キーボードやマスウを操作すれば手と腕がIKで動くので、トラッカーがない人でもそれっぽく動けるのが特徴。グリーンバッグができるのでそのままOBSに流せる。
booth.pm

LIV

SteamでVR空間にモデルを合成するツール。Webカメラ・キャプチャカードを使うと実写合成、フルトラッキングしたいならViveトラッカーが必要。実写の場合はグリーンバックが必要。
VMCでは仮想Webカメラとして入力することで合成できる。
store.steampowered.com
LIVで合成 · sh-akira/VirtualMotionCapture Wiki · GitHub


最後に

未だにVTuberデビューまでこぎつけてません。


参考文献

LIV - vrapp Wiki*