ikoan unity 開発メモ

Unityに関するアレコレを日々つづっていこうと思います

ProBulider事始め(2) -

環境

Unity2018.3.0f2

概要

ずっと気になっていたけどさわれていなかった機能の一つ、ProBuider。実際に触ってみたメモです。
思ってたより機能が多いので、複数回に記事を分けたいと思います。

以前までの記事はこちら
ikoans.hatenablog.com

自由な形状のオブジェクトを作成する

前回はあらかじめ用意されていた形状のオブジェクトを作成してみました。
今回はより自由な形状のオブジェクトを作成してみたいと思います。
ProBuilder のウィンドウから「New Poly Shape」を選択します。
そうするとHierarchyにNew Game Objectが生成されます。
その状態でシーン上のどこかをクリックすると点が生成されます。
カーソルを移動させてクリックすると、次の点が生成され、一つ前に生成した点と繋がれます。
さらに同じ操作を行うと自動で面が生成され、四角形、五角形・・・と点が追加されていきます。
Enterを押すことで面の生成が完了します。
次にそのオブジェクトの高さを編集することになります。
アクティブになっているポイントがあるので、それを操作することでオブジェクトの高さを編集します。
再度Enterを押すことで、オブジェクトの生成が完了となります。
一度完了させてしまったオブジェクトもPolyShapeコンポーネントの「Edit Poly Shape」を押すことで再編集が可能となります。
また、ただ高さを編集するだけならば、PolyShapeコンポーネントの「Extrusion」の数値を変更すればいいだけです。

あらかじめ用意されているShapeでは表現できない自由な形状を作成したい場合はこちらにつきますね!

せっかくなので合成もしてみる

ProBuilder同士で作成したオブジェクトを結合できるみたいなので、やってみます。
操作は簡単ですね。
結合したいオブジェクトを複数選択します。
その後、ProBuliderウィンドウのMerge Objectsを選択します。
そうすることで、複数あったオブジェクトが1つのオブジェクトになりました!
ただ、これ結合したところで頂点数や面の数に変化がありません・・・
頂点カラーの設定とかいじると変わるんでしょうか?
マテリアルの数はおそらく2つから1つになっているっていうのはあるんでしょうけど。
結合する意味は後々調査できればな、と思っています。

ProBulider事始め(1) - 基本となるオブジェクト生成と簡単な変形

環境

Unity2018.3.0f2

概要

ずっと気になっていたけどさわれていなかった機能の一つ、ProBuider。実際に触ってみたメモです。
思ってたより機能が多いので、複数回に記事を分けたいと思います。

準備

まずは環境を整えます。
Package Managerから必要なパッケージをインストールする必要があります。
Window > Package Manager を選択し、リストの中から「Pro Bulider」を探し、インストール!
インストール後にTool > ProBulider > ProBulider Window を選択すると、専用のウィンドウが表示されます。
f:id:ikoans:20190128191040p:plain

思ってたより機能が多くてびっくりしています。。。

とりあえず作成してみる

とりあえず、一番基本となりそうな、[ New Shape ]を選択してみます。
そうすると Shape Tool というウィンドウが表示されます。
f:id:ikoans:20190128191759p:plain

Shape Selectorで作成するオブジェクトの形状を選択できそうです。
ここの選択状態を変更すると、Shape Settingの情報が変化します。
色々と試してみてください。
この記事では一旦 Cube を作成します。
Sizeはデフォルト値の(1,1,1)のまま、Buildを押すと、HierarchyにCubeというオブジェクトが生成されました。
これ、3DObjectのCubeとは何が違うんでしょうか。
比較してみると・・・
3DObjectのCubeはMeshにUnityデフォルトのCubeがついている代わりに
ProBuliderで作成したCubeはPb_Mesh****という今作った独自のメッシュだよ!っていう感じのMeshがついています。
また、Materialに関しても、3DObjectのCubeはStandardシェーダ−がついていますが、
ProBuilderで作成したCubeはProBuilder/Standard Vertex Color がついています。
また、Colliderに関して、3DObjectではBoxColliderがついていますが、ProBuilderで作成した方に関しましては、MeshColliderになっていました。
これら上記の違いは今後の設定や柔軟に変化させるための違いなのでしょう。

