20211014のUnityに関する記事は7件です。

(Unity) VContainer + MessagePipe を用いた動的に生成したGameObjectへのInject

ソース // LifetimeScope で登録 public class GameLifetimeScope : LifetimeScope { protected override void Configure(IContainerBuilder builder) { var options = builder.RegisterMessagePipe(); builder.RegisterMessageBroker<FlickEvent>(options); builder.RegisterMessageBroker<AttackData>(options); } } // Flickイベントを購読し、Prefabを生成するクラス // 注 Hierarcy 上ですでにLifetimeScope で紐付いている public class ObjectManager : MonoBehaviour { [SerializeField] private GameObject linePrefab; [Inject] private ISubscriber<FlickEvent> flickSub; [Inject] private IObjectResolver container; public ObjectManager(IObjectResolver container) { this.container = container; } void Start() { this.transform.position = Vector3.zero; flickSub.Subscribe(fev => DrawLine(fev)).AddTo(this); } void DrawLine(FlickEvent fev) { if (linePrefab == null) { throw new ArgumentNullException("ObjectManager needs linePrefab."); } var line = container.Instantiate(linePrefab, this.transform); } } // 生成されるPrefabが持つInjectを利用したいクラス public class AttackObject : MonoBehaviour { [Inject] private IPublisher<AttackData> atackPub; // 触れた物体が敵の場合、攻撃を発生させる処理 private void OnTriggerEnter(Collider other) { if (other.gameObject.tag != "Enemy") return; atackPub.Publish( new AttackData(damage, other.gameObject) ); } } 参考 公式ドキュメント 補足 ファクトリーパターンでの実装もあるようです、余裕があればこちらもやってみたい 記事について ソースに関しては、抜粋のためコピペでは動作しない可能性があります。 コメント、補足、LGTM大歓迎です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ifLinkにサイコロIMSが新たに追加になりました。

はじめに ifLinkマイクロサービスを開発している八教と申します。 新たに3つのサイコロ出目及び出目の合計を取得し、ifLinkに通知するIMSが追加されましたので、 紹介させていただきます。 ifLinkとは サイコロIMSとは 3つのサイコロの出目、または出目の合計をifLinkのIFとして設定できます。 例えばIF条件をサイコロ出目の10以上とし、サイコロを振って10以上が出た場合に「あたり!」をトーストメッセージIMSで表示できます。 サイコロで遊ぶまで サイコロで遊ぶまでに以下の準備が必要です。 1.IAIIMSをインストールする   IAIIMSはサイコロIMSとifLinkをつなげる為に必要です。   以下リンクよりインストールしてください。   https://dev.iflink.link/ 2.SaicoroIMSをインストールする   さいころゲーム本体で、以下リンクのReleasesのSaicoroGame.apkをダウンロードしてください。   https://github.com/ifLinkOpenCommunity/SaicoroIMS 3.ルールを作成・配信する   IF条件で「Saicoro-Game-ToifLink」を選択してください。  条件は以下の通りです  ①.サイコロの目が設定通りなら    3つのサイコロの出目が設定した値と一致したらTHENが起動します    出目の順番はサイコロを振った順(ランダムで振られます)  ②.サイコロの目の合計値が設定通りなら    3つのサイコロの出目の合計値が設定した値と一致したらTHENが起動します  ➂.サイコロの目の合計値が設定以上なら    3つのサイコロの出目の合計値が設定した値以上ならTHENが起動します  ④.サイコロの目の合計値が設定以下なら    3つのサイコロの出目の合計値が設定した値以下ならTHENが起動します 4.SaicoroGameで遊びましょう!   以下アイコンをタップしてサイコロゲームを起動します。 起動すると何も表示されていない画面が表示されます。 画面をタップするとサイコロが振られます。 サイコロの動きが止まると出目が確定します。 確定した出目と出目の合計がトーストで表示されます。 IFで設定した条件に合致するとTHENが起動しトーストメッセージ「あたり!」が表示されます。 是非お試しいただければと思います。 【検証端末】  Pixel 4a XL Androidバージョン11  Oppo A5 2020 Androidバージョン10
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityEditor スクリプト制御 アセットの扱い方など

