2D Animationでボーンを入れたスプライトに物理演算を適用させる
Unity バージョン
unity 2019.4.19f1
はじめに
Unityにはスプライトに3DオブジェクトのようなBoneを組み込み動かすための機能が公式に用意されています。2D Animationというもので、これはPackage Managerからダウンロードすることができます。
そして、布など重力で揺らしたいものにBoneを適用させRigidbodyをBoneにアタッチすれば簡単に物理演算に即した動きを表現することができるようになります。
Boneを組む
今回は長方形の画像を用意しました。この画像にBoneを組んでいきましょう。
Sprite Editorを開き、左上のSkinning EditorをクリックするとBoneを組む専用のエディタが表示されます。
左のメニューからCreate Boneを選択しましょう。
さて、Boneを組み込んでいきます。今回はこのような感じにしました。上から垂れ下がるようにしたいので上から下方向へのBoneをまず作り、その子Boneとして両側にBoneを配置しました。
完了したら左のメニューのAuto Geometryを選びポリゴンを自動生成します。右下にあるメニューからGenerate for All Visibleボタンをクリックし、生成すると完了しました。Boneをドラッグするとそれに応じて画像の形が変わっていたら成功です。
Unityのシーン内で使う
画像をHierarchyウィンドウにただドラッグアンドドロップしても、Boneはまだ反映されていません。
Boneを適用させた画像のSpriteRendererにSprite Skinというスクリプトを追加します。そしてCreate Bonesと書かれたボタンを押しBoneを生成しましょう。
生成するとこのようにSceneウィンドウにBoneが表示され、Sprite SkinにもBoneのリストが表示されます。
Rigidbody2Dをつける
Rigidbody2Dを追加し布が揺れる表現を作りましょう。布の両脇にあるすべてのBoneのTransformを選択しRigidbody2DとDistance Joint 2Dを追加します。
このままでは支えがなくて布が自由落下してしまうので、上側のBoneを固定します。一番上にある両端のBoneにあるRigidbody2DをStaticにします。(Distance Joint 2Dも必要ないので削除します。)
そしたらそれぞれのBoneにあるDistance Joint 2DのConnected Rigidbodyを上にあるRigidbodyにセットしましょう。こうすることでBoneが自分の上にあるBoneにぶら下がるようになり物理演算が適用できます。
すべてのBoneについて完了したら、Rigidbody2DやDistance Joint 2Dの設定を変更します。
Boneが回転すると布がおかしくなるので、Rigidbody2DのConstraintsからFreeze Rotationにチェックを入れます。また、Distance Joint 2DにAuto Configure Distanceという項目がありますが、これがゲーム中もオンになっていると布がどんどん垂れ下がっているのでオフにしておきます。
これで布が重力ではためくようになりました!ただし現在は空気抵抗がまったくない状態です。お好みでRigidbody 2DのLiner Dragの項目を設定してください。
AddressableのLoadAsyncをStart()内で待つと固まる
最近UnityでAddressableを使ったアセットのロードをすることが増えてきました。
ある時MonoBehaviourのStart()関数内でこのような関数を実行したとき、Unityが固まるようになりました。
void Start(){ m_handle = Addressables.LoadAssetsAsync<GameObject>(_labelReference, null); m_handle.Task.Wait(); }
原因
どうやら、Start()内でAddressables.LoadAssetsAsyncの完了をWait()関数で待とうとするといつまでたっても終わらずにフリーズしてしまうようです。
非同期でのWait()関数はデッドロックが発生しやすいらしく、調べてみると他にも色々な事例を見ることができます。
qiita.com
解決策?
解決策としては、Wait()をせずにコールバック関数などで制御するかでしょうか。
非同期はデッドロックが起こった場合の対処が難しいです…
【XMLHttpRequest】ajaxで非同期通信できずにエラーになってしまう
例えば、ページを読み込むときに他の.jsonや.htmlファイルを読み込みたいときがあります。そういうときはaxiosやjQueryなどでajax非同期通信をする必要があります。
そういったときにhtmlを書きローカル環境(file:///~)でページを表示するとエラーメッセージが出てきて読み込んでくれない場合があります。
Access to XMLHttpRequest at '{{ファイル名}}' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https. というエラーが出て読み込めない
それもそのはず、ローカル環境ではセキュリティ上ajax通信ができないようになっているからです。回避方法はいくつかありますが、どれも設定が複雑で初心者にはとっつきづらいのではないかと思います。
目次
簡単な解決方法
そこでワンクリックでXMLHttpRequest 関連のエラーを回避し、htmlを見ることができる方法があります。
この解決法の必須ソフトは
- Visual Studio Code(以下VSCode)
- VSCodeの拡張機能 live server
です。
VSCodeにある拡張機能にlive serverというものがあります。ローカルホストでサーバーを開き、見たいhtmlファイルをサーバー上で見るものです。
Live Serverについての詳しい説明はこちら。
Live Serverのインストール方法
VSCodeを起動し、左側にあるメニューから拡張機能を開き、Live Serverをインストールします。
インストールに成功したら、VSCodeでワークスペースを作成します。
ワークスペースとは、VSCode上で複数のファイル・フォルダを管理するための環境です。
参考:
ワークスペースを使うとフォルダ内のファイルの行き来がしやすくなったりします。
自分の作成しているhtmlファイルのあるディレクトリにワークスペースを作成し、環境を整えましょう。
「Go Live」ボタンでローカルサーバーを立ち上げる
ワークスペースをVSCodeで開いているときに右下に「Go Live」というボタンが表示されます。これをクリックすればローカルサーバーが起動し、自身のページがブラウザで表示されます。この機能を使えばXMLHttpRequestを行うことができ、エラーが発生しなくなります!
まとめ
- ローカル環境(file:///~)ではhtmlから他のファイルを読み込むという処理はできない
- VSCode の拡張機能「Live Share」が簡単
- 使うときはワークスペースについて把握しておくとなおよい
ありがとうございました。
UnityのScroll Viewでうまくスクロールバーができなかった話
実行環境
Unity 2019.4.12f
起こった問題
UnityのUIにはScroll Viewというものがあります。
複数のコンテンツをスクロールできるウィンドウが作れます。
Unityでは縦横にスクロールバーを自動で表示したり、スクロールの感度、スクロールの速度の変化など細かく設定することができます。
今回直面した問題はScroll ViewのContent内に生成したコンテンツのスクロールがうまくできないという問題です。
このgifではボタンがスクロールウィンドウの外にあるにも関わらず、スクロールバーが表示されていません。おかげでスクロールがうまくできてないです。どうしたらよいのでしょうか?
答えは、Scroll View内にある「Content」のRect Transformの大きさにあります。スクロールバーの大きさはContentの大きさに連動しています。
なので、スクロールバーをコンテンツに応じて変えたい場合、ContentのRect Windowの幅・高さをContent内の子オブジェクトに合わせる必要があります。
解決方法
「Content Size Fitter」というコンポーネントをContentに割り当てると解決できます。
Content Size Fitterを割り当てたUI要素は、その大きさ(Rect Transform)を子要素に合わせます。
したがって、Scroll ViewのContentのRect Windowを子要素に合わせることでスクロールバーを要素に応じて自動で変更されるようになります。
「Content Size Fitter」は便利
Content Size Fitterは子要素に応じて自身の幅、高さを変えられます。そのため文字列の長さに合わせて枠線の大きさを変えるダイアログの作成にも使えます。
出典
他の手段
バンダイナムコスタジオのオンラインテスト感想
バンダイナムコスタジオ様のオンラインコンテストがathletics様から応募を受け付けていたので参加させていただきました。
企業が行っているコンテストに参加するのは初めてだったので緊張しました。
(開催は既に終了しています)
内容
簡単に説明するとC++で球と三角形(ポリゴン)の衝突判定を行い、どれだけ正確に・高速にできるかを競う問題でした。
テストケースは複数与えられます。1つのテストケースには三角形と複数の球のパラメータが与えられ、球一つ一つに対してどれだけ三角形が衝突しているかのカウントを出力します。球のカウントが想定解とどれだけあっているのかの正答率を高くするコードを書く必要があります。
注意するべきこととして、三角形は球の内部ではなく球面に交差もしくは接していると衝突した判定になるというものです。単に三角形と球の中心との距離が球の半径未満であるというコードでは不十分です。
コンテスト開催中に感じたこと
コンテスト開催期間中、参加者のスコアのランキングが日々Slackで更新されるのが自分にとっては新鮮で面白かったです。他の参加者とスコアを比較したり(上位の人たちと自分のスコアに驚いたり)、アルゴリズムを変えたことによるスコアの向上を見れたりなど楽しかったです。
また、Slackで気軽に質問することもでき、フィードバックも早かったのでとても助かりました。
コードはブラウザ上の特定のサイトで実行・提出するのですが、実行時テストケースがどれだけあっているのかが見やすかったです。(ファイルを分割して実行することもできたようですが、やり方が最後まで分からなかったです…)
反省
工夫した点は
- 小数を10倍して整数で管理(すべての入力で小数点以下は1桁なので)
- 球とポリゴン間の距離を比べるとき、距離をsqrtで算出しない
- 座標をVec3クラスで管理(演算子のオーバーライドも定義しコードを簡略化)
- 8分木で空間全体を分割し、球に近いポリゴンしか判定を行わないようにする
コンテストの結果は9位でした。ここまで高い順位になるとは思ってなかったのでとても嬉しかったです!
反省点は
- 8分木で空間分割をしたとき、球が属する空間とそれに隣接する6つの空間も探索すればよかった(球と三角形が空間を隔てて接していた場合を判定できない)
- 公開されていたテストケースのうち、一つ正答できていなかったので、原因を探りたかった
などなど…
他の参加者には自分では思いつかなかった工夫をしている人もいました。自分はまだまだ知識が足りないことを痛感しました。
さいごに
コンテスト終了後の参加者のランキング発表や懇親会はとても楽しく、有意義な話が聞けてすごい良かったです!このコンテストを提供してくださったバンダイナムコスタジオ様、本当にありがとうございました。
Asepriteというドット絵ツールの紹介
僕は2Dゲームを作っていることが多いので、ドット絵やイラストなんかを描くツールをよく使います。
ドット絵を描くとき便利なツールに「Aseprite」というものがあります。steamで2050円(2020/09/19現在)で購入できます。このツールはかなりすごいのでぜひ見てほしいです!
このツールの何がすごいのかといいますと、値段がリーズナブルなのに高機能で動作が軽いところです。
主に使える機能として以下のものがあります。
- レイヤー機能
- ブレンディング(加算、乗算、オーバーレイなど計19種)
- 透明度(0~255)
- アニメーション
- オニオンスキン(前後のフレームの絵を薄く表示)
- ブラシ、ぼかし
- 投げ縄、矩形選択、バケツ選択(マジックワンド?)
- bmp, ico, gif, jpgなど様々なファイルの対応
- トーンカーブ、色相・彩度・明度変換
- 文字入力
これ以外にもたくさんの機能がありますが、詳しくはAsepriteのホームページで確認してみてください。
このツールを使うメリットとして透明度の対応があります。Windows標準のペイントとかだと透明や半透明ピクセルをそのままpngファイルとして出力することができないので、Asepriteはかなり便利です。
またAsepriteはアップデートの頻度が高く、新機能が続々追加されているのでバグや不具合が修正されないままということもないです。
ぜひ、公式ホームページやSteamでチェックしてみて下さい!