20210911のUnityに関する記事は10件です。

Deferred Renderingの強み

概要 Deferred Renderingを詳しくしりたい ついでにUnityでサンプルを作って負荷比較しました サンプル とりあえず効果がわかりやすいケースでForwardとDeferredで比較します Forward Rendering Deferred Rendering 効果がない それはそう。なぜならDeferred Renderingの強みを活かせてないから。 本命はこっち Forward Rendering Deferred Rendering SetPassがForwardだと10倍以上増えてるのに、Deferredだと2倍ぐらいしか増えてない! FPSには露骨な差がでてます 違いはDirectional Lightに追加して街灯に2個ずつ計4個のPoint Lightを設置しただけ Deferred Renderingは複数の光源がある場合に負荷を大きく減らすことができます (限定的な影響範囲の光源が多く、かつ近くに複雑なメッシュがあるとより効果が大きい) 技術解説 一般的なレンダリングでは スクリーン座標変換 → ラスタライズ → ライティング → レンダリング結果 が行われる Deferred Renderingで高速になるのは「ライティング」の処理 Forward Renderingのライティング オブジェクトのバウンティングボックスを元に影響のあるライトを探索 オブジェクトの全ピクセルにライティング処理 スクリーンスペースに変換してレンダリング これには計算の無駄が多い ・ライト範囲外のピクセルにも計算してる ・スクリーンスペースに変換すると描写されないピクセルも計算してる Deferred Renderingのライティング ラスタライズ後にジオメトリ情報をG-Bufferにキャッシュ G-Bufferを元にライティングする考えがDeferred(遅延) Rendering スクリーンスペース変換されたG-Bufferに位置・法線・色を書き込み ライト範囲内のピクセルのみライティング計算 レンダリング Forward Renderingと比べて効率的なのがわかる しかもライトが多くライト範囲外のピクセルが多いほどキャッシュ利用頻度が高くなり効果が大きくなる Deferred Renderingの苦手なこと 半透明のオブジェクトを処理できない G-BufferにAlpha情報を保持できない。保持しようと思うとメモリが必要になる 代わりにForward Renderringを使うのが一般的 MSAAが使えない 使えないわけではないがコスパが悪い SSAAと大して変わらない結果になったりするらしい ライトの数には強いけど距離が長いのは苦手? 苦手というか強みが薄れる。Directional LightのみならForward Renderingと大差ない Unityでは平行投影でのDeferred Renderingはサポートされてない 理由不明 でも平行投影カメラで複数ライトが必要なケースが思いつかないしいいか 利用ケースの考察 ・PBRでライティングが変わる想定でモデリング ・広めのマップ ・光源を複数おく などのリッチな絵作りが必要なら試す価値がありそうです 夜の街を歩くマップなら効果が大きそう サポート端末 Deferred RenderingにはMRT(Multi-Render-Target)が必須となる MRT(Multi-Render-Target)とは一度のレンダリングパスで複数バッファに異なる値を同時出力する機能。 これがないとG-Bufferで位置・法線・色をバッファに書き込めず、ライティングを効率化できない。 ほとんどの PC グラフィックスカードはディファードシェーディングをサポート モバイル:最低 OpenGL ES 3.0 を実行するすべてのデバイスでサポート 参考文献 ↑レンダリング基礎をわかりやすく教えてもらえる。おすすめ度◎ ↑Unity公式ドキュメント。Deferred Rendering自体はあまり説明してくれない。 あくまでUnityの実装について簡単に書いてるだけ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity Memory 削減したい。参考先一覧。勝手に順位つけた。