Shapeを変形させる

さて、3DObjectで作成したものとProBuilderで作成したものの一番の違いはUnityEditor上で変形できるかどうかだと思います。
ProBuilderウィンドウを開いていると、Scene Viewに下画像のようなUIが表示されます。
f:id:ikoans:20190128195150p:plain

左から順に説明すると
一番左:Transformの選択
左から二番目:頂点を選択し、変形できる
右から二番目:辺を選択し、変形できる
一番右:面を選択し、変形できる

これらを使うことで、一つの形状をいろんな形に変形することができますね。
こういうことができるから、コライダはMesh Colliderなんでしょうし、Meshも特殊なMeshなんでしょうね。
逆に色々な形状に変形できすぎて怖いぐらいです(笑)

Cubeを適当な形に変形させ、3DObjectで作成したCapsuleと衝突させてみました。
f:id:ikoans:20190129001506g:plain

結構手軽に変形し、さらにその形状で衝突判定も作成できています。
まだ他の機能を使用していない現時点で色々と夢が広がる機能です!
ステージデザインもUnity上で解決できそうな感じですね!

懸念というか

とはいうものの、
・作成したステージデータを外部出力できるのか
・ステージデータを出力できたとして、それをさらに複数組み合わせることでさらなるステージ化できるのか
という点は気になるところです。
それによってアプリのサイズや、プランナーさんのデータ作成時の利便性、ひいてはユーザーがステージをエディットできるのかなどに関わってくるかと思います。
また、meshやマテリアルのデータが新規で作られているので、表示上変更はできるのでしょうが、UV関連をどう設定するのか、などまだまだ疑問点は多いので、引き続き調査していきたいと思います。
とはいえ、機能が多い・・・!!すごいぜ、Unity!!

ゲームの敵が消滅するようなシェーダーなど

環境

Unity2018.3.0f2

概要

確かテラバトルなどで、敵を倒した際に消えていくエフェクトってありますよね。
サラサラと敵が粉末のようになって消えていくアレです。
アレを以前から実装したいなーと思っており、何か難しく考えすぎててできないなーって思ってたのですが、なんかやってみたら普通にできたので記事を書いてみました

実装方法

まずはシェーダーでサラサラと消えていく部分を実装します。
とりあえず汎用性を考えずに右上から順に右に流れていくものとします。
一応、各ピクセルごとにランダムな値を算出して、その値を流れていく強さに変換することでいい感じにしてますが、ノイズテクスチャ用意してもいいかもしれません。
下記シェーダーはその名残があります。


※編集画面でインデント揃えたら、保存したら逆にずれたよ。。。動作がよくわからない。

uv値から算出しているので、元画像が一枚絵であるならば各敵ごとに動きの変化はないと思いますが、ノイズテクスチャを利用した方が確実かもしれません、と思いましたが、アトラス化されても、消えていく元画像の位置によっては、ノイズテクスチャの参照場所が変わるので、どちらでも変わらないかもしれません。

このシェーダーをマテリアルにセットし、_Paramを変化させて動作させたのが下記動画になります。
f:id:ikoans:20190108202620g:plain

消えるところや消える順序、_Paramへの値のセットなどはいい感じに対応していただければと思います。

さらに改良

さて、一応サラサラと消えるようにはできましたが、これだとテクスチャのサイズで切れてしまいます。
あまり美しくないですね。
そのために、消える対象のテクスチャとメッシュを改良・再生成します。
今回はUnityのPlaneを基準にメッシュを再構築しています。SpriteやQuadを使う場合、このままでは動かないと思いますのでご注意ください。、

