PreviewRenderUtilityを利用してParticleを表示したい!
UnityでParticle SystemのPreview欲しいですよね
でもデフォでいい感じのものがない(カメラの位置とか再生位置どこにしとくんや、BoundingBoxが一番でかいTimeを毎回計算するんかホンマか!?みたいな話があるのでそれはそうなんですが
そこでPreviewRenderUtilityを使っていい感じのアイコンを作ってしまいましょうというのが今回の記事です
そもそもPreviewRenderUtilityって何ぞやという話はこちらから
とはいえPreviewRenderUtility自体は公開されているものではないため、Unityの気分次第で変更されることも粉砕されることもあると思いますので、そこらへんは自己責任でお願いします
Prefabインスタンスを生成する際にはGameObject.InstantiateではなくPreviewRenderUtility.InstantiatePrefabInSceneを使おう
お察しのよい方はお気づきかもしれませんがGameObject.Instantiateなんて使おうものなら、今Editorで開かれているSceneにPrefabのインスタンスが作られてしまいます
GameObjectをプレビュー用のSceneに配置する際にはPreviewRenderUtility.AddSingleGO
PreviewRenderUtility.AddSingleGOにGameObjectを渡すだけでプレビュー用のSceneに配置されます
StaticPreviewとPreviewの使い分け
Textureが欲しい場合はBeginPreview&EndPreview
Texture2Dが欲しい場合はBeginStaticPreview&EndStaticPreview
です
StaticPreviewでない場合はPreviewRenderUtilityのCleanupを書けるとレンダリング結果も消えてしまいます
それらを踏まえて
var previewRenderUtility = new PreviewRenderUtility();
var gameObject = previewRenderUtility.InstantiatePrefabInScene(prefab);
previewRenderUtility.BeginStaticPreview(rect); //初期化
SetupParticles(gameObject); //ここでなんやかんやParticleSystemの設定をします
previewRenderUtility.AddSingleGO(gameObject);
previewRenderUtility.camera.farClipPlane = distance * 2;
previewRenderUtility.camera.transform.rotation = Quaternion.Euler(10, 0, 0);
previewRenderUtility.camera.transform.position = new Vector3(0, なんかいい感じの高さ, いい感じの距離);
previewRenderUtility.Render();
var texture2D = previewRenderUtility.EndStaticPreview(); //出力
previewRenderUtility.Cleanup(); //使い終わったら破棄してあげましょう 破棄しないとSceneが残り続けます
return texture2D;
SetupParticlesの中には、ParticleSystem.Simulateを入れたりだとか、子とかSubEmitterとかの処理を入れておくとよいと思います。
Unity&MacでShell scriptを使いたい!
UnityでShell scriptを使ってなにがしかを実行したいことってありますよね。
いろいろ試してみてこれが良さそうだとなったものを記録しておきます。
Unity起動時にズバババっと処理されるように、InitializeOnLoadにしてあります。
[InitializeOnLoad]
public class Startup
{
static readonly string shPath =
Application.dataPath + "/Hoge.sh";
static Startup()
{
#if UNITY_EDITOR_OSX
StartExecForMac();
#endif
AssetDatabase.Refresh();
}
static void StartExecForMac()
{
var p = new Process();
p.StartInfo.FileName = "/bin/zsh";
p.StartInfo.Arguments = $"-c \"zsh {shPath}\" ";
p.StartInfo.Verb = "RunAs";
p.StartInfo.UseShellExecute = true;
p.Start();
p.WaitForExit();
}
}
UnityでWire Frame Renderingをしたい!
UnityでWire Frame Renderingをしたい場合の方法をご紹介します。
通常の状態でもScene ViewはWire Frame Renderingを行えますが、Unity RecorderでRenderingしたい場合などがあると思います。そういった場合はGame ViewでWire Frame Renderingができた方が都合がいいですね。
こちらに記載通りのScriptをCameraにAttachします。
https://docs.unity3d.com/ja/2019.4/ScriptReference/GL-wireframe.html
using UnityEngine;
public class ShadedWireframe : MonoBehaviour
{
// Attach this script to a camera, this will make it render in wireframe
void OnPreRender()
{
GL.wireframe = true;
}
void OnPostRender()
{
GL.wireframe = false;
}
}
そして、CameraのClear Flagsを"Depth only"に変更します。さぁ実行してみましょう!
綺麗なWire Frameが表示されますね。
Unityの作業効率を上げる系Editor ScriptのTips集
クラスター Advent Calendar 2021 12日目の記事を書きました。
Editor Scriptの意義と軽い導入、Editor Scriptを作る上ではまりがちなTipsをまとめてみました。
https://qiita.com/MSA-i/items/bf9da9a5c5ba00485da3
Unity Editor実行時にbatを走らせてみる
Unity Editor実行時にUnity外で何か処理を走らせたい!ということがありますよね?🤗(ほんまか?
そこで今回はProject外で何かしらのファイルを操作したいときについての話を書いていこうと思います!(備忘録もかねて
基本的には流れとしては、EditorScriptからbatを起動させるだけです。
が、Unity起動後にUnity以外からProject内のファイルを操作すると何かと面倒です。
そこで、Editor起動直後、Unityが動き出す前に何かする方法はないのかと探し回るわけですが、なんと!!
ありがたいことにUnityさんがInitializeOnLoadという属性を用意して下さってます🙏
https://docs.unity3d.com/ja/2019.4/Manual/RunningEditorCodeOnLaunch.html
というわけで
using System;
using System.IO;
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
namespace Hogehoge
{
[InitializeOnLoad]
public class Startup
{
private static readonly string batPath = Application.dataPath + "/hoge.bat";
private static Process p;
static Startup()
{
if (canDo)
{
ExecuteBat();
AssetDatabase.Refresh();
}
}
private static void ExecuteBat()
{
p = new Process();
p.StartInfo.FileName = batPath;
p.StartInfo.Verb = "RunAs";
p.StartInfo.UseShellExecute = true;
p.Start();
p.WaitForExit(); //これを忘れると処理終了を待たずに何回も実行されることになるので注意
}
}
}
これだけでbatをEditor起動直後に実行させられます。バンザイ
注意点は、WaitForExit()を入れることぐらいですかね。これ忘れると悲惨です。
以上です!
UnityのAnimatorを利用する際に気を付けるべきこと
クラスター Advent Calendar 2020 にVRライブなどの非インタラクティブ分野でUnityのAnimatorを利用する際に気を付けるべきことについての記事を書きました。
非ゲーム分野でUnity Animatorの想定外の挙動を避けるために
想定外の挙動を避けるために
1. Rootを配置しよう
2. Apply Root MotionはONにしよう
3. Remove Start OffsetはOFFにしよう
ぐらいのことが書かれています。
Shader Forgeでcluster用のShaderを作る
Shader Forgeでclusterに対応したすべての端末で使用できるShaderをつくりたいという場合は
基本的には以下、二点にチェックを入れるだけで大丈夫です。
「Compile to all platforms」でMetal対応に
「Force Shader Model 2.0」で古いAndroid端末にも対応できます
ただし、上記二点にチェックを入れたとしても軽量化がされるわけではありませんので、重いShaderは重いままです。モバイルで使うShaderは処理を軽くしておきましょう。
自作のUnityPackageを作ってみる
重要なことはここに書かれているので補足をつらつらと書いていきます
https://docs.unity3d.com/Manual/CustomPackages.html
C#スクリプト(.cs)はAssembly Definition Filesがないと読み込まれない
.asmdefがないとcan not be loadedとなります。作り忘れないようにしましょう。
MyCompany.MyFeature.Runtime.asmdefとかと書くのがよさそうです
(Assembly Definition Filesについては↓
http://tsubakit1.hateblo.jp/entry/2018/01/18/212834
ssh接続にすればプライベートリポジトリでもPackageにできる
ssh接続にすればgithubのプライベートリポジトリでもPackageにできるようです。
注意点としては、パスの通ってるGitクライアントからgithubへssh接続できるようにしておかなければいけないということです。SourceTreeなどのGUIクライアントを利用していて、なおかつパスを通してるGitが別にある方は注意
GrabPass {}が便利
clusterやVRChatといったサービスではC#のスクリプトが利用できませんが、Standard Assetsに入っているような
ちょっとリッチなWaterを手軽に利用したいんじゃ~ということがあると思います。(Asset Storeからよさげなヤツ探すのすらめんどくさいときとかありますよね?)
そんなときにGrabPassを使うとShaderだけでSSR(Screen Space Reflection)的なことや屈折表現が簡単にできるよというお話です。
Subshader {
GrabPass {}
Tags {"Queue"="Transparent" "RenderType"="Transparent"}
Pass {
CGPROGRAM
~
#include "UnityCG.cginc"
sampler2D _GrabTexture
実際にStandard AssetsのWaterを魔改造すると↓のようになります
Unityに感謝
UnityHDRP+MMDBridgeで動画を作ってみた
タイトルの通りなんですが、何点か引っかかった点があるためご紹介します。
今回の構成
Unity 2018.4.22f1
・Alembic 1.0.6
・High-Definition RP 4.10.0
・Shader Graph 4.10.0
・Unity Recorder 2.2.0
WaterShaderの挙動がおかしい!
今回は、ShaderGraphで作成したオリジナルのWaterShaderを利用していたのですが、WaveOffsetをTimeNodeのTimeを利用して行っていました。
ところが!
なんとこのTimeはDeltaTimeでは無いようで(DeltaTimeもTimeNodeにあるのですがこちらも機能せず…
UnityRecorderで撮影を行うと、水が高速で波打つなんてことになってしまいました。
今回はC#⃣ScriptからNodeへ直接DeltaTimeを渡してあげることで解決しました。こちらが参考になると思います。
https://forum.unity.com/threads/recorder-writting-exr-files-with-time-based-shader-are-wrong.662551/
基本的には↑のまま、少しだけ処理速度改善
using UnityEngine;
public class FunctionRenderTime : MonoBehaviour
{
[SerializeField] Material waterOffset;
[SerializeField] float timingValue;
[SerializeField] float timer;
static string vectorNodePropertyName = "Vector1_8A6A3EC4";
private static readonly int vectorNodePropertyID = Shader.PropertyToID(vectorNodePropertyName);
// Start is called before the first frame update
void Start()
{
waterOffset.SetFloat(vectorNodePropertyID, timer);
}
// Update is called once per frame
void Update()
{
timer += timingValue * Time.deltaTime;
waterOffset.SetFloat(vectorNodePropertyID, timer);
}
}
なんか出力結果おかしくない?
なんか黒い部分がありますね
こりゃなんだ、というわけで…
実際は黒いわけではなくRGBにはノイズ、Aチャンネルは黒よりのグレーになっています。
結局こちらの問題の原因はいまいちわかりませんでした。
HDRPのBugでしょうか?最新のバージョンでは直っていることを願うばかり
とりあえず今回はゴリゴリpngそのものを修正していきました…
おまけ HDRPだと簡単にきれいに作れて良いですね~