1位 シンプルに凄くためになる。 2位 Mesh Bakerの使い方 あれ??wasmじゃなくない?? そういえば3D Kit Lite いれた時変わってた気がする。orz((^ ^
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity 攻撃基礎参考にしたもの一覧

動き https://miyagame.net/vroid-unity-unity/ なんか色々 https://www.ame-name.com/archives/tag/%E6%94%BB%E6%92%83 3D Game Kit Lite とキャラの差し替えをした https://hoshimi12.com/?p=20488#i-7 https://hoshimi12.com/?p=20503 3D game kit について
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityを始める際にみたサイトetc.

VScode設定 https://qiita.com/GengroHirano/items/e2e72102446a810fa119 https://www.exceedsystem.net/2020/08/25/how-to-enable-intellisense-in-vscode-for-unity/ https://unity-yuji.xyz/vscode-unity-omnisharp-netframework-mono/ class 参照けい https://qiita.com/Teach/items/8d1cdb90a3b533707c9a // 下重要 https://miyagame.net/other-script-method/ onpress 動的色変更 カメラ回転
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アバターの衣装バリエーション作成にPrefabを使う(VRChat)

はじめに どうも。「バーチャルためにならない改変お姉さん」の水無月せきなです。 アバターの改変とそのバリエーション作成をしていたら、「そう言えば、プレハブ化したら部分的に楽ができるんじゃないか」と思った話です。 環境 Unity 2019.4.29f1 プレハブ(Prefab)って何? Unity公式に説明を譲ります(丸投げとも言う)。 ざっくり言えば、シーンに配置するオブジェクトの設計図、でしょうか。 このプレハブをドラッグ&ドロップしてシーン上に配置されたオブジェクトのことは、そのプレハブの「インスタンス」と呼ぶようです。 プレハブをぽいぽいと置いていけば、中身がそっくり同じなインスタンスを望むだけ作れます。 また、インスタンスそれぞれで変更された内容は、元となったプレハブには反映されません。1 逆に、プレハブの内容を変更した場合は、派生したインスタンスすべてに反映されます。2 プレハブ化で何が楽になるのか? 別にアバターに限った話ではありませんが、今回はアバターの改変で話を進めます。 あるアバターの髪型や髪色を変え、アクセサリーを追加し、改変したとしましょう。 次に、新たに衣装の違うバリエーションを別で作る必要に迫られました。 先に作成したバージョンを複製して、衣装を変えることで作成します。 これで別バージョンも出来てめでたし……と思いきや、アバターの髪型を変えたくなってしまいました。 アバターの髪型を統一して変えようとすると、最初に作成したアバターと、次に作成したアバターの両方を修正しないといけません。 今回の例では作成したバリエーションが2つなので、そう大した手間ではありませんが、修正箇所が多数に及ぶ場合やバリエーションがより多い場合には、大変な手間となってしまいます。 というか、バリエーションを1つずつ1から作るのも面倒です。 ……先ほど、プレハブという機能の存在を紹介しました。1つ1つ別に作っていくのではなく、どのバリエーションでも共通する部分(たとえば髪・顔・体など)をまず作ってプレハブ化します。そしてそのインスタンスを作れば、後はバリエーションの部分を作るだけです。修正も、共通部分であればプレハブ側で変更するだけで全てのインスタンスを修正することができます。プレハブを利用することで、だいぶ手間を省けるのではないでしょうか? 改変後で共通する部分を素体としてプレハブ化 ということでやっていきましょう。 プレハブ化は、Hierarchy から Project タブへドラッグ&ドロップすることで簡単にできます。 プレハブ化すると、シーン上のオブジェクトはインスタンスに変わります。 新たにインスタンスを作成する場合は、プレハブをシーン上にドラッグ&ドロップするだけです(VRChatter には馴染み深いと思います)。 さて、改変をどんどん進めていき、こんなインスタンスが出来上がりました。 かなり色々変えましたが、元のプレハブはどうなっているでしょうか。 元のプレハブには、インスタンス側での変更は反映されていません。 他のインスタンスにも反映されていません。 では逆に、プレハブの内容を変更してみます。 プレハブの編集画面へは、プレハブ右の「>」から入れます。 編集画面がこちら。 試しに、Action Layer に Animator を設定してみます。 画像左上(Wolferia_Base の左)にある「<」から元の画面に戻ります。 これでプレハブの内容を変更したわけですが、インスタンス側ではどうなっているでしょうか。 インスタンス側の Action Layer にも 同じ Animator が設定されました。 既にあるインスタンスは全て反映されますし、これから新たに作る場合も変更済みで作成されるので、だいぶ便利じゃないでしょうか。 注意点 既にインスタンス側で変更がされている内容については反映されません。 たとえば、体のシェイプキーをプレハブの値から変更しているインスタンスには、プレハブでそのシェイプキーの値が変更されても反映されません。3 プレハブとの関連が絶たれているため、プレハブがアンパッケージ( UnPack Prefab )されている場合も反映されません。 また、プレハブ内のオブジェクトの削除はできない4などの制約があったりします。 おわりに 既にご存知の方も多いかなと思いながら書きました。また、SDK3 の導入によって1つのアバターに多数の衣装を詰め込んで着替えることが容易になったため、バリエーションを別個のアバターとして作成する機会は減ったかと思います。 ただ、他に応用が利くかもしれませんので、とりあえず勉強成果ということで。 それでは。 参考 インスタンスで変更した内容をプレハブに反映する方法もありますが、今回は割愛します。 ↩ 後述の通り、インスタンス側で変更済みの項目・UnPack Prefab されている場合については反映されません。 ↩ インスタンスの状態をプレハブに合わせることによって、結果的に反映させることはできますが、今回はそこまで考えません。 ↩ Inspector 上で Enable のチェックボックスを外し、Tag を Editor Only にすることで、事実上の削除は可能です。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

対称性のあるmeshを作る

はじめに Unityでスクリプトからmeshを作って 対称性のあるオブジェクトを描画しようとしてみた備忘録 環境:Unity 2020.3.12f1 対称なものをつくる Quaternionであらかじめ 軸に対して対称となる回転系を用意しておく。 これに、中心から少し離れた位置にある座標を掛けることで、球面上のどこかの点をとるようになる。 うまく内側の球と外側の球の大きさや角度を調整すると 多面体や星形多面体などの対称性のある形が現れるはず。 流れ まず一つ  三角ポリゴンを描画し、 前後にミラーし、 上下にミラーし、 あと、X軸、Y軸に90度づつねじれた形に回転しつつ複製しています。 スクリプト MakePolyhedron.cs using System.Collections.Generic; using UnityEngine; public class MakePolyhedron : MonoBehaviour { // 3軸対象 readonly Quaternion[] _qs3S = {Quaternion.Euler(0, 0, 0), Quaternion.Euler(0, 90, 90), Quaternion.Euler(90, 0, 90)}; // 前後対象 readonly Quaternion[] _qfbs = {Quaternion.Euler(0, 0, 0), Quaternion.Euler(0, 180, 0)}; // 上下対象 readonly Quaternion[] _qtbts = {Quaternion.Euler(0, 0, 0), Quaternion.Euler(0, 0, 180)}; private readonly List<Vector3> _vertices = new List<Vector3>(); private Mesh _mesh; private void Start() { GetComponent<Renderer>().material.SetColor("_Color", new Color(Random.Range(0.25f, 0.85f), Random.Range(0.25f, 0.85f), Random.Range(0.25f, 0.85f))); _mesh = new Mesh(); TriangleSetUp(); var meshFilter = GetComponent<MeshFilter>(); meshFilter.mesh = _mesh; } private void TriangleSetUp() { foreach (var qs3 in _qs3S) { foreach (var qfb in _qfbs) { foreach (var qtbt in _qtbts) { for (int i = 0; i < 3; i++) { // 頂点を用意 _vertices.Add(Quaternion.Euler(Random.Range(0, 45), Random.Range(0, 45), Random.Range(0, 45)) * new Vector3(0, 1, 0)); } } } } // 頂点登録 _mesh.SetVertices(_vertices); var triangles = new List<int>(); for (int i = 0; i < _vertices.Count; i++) { triangles.Add(i); } _mesh.SetTriangles(triangles, 0); } private void Update() { TriangleSeed(1 + Mathf.Sin(Time.timeSinceLevelLoad), 1, 45 + Mathf.Sin(Time.timeSinceLevelLoad) * 45); _mesh.SetVertices(_vertices); _mesh.RecalculateBounds(); _mesh.RecalculateNormals(); } private void TriangleSeed(float l1, float l2, float fa) { var id = 0; foreach (var qs3 in _qs3S) { foreach (var qfb in _qfbs) { foreach (var qtbt in _qtbts) { // 頂点を用意 _vertices[id++] = qtbt * qfb * qs3 * Quaternion.Euler(0, 0, 0) * new Vector3(0, l1, 0); _vertices[id++] = qtbt * qfb * qs3 * Quaternion.Euler(90, fa, 0) * new Vector3(0, l2, 0); _vertices[id++] = qtbt * qfb * qs3 * Quaternion.Euler(90, -fa, 0) * new Vector3(0, l2, 0); } } } } } Mesh描画のためのコンポーネント MeshFilterとMeshRenererが必要なようです。 ちょっと複製の仕方を変えてみる // 前後対象 -> 4回回転対称 readonly Quaternion[] _qfbs = {Quaternion.Euler(0, 0, 0), Quaternion.Euler(0, 90, 0), Quaternion.Euler(0, 180, 0), Quaternion.Euler(0, 270, 0)};
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MessagePipe + VContainer で Hierarchy 内の GameObject にSubScriber を Injectする方法

結論 公式ドキュメント 発端 EnemyクラスにてSubscirberをInjectしたがPublish側はPublishできたのにEnemyが受け取れないぞ? しっかり処理も書いてるのにどういうことかな と詰まりました(ありがち) 以下参考 public class GameLifetimeScope : LifetimeScope { protected override void Configure (IContainerBuilder builder) { // 抜粋 var options = builder.RegisterMessagePipe (); builder.RegisterMessageBroker<DamageData> (options); } } // DamageData を購読して 体力が減ったら自らを消す Enemyクラス public class Enemy : MonoBehaviour { private int _HitPoint = 3; [Inject] private ISubscriber<DamageData> _damageData { get; set; } private IDisposable disposable; void Update () { if (_HitPoint <= 0) { Destroy (this.gameObject); } } private void Start () { var bag = DisposableBag.CreateBuilder (); _damageData.Subscribe (damageData => { this.supplyDamage (damageData); }).AddTo (bag); disposable = bag.Build (); } private void supplyDamage (DamageData d) { _HitPoint -= d.damage; } private void OnDestroy () { disposable?.Dispose (); } } public class DamageData { public int damage = 0; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityにpythonをインストールする。

1 この記事は何? Unityにpythonをインストールする方法を説明します。またUnity上で簡単なpythonのコードを実行してみます。 前提条件 Unity2919.4.29f1が導入されているものとします。 2 その方法は? 2-1 必要データのダウンロード まず下記のサイトにアクセスしサイトの筆者が準備したUnity Packageをダウンロードします。 2-2 データの取り込み 前述のPackageをUnityにImportします。 AssetsフォルダにあるPythonExample.prefabを描写エリアにドラッグドロップします。 2-3 コーディング まずは、pythonコードから始めます。Assetsのフォルダにgreeter.pyがあります。 greeter.pyを下記のとおり変更してみます。(Python2.7がインストールされています。Python3.xは使用できないことをご認識ください) greeter.py import random import sys class Greeter(): def __init__(self, name): self.name = name def greet(self): return "Hiii, " + self.name def versionget(self): sysv=sys.version #pythonのverisonを取得します。 return "python version:" + sysv 次にC#をコーディングします。Assetsディレクトリの中に配置されているPythonExample.csを開きます。 下記の通り修正してください。 PythonExample.cs using System.Collections; using System.Collections.Generic; using IronPython.Hosting; using UnityEngine; public class PythonExample : MonoBehaviour { // Use this for initialization void Start() { var engine = Python.CreateEngine(); ICollection<string> searchPaths = engine.GetSearchPaths(); //Path to the folder of greeter.py searchPaths.Add(Application.dataPath); //Path to the Python standard library searchPaths.Add(Application.dataPath + @"\Plugins\Lib\"); engine.SetSearchPaths(searchPaths); dynamic py = engine.ExecuteFile(Application.dataPath + @"\greeter.py"); dynamic greeter = py.Greeter("Mika"); Debug.Log(greeter.greet()); Debug.Log(greeter.versionget()); } // Update is called once per frame void Update () { } } 上記のコードはC#の一連の作業の中でpythonを実行します。pythonにデータを渡し、pythonから返された値をC#が受け取ります。 コーディングか終わりましたら、PythonExample.csをビルドします。 2-4 実行 実際に実行してみます。Gameを選択のうえ、矢印をクリックすると動作が開始されます。 実行結果がConsoleに表示されております。pythonコードでは、「Hii,Mika」と使用しているPython versionの表示を行っているので、C#がそれらのデータを受け取りConsoleに表示しております。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity TimelineのPlayable Trackとその実装方法について

記事の目的 Playable Trackとその実装方法について簡単にご説明すること レポジトリ Playable Trackとは? アニメーションや音源の再生時間を管理するTimeLine上に、スクリプト制御を設定できるTrack 下記の動画ではPlayable Trackを用いて、スライドの切り替えを行っている ※同時にAnimation Trackで球のサイズを大小している Playable Trackのメリット 時間管理が楽 動画のタイミングに合わせた空間演出が可能(プレゼンや研修動画などを3Dデザインできる) スクリプトが分からない人に仕事を任せられる 設定方法 PlayableBehaviourクラスを継承したクラスで、振る舞いを設定 SlideChange.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; public class SlideChange : PlayableBehaviour { public Sprite slideImage; public GameObject spriteObject; //タイムライン開始時実行される public override void OnGraphStart( Playable playable ) { base.OnGraphStart( playable ); //スライドを表示するGameObjectを取得 spriteObject = GameObject.FindGameObjectWithTag("Window"); } //PlayableAsset(コマ)再生時実行される public override void OnBehaviourPlay( Playable playable, FrameData info ) { //スライドの画像(Sprite)を変更 spriteObject.GetComponent<SpriteRenderer>().sprite = slideImage; } } PlayableAssetクラスを継承したクラスで、振る舞いをTrack上に差し込めるAssetを作成 SlideAsset.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; public class SlideAsset : PlayableAsset { public Sprite image; public override Playable CreatePlayable( PlayableGraph graph, GameObject owner ) { //PlayableBehaviourを継承したSlideChangeクラスを元に、PlayableAsset(コマ)を作る var player = ScriptPlayable<SlideChange>.Create( graph ); //SlideChangeクラスにあるプロパティを設定 var behaviour = player.GetBehaviour(); behaviour.slideImage = image; return player; } } ※基本的にはPlayableAssetでコマの設定が出来、そのPropertyを設定できる。 ただしMonobehaviourを継承していないので、Scene内のものを取得したい場合は ExposedReference<Object> といった記述が必要になる。 UnityのGUIでTimelineのPlayable Track上にPlayable Assetを挿入(右クリックで勝手に出てくる) Assetにプロパティがあれば、AssetをクリックしたときにInspector上で表示される場所にデータを入れておく
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

他人のC#のコードの継承元が複雑すぎて、理解できない話

unityとC#初心者が色々触ろうとした結果 今回はunityで他人のgithubから落としたコードを読む際に、継承が多すぎて、どうなっているのかわけわからなくなったという状況に陥りました。 もともと、hololensをunityとROSで連携させたいということで、unityとROSを連携させるROS#というassetを扱っていました。 unity上で、ボタンを押すとROSのほうに簡単なメッセージが出るというようなプログラムをROS#を再利用、改変して作ろうということになりました。 それで、ROS#のプログラムを見たんですが、これが全く読めない。 どこをどのように継承してるのか、わけがわからなくなって、結局改変せずにROSのほうで解決するということになりました。 自分が書いたプログラムはわかるんですが、他人が書いたプログラムは、一つのスクリプトでもきついのに、複数スクリプトまたがって継承されると、全然理解できませんでした。 また、unity独自の型とか使われてたりしていたので、そこでつまづいたりもしました。 そんな状態だったので、改変すると継承の部分でエラーが出て、動きませんでした。 エラーの原因もわからずお手上げでしたね。 C#も、unityも勉強不足 結論としては勉強不足。今回私が扱ったROS#は、かなり読みやすい部類。それでも読めませんでした。 こればっかりは、自分でC#のソフトウェアを色々作ったり、人のプログラムを多く読んで慣れて勉強していかないとなと思いました。 読めるようになったら、どこで躓いてたのか、どう考え方を変えたら読めるようになったかとか、読むコツとかの記事を書ければと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む