広げるサイズは1.5倍としてます。なんとなくです。随時適当に変更していただければと思います。
また、今回は先ほども書いた通りUnityのPlaneを修正しています。
vertexの位置が大きい数字の方がuvの値が小さいという、よくわからない仕様になっているのを初めて知りました。
ここも自身のプロジェクトで使用される場合は気をつけてもらえればと思います。

修正した動作は下のgifのようになります。
f:id:ikoans:20190108204015g:plain

いい感じに四角できれずに消えていますね。
RenderTextureで再描画した画像に謎の黒帯があると思います。
これは元Terxtureがwrapモードでテクスチャの端まで描画情報がある場合に表示されるみたいです。
回避方法は元テクスチャの端を1ドット何も描画しないとかでしょうか。
アンチエイリアスが悪さしているなら、そこらへんの設定を変更すればどうにかなるかもしれません。

補足

シェーダーが書き込んでいるのはバッファだし、バッファの基準?になるであろうメッシュだけ幅を広げればうまくいくかな、と思ったら、そんなことはなく、テクスチャも再構築しないと思った通りの動作にはなりませんでした。
理由はわかりませんが・・・・。
誰かわかる人教えてください。
とはいえ、パーツアニメするような敵の場合は、どちらにしろRenderTexture化してどうにかするのかな、と思うので、それなりに実用性はあるかと思います。

また、敵画像、どこかのサイト様からいただいたものなのですが、どこだか忘れました。。。
本当に申し訳ありません・・・・。

Nested Prefab触ってみた

環境

Unity2018.3.0f2

概要

少し時間が経ってしまいましたが、ついにUnity2018.3が本リリースされましたね。
既存機能の更新もありますが、新機能の追加もたくさんあります!
今日はその中で昔から要望が多かったと言われる「Nested Prefab」を触っていこうと思います。
※2018.3の更新では「Nested Prefab」の機能追加もそうですが、それに関しては一部のことで大きくいうとPrefab機能の更新、PrefabEditorの追加となっています。

Prefabとは

そもそもPrefabとは何かと言うと、同じ形状や見え方をするGameObjectの金型みたいなイメージでしょうか。
例えば、森を表現したいときに、木のPrefabを用意して、それをシーンに複数配置することで実現できます。
その時、木の高さを高くしたい場合、シーンに配置したGameObjectを一つ一つ修正するのではなく、金型であるPrefabを修正することで全ての木にその修正を反映させることができる便利な機能です。

Nested Prefabとは

ざっくりいうとPrefabの入れ子のことです。
先ほど挙げましたPrefabの修正でシーン上に配置されている全GameObjectを修正できるというのは制限がありました。
それは「子にPrefabBを元にしたGameObjectBを配置したGameObjectA」をPrefab化した場合、PrefabBのリンクが切れてしまい、PrefabBを修正してもGameObjectBには反映されなくなる、ということです。
逆にそれを利用するという考え方もあるとは思いますが、Prefabという思想上、それが実現できないというのは、やはり少しやりづらい場面が多かったです。
今回リリースされた2018.3では、そのNested Prefabが実現できるということで、同時に実装されたPrefab Editorと一緒に触ってみました。

実際の操作・挙動

まずはSphereCapsuleを子に持ったPrefabAを作成し、適当に配置します。
f:id:ikoans:20181226175101p:plain

次にCubeとPrefabAを子に持ったPrefabBを作成し、適当に配置します。
f:id:ikoans:20181226175220p:plain

この時、ProjectView内のPrefabを選択すると、Inspector内にOpen Prefabというボタンが表示されます。それを押すか、もしくはProjectView内のPrefabをダブルクリックすることで、PrefabEditorが表示されます。ここで、Prefab内の情報を操作することができるわけですね。
試しにPrefabAをPrefabEditor上で編集してみます。
PrefabA内のCapsuleを少し上に移動させると、、、割とすぐにScene上のObjectにも反映されますね!
f:id:ikoans:20181226175413p:plain

