20220402のUnityに関する記事は6件です。

Unity 回転とスケールだけを用いたShear(せん断)の実装

Shearとは Shear(せん断)とはアフィン変換の一種で、下の様にある軸にそって引き伸ばす変換です。 しかし残念ながら、UnityにはShearを行う機能はありません。 ただ実は回転とスケールの合成だけでShear変換を作ることができるので、代わりにこれで実装します。 Shear変換行列の分解 実装の前に行列ではどのように表現されるのかみてみましょう。 Shearは次の変換行列で表される変換です。 \begin{pmatrix} 1 & x \\ 0 & 1 \\ \end{pmatrix} 唐突ですが、$x$を次のように表します。 x = \frac{1}{\tan \theta} すると、Shearは次のように回転行列と対角行列の積に分解できることが知られています。 (この導出は調べた限り分かりませんでした…ご存知の方は教えてください) \begin{pmatrix} 1 & \frac{1}{\tan\theta} \\ 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} \frac{\sqrt2}{\sin\theta} & 0 \\ 0 & \sqrt2 \end{pmatrix} \begin{pmatrix} \cos -45 ^\circ & -\sin -45 ^\circ \\ \sin -45 ^\circ & \cos -45 ^\circ \end{pmatrix} \begin{pmatrix} \sin\frac{\theta}{2} & 0 \\ 0 & \cos\frac{\theta}{2} \end{pmatrix} \begin{pmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{pmatrix} これはつまり、単純な回転とスケールだけでShearを行えることを意味しています。 また、 \phi = 90 ^\circ - \theta とおくことで \begin{pmatrix} 1 & \tan\phi \\ 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} \frac{\sqrt2}{\sin90^\circ - \phi} & 0 \\ 0 & \sqrt2 \end{pmatrix} \begin{pmatrix} \cos -45 ^\circ & -\sin -45 ^\circ \\ \sin -45 ^\circ & \cos -45 ^\circ \end{pmatrix} \begin{pmatrix} \sin\frac{90^\circ - \phi}{2} & 0 \\ 0 & \cos\frac{90^\circ - \phi}{2} \end{pmatrix} \begin{pmatrix} \cos\frac{90^\circ - \phi}{2} & -\sin\frac{90^\circ - \phi}{2} \\ \sin\frac{90^\circ - \phi}{2} & \cos\frac{90^\circ - \phi}{2} \end{pmatrix} \tag{1} と表すこともできます。 Unityでの実装 (1)の変換をコードに落とし込んでいきましょう。 次のようなコンポーネントを作ります。 using UnityEngine; [ExecuteAlways] public class Shear : MonoBehaviour { [Range(-90, 90)] public float phi = 30f; private void OnValidate() { // z軸回りにShearさせる float angle = 90 - phi; // 一つのTransformでは、Scale→Rotationの順に適用されることに注意 transform.localRotation = Quaternion.Euler(0, 0, angle / 2); transform.parent.localScale = new Vector3(Mathf.Sin(angle * Mathf.Deg2Rad / 2), Mathf.Cos(angle * Mathf.Deg2Rad / 2), 1); transform.parent.localRotation = Quaternion.Euler(0, 0, -45); transform.parent.parent.localScale = new Vector3(Mathf.Sqrt(2) / Mathf.Sin(angle * Mathf.Deg2Rad), Mathf.Sqrt(2), 1); } } これをShear対象のオブジェクトにアタッチし、親として2つEmptyオブジェクトを設定します。 その状態でスライダーを動かすとShearすることがわかります。 参考 https://www.cs.cmu.edu/~fp/courses/02-graphics/asst2/solution/asst2-sol.pdf https://answers.unity.com/questions/961330/shear-transformation-using-gameobject-transformati.html https://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] すり抜けない当たり判定の実装方法 MeshCollider Convexなしでもすり抜けない。

Unityですり抜けない当たり判定を実装するのに苦労したので、実装方法をアップさせてもらいます。 MeshCollider の convex が true の場合は簡単なのですが、それだと Mesh に対して 正確な当たり判定 Collider が生成されません。 convex true の場合は Colliderの三角形の面の上限数が255になるために正確になColliderにならないようです。(↓画像:建物に対してColliderの緑線がずれていることがわかる。) https://docs.unity3d.com/ja/2018.4/Manual/class-MeshCollider.html convex を falseにしたまますり抜けない正確な当たり判定を作るには以下の3つの要素が必要です。 (1) 衝突するオブジェクト(プレーヤーなど)の移動方法は Rigidbody の AddForce();を用いること。 (2) 1に伴い衝突するオブジェクト(プレーヤーなど)に Rigidbody をアタッチすること。 (3) 衝突するオブジェクト(ぷれーやーなど)にアタッチした Rigidbody の Collision Detection が Discrete ではないこと それぞれ解説していきます。 Rigidbody.AddForceで移動させる Rigidbodyの物理演算によって当たり判定もより正確になるようです。そのためすり抜けを減少させることができます。 基本的な AddForce の書式は以下の通りです。 GetComponent<Rigidbody>().AddFroce(x,y,z,ForceMode.モード); //Vector3などを使う場合は以下のように引数を2つにすることもできます GetComponent<Rigidbody>().AddFroce(移動量,ForceMode.モード); ForceMode ↓ 好きなのをどうぞ。力の加え方が継続的な Force と Acceleration は一度実行すると止まらなくなるので、弾幕の動きなどに使います。 一方、力の加え方が一瞬の Impluse と VelocityChange は進んだりとまったりする プレーヤーの動きなどに使います。 プレーヤーを動かすなら、Impluse が良いと思います。 参考サイト↓ https://nekopro99.com/move-rigidbody-addforce/ 種類 力の加え方 質量を考慮 Force 継続的 考慮する Acceleration 継続的 無視する Impluse 一瞬 考慮する VelocityChange 一瞬 無視する これだけではわかりずらいので今回は FPSゲーム* を例に見ていきます。 (1) まず、プレーヤーと衝突される側のオブジェクト(建物など)に BoxCollider などの Collider が入っていない場合、適切な Collider をアタッチします。(複雑な形には今回の MeshCollider を使用します。その場合、convexのチェックは入れません。) (2) 次にプレーヤーに Rigidbody をアタッチします。 アタッチしたら、Rigidbody の Collision Detection を Discrete以外 にします (3) 最後にプレーヤーにスクリプトをアタッチします。 プレーヤー の FPS視点および移動のスクリプト は以下のgithubページのコードを一部改変したものになります。(私のコードではありません↓) https://gist.github.com/Naoya42/59ee65bdfba9cb03504300d560d0f236#file-fpscontroller4-cs このgithubのコードを FPSController.cs にしてプレーヤーにアタッチします。 アタッチしたら FPSController.cs を修正および追記していきます。 public class FPSController() 内に以下を追記します public Rigidbody rb; public class FixedUpdate() 内の以下の部分を削除します。 //transform.position += new Vector3(x,0,z); transform.position += cam.transform.forward * z + cam.transform.right * x; public class FixedUpdate() 内に以下を追加します。 //↓以前の移動方法 //transform.position += cam.transform.forward * z + cam.transform.right * x; //AddForceを使い移動するcolliderのすり抜け対策! rb.AddForce(cam.transform.forward * z + cam.transform.right * x,ForceMode.Impulse);//前後左右の移動 if (Input.GetKey(KeyCode.Space)) { rb.AddForce(0,speed,0,ForceMode.Impulse);//ジャンプ } これでプレーヤーは Collider をすり抜けずに移動できるようになります。 成功すると以下の動画のようにすり抜けなくなると思います。 https://www.youtube.com/watch?v=e0cPsm8_cN8
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity+DeckLinkのHDMI出力の不思議

はじめに Blackmagic製品を使っていると 「何か色違わない?」 って聞かれます。 特に確認用のリファレンスモニタを決めたり、カラーマネジメントされているモニタを使っているわけではないので見え方はそれぞれの環境で多少違うかもしれませんが、気になると言われると調べないわけにはいかないので… なおBlackmagicの全ての製品の話ではなく、対象は比較的安価に買えるHDMI出力がついているDeckLinkシリーズです。 Unity Editor上から簡単に映像出力できるので、使っている人はそれなりにいるのかな? ちなみに映像は専門ではありません。 あくまで現象から対処案を出しただけです。 というか専門の人に教えて欲しいぐらいです… 結論 SDIを使いましょう HDMIを使いたいならSDI-HDMI変換を使いましょう 検証環境 Windows10 Pro 21H2 Unity2020.3.30f1 AVProDecklink 1.9.2 Blackmagic DeckLink Mini Monitor 4k (Driver 12.2.2) Blackmagic Video Assist 7インチ 12G Blackmagic ATEM Mini Pro ISO Blackmagic Micro Converter BiDirectional SDI/HDMI 3G 近年よくあるUnity Editorの映像をMonitor 4kで送出してATEMに入れる構成です。 まずはATEMは接続せず、Monitor 4kのHDMI/SDI OUTをVideo Assistのそれぞれの入力つなげて両方から収録出来るようにして検証します。 Monitor 4k---(HDMI/SDI)--->Video Assist 検証 Unityでカラーバーと3Dモデルを表示して、HDMIとSDIのそれぞれの出力結果をVideo Assistで収録(コーデックはProRes HQ)して確認します。 ニコニ・コモンズの南部185さん作成のカラーバー画像を使わせて頂きました。 https://commons.nicovideo.jp/material/nc210520 3Dモデルはササリーヌさん http://aodamatei.sakura.ne.jp/castlevernier/ レンダリングパイプラインはURPです。 3DモデルはUniversal Toon Shader for URP 2.5.0、カラーバーはUnlitで描画しています。 注意点としてはDecklink Outputの設定でPixie Formatは 8-bit ARGBにしてください。8-bit UYVY 4:2:2だとまた別の原因があるのかSDIでも想定した色で出力されていません。 まずはSDIとHDMIのそれぞれの出力結果です。 SDI HDMI あれ?確かにちょっと違うような…HDMIの方がちょっと明るい? 差の絶対値で確認すると確かに違う。 SDIとHDMIの差の絶対値 何やら差が出てますねぇ 確認のため、Unity上の画像とSDIの差の絶対値を確認します。 エッジ部分に差が出るものの、全体としてはほぼ同じですね。 どうやらHDMIで出力した場合は指摘された通り「何か色違わない?」出力になっているようです。 拡大して同じ座標の色を確認すると、SDIは想定した色で出ているけどHDMIの方が何か違うぞ…? 例えばSDIのRGB(192,192,192)のところがHDMIだとRGB(205,205,205)になっていますね。 うーん、SDIは問題なくHDMIだけ違うということは…もしかしてHDMI出力のレンジか!? HDMIは フルレンジ:RGBの範囲は0~255 リミテッドレンジ:RGBの範囲は16~235 となっているので、もしHDMI出力がフルレンジで受信側がリミテッドレンジと解釈しているならば明るく表示されそう。 リミテッド→フルの変換はシェーダーで書くと const float scale = 255.0 / (255.0 - 20.0 - 16.0); const float offset = 16.0 / 255.0; float4 col = ターゲット色 return ((col - offset) * scale); になるので、当てはめて計算するとRGB(192,192,192)はRGB(205,205,205)になりますねw どうやらビンゴかも。 そこで検証するためにAVProDecklinkのシェーダーを改造します。 といってもAVProDeckLink_toARGB.shaderのフラグメントシェーダーに3行追加するだけです。 float4 frag(v2f i) : COLOR { // ~ 省略 ~ // 最後にフル→リミテッド変換 const float scale = (255.0 - 20.0 - 16.0) / 255.0; const float offset = 16.0 / 255.0; col = (col * scale) + offset; return col.argb; } この改造で出力する映像のRGBをリミテッドの範囲にスケールします。 実際にこのリミテッド化したHDMI出力と前のSDI出力と差の絶対値を確認すると差がなくなりました。真っ黒な画像なので完全一致ですね。 これはMonitor 4kのHDMI出力自体はRGBフルレンジですが、どうやらリミテッドレンジと認識されて受信側でリミテッド→フル変換(実際にはフル→フル変換)が走っているようです。 んーどうしてこうなった… 対策 気にしない。もしかしたら実写なら気がつかないかも… シェーダーを改造して自前でRGBリミテッド化してからHDMI出力する。ただしSDI出力も影響を受けてしまう(リミテッドレンジで表示される) SDIのみ使う。一番安全。 とはいえ、ATEMと繋げるならHDMIしかありません。 そこでSDI-HDMI変換を使うとどうなるかも検証しましょう。 SDI-HDMI変換機は各社から出ていますが、今回はBlackmagic Micro Converter BiDirectional SDI/HDMI 3Gを使いました。双方向に変換出来る便利なヤツです。 Monitor 4k---(SDI)--->SDI-HDMI Converter---(HDMI)--->ATEM---(HDMI)--->Video Assist 結果は問題なく表示出来ました。 もちろん自前RGBリミテッド化すれば Monitor 4k---(HDMI)--->ATEM---(HDMI)--->Video Assist でも正しく表示できました。でもこれだとSDIが(ry 最後に HDMIはレンジ問題以外にもケーブルの長さや品質でトラブルを起こすことがあるので、費用はかかりますが出来るだけSDIを使うのが一番確実なのかもしれません。 Blackmagic製品はコストパフォーマンスに優れているので重宝していますが、ちょいちょいやらかしている印象もありますw それでも今日も検証機材として大活躍!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity講座をアップデートしたって話 セールもあるよ。

どうもオオモリちゃんです。  本日、Unity講座をアップデートしたのでそのお知らせです。 Unity3DゲームStandard講座Vol2 現在、アップデート記念として80%OFFセールをやっています。  こちらのセールは、4月14日までとなりますので。  アップデート版では、2021.2の機能やアーティスト向けの機能を 中心に解説しました。  更に新しくUnityファミリーに加わった、PlasticSCMの解説もしています。  PlasticSCMをちゃんと解説している講座はまだ殆どないので  これだけでも見る価値があると思います。  【GitHubを使っている人も、Plasticに移行する人が増えるでしょうね】 VOL1と合わせると、なんと合計で約9時間あります。  見るだけでも大変でしょうが。 これ一本見れば  とりあえず基礎はマスター出来ると思います。 興味があれば、ぜひ御覧ください。 PS そういえばゲーミングサービスも6月から正式リリース されますよね。  そっちの解説も入れたかったので Unity講座は  今年中にはもう一回 アップデートするかもしれません。 そのうち、VR講座も出す予定です。 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityでアセットをインストールしたらエラーが...

1. はじめに Unityのアセットを導入する際エラーが出てしまい、うまくインポートできなかったのですが解決ができたので備忘録として本記事を作成しました。 同じエラーが出てる人にとって参考になれば幸いです。 2. エラーコード [Package Manager Window] Error while getting auth code: System.InvalidOperationException: Failed to call Unity ID to get auth code. UnityEditor.AsyncHTTPClient:Done (UnityEditor.AsyncHTTPClient/State,int) (at /Users/bokken/buildslave/unity/build/Editor/Mono/AsyncHTTPClient.cs:248) エラーコードを感じだとUnity IDがうまく取得できなかった、といった感じでしょうか? 解決方法 結論から言うと、Unityを再起動したうまく読み込んでくれました。笑 たまたまUnity IDがうまく読み込まれてなくて再起動する必要があったと言うことなのだろうか?わからない...ただもしこれを読んでくれている人も同じエラーが出ているのであれば一度試してみるのもいいかもしれません。 拙い文ですが、最後まで読んでくださりありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityのTextを豆腐にしない、Font.HasCharacter

概要 Unityのテキスト表示で、顔文字とか、なんかよくわからない難しい漢字を表示しようとすると、Text表示でエラーが出たり、TextMeshProが通称"豆腐"になったりします。(下図は、アルファベットしか対応してないフォントで「TextMeshぷろ」と入力したときの表示) 新しくリリースされたソシャゲなどでユーザー名を入力する際に、表示対応してなさそうな様々な文字を入力してアプリをクラッシュさせる遊びを皆さん嗜んでおられると思いますが、自分のゲームでやられると嫌なのでしっかり対策しましょう。 様々方針はあると思いますが、文字の扱いって歴史が深くてできれば関わりたくないので、Unityが用意してくれてるAPIを利用してみます。 フォントに文字が含まれてるか返すメソッド UnityEngine.Font.HasCharacter UnityEngine.UI.Textを使用する際に使えます。 charを引数に渡して、それがフォントに含まれる文字かどうかのboolを返してくれます。 using UnityEngine; using UnityEngine.UI; public class Test : MonoBehaviour { [SerializeField] private Text text; private void Start() { // なんかすごい難しそうな漢字 var userInputChar = '亹'; // この文字は表示できる? var canRender = text.font.HasCharacter(userInputChar); } } フォントに含まれてるなら表示できるし、含まれてないなら表示できないっていうのが一番素直なので、特定の文字はどうしても使わせたくないとか特別な事情が無いならこれで十分かなと思います。 TMPro.TMP_FontAsset.HasCharacter TextMeshProを使用する際にも同様のメソッドを使用できます。プロパティ名はfontと、前述のTextと同じですが型は違います。 なお、オプション引数として、「フォールバックのフォントも検索するか」、「フォントアセットに動的に文字を追加するか」を選べます(デフォルトfalse)。 using UnityEngine; using TMPro; public class Test : MonoBehaviour { [SerializeField] private TextMeshPro tpm; private void Start() { // なんかすごい難しそうな漢字 var userInputChar = '亹'; // この文字は表示できる? var canRender = tmp.font.HasCharacter(userInputChar); } } TMPro版はさらにstringを渡して文字列を一括で判定してくれる、HasCharactersもあります。 using UnityEngine; using TMPro; public class Test : MonoBehaviour { [SerializeField] private TextMeshPro tpm; private void Start() { // なんかすごい難しそうな文字列 var userInputString = "齷齪"; // この文字列は表示できる?(1つでも表示できない文字があればfalse。そうでなければtrue) var canRender = tmp.font.HasCharacters(userInputString); } } おわり こういうメソッドをUnityサイドが文字表示するために用意してるのは考えてみれば当たり前の話ですが、実はpublicで公開されてるので我々Unityユーザーも使えるんですね。文字表示に限らず、もしかしてUnityに元からあるんじゃね?と思える処理なら、一度Unityが公開しているソースコードを調べてみるのは悪くないと思います。 とはいえ調べた結果internalで宣言されてるのを見つけて悲しい気持ちになる可能性はなくはないです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む