UnityEditor AnimatorControllerの場合 Editor で、AnimatorControllerアセットを参照しながら処理をしたいとき。 ↓ UnityEditor.Animations.AnimatorController型として取り扱う。 教訓: UnityEditorでAssetを読み込むときの型は特殊である。型を特定する前には罠が張られている。本物はどこかに隠されているという事。F 流れ。 先ず、StateMachineを取り出したかったが スクリプトからAnimatorControllerアセットを読み込んで、Get~とは簡単にできなかった。 まず、AnimatorController型として読み込むことが出来なかった。 次に、 アセットはRuntimeAnimatorController に対応すること知った。これによって以後ずっとこの型に関する情報を探した。(AnimatorControllerと思っていたAssetは RuntimeAnimatorControllerだったのだ。) だがこれが大きな間違いだった。 どうしても、欲しい情報が取り出せなかった。 ここからStateMachineを読み出すには??? AnimatorControllerであればLayerを参照できるはずなのだが。 RuntimeAnimatorControllerではそれが出来ない。 Animator.RuntimeAnimatorController このような関係になっているみたいだったが。 そしてついに判明した事実。 __UnityEditor.Animations.AnimatorController__型として読み込める。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity] 重なり合うボタンを処理する

全てのボタンが同じtransformの子になっている前提で、 重なり合っているボタンをこんな風に処理したい 一番簡単なのは、OnClick()で button.gameObject.transform.SetAsFirstSibling(); のように最背面に移動してしまうことなのですが、これだと次のボタンが押せるようになる代わりに表示も背面に隠れてしまいます。 そこで、 for (int i = 0; i < transform.childCount; ++i) { UnityEngine.UI.Image img = _transform.gameObject.GetComponent<UnityEngine.UI.Image>(); if (transform.GetChild(i).Equals(_transform)) { img.color = Color.red; img.raycastTarget = false; transform.GetChild(i).SetAsLastSibling(); // 今回選択したものを最前面に } else if (!img.raycastTarget) // 前回最前面だったものを最背面にする { img.color = Color.white; img.raycastTarget = true; transform.GetChild(i).transform.SetAsFirstSibling(); } } のように、今回選択したものは raycastTarget をfalseにして押せなくしつつ最前面に、前回選択していたものはraycastTarget を元に戻しつつ最背面に送ることで、選択したものを最前面に残しつつ、後ろのボタンを押せるようになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

URPでマトリックスコードシェーダー

マトリックスのやつ公式サイトを参考にShaderGraphで書いてみました#unity #madewithunity #shader pic.twitter.com/1N0abj5Wr3— おうどん (@oudon) October 14, 2021 マトリクスの新作が発表されたので 公式のマトリックスコードを参考にURPのShaderGraphで模写してみました。 雰囲気はでてると思います。 ソースコード Unity 2019.4.16f1 URP ShaderGraph 概要 元となる文字の8×8のテクスチャシートからランダムに文字を抽出、 一枚の板ポリに複数列下へ流れるようにします。 おおまかな流れとしては以下の通りです。 テクスチャシートを用意 Shader作成 シートの中からテクスチャを拾う 複数行列分、ランダムに表示できるようにする。 ランダムの調整 文字のスクロール emissionとfadeoutの調整 複数列で、文字の並びとスクロールタイミングをズラす。 オブジェクトの配置 テクスチャシートの作成 なにより都合の良いテクスチャがなかなか見つからなかったので やり方は色々ありそうですが、今回はPhotoshopで作成しました。 まずは1文字ずつpngに書き出して コンタクトシートIIで読み込み・等間隔に整列して完成です。 せっかくなのでphotoshopのスクリプト書いてみました。 レイヤー作成 テキストに指定した文字分のレイヤーを作成・センタリングします。 後続のスクリプトのため、レイヤー名に「文字.png」という名前をつけています。 あとで縮小されますが、とりあえず48pxのサイズで作成してます。 function layerMoveToCenter(layer) { const docWidth = activeDocument.width; const docheight = activeDocument.height; const bounds = layer.bounds; const layerWidth = bounds[2] - bounds[0]; const layerHeight = bounds[3] - bounds[1]; layer.translate(-bounds[0] + docWidth / 2 - layerWidth / 2, -bounds[1] + docheight/2 - layerHeight/2); } function resetLayers() { var doc = activeDocument; for(var i=0; i<doc.artLayers.length; i++) { var lname = doc.artLayers[i].name; if (lname.substr(-4) == ".png") { doc.artLayers[i].remove(); } } } function createTextLayer(text) { var doc = app.activeDocument; var layers = doc.artLayers; var l = layers.add(); l.name = text + ".png"; l.kind = LayerKind.TEXT; l.textItem.contents = text; l.textItem.size = 48; l.textItem.font = "Meiryo-Bold"; l.textItem.justification = Justification.CENTER; l.textItem.color.rgb.red = 0; l.textItem.color.rgb.green = 0; l.textItem.color.rgb.blue = 0; l.textItem.horizontalScale = 100; l.textItem.verticalScale = 100; return l; } var text = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンABCDEFGHIJKLMNOPQRSTUVWXYZ"; resetLayers(); for (var i = 0; i < text.length; ++i) { var target = text.charAt(i); var layer = createTextLayer(target); layerMoveToCenter(layer); } ちなみに作成したスクリプトは 「Photoshop.exeがあるフォルダ」→「Presets」→ 「Scripts」 に管理者権限で配置してphotoshopを再起動すると利用できるようになります。 新規作成→スクリプト実行でレイヤーが生成されると思います。 レイヤーをファイルに書きだす 次に生成したレイヤーを1枚ずつファイルに書き出します。 これはこちらのスクリプトをそのまま利用させてもらいました。 ps-export-layers-to-png-jsx 接尾辞が「.png」という名前のレイヤーだけを保存してくれます。 デフォルトの保存先はPSファイルと同階層の「out」ディレクトリとなってます。 コンタクトシートIIでシート化 先にやっとけなんですが 8x8のシートを作成するので、outフォルダ内の文字pngを64個になるよう選定します。 それから「ファイル」→「自動処理」→「コンタクトシートII」 先ほどの「out」フォルダを指定して、サイズ・間隔を調整して実行するとシートが生成されるので 背景の透過・文字を白にして、任意にぼかしたりして完成です。 ShaderGraph作成 シートの中から1枚拾う まずは1文字につき以下のように番号を割り当てるイメージで index番号(↑図の赤い箇所)を指定すると該当するテクスチャが取得できるようにしてます。 とりあえず1文字だけ表示するのですが まずuv値を8で割るだけで左下の文字だけが表示されると思います。 1.0 / 8.0 = 0.125 (0,0) ~ (0.125, 0.125) のuv座標の絵を取得するイメージ。 あとはindexからuvの移動量を計算してやれば 希望のindexのuvの絵を取得できるようになります。 x軸への移動量は番号/8の余り y軸への移動量は番号/8の商。 これらをuv座標に変換(8.0で割る)したものを↑に加算 例えば番号が8だとすると x軸の移動量 = 8/8の余り0、 y軸の移動量 = 8/8の商1 となり (0.125 * 0, 0.125 * 1) ~ (0.125 + 0.125 * 0, 0.125 + 0.125 * 1) ↓ (0, 0.125) ~ (0.125, 0.25) のuv座標の絵を取得するイメージ。 後ほどindexにランダムな値をセットするようにします。 複数行列分、ランダムに表示できるようにする。 次に出力にn×n分文字を表示できるようにします。 仮に3×3分表示する場合、このようなイメージです。 ノードは以下の箇所です。赤部分がそれぞれuvとindex番号のinputになります。 図の中ではShowCodeMatrixがn×nのvector2パラメータです まず上部でuvの計算をするのですが uvを3等分してそれぞれの0~1で渡せるようにすれば完了です。 この辺りは楽しい!Unityシェーダー お絵描き入門!が非常に参考になります。 またこれも事前にやっとけなんですが、ここで文字を反転してます。 下部も同様マスごとに乱数を生成できるように 3×3の各マス毎に乱数生成(0~63)→整数部をindex値として渡してます。 以上で基本構造完成です。 ランダムの調整 もう少しランダム性を強化する為オブジェクト座標のxyzを足し合わせてseedに加えてます。(適当) 一定時間ごとに変化していたので同じように調整しています。 (突き詰めると実際は変化のタイミングが文字単位で異なるようです) 文字のスクロール スクロールと言いつつAlphaでフェードインしながら徐々に表示するようにしています。 元の絵を見た感じ単純なuvスクロールというよりドットアニメーションの動きがイメージ近かったので 文字単位でFadeInするようにしています。 ここではy軸のマス毎にTimeを加算して少数部をとる(fraction)ことで 0~1間で値を変化させてグラデーションを表現しています。 emissionとfadeoutの調整 上部のフェードアウトは自然にかけ、調整できるようにしてます。 同様に下部の方の発光も影響度を調整できるようにしてます。 またEmitはcolor側、Fadeはalphaにつなぐようにします 複数列で、文字の並びとスクロールタイミングをズラす。 後は複数列にいい感じに表示する様、マスのx軸のindexをseedに乱数でいろいろ調整します。 最下部のノード群で列毎の出力の有無を調整 同様にスクロールのタイミングも列毎にズレるようランダム値を加える オブジェクトの配置 タイトルの絵はshaderを適用した板ポリを複数毎、ズラして配置しるだけです。 後はpostprocessの力です。 あくまでuvに沿ってアニメーションしますが 色んなオブジェクトに適用しても面白そうです。 参考 Photoshopスクリプト関連 Photoshop Scripting のスニペット集 Photoshopでテキストレイヤーを作成するスクリプト ps-export-layers-to-png-jsx Shader関連 楽しい!Unityシェーダー お絵描き入門!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity設計入門:第1章「ModelとView」・理論編

Unity設計入門の目次はこちら はじめに Model View Controller Presenter ViewModel etc... 設計について調べると必ずと言っていいほどこれらの用語が出てきます。 今回はこの中で「Model」と「View」について根本的に理解することを目指しましょう。 Modelとは フロントエンド・バックエンド・ゲームなど文脈によって定義や使われ方が異なる場合が多いです。 結果的に「データベースいじるやつ」とか「ビジネスロジック(Unityだとゲームロジック)」とか言われて、あいまいな理解になってしまうこともあるでしょう。 今回は「画面がなくてもゲームの本質として存在するような処理とデータのこと」として定義します。 具体的に考えてみましょう。 例えば、テトリスでは、「横一列にブロックが並んだら消す」とか「ランダムにテトリミノ(4つブロックがつながったアレ)を選ぶ」という処理は3DSで実装しようが、スマホゲームで実装しようが、Unityを使おうが、UE4を使おう、なんならコンソールアプリケーションとして実装しようが変わりません。このような処理をModelと呼びます。 また、「現在の盤面の状態」も同様に、どのプラットフォームで実装しようと変わらない画面に依存しないデータです。このようなデータもModelと呼びます。 具体的なアプリケーション実装においても、判断に迷った場合には「これ、ゲームエンジン移植しても変わらないコードになるかな?」と自問自答すれば良いと思います。 Viewとは Viewに関しては、「見えるもの!」という分かりやすい基準があるのでそこまで認識にずれが生じるものではないかと思います。むしろ、Viewじゃないものを無理やりViewに抱え込んでViewが爆発することの方が多い気がします。 そこで、今回はあえて「見えるもの」ではなく、「Unityがないと絶対に動かせないもの」と定義したいと思います。 例えば、transformを操作したり、Monobehaviourを継承したりしている部分です。 これはなぜかというと、Unityがあまりに強力だからです。Webだと、根本的なデータは全部サーバーに存在するのでModelときっちり別れさせざるを得ないですし、同じC#でもWPFなどだと厳格にViewが区切られていて、他の部分からViewにアクセスする手段がバインディングを除くとあまりないです。(このあたりの話はUnityと協調するためのアーキテクチャ『MVP4U』という記事でも触れられているます。) それに対して、Unityはその気になればすべてのロジックをMonobehaviourで完結させることが出来ます。Viewをいくらでも拡大解釈できるのです。したがって、Unityの文脈においては「Unityがないと絶対に動かせないもの」という定義がより適切だと考えられます。 ModelとViewを分離するとよい理由 1. 再利用性が上がる Modelは、その定義から「どんな画面でも使えるデータと処理」の集合体です。これはつまり、全画面・シーンで使うことが出来るようなデータと処理がまとまった、と言うことです。もしも、ModelとViewが結合していた場合、Modelが使いたくても、Viewが抱き合わせでついてきてしまうので、Viewの持つ「特定の画面特有の他では絶対使えない処理」のせいで再利用が厳しくなってしまいます。 2. Modelのテストが容易になる Viewから分離されたModelは純粋なC#のプログラムです。すなわち、簡単にユニットテストを書ける存在だということです。これは、コードを安定化させてくれます。テストのメリットについてはここ以外でも大量に語られているのであえて書くことはしません。 「テストなんて書かないよ!俺は趣味でUnityやってんだよ面倒なことやってられっか!」みたいな人にとっても価値のある存在です。というのも、テストが容易な設計それ自体が、周囲との依存関係を少なくして、コードの影響範囲を明確にした設計ということなので、最低限の品質を担保してくれるからです。 また、「テストを書いて仕様変更したら悲しくなるからやだ」みたいな人にとっても有用です。Viewの変化に比して、Modelの変更は圧倒的に起こりにくいです。Modelのコア部分にテストを書いておくことは効率のいい投資になります。 3. Unityの再生ボタンを押す回数が減る Viewは実行コストが桁外れに大きいです。なぜなら、その定義から「Unityの再生ボタンを押して、実行を待って、ボタンを押して反応を見て、インスペクタから値をチェックして、ヒエラルキービューをチェックして…」といった手作業でのチェック回数が増えるからです。2.で触れたModelのテストの容易さとは異なり、相当苦労しないと自動化などが出来ません。ModelとViewを分離することでViewが小さくなり、煩わしい作業が減ります。 「Unityでいい設計をしたい場合には、Unityから離れてコードを書かないといけない」ということを覚えておきましょう。 ( PureなC#を書くことの重要性についてはUnityにおける「設計レベル」を定義してみた という記事が参考になります) 4. 見た目を変更するコストが下がる 「ボタンの色を変更したらバグが発生した」とか「レイアウトを変えたら動かなくなった」とかの不具合による負担が減ります。 その理由は、「見た目のバグは絶対にViewに存在する」という確証が持てるからです。いままで動いていたということは、Modelにおかしな点はないということですから、見るべきコードの範囲が減ります。 また、「Viewが表示に徹すれば必然的にViewがシンプルになるのでバグを埋め込みにくく、不具合自体が減る」「Viewに依存したロジックを書くこと自体が出来なくなり、見た目の変更がバグを誘発する状況を作りにくくできる」といった理由から、見た目の変更、すなわちViewの柔軟性が上がります。 Viewの柔軟性が下がる原因のうち、「見た目変えたらボタンの位置や色に依存するロジックが壊れるからやりたくない」というものを完全に排除できます。 詳しくは、補足記事を参照してください。 5. 純粋なオブジェクト指向による開発が出来る ショッキングな書き方をすれば、実はUnityは、純粋なオブジェクト指向プログラミングを破壊する存在と言っていいです。 Unityの根本的な設計思想は機能ごとにコンポーネントを作ってそれを組み合わせたゲームオブジェクトによってゲームを構成することにあります。Unityはコンポーネント指向のゲームエンジンなのです。 したがって、ユーザーが定義できるプログラムはUnity上に存在する限りはMonobehaviourに限られてしまいます。 C#では多重継承が許されていないので、ユーザーはMonobehaviourを継承する限りは、他のクラスを継承することはできず、オブジェクト指向の機能は制限されてしまいます。 これは、ソフトウェア開発の方針の違いであって、優劣がつくものではありません。しかし、すくなくともModelを開発する段階においては、コンポーネント指向が足かせに働くことも多くなってしまいます。詳しくは、補足記事(10/20投稿)を参照してください。 ModelとViewが分離した状況下では、ModelはUnityの存在を知らない(今回の定義によれば、using UnityEngineした瞬間にそれはViewとなる)ので、Modelは純粋なオブジェクト指向の技法を用いてプログラムを書くことが出来ます。 ソフトウェア工学の書籍で学んだ技法を生かそうとしても、「実際問題Unityだとそう書いたら動かんじゃんどうすんの!」みたいに嘆く必要はもうないのです。 ModelとViewの分離の達成度のチェック項目 Modelが純粋なC#のみで構成されている ModelはUnityのことを全く意識していないつくりである。using UnityEngineしていない。また、「特定のボタンの表示可否」とか画面ありきの情報をもっていない Viewが十分に小さい。理想は、流し込まれたデータを一直線に処理して条件判断をしないViewであること おわりに ModelとViewを分離したほうがいいというのは、多くの記事で暗黙の了解として扱われがちな事項ですが、初めてMVXアーキテクチャに触れる際にはその理由やメリットをしらず、アーキテクチャ自体の正当性に疑問を持ってしまいがちです。MVCでもMVVMでもMVPでも、ModelとViewは共通の存在で、もっとも重要な概念と言っても過言ではありません。しっかりと腹落ちさせておきましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityでAlpha値を変更するshaderメモ

はじめに これは自らの戒めのために記事である.参考にならない人も多いかもしれない. 背景情報 objファイルに記載されているvertexカラーをunityに反映させると同時にalpha値をいじりたくなった. アルファ値を追加する前のコードは以下の通り.メッシュに記述された情報を参照して反映している. _.shader Shader "Custom/VertexColorShader" { SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert vertex:vert #pragma target 3.0 struct Input { float4 vertColor; }; void vert(inout appdata_full v, out Input o){ UNITY_INITIALIZE_OUTPUT(Input, o); o.vertColor = v.color; } void surf (Input IN, inout SurfaceOutput o) { o.Albedo = IN.vertColor.rgb; } ENDCG } FallBack "Diffuse" } やったこと 今回はvectorColorのアルファではなく,別の値を代入できるようにする. SurfaceOutputとやらを使っているので,Unity公式を参考にするとAlphaを代入できるらしい. ほならばsurfacePutputに一行追加するだけで済むはず. _.shader void surf (Input IN, inout SurfaceOutput o) { o.Albedo = IN.vertColor.rgb; o.Alpha = 0.1 // ここに追加 } しかし,alpha値は反映されなかった 解決 "RenderType"="Opaque"を"RenderType"="Transparent" "Queue" = "Transparent"}に変更 pragmaにalphaを追加 Opaqueというレンダリングタイプでは,alpha値を無視するようになっているらしい.Unity公式-レンダリングモード- #pragma vertexだけではalphaが使えない.ややこしい... Unity公式-pragmaスニペット- 以下,完成コード _.shader Shader "Custom/TransParentShader" { SubShader { Tags { "RenderType"="Transparent" "Queue" = "Transparent"} Blend SrcAlpha OneMinusSrcAlpha LOD 200 CGPROGRAM #pragma surface surf Lambert vertex:vert alpha #pragma target 3.0 struct Input { float4 vertColor; }; // fixed4 _Color; void vert(inout appdata_full v, out Input o){ UNITY_INITIALIZE_OUTPUT(Input, o); o.vertColor = v.color; } void surf (Input IN, inout SurfaceOutput o) { o.Albedo = IN.vertColor.rgb; o.Alpha = 0.1; } ENDCG } // 影を描写しない FallBack "Transprent/Cutout/Diffuse" }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む