次はシーン上のObjectを直接操作して、それをPrefabに反映してみましょう。
今度はシーン上でPrefabAオブジェクトのSphereを少し大きくしてみます。Sphereを選択してTransformのScaleを2倍にしてみます。
この状態ではPrefab自体には更新がかかっていないので、PrefabBオブジェクトの子に配置されているPrefabAオブジェクトのSphereは更新されていません。
f:id:ikoans:20181226175848p:plain

Prefabの変更を反映させるために、Hierarchy VIewで更新を加えたPrefabの一番親であるGameObjectを選択します。そうするとInspector上にPrefabという項目が表示されています。(通常のGameObject上にはこの表示はありません)
f:id:ikoans:20181226180431p:plain

項目内の右端にあるOverridesをクリックします。そうすると、対象Prefab内に含まれるGameObjectの一覧が表示されます。表示された一覧内のアイテムをクリックすると、変更があるGameObjectだった場合、その変更箇所も表示されます。
f:id:ikoans:20181226180820p:plain

変更を全て更新する場合は「Apply All」を、すべて元に戻したい場合は「Revert All」を選択します。
変更の一部を反映させたい場合は、Overridesをクリックした時に表示される一覧から、反映させたいGameObjectの変更箇所を選択し、それぞれApplyしていきます。
今回は「Apply All」を選択します。そうするとPrefab Bに含まれるPrefabAのGameObjectにも変更がかかりました!
f:id:ikoans:20181226181345p:plain

注意点

「Nested Prefab」便利ですが、一つ注意点があります。
例えば上記のPrefabBの子であるPrefabA ObjectのパラメータCを変更してしまった場合、PrefabAのパラメータCをいくら変更しても、PrefabBの子のPrefabA ObjectのパラメータCは変更が反映されません。
というか、これはNested Prefabだけに限らず、通常のPrefabでも同様ですね。
シーン上に配置したPrefabから作成したGameObjectのパラメータを変更した後、PrefabEditor上で同じパラメータを変更しても、シーン上のGameObjectには変化がありませんでした。
シーン上で変更があるパラメータに関して、元のPrefabに変更がかかっても、その変更は反映されません!!
オリジナルから変更が入っている時点で、そのパラメータまで上書きされるというのはやりにくいところなので、いいことだとは思いますけどね。

まとめ

「Nested Prefab」、ベータ版で揉まれたのでしょうか、とても使いやすいですね。
唯一、シーン上からの変更をApplyする箇所、あそこは画面小さいですし、操作がしにくそうではありますが。。。
別Windowで変更があるシーン上のオブジェクトを一覧で表示して、どれを反映させるかのチェックがあるEditorWindowとか作成すると、少し需要があるような気はします。
そのGameObjectがPrefabが存在して、どこのパラメータがどのように変更されたかを手軽に検知・表示できるとサクッと作れるのですが。

戯言

副鼻腔炎というのにかかってました。
微熱ではありますが、熱は出るし、頭や頬、歯が痛くなったり、喉の痛み、鼻水・痰など症状が多く、とても辛いわけではないのですが、10日間ぐらい寝込み、地味に辛かったです。
かからないための予防はこれといってないとは思いますが、日頃からの免疫力強化や不摂生をしないっていうことは大事だなぁと思った年末でした。
皆さんも、体調には十分お気をつけください。

MacでAndroid開発時に少し困ったメモ

adbのコマンドが認識されない

ターミナルでadbコマンドを叩いても、pathが通っていないため、実行されない。
ターミナルの場合は~/.bash_profileにパスを通す
export PATH=$PATH:[Android Sdk(platform-toolsまでのパス)]

monitorの場所がわからない

AndroidStudioのTools/Androidにあると見たけど見つからない。
なので、ターミナルから直接起動する。
AndroidSDK/tools に monitorがあるので該当ディレクトリまで移動し、./monitorで起動

monitorが起動しない、フリーズする

