Enumのリストが欲しいときいつも使っているコードを紹介します。
やりたいこと
こういうEnumをリストですべて取得したい
ついでにデフォルト要素の排除は選択可能にする
コード
使い方
出力結果
使ってみてね
今回はBlenderで出力したFBXをUnityにインポートしたところUnity側で位置ずれが起きていたのでメモ
当記事は根本的なことが解決できるわけではなく、こういう問題があるよというメモ書き程度になります。
3階層以上の親子関係がある場合Unity側で3階層目以降は位置がずれる。
以下のオブジェクトをBlenderで作成していました。
親子関係はこんな感じで多いところで最大4階層の親子関係があります。
これをUnityにインポートしたところ
親子関係は保たれていますが、孫以上の金具の部品は選択している位置までずれています。
この現象はBlender側で回転やスケールを適用して修正していても起こる問題です。
何故...?
根本的な解決方法ではないですが、今回はBlender側で3階層以上の親子関係をやめることで解決しました。
3DSubstancePainter(SP)でも同様のことが起こっていました。
SPでは親子関係などいじれないため不便だと思ったので、今回はこの方法で解決しました。
調べ方が悪いのかこの問題に関する記事が一切でてこないので問題を共有するだけにとどめておきます。
時間があれば根本的な解決に向けてもっと詳しく調べた後追記しておきます。
タイトル通り両端から減っていく(もしくは増えていく)ゲージを作成していきます。
完成形
両端から減っていくゲージはImageコンポーネントだけでは作成不可能なので自作していきます。
※SliceタイプのSpriteを使えばwidthを変更するだけでそれっぽくは見える
やり方としてシェーダーでも作成可能なのですが、今回はRectMask2Dコンポーネントを使ってさくっと作っていきます。
BarBackgroundImage(背景)、BarFrontImage(増減ゲージ)はただのImageコンポーネントが付いたものです。
間にRectMaskがあり、ここにRectMask 2Dコンポーネントと後述するコード(BothSidesFill.cs)がアタッチされています。
width,heightは全て同じ
Sliderは動作確認用なのであってもなくても大丈夫です。
ImageタイプがSlice対応画像ならwidth変更するだけでいいと思うけど、これなら非Slice画像でもいけます!
[blog:g:12921228815717619800:banner]
右クリック>Create New Group>Packed Assets
※バージョンによってはCreate New Groupだけ押せばいい時もある
名前も変更可能です。
みんな当たり前のようにやっているのか、たったこれだけなのに全然情報なくて何時間か無駄にしたのでメモです。(結局人に聞きましたが)
DefaultGroupで運用していると結構コンフリクトして面倒なので分けることをおすすめ。
おそらく最短記事笑
まあたまにはこんなのがあってもいいかな
今回はBlenderでモデルを作成、SubstancePainterで色付け(Texture作成)
最後にUnityにimportするまでのソフト間ワークフローを実際にやってみました。
間にSubstancePainterがありますが、Blender→Unityへのフローだけが知りたい人でも見れるようになってます。ではどうぞ
Unity 2021.3.16
HDRP 12.1.8
Blender 3.1.2
3DSubstance Painter 8.3.0(以下SP)
汚れや表面の凹凸もSubstance Painterで簡単に作成できました。
それでは手順を解説していきます。
※モデルの作成方法やSubstancePainterでのペイント方法は解説していないので注意。あくまでフローやimport/export設定のみ
今回の記事を書くにあたって題材となるモデルが必要だったのでこちらの動画を参考にしました。
まじで簡単にできたのでおすすめ。
完成(Blenderのレンダリング結果)
Blenderのレンダリング絵作り下手すぎる...
モデルを最終的にUnityで扱うためにやっておくことがいくつかあります。
現実に存在するものであれば、実際のサイズに合わせて作りましょう。
まずはLength(単位)をメートルに変更します(2.9あたりからはデフォルトでメートルだった気がしますが一応)
object選択モードに変更>Nキー>Item>Dimensions
からサイズを調整します。
英語版を使っているのでわかりにくいですが場所は同じです。
サッカーボールは22cmなので「0.22m」に設定
原点が正しい位置にない場合があるので原点をそのオブジェクトの正しい場所に配置する必要があります。
今回はボールなので原点をオブジェクトの中心にします。
Object>Set Origin>Geometry to Origin
Unityではスケール1にしておいた方が扱いやすいので今のサッカーボールのスケールを1に変更します。
Object>Apply>Rotation & Scale
もし動画を見ながら作成していたらマテリアルを用意する部分まで説明されているので大丈夫だと思いますが、マテリアルはSubstancePainte側で個別に設定するために部分ごとに分けて設定しておきます。
今回はサッカーボールの白い部分を「soccerWhite」、黒い部分を「soccerBlack」という名前でマテリアルを割り当てました。
SubstancePainterではUV展開したモデルの頂点などを編集することができないのであらかじめUV展開して調整をしておきます。
編集モード>全選択>Uキー>Unwrap
今回はシームつけなくてもUV展開うまくいきましたが、もう少し複雑な形のモデルの時はこちらを参考にしてみてください。
下図はBlenderからUnity向けにExportする出力内容になります。
一度Unityにインポートして大きさを確認してみました。
うん!いい感じ!
先にUnityで確認していた方が手戻りが少なくて済むかも。
Blender→Unityだけが知りたい方はここでおしまいです。以降SubstancePainterの作業になります。
これでも十分にサッカーボールなのですが、ここからさらにSubstancePainterで表面の凹凸や縫い目、汚れなどを表現していきます。(SubstancePainter練習したいだけ)
ファイル>新規>テンプレート>Blender
その後にファイルを選択して何も設定は変えずにOKボタン
読み込まれると画面はこんな感じ
画像右上で確認できますが、マテリアルもちゃんと分かれてる。
ここからSubstance Painterで作業を行っていきます。
SubstancePainterでTextureを作成したのがこちら(料理番組かな?)
初めてのSubstancePainter作品ですが、ブラシでモデルをへこませたりしてNormalが簡単に作成できるのは超楽しいです。
ここからが本番。この状態をUnityでしっかり再現できるかどうかです。
ファイル>テクスチャを書き出し
ひとまず試しにUnityHDRP向けの出力テンプレートがあるのでそれで出力してみます。
結果からいうとHDRPならばこの出力方法で問題なく使えました。
簡単に説明すると
左側:テンプレートリスト(自分で新しく増やすことも可能)
中心:出力される名前とチャンネルのリスト
右側:書き出せるマップのリスト
となっていて中心の色と右側の色はリンクしています。色のついてあるマップを出力するということになります。
アルファ、メタリック、ラフネス、AOはグレースケールなので
RGBAにそれぞれ情報を持たせることができるみたいですね。UnityのLitShaderではこのまとまったTextureはMask mapと対応しています。
今回これが知れただけでもでかい
そして罠なのが設定に戻って出力テンプレートを指定の選択しないとさっきのUnity用だったり自分で作成したテンプレートが使えないということです。
右下の書き出しを押して書き出し後、以下のテクスチャが書き出されました!
サッカーボールのMaterialにTextureを設定していきます。
Texture設定前のLitMaterial
そもそもFBXインポートしたときにマテリアルないんだけどって人はimportしたModelを選択>Materials>Extract Materials
を押せばマテリアルが作成されます。
読み込んだNormal mapのみInspectorからTexture Typeを「Normal map」にしてあげる必要があります。
各TextureをLitMaterialに設定
汚れとか表面の凹凸が再現できました!
モデルの隙間から若干床の色が見えているのは、LitShaderのDouble-Sidedを有効にするとわからなくなります。まあ今回そこまで気にならないので放置します。
これからもSubstancePaitner活用していきます!
それではまた
今回はTextMeshProやTextMeshProUGUIで扱えるプロパティ、textInfoを使っていて困ったことと対処方法を書いていきます。
※TextMeshPro自体の使い方や説明は省きます。
Windows 11
Unity 2021.3.16f1
URP 12.1.8
TMP_TextInfoとは、TextMeshProやTextMeshProGUIが継承しているTMP_Textクラスに存在するクラスの一つです。
このTextInfoクラスには文字数だったり、テキストメッシュの座標情報が格納されていて結構使い勝手が良いです。
ここからは使っていて困ったことと解決策を書いていきます。
ちなみにTextMeshのメッシュが板ポリだったってことに気が付くのは結構最近のお話笑
困ったことの1つ目です。Debug.LogでcharacterInfoを出力してみても文字が入ってなかったりクラス自体がNullだったりします。
準備としてTextMeshProUGUIを用意しました。
NGコード×
原因は呼び出しタイミングが早すぎることです。
AwakeやStartからの呼び出しで使わないこと
OKコード〇
AwakeとStartから呼び出すとInspectorで文字が入っていたとしてもcharacterInfoやmeshInfoが正しく呼ばれることはありません。
必ず、Startよりあとのタイミングで呼び出すようにしましょう
2つ目の困ったことは新しくtextを設定したとき、最新のtextInfoを取得してこないという問題があります。
NGコード×
※他は同じなのでUpdateのみ記述
「T」という文字が取得したいのにデフォルトの「New Text」の「N」が出力されます。
GetTextInfo(newText)関数を使う
OKコード〇
TMP_TextInfo textInfo = uiText.GetTextInfo(newText)とやると内部的にtextも「newText」にセットできるし、「newText」のtextInfoも取得できる。(Get関数なのに内部でtextをSetしているのは少しわかりにくいですが関数の中身を見たら気が付けます...)
よく紹介されている手法として、textInfo.meshInfoから全てのvertex(頂点)情報を取得後4を掛けてn文字の中央座標を求めることができます。
以下のコードでは「New Text」の3文字目、「w」の中心座標を求めて上からspriteをかぶせています
コード
参考:uGUI Textの文字の座標を取得してインライン画像を実現する - おもちゃラボ
上記コードはNGというわけではありませんがもっと簡単な方法があったので紹介します。
characterInfoのtopleftやbottomrightといった座標プロパティが存在するのでそこから計算すればok。
改善コード(Updateだけ)
やってることは同じです。
textInfo.characterCountのカウントは残念ながら思った通りには返ってきません。
例えばhoge hoge¥nfuga fuga
というtextが存在すると、このテキストの正確な文字数は16文字
です。空白も改行も数えてしまいます。
なのでこういう時はスペース数を取得して引いたものが正しい文字数です。
なぜ改行もスペースとして数えられるのかはわかりませんがこれで正しい文字数は出せました。これをループに使えば各文字に何らかの処理を行えます!
いかがだったでしょうか、textInfo便利なのでぜひ使ってみてください。
今回はRigidbodyを使わずにSpriteが重ならないようにする方法を紹介します。
Spriteが重ならないようにしたい場面は頻繁にあるのですが、重ねないためだけにRigidbodyを使うとパフォーマンス的に心配ということもあり
今回はTransform移動だけでRigidbodyを使った時のようなSprite同士が反発しあう表現を行っていきます。
今回の記事ではTransform移動だけでこんな感じの反発表現ができるようになります。
・ヴァンパイアサバイバーの敵
・Stocklandsのカード
検証するための簡単にステージを用意しました。
貝(敵)のモンスター画像は以下のサイトから拝借
七三ゆきのアトリエ
https://nanamiyuki.com/
今回はこの貝を敵として大量描画を行い、画面外から中央に向かって移動させます。画面中央に設置した判定に当たると敵は消えるようにしています。
※敵の出現方法のコードは割愛します。
まずはRigidBodyを使ってどんなことがしたいのか見せます。
Spriteを重ならないようにする方法で検索すると大体このRigidBodyのDynamicを利用しています。(そういう紹介をしている人がほとんど)
※ただRigidbodyを使うには物理挙動を理解していないといけないし、FixedUpdateが必須となってくるので導入難易度は少し高いです。
TargetMove.cs
このスクリプト時の貝(敵)のコンポーネントはこんな設定です。
プレイしてみる
これをTransform移動で表現していきます。
TargetMoveスクリプトは以下です。
毎フレーム自身と同じobjectが重なっているかどうかチェックして、重なっていればそのobjectと反対方向に速さが加わります。
Physics2Dは物理挙動を一部利用、設定できるクラスです。
Unity - Scripting API: Physics2D
このコードで問題点があるとすれば進行方向と逆側で重なってしまうと少しスピードが上がります。
Inspectorの作業としては
・レイヤーを作成してEnemyObject本体とTargetMoveスクリプトに設定
・各種パラメーターを設定します
・Rigidbodyは必要ありません
この状態で実行するとSpriteが重ならず、お互いに反発しているように見えます!
(最初の動画と同じ)
どちらも似たような表現ができますが、大切なのはどちらがパフォーマンスがよいかということです。今回はシンプルに敵の数を増やして検証します!
結果から言うとパフォーマンス的にはほぼ同じに見て取れます。
ですのでFixedUpdateを使うことができないなど、ケースによって使い分ければよいかなと思います。
検証方法はProfilerで確認していきます。
結局Transform移動といってもPhysics2Dは使っているので、双方FPSはそんなに差はなかったです。RigidbodyありのほうがPhysics(ピンク)の処理が大きいということはやっぱり反発以外の処理も行っているという予想は当たってました。
あと当たり前かもしれないですが、双方オブジェクト数が増えすぎるとFPSは下がるので、今回のセンターに集まったら消える処理のような全体数を一定にコントロールするようなコードがあってもいいと思います。
久々に技術系書いた、終わりー
今回はせっかく配置したキャラクターがなんか暗いなーといった現象の解消方法を書きました。初心者向けです。
結果から先に伝えると
こんな感じに変わります
Unity:2019.4.10f1
HDRP:7.4.1
上記画像はUnityちゃんを配置して真上からDirectional Lightを当てています。直接光が当たっていない部分がとても暗くなっていて少し怖いです。
今回これを適切な明るさに調節していきます。
まずこの状態がなぜ起こっているかというとUnityちゃんが「間接光」(ベイクしたときに生成されるLightmap)の影響をほとんど受けていないためです。
※間接光はオブジェクトに光が当たって跳ね返った光のことです。今回この間接光がUnityちゃんに適用されてないことになります。
本来間接光が適用されたらUnityちゃんの横の壁のように、床から跳ね返った色なども反映されるようになります。
ではそれをするにはどうすればいいか?
動的オブジェクトに間接光の情報を与えるためにはLight Probeを利用します。
Light Probeは配置した地点の間接光情報を持ち、近くのオブジェクトに影響を与える役割があります。
このLight Probeの範囲外に出るとLight Probeの恩恵は受けられません。
Hierarchyビューで右クリック> Light > Light Probe Group
シーンに配置しただけでは何も変わりません。
一度bakeしないとLight Probeが適用されないためLightting Settingビュー>Scene>Generate Lighting
を押してbakeします。
今回はUnityちゃんにLight Probeを適用したいので、Unityちゃんにアタッチされている
Mesh RendererもしくはSkinned Mesh Renderer>Probes>Light Probes
をBlend Probesに変更します。
【Unity HDRP】Lighting検証 表にまとめて考察してみた
間接光が適用されました!Light Probe簡単だし効果絶大!
低壁と同じように床のバウンスした色と同じものが、Unityちゃんにもかかっているのがわかります。
動画も載せたかったのですが、キャプチャの調子が悪いのでまた用意できしだい追加します。
一応生成したLight Probe GroupのコンポーネントのEdit Light Probe
を押すことで数の調整ができます。
ただ、 Light Probeも一つひとつ情報なので多いとメモリを圧迫します。
私は「Light Probeはとりあえずつけとけ!」くらいに思っていますが、闇雲に増やせばいいというわけでもないですし、コンポーネントから編集するとかなり大変です。
そこで便利アセット「Magic Light Probes」を使えば簡単に多くのLight Probe Groupを綺麗に配置してくれます。
是非使ってみてください!
いかがだったでしょうか。簡単ですが、以上になります。
それでは
今回はLightingの設定ごとにシーンやオブジェクトにどのような影響があるか調査して表にまとめていこうと思います。
Unity:2020.3.31
HDRP:10.8.1
今回は以下のような環境でテストを作成して、それぞれのLightingのType(発光側)とMeshRenderer(光を受ける側)の設定がどのように作用するか全てを表にまとめていきます。あとLight Probeの有無も含めます。
シーンには光が一切ない状態
Light Probeを配置したときのシーンはこんな感じ
その他全体の設定としては
・ベイクした情報は毎回クリアしてる
・Lightは全てShadowを有効
・Mesh Rendererはcast shadowをOn
以下の表にまとめているのでそこから気になった部分の考察や検証を行なっていきます。
ここから「specular反射」と「色にじみ」という単語が出てきます。簡単に説明するとspecular反射が鏡面反射で、色にじみ(カラーブリード)が近くのオブジェクトの色が他の色に影響を与えることです。
「色にじみ」に関しては本に載っていた単語なのでUnityでは別の呼び方をしているかもしれませんが、当記事では「色にじみ」の表現を使います。
Specular反射について詳しく知りたい方はこちらの記事が参考になります。
物理ベースレンダリングを柔らかく説明してみる(1) - Qiita
Type | RealTime | Mixed | Baked | |
---|---|---|---|---|
Static/ Light map |
Direct ional |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) 色にじみ有(固定) |
specular反射有(固定) 影有(固定) 色にじみ有(固定) |
Point |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射有(固定) 影有(固定) |
|
Spot |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射有(固定) 影有(固定) 色にじみ有(固定) |
|
Area |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射有(固定) 影有(固定) |
|
Static/ Light Probe |
Direct ional |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) 色にじみ有(固定) |
specular反射無 影有(固定・粗い) 色にじみ有(固定) |
Point |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射無 影有(固定) |
|
Spot |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射有(固定) 影有(固定) 色にじみ有(固定) |
|
Area |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射無 影有(固定) |
|
Dynamic |
Direct ional |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) 色にじみ無 |
specular反射無 影無 色にじみ無 |
Point |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射無 影無 |
|
Spot |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射無 影無 |
|
Area |
specular反射有(動的) 影有(動的) |
specular反射有(動的) 影有(動的) |
specular反射無 影無 |
検証環境の画像にはcontribute GI/Lightmapが入っています。何故表にないかというと
実は私がcontribute GIを理解していなかったこともあり、最初一緒に検証しました。
後々ドキュメントを見るとcontribute GIをつけることこそがオブジェクトにLightmapとLight Probeの影響を与えるトリガーだったみたいです。
つまり画像左上(Static/Lightmap)と右下(contribute GI/LIghtmap)は同じ状態のオブジェクトということです笑
通りで何も変わらないと思いました。
RealTimeでは以下の画像のような、オブジェクトの色が他のオブジェクトに影響する色にじみが表現できませんでした
後述していますが、色にじみの結果はLightmapに一緒に書き込まれるので、Lightmapを生成しないRealTimeだけでは色にじみは表現できません。
今回わかったこととしてLight Probeをつけることで、動的なオブジェクトがあるときにより正確なライティングが再現可能だったということです。
Light ProbeはそのポイントでのLight情報を持っていて他のオブジェクトに渡すので、計算コストを抑えた間接光の再現する手法かなと理解しました。
Light Probeついてないアセットあんまりみたことないし、とりあえずつけておくで良さそう。ただ、配置方法についてはもう少し研究する必要があるかなと思いました。
RealTime
mixed
LightmapデータをクリアにすることでmixedはRealTimeの影に近づきます。
つまり、mixedでもベイク可能(Lightmapが生成される)ということ。
mixedでベイクをすることで間接光のLightmap Data情報を用意することが可能。Specular反射と影はRealTimeに近い形がとられ、間接光は予め用意したものを使っていた。それと比べてRealTimeではLightmap Dataが生成されないのでこういう現象が起こっていたのでした。
bakedのSpot Lightを用意してbakeした状態が以下です。この状態から反対側にmixedのDirectional Lightを用意したときにどうなるか検証します。
Dynamic以外のオブジェクトには影が二つできた!
もちろんSpot Lightの方はbakedなのでSpot LIghtを動かしても影は動かない
ちなみにSpotLightをmixedに変更してみたらSpot Lightのon/offが動的に切り替えられた!この表現はよく使うので覚えておきたい
また、今回はLighting Modeはbakedで行いましたが、公式のmixedライティングの説明ではLighting Modeによって動作が変わるみたいです。それはまた別の機会に検証行おうかなと思います。
自分の考察ではLight Probeがあれば動的なオブジェクトにも影が落ちると考察していましたが、Light Probeは正確な影の情報は持っていないみたいでした。
正確な影は落ちないが、暗い場所なのでオブジェクトが暗くなるといったことは再現できるっぽい
今回の検証では動的になくすなどはできなかった。
→LightProbeの情報をランタイムで更新する方法がないか調べてみます。
以下の画像を見てもらいたい(見にくいけどごめん)
Area Lightがもし全面均一に発光しているのだとしたら、影は本来Sphereの真下に現れるはず
なのに影は明らかにArea Lightの中心からのみ発光されているように出ていた。
これは自分の仕様に対する勘違い。Directinal Lightのような挙動だと思っていた。皆さんも間違えないように注意
bakedのライトのみが存在するシーンで一度ベイク、その後にベイクしたLightmap情報を削除してもシーンは明るいまま?どういうこと?
普通暗くなるのでは...?
今回ついでにEmissionも使ってみました。今までEmissionも単体で光源になると思っていたが認識が違っていた。
Lightなどの光源に反応して発光する効果という意味で使われるものということがわかりました。
Lightが何もない状態でHDRI Skyのみ20000Luxにしてベイク
結果→落とさない
今回かなりLightに関して理解が深まりました。
他にも気になることがあれば検証していきたいと思うのでTwitterのDMかこの記事にコメントしていってください!
それでは
ライティングを勉強したいときにLightが全くないところから始めたいときありますよね
今回はUnityのHDRPで真っ暗にする方法に少し手間取ったのでメモします。
Unity 2019.4.10
HDRP 7.4.1
状況としては以下のライティング要素が存在している状態です
・Directional Light(Lighting Mode: Mixed)
・PointLight(Lighting Mode: Mixed)
・HDRI Sky Volume
・Static Light Sky
・Exposure(Fixed)
・Reflection Probe
・Light Probe Group
・ベイク済み
これらの状態からなるべくオブジェクトを無効にせずに
真っ暗(ライトの影響が何もない状態)にしていきます
Directional Lightを上向きにしてベイク
ベイクされているので明るさは残っている
Directional Lightを0Luxにしてベイク
背景がまだ明るいので空の明るさ(環境光)を調整します。
HDRI Sky>Desired Lux Value
を0にします。
Point LightのEmission>Intensityも下げておきます。
この状態でベイクした物がこちら
大体暗くなったのですが、まだBox上側の輪郭が見えますね。
この状態でExposure Volumeなどの値を上げれば真っ暗にはなるのですが、逆に0にすると結構明るくなります。
Exposureは光を取り込む量を設定するVolumeなのでここを変更して明るさが変わるということはまだどこかにわずかな光量があるということになります。
結構探しましたが、最後はLighing Settingで設定可能なStatic Lighting Skyの光量が効いていたみたいです。この値をNoneに変更してベイクしたところ
ようやく真っ暗になりました
Exposureを変更させても明るくはなりません。
これで完璧にUnityから光が消えたと言ってもいいでしょう
ReferenceをみるとStatic Lighting Skyはベイク用の環境光ということでした。
Static Lighting Skyで選択できるものはGlobal Profileの内容によって異なるみたいです。
同じGlobal ProfileをVolumeにも設定できます。
Lighting SettingとVolumeで設定できるHDRI Skyの違いはベイク用とランタイム用の違いです。
証拠に真っ暗な状態からVolumeのHDRI SkyのLuxだけ元の値(20000)に戻してベイクしてもLightmapに変更はありません。
この状態でHDRI SkyのLuxを再び0に戻したら真っ暗になります。(ベイクはしてない)
暗闇にしたいだけだったのに、また1つLightingに詳しくなれました笑
ということで簡単ですけど以上になります。
それではまた
今回は「うにty生活」の世界にクリエイティブ要素を追加したいと思います
Unity2019.4.10f1
HDRP7.4.1
今回は単純にクリックした場所にオブジェクトの生成を行なっていく機能と配置プレビュー機能など実装していこうと考えています。
今回作成する機能は以下の4つです。
・クリックした先を衝突検知してオブジェクトが生成されること
・Colliderに沿って生成されること
・配置プレビュー
・オブジェクト生成をスライスシェーダー で行う
とりあえずCubeオブジェクトを、カメラから発するRayがぶつかるところに生成できるか検証
床にめり込んではいますが、クリックした場所にオブジェクトを生成することができました。
以下のコードを使って実現可能です。
これは以前ピン差し記事を書いたときに汎用的に作成したものを変数名変えてそのまま使いました。
ピン/シグナル/マーカー設置システムを作ってみた #34 - うにty生活
上記コードのcloneにただのCubeオブジェクトのPrefabをアタッチして利用します。
このままでは床にCubeがめり込んでいます。
これをちゃんと床の上に生成されるように機能を改善していきます。
まずは以下のコードでCubeがめり込んでしまうことを回避します。
25行目のif内を以下のように変更します
Vector3 movement = Vector3.Scale(previewClone.transform.localScale, hit.normal) / 2;
target = Instantiate(clone, hit.point, Quaternion.identity)
target.transform.position = new Vector3(hit.point.x + movement.x, hit.point.y + movement.y, hit.point.z + movement.z);
上記コードを簡単に説明すると、
ヒットしたオブジェクトの法線ベクトルを取得。
法線ベクトルが1か−1の方向に、Cubeのスケールの半分をプラス。
そうすることで生成される原点をヒット先から半分ずらしています。
また、上記のコードではRayがヒットした先のオブジェクトに関してのみめり込まないようにするものなので、床と既に存在しているオブジェクトの境界あたりをタップするとめり込みます。
それを回避するために、生成するオブジェクトには新たにRigidbodyコンポーネントをアタッチしています(結局)。
Rigidbodyを使わずにできる方法はこれから模索してみます。
今のところ、どこにCubeが置かれるか全然わからないので、配置プレビュー機能を作成します。
まずはマテリアルを作成します。
先ほどまでのコードを以下になるように修正した後previewMaterialに、作成したマテリアルをアタッチします。
オブジェクトが生成されるときに下から徐々に表示されていくように変更します。
作成したシェーダー グラフはこんな感じです。
シェーダー は以下の動画を参考にしてます。
Faderのスライダーを動かすことで下から表示されます。
このスライダーをオブジェクト生成時に自動的に動かしたいので、生成するオブジェクトにFaderを−1から1にするアニメーションを追加します。
ループはしないので、作成したAnimationのLoop Timeのチェックは外しておきましょう。
これで完成です。
ブログ始めた当初からこのクリエイティブ機能は作成したかったので、嬉しいです!
これから他のオブジェクトも置けるように機能拡張していくつもりです!
それではまた
今回はUnityのHDRPでPhysically Based Sky(物理ベースの空)で設定できる
プロパティを見ていきます。
Unity2020でこの記事を書いていたところPhysically Based Skyが大幅アップデートするUnity2021.2がでたということで2021.2で書き直しました!
Unity2020との違いも含めてPhisically Based Skyのプロパティを見ていこうと思います。
Unity 2021.2.6f1
HDRP 12.1.2
※LTSではないので注意
直訳すると物理ベースの空で、設定を行うと 太陽の角度によって昼/夕方/夜の再現が簡単にシミュレーションが可能になります
Physically Base Skyを設定した時の太陽です(Unity2020.x)
今まではPhisically Based Skyといえばこれでした。
Unity2021.2.xからはこうなります!
↓↓↓↓!!!
やばくないですか!?
これはPhisically Based Skyだけの進化ではありませんが、雲とフレアが追加されたことによってなんとも美しいデモシーンになっています。
さらにUnity2020ではHDRI Skyでは太陽は描画されてなかったのですが、Unity2021.2ではHDRI Skyでも太陽が出てくるようになりました!
これからはHDRIでもPhysically Based Skyでもどちらでも高クオリティなライティングや絵作りが可能です
※HDRI Skyの場合、太陽の角度によって昼/夕方/夜のシミュレーションはできません。
それでは簡単にPhysically Based Skyの準備方法と基本操作からおさらいしていきましょう
まずはデフォルトではHDRI SkyになっているのでPhysically Based Skyに変更します。
1. GlobalのVolumeを作成
以下の方法で作成可能です(既に存在している場合は新たに追加する必要なし)
ヒエラルキービュー>右クリック>Volume>Global Volume
多分初めに開いた時には既にこの状態だと思います。
2. 作成したVolumeのVisual EnvaironmentをPhysically Based Skyに変更する
3. Global VolumeにPhysically Based SkyのOverrideを追加する
4.Visual EnvaoronmentがHDRI SkyのときはHDRI SkyのVolumeを、
Physically Based SkyのときはPhysically Based SkyのVolumeをにチェックを入れます。今回はHDRI Sky Volumeのチェックは外します。
これで準備完了です。
太陽はDirectional LightのRotationで移動可能
大きさはDirectional Light > Shape > Angular Diameter
から設定可能です。
ここからはプロパティを紹介
パッと見プロパティについてはUnity2020とUnity2021.2で変化はありません
後続の設定のテンプレートを提供してくれています。
作成するシーンが地球である場合、Earthを選択します。それ以外の惑星を表現したい場合はCustom Planetを選択します。
EarthのSimpleとAdvanceの違いとしてAdvanceの方がより詳細にプロパティを調節可能です。
Spherical Mode(Earth-Advanced,custom only)
惑星が球面であるかを設定します。
球面モードにチェックが入っているとき、Planet Center Position
チェックが入ってないときは、Sea Level(後述)が設定できるようになります。
Sea Level(Not Spherical Mode only)
海面の高さを設定できます。値をマイナスしていくと地平線が下がり、増やしていくと上がっていきます。
また、海抜が高いほど大気の密度が低くなります。以下の画像はSea Level「0」と「-10000」の比較画像です。太陽の位置は変更していませんが、大気が薄くなっていることがわかります。
山の上を想定した場合はマイナス値を増やすことでよりそのシーンを再現することができます。
Planet Center Position(Spherical Mode only)
惑星のセンターポジションを設定。この設定は基本的にそのままで良いと思います。
Planetary Radius(Type = Custom Planet only)
惑星の海面からの半径です。
半径が大きくなるということは惑星の弧が真っ直ぐに近づくということなので、
地平線の位置が高くなっていきます。またデフォルトの「-6378100」は地球の半径である、6378kmのことです。
Planet Rotation
惑星の傾き具合。惑星の自転ということですが、変更しても別に太陽の位置が変わるわけではなかったです。
次に紹介するGround Color Textureと一緒に利用します。
Ground Color Texture
Ground Tint
Ground Emission Texture
Ground Emission Multplier
これらは地表の色を決めます。地表からの照り返しなどに影響します。
Ground Color Textureに地球儀のようなTextureを設定することで現在いる場所の正しいGround Colorが取得できます。海の位置にPlanet Rotationが設定されているならGround Colorは青色、地表なら茶色みたいな表現が可能です。
この設定をして、どんどん画面を引いていくとなんと宇宙空間に飛び出て地球を確認することができます。
※宇宙空間に飛び出るにはVolumetric Clouds Volumeを無効にする必要があります。
このような地球儀Cubemapを作成するには以下から画像を取得します。
December, Blue Marble Next Generation w/ Topography and Bathymetry
そして、取得したTextureを以下のように変更します。
・Texture Shape → Cube
・Mapping → Latitude-Longitude Layout
・Applyを押下
Space Emission Texture
この項目は結構大事です。 この項目にcubemap Textureを設定することで、夜をシミュレーションで利用するEmissive効果を持ったTextureを設定することができます。
ここに星空を設定することで夜を星空に変更することができます。
星空のcubemapは以前作成したので参照して見てください。3分もあればできますよ!
Space Rotation
上記TextureのOffsetを調節可能です。
Space Emission Multiplier
上記テクスチャの発光の強さを設定します。
星空は少しこの値を上げないと見えにくいと思います。
Air Maximum Altitude
Sea Levelの項目で、「海抜が高くなるほど大気が薄くなっていく」という説明をしましたが、Air Maximum Altitudeはその割合を設定できます。
Air Density RGB
単一散乱アルベドの散乱設定項目です。値はRGBを0~1に正規化したもので値が小さいほど色は光を吸収し大きいほど散乱します。
どういうことかというとこのようにAir Tintに赤色を設定した状態でAir Density Rを1にすると赤色は吸収される(透過する)ということです。
この設定OrverrideしたVolumeをボックス配置しておくと、砂嵐に入ったような演出をすることが可能です。
Air Tint
単一性アルベドを設定できます。この色がベースカラーとなって上のAir Densityの影響を受けます。
気体中に浮遊する微小な液体または固体の粒子と周囲の気体の混合体をエアロゾル(aerosol)と言います。
https://www.jaast.jp/new/about_aerosol.html
エアロゾルが存在している範囲では、境界線付近の白いモヤのような現象を再現できます。これはミー散乱によるもので白っぽく見えます。
以下はそのエアロゾルに関する設定項目
Aerosol Maximum Altitude
Air Maximum Altitudeの説明と同じで、高度に応じた密度降下の割合をメートルで表しています。具体的にどうなるかというとミー散乱で白っぽく見えている部分の範囲が広くなります。
Aerosol Tint
Aerosol Density
エアロゾルの単一散乱アルベドです。以下のAerosol Densityの割合によって透明度が変化します。
Aerosol Anisotropy
3種類の散乱方法が設定できます。
・1:前方散乱強め
・0:異方性なし
・−1:後方散乱強め
結果から先に言うとこの値は見た目に大きな影響はありません。
ミー散乱は、エアロゾルなどの大気中の大きい粒子に光がぶつかって散乱することです。地平線付近が白く見えるのはミー散乱の効果になります。
Unityでのミー散乱について、私が腑に落ちていない部分があるのでまた調査したいと思います。→ちょっと待ってね
とにかくこの値は0のままでいいということです。
空の色に関する微調節を行う設定項目です。
Color Saturation
彩度の変更
Alpha Saturation
Alpha Multiplier
透明度の変更。0に近づけるとDirectional Lightが白くなります。
Multi plierは適用する透明度の倍率です。
あんまり変化はわからないです。
Horizon Tint
境界線の色が変化します。空の色がHorizon TinitとAir Tint(後述するZenith Tint)とのグラデーションになります。
Zenith Tint
Horizon Zenith Shift
Zenith Tintは空の頂点カラーを設定できます。Air Tintとは乗算されているような色合いになります。Horizon Zenith ShiftでZenith Tintの影響度を変更可能です。
Horizon Tint、Horizon Zenith Shift , Zenith Tintを設定した時の画像
Physically Based Skyを設定したときのLighting設定です
Number Of Bounces
光が散乱する回数
値を上げるとより現実に近い表現ができるが、ベイク時間も長くなる
Intensity Mode
空の環境光の明るさを調節するモードです
Exposure:Exposure Volumeの値の2乗の計算をします。なので0だと変化なし
Multiplier:環境光の倍率
Update Mode
環境を更新する頻度です。
On Change:設定が更新されるたびに変化
On Demand:スクリプトから更新を手動で呼び出すまで待つ
Realtime:このモードを選択して表示されるUpdate Periodの間隔で更新する
Include Sun In Baking
Reflection Probに空と一緒に太陽が表示されるかどうかの設定だそうですが、
違いがうまく現れなかったです。
ということで長くなりましたが、Physically Based Skyのプロパティ紹介は以上です。
2021年内に記事を投稿できるのは最後になると思います。
2022年もどうぞ、よろしくお願いします。それでは。
参考
単一散乱アルベド single scattering albedo - aerosolpedia エアロゾルペディア
大気はどこにあるの? | 科学の普及活動 | 公益財団法人日本科学協会
成層圏エアロゾルと対流圏エアロゾル Stratospheric and Troposphric aerosols - aerosolpedia エアロゾルペディア
レイリー散乱とミー散乱 Rayleigh and Mie scattering - aerosolpedia エアロゾルペディア
どうも、ラブヘイトです。
BlenderからUnityにモデルをインポートした際に、
・Normal mapはどうやって適用するの?
・Bleder側で割り当てていたUVmapはどこへ?など
いくつか疑問があったので、自分が行ってできた一例を紹介しようと思います。
まずはBlender側から
今回はこちらのモデルを使います。
街灯の窪んでいる部分が、Normal mapの適用されている箇所です。
これをUnity側に持っていった時も適用したいというのが、今回の課題です。
BlenderでのNormal mapの作成方法がわからない方は、過去記事に書いています。参考にしてみてください
【Blender】UV mapの一部にだけNormal mapを適用する方法 - うにty生活
オブジェクトの一部にNormal mapを割り当ててる(以下Normalオブジェクト)
つまり1つのオブジェクトの中でNormal mapを割り当てる部分のマテリアルは分けている状態
また、全ての箇所に仮でもいいのでマテリアルを割り当てといてください。
Unity側でオリジナルのマテリアルを設定するのに必要です。
UV mapは二つ存在
一つはベタ塗り用、一つはNormal map用です。
※ 上側の画像背景はnormal mapですが本来は透明です
Normalオブジェクトのshaderはこんな感じ
この状態のモデルをエクスポートします。
エクスポート設定は以下の通り
エクスポート設定はいちいち覚えておくのも面倒なので、プリセットとして覚えさせておくことをお勧めします。
そしてUnityにインポートします。
人によって違うとは思いますが、マテリアルはBlenderから運んできても、色味が違うので自分はそもそもBlender側では本気でShaderいじらないです。こんなもんかなーと確認が取れたらもう出力しちゃって、Unity側でガッツリShaderいじります。
インポートしたモデルのマテリアルをUnity側で設定する場合
インポートしたオブジェクト>Inspector>Material
からマテリアルを設定して
ApplyすることでUnity側のマテリアルをモデルに簡単に割り当てることが可能です。
normal map用のマテリアルもここで割り当てます。
※Blender側でマテリアルが割り当てられてないまま、Unity側にインポートするとインポート設定で出てこなくなるので注意
normal map用のマテリアルを作成していきます。
と言ってもめちゃくちゃ簡単です。
Blenderで作成したTextureはBlenderエクスポート時にCollectionとして一緒に出力してもいいし、画像を保存しているなら手動でインポートでもどちらでもいいと思います。
Create > Shader > HDRP > Lit Graph
で新しいShader Graphを作成。選択した状態でCreate>Material
からShader Graphが割り当てられたMaterialを作成します。
Sample Texture 2Dノードを利用する方法とNormal From Textureノードを利用する方法、2つあります。どちらもTextureにNormal mapを設定するのは同じです。
それぞれの結果を見てみましょう。まずはNormal From Textureから
近くで見た時
遠くで見た時
なぜかぼやける...
次にSample Texture 2D
近く
遠く
かなり遠くからでも窪んで見えるため、Sample Texture 2Dを採用
もしかしたら、Normal From Textureの使い方が悪いのかもしれないが今回は体験談ということでよしとしましょう。
今回はここまで、ここまで見てくださってありがとうございました。
Unityで夜のLighting&星空作成!
明けましておめでとうございます。どうもラブヘイトです。
2021年もUnityで遊び尽くしていくので、よろしくお願いします。
以前街灯のモデルを作ってみたので、夜のライティングをしてみようと思います。
ついでに夜のライティングをするなら、星空も作成しよう!ってことで
今回は夜のライティング+星空を作ってみました。
以前からHDRP環境ってどうやって夜にするんだろうと思ってましたが、HDRPのライティングはカメラと合わせてライティングなので、Exposure(絞り)を調節して光を取り込む量を調節します。
以下の動画で、その辺も含めて紹介されてます。
ライティングは基本この動画に沿って行っていきます。
こちらの記事で作成した、モデルをインポートして使っていきます。
【Blender】UV mapの一部にだけNormal mapを適用する方法 - うにty生活
Unity側でのNormal mapの設定方法などは今回やりたいこととは外れるので、別の記事で紹介します。
→ ちょっと待ってね
まずはVolumeの設定から。デフォルト設定の影響を無くしたところから作業します。
デフォルトで作成している人は最初から存在する「Directional Light」「Sky and Fog Volume」のアクティブを切りましょう。
また、「Post Process Volume」はExposureとBloomも一旦切っておきます。
Create>Volume Profile
で新しいVolumeを作成します。設定は以下の通りです。
これだけでは反映されなくて、Window>Lighting
設定のEnvironment(HDRP)にProfileを設定する必要があります。
内側から発光する表現するためには街灯のカバーにあたる部分の、マテリアルのEmissioin項目を変更します。
Emissive Colorは配置するライトの色温度に近づけます。
Emissino Intensityは動画の通り791を設定。
791はLumenからカンデラに変換した値です。
カバーの中にポイントライトを設置します。設定は以下の通り
Lumenには現実の値を参照して10000〜40000の値を設定します。
こんな感じになりました
過去にskyboxを自作していますが、今回は再度紹介します。
skyboxについての基礎や詳細を知りたい人は以下のこちら↓
できるだけ綺麗な画像が欲しかったので、NASAの画像にしました。
SVS: The Alternative Night Sky - Another Time - Another Place
8kの画像をダウンロードしました。
超簡単にskybox作成の解説します!
画像を取り込んで、取り込んだ画像のInspectorを以下のように変更します。
・Texture Type → Cube
・Mapping Type → Latitude - Longitude Layout
・Default > Compression → High Quality
・Apply
これだけでライティングの時に設定したHDRI skyの名前右側を押すと、先ほど取り込んだ画像がsky boxとして設定可能です。
星空はあっけないほど簡単に設定できました!
一気に写実的な画面になって驚きです。以前UnityちゃんをHDRP環境に移行した時に予想していましたが、やはりHDRPでのLightは現実世界の数字を当てはめていくことがわかりましたね。
相変わらず、この世界何もないな笑
今回は最近の協力ゲームでは必須の機能!
仲間などに意思表示するためのシグナル(ピン立て)機能を作成します。
みんな大好き(知らんけど)Fortniteの、シグナルシステムを参考にしようかなと考えてます。
余談ですが最近のfortniteは有名どころとコラボしまくって結構おもしろいです笑
色々呼び方あると思いますが、以下「ピン」に統一します。
見てわかる範囲ですが、Fortniteのピンの特徴としては以下の通りです。
・指定箇所にピンを立てる
・動かない(または動く)
・ピンを指したオブジェクトのアイコン表示させる
・どの距離でもピンの大きさが同じ
・アイテムの上にピンが表示される
・ピンが画面外に出た時に、画面の四角を移動する
・障害物で表示切り替え
・距離を表示etc...
いろいろ挙げましたが今回は以下の仕様を実装します
・指定箇所にピンを立てる
・ピンを指した場所から動かない
・障害物で表示切り替え
こんなイメージ
適当に作成しました。以下の画像はご自由に使ってください。
グリーンバックにしているので、ご使用の際は背景を透過してから使用すること推奨
クリックした場所にピンを立てるので、視点操作はあってもなくてもいいのですが一応
現在のUnityちゃんの視点や動きを紹介しておきます。
コード
gistcee3a5249862de6ecdec4929980c30b8
カメラは固定で、このコードは縦方向のみの視点移動を行います。
横方向はキャラクターの子にして、キャラクター移動に依存させています。
※動画内のズーム機能はついてません。
過去にもカメラ紹介してます
【改良版】追従+マウス視点移動のTPSカメラ #18.1 - うにty生活
Unityちゃん移動方法
キャラクターの動かし方を見直してみた #15 - うにty生活
個人的なことを言うとUnityちゃんの顔が見えなくなるカメラはあまり好きじゃないです。が、簡単に実装できるカメラを一つ作成しておきかたっかので作りました。
照準はOverlayのCanvasの中央にドットを配置しているだけです。
ピンを立てるためのイメージはこんな感じ
①ユーザーからアクション(クリック)を受け取る
②PinPointを作成する
③PinPointからRayを飛ばして、位置情報や、物に隠れてないかを判断
④ピンの描画
※PinPointはUnityの単語ではありません。自分で適当につけた名前です。
CreatePinPoint
CreatePinPointはカメラにアタッチします。クリックした場所からRayを飛ばして衝突検知した場所にPinPointオブジェクトを作成します。(PinPoint自体は透明で、見えるようなものではありません)
12行目 pinPoint
ピン情報を保持、発信するプレファブで構成は以下の通りです。
このPinPointにアタッチされているスクリプトはこちら↓↓↓
PinSystemOverlay
簡単に概要を説明するとこのスクリプトがアタッチされたオブジェクトの、位置場所によってUIをCanvas上で移動させたり、障害物があれば非表示にする判定を行います。
11行目 pinPrefab
Canvas上に表示するピンのイメージプレファブで、OpenPrefabした時の構成は以下の通りです。
Cnavas(Overlay) └ pinUI └ image
上記プレファブのImageコンポーネントにアタッチされている画像はこちらで載せている画像を使ってます。
※ただここは任意で良いので、ピンっぽい画像ならなんでもいいです。
基本的な流れとして、Canvas上での「pinUI」の位置決定方法は、Start()内の手順で行います。
20行目 ScreenPositionの取得
21行目 Canvas上のlocalPositionを取得
22行目 Canvas上にピンのイメージを配置
衝突検知+表示制御+位置決定をLateUpdate()内で行っています。
30行目で障害物検知としてカメラに向かってRayを飛ばして、
カメラに到達しなかったものや、カメラとの間に障害物がある場合は表示されません。
次に画面内検知は二重で行っています。
33行目 Vector3.Dotでは、カメラベクトルとPinPointからカメラ方向へのベクトルの内積を取得。視野範囲を決定しています。
この範囲から外れたら、画面外と言うことなのでpinUIは非アクティブにしています。
最初はカメラフレームへのIn/Out判定に
OnBecameVisibleメソッド
とOnBecameInvisible
メソッドをセットで使用していました。
OnBecameVisibleメソッド
は、オブジェクトがカメラフレームにInしたとき、
OnBecameInvisible
メソッドは、オブジェクトがカメラフレームからOutしたときを検知して動作します。
確かに、説明の通りに動いてはいるのですが、検証しているうちにカメラがPinPointの裏側を向いていても反応することが判明しました。
これによってカメラを挟んだPinPointと対角線にもUIが表示される問題があったため、今回の方法になりました。
視野範囲のコードはいろんなところで使えそうだし、応用が効きそう!
ピンシステムの完成!
かなり安定したピン立てシステム完成しました!
— ラブヘイト@うにty生活ブログ (@unity_stamp) November 10, 2020
worldのcanvasではなくoverlayのcanvas使ってるので、ピンの位置による大きさの変動がありません。#unity pic.twitter.com/bYb1BuTYAk
スクリーン座標からCanvasにUIを表示させて、さらにそれを動かし続けるのはまじで苦労しました。
座標を取得・変換する流れはこの通り
WorldPoint取得→ScreenPointに変換→配置したい親のlocalPositionに変換
2日間くらい悩んでいたので、Twitterで質問してできたコードです。
【質問】
— ラブヘイト@うにty生活ブログ (@unity_stamp) September 14, 2020
特定の3Dオブジェクトのスクリーン座標の位置にUIを配置したい場合どうすればよいですか?
Canvasはcameraです
役立ちそうなURLだけでももしあればよろしくお願いします
追加で欲しい情報があれば返信します
2日試行錯誤しましたがわかりまさんでした
協力していただいた方々、どうもありがとうございます。
やっとUnityちゃんを登場させることができました!
以前登場させたのが過去記事なので、8ヶ月ぶりです...笑
その間はshaderやparticleの学習に励んでいたので、表現力は豊かなUnityちゃんをこれからもお届けします!