どうもJDKのバージョンが新しいと動作しないみたい。
JDKのバージョンが jdk-8u151 では動作するみたいなので、ダウンロードしてインストール。
インストールディレクトリは /Library/Java/JavaVirtualMachines などになっていると思う。
インストールされているJDKがこれだけなら、このままでも大丈夫かもしれませんが、自分の場合、もう少し新しいバージョンもインストールされている状態でした。
なので、monitorで使用するJavaのバージョンを指定します。
AndroidSDK/tools/lib/monitor-x86_64/monitor.app/Contents/MacOS に monitor.ini というファイルがあるのでこれを編集します。
@noDefaultの下あたりに

JDKのPATH/Contents/Home/bin/java
と記載して保存。
これでmonitorを再起動すると、私の環境では動作するようになりました。

Spriteを画面サイズへの対応

環境

Unity2018.2.16f1

概要

uGUIはCanvasのCanvasScalerを適当に設定することで解像度が異なる端末への挙動をいい感じに吸収してくれています。
しかし、Spriteに関してはそもそも想定解像度に対してのサイズ調整やそこからさらにアスペクト比が異なる端末への対処などが厄介です。
なので作ってみました。

実装

gitにアップしました。
GitHub - ikoan310/SpriteScaler

何か問題がありましたら、教えていただけると助かります。

Animatorで同一アニメを一定回数loopしてから別のstateに遷移させる

環境

Unity2018.2.16f1

概要

Animatorのstateにセットしたアニメーションが終了する、もしくは状態が変更したのを検知したい時があると思います。
そんな時には「StateMachineBehaviour」を使って、制御しましょう。
StateMachineBehaviour - Unity スクリプトリファレンス

実装手順

まずはStateMachineBehaviourを継承したクラスを作成します。
通常通り、Scriptを作成し、通常ならMonoBehaviourを指定している箇所をStateMachineBehaviourに変更します。

StateMachineBehaviourにはいくつかのcallbackが用意されていて、自分の目的にあったcallbackをoverrideすることで、必要な処理を実装します。
例えば、stateに切り替わったタイミングを検知したい場合は下記のようになります。

作成ができたら、UnityのAnimatorビューに移動します。
Animatorビュー上の監視したいstateを選択すると、Inspector上に「Add Behaviour」というボタンがあるので、それで先ほど作成したスクリプトを追加してください。

あとは再生すれば、監視対象に設定したstateの状態に応じてcallbackが呼ばれるので、それを元に様々なことができると思います。

同一アニメを繰り返したい場合

いよいよ本題についてです。
通常なら、一つのステートに一つのアニメーションを割り当てると思います。そのアニメーションはloop設定しなければ、一度再生され、そしてそのstateのまま状態が保持されると思います。逆にloop設定すると延々と同じアニメーションを繰り返してしまいます。
同一アニメを繰り返すのは、例えば同じアニメを設定したstateを複数個用意し、アニメが終わったら次のstateで同じアニメ、それが終わったら次のstateで同じアニメ・・・、といった方法も取れなくはありませんが、美しくありませんし、数が増えるとなると現実的ではありません。
その場合、どうするかというと、先ほどのStateMachineBehaviourを使用します。
StateMachineBehaviourのcallbackに「OnStateUpdate」というのが存在します。これはAnimatorがそのstateにいる時に毎フレーム呼び出されます。
このOnStateUpdateで渡される引数の中に、AnimatorStateInfoというものがあり、これはそのstateの現在の状態を保持しています。
AnimatorStateInfoのリファレンスを見てみましょう。

AnimatorStateInfo - Unity スクリプトリファレンス

変数の中に「normalizedTime ステートの正規化された時間」というのがありました。
これはつまり一回のloopを0〜1で表した時間ということになるんですね。
つまり、この数値が3以上になった時、それは3回ループしたよ、ということになります。
この数値でループ回数を判断して、条件を満たした時にstateを変更するように命令すれば、やりたいことができると思います。

まとめ

リファレンスは神。