2D Animationでボーンを入れたスプライトに物理演算を適用させる

Unity バージョン

unity 2019.4.19f1

はじめに

Unityにはスプライトに3DオブジェクトのようなBoneを組み込み動かすための機能が公式に用意されています。2D Animationというもので、これはPackage Managerからダウンロードすることができます。
f:id:ky0ichi:20210410194303p:plain


そして、布など重力で揺らしたいものにBoneを適用させRigidbodyをBoneにアタッチすれば簡単に物理演算に即した動きを表現することができるようになります。

Boneを組む

今回は長方形の画像を用意しました。この画像にBoneを組んでいきましょう。
Sprite Editorを開き、左上のSkinning EditorをクリックするとBoneを組む専用のエディタが表示されます。
f:id:ky0ichi:20210410185627p:plain


左のメニューからCreate Boneを選択しましょう。
さて、Boneを組み込んでいきます。今回はこのような感じにしました。上から垂れ下がるようにしたいので上から下方向へのBoneをまず作り、その子Boneとして両側にBoneを配置しました。
f:id:ky0ichi:20210410190413p:plain


完了したら左のメニューのAuto Geometryを選びポリゴンを自動生成します。右下にあるメニューからGenerate for All Visibleボタンをクリックし、生成すると完了しました。Boneをドラッグするとそれに応じて画像の形が変わっていたら成功です。
f:id:ky0ichi:20210410190448p:plain

Unityのシーン内で使う

画像をHierarchyウィンドウにただドラッグアンドドロップしても、Boneはまだ反映されていません。
Boneを適用させた画像のSpriteRendererにSprite Skinというスクリプトを追加します。そしてCreate Bonesと書かれたボタンを押しBoneを生成しましょう。
f:id:ky0ichi:20210410190743p:plain
生成するとこのようにSceneウィンドウにBoneが表示され、Sprite SkinにもBoneのリストが表示されます。

Rigidbody2Dをつける

Rigidbody2Dを追加し布が揺れる表現を作りましょう。布の両脇にあるすべてのBoneのTransformを選択しRigidbody2DとDistance Joint 2Dを追加します。
f:id:ky0ichi:20210410195055p:plain


このままでは支えがなくて布が自由落下してしまうので、上側のBoneを固定します。一番上にある両端のBoneにあるRigidbody2DをStaticにします。(Distance Joint 2Dも必要ないので削除します。)
f:id:ky0ichi:20210410195403p:plain


そしたらそれぞれのBoneにあるDistance Joint 2DのConnected Rigidbodyを上にあるRigidbodyにセットしましょう。こうすることでBoneが自分の上にあるBoneにぶら下がるようになり物理演算が適用できます。
f:id:ky0ichi:20210410195643p:plain


すべてのBoneについて完了したら、Rigidbody2DやDistance Joint 2Dの設定を変更します。
Boneが回転すると布がおかしくなるので、Rigidbody2DのConstraintsからFreeze Rotationにチェックを入れます。また、Distance Joint 2DにAuto Configure Distanceという項目がありますが、これがゲーム中もオンになっていると布がどんどん垂れ下がっているのでオフにしておきます。
f:id:ky0ichi:20210410200104p:plain


これで布が重力ではためくようになりました!ただし現在は空気抵抗がまったくない状態です。お好みでRigidbody 2DのLiner Dragの項目を設定してください。
f:id:ky0ichi:20210410200637g:plain

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:///~)でページを表示するとエラーメッセージが出てきて読み込んでくれない場合があります。

f:id:ky0ichi:20201122205113p:plain

ダブルクリックなどでhtmlファイルをブラウザで開くとエラー

(所属中のサークルのサイト)

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通信ができないようになっているからです。回避方法はいくつかありますが、どれも設定が複雑で初心者にはとっつきづらいのではないかと思います。

 

 

目次

簡単な解決方法

Live Serverのインストール方法

「Go Live」ボタンでローカルサーバーを立ち上げる

まとめ

 

 

簡単な解決方法

そこでワンクリックでXMLHttpRequest 関連のエラーを回避し、htmlを見ることができる方法があります。

この解決法の必須ソフトは

です。

 

VSCodeにある拡張機能にlive serverというものがあります。ローカルホストでサーバーを開き、見たいhtmlファイルをサーバー上で見るものです。

 

 Live Serverについての詳しい説明はこちら。

marketplace.visualstudio.com

 

 

Live Serverのインストール方法

VSCodeを起動し、左側にあるメニューから拡張機能を開き、Live Serverをインストールします。

 

f:id:ky0ichi:20201123200634p:plain

インストールに成功したら、VSCodeワークスペースを作成します。

 

ワークスペースとは、VSCode上で複数のファイル・フォルダを管理するための環境です。

参考:

www.premium-tsubu-hero.net

 

ワークスペースを使うとフォルダ内のファイルの行き来がしやすくなったりします。

自分の作成しているhtmlファイルのあるディレクトリにワークスペースを作成し、環境を整えましょう。

 

 

「Go Live」ボタンでローカルサーバーを立ち上げる

ワークスペースVSCodeで開いているときに右下に「Go Live」というボタンが表示されます。これをクリックすればローカルサーバーが起動し、自身のページがブラウザで表示されます。この機能を使えばXMLHttpRequestを行うことができ、エラーが発生しなくなります!

f:id:ky0ichi:20201123202440p:plain

 

 

まとめ

  • ローカル環境(file:///~)ではhtmlから他のファイルを読み込むという処理はできない
  • VSCode拡張機能Live Share」が簡単
  • 使うときはワークスペースについて把握しておくとなおよい

ありがとうございました。

UnityのScroll Viewでうまくスクロールバーができなかった話

実行環境

Unity 2019.4.12f

 

起こった問題

UnityのUIにはScroll Viewというものがあります。

複数のコンテンツをスクロールできるウィンドウが作れます。

Unityでは縦横にスクロールバーを自動で表示したり、スクロールの感度、スクロールの速度の変化など細かく設定することができます。

今回直面した問題はScroll ViewのContent内に生成したコンテンツのスクロールがうまくできないという問題です。

f:id:ky0ichi:20201116013507g:plain

 

このgifではボタンがスクロールウィンドウの外にあるにも関わらず、スクロールバーが表示されていません。おかげでスクロールがうまくできてないです。どうしたらよいのでしょうか?

 

答えは、Scroll View内にある「Content」のRect Transformの大きさにあります。スクロールバーの大きさはContentの大きさに連動しています。

 

f:id:ky0ichi:20201116013947g:plain

 

なので、スクロールバーをコンテンツに応じて変えたい場合、ContentのRect Windowの幅・高さをContent内の子オブジェクトに合わせる必要があります。

 

解決方法

Content Size Fitter」というコンポーネントをContentに割り当てると解決できます。

 

f:id:ky0ichi:20201122201718p:plain

 

Content Size Fitterを割り当てたUI要素は、その大きさ(Rect Transform)を子要素に合わせます。

したがって、Scroll ViewのContentのRect Windowを子要素に合わせることでスクロールバーを要素に応じて自動で変更されるようになります。

「Content Size Fitter」は便利

 Content Size Fitterは子要素に応じて自身の幅、高さを変えられます。そのため文字列の長さに合わせて枠線の大きさを変えるダイアログの作成にも使えます。

出典

qiita.com

 

他の手段

tech.griphone.co.jp

バンダイナムコスタジオのオンラインテスト感想

バンダイナムコスタジオ様のオンラインコンテストがathletics様から応募を受け付けていたので参加させていただきました。

企業が行っているコンテストに参加するのは初めてだったので緊張しました。

athletix.run

(開催は既に終了しています)

 

内容

簡単に説明するとC++で球と三角形(ポリゴン)の衝突判定を行い、どれだけ正確に・高速にできるかを競う問題でした。

テストケースは複数与えられます。1つのテストケースには三角形と複数の球のパラメータが与えられ、球一つ一つに対してどれだけ三角形が衝突しているかのカウントを出力します。球のカウントが想定解とどれだけあっているのかの正答率を高くするコードを書く必要があります。

f:id:ky0ichi:20200920183629p:plain

三角形と球の例

注意するべきこととして、三角形は球の内部ではなく球面に交差もしくは接していると衝突した判定になるというものです。単に三角形と球の中心との距離が球の半径未満であるというコードでは不十分です。

f:id:ky0ichi:20200920184224p:plain

球と三角形の衝突判定の可否(球面に接している三角形のみ衝突した判定に)

 

コンテスト開催中に感じたこと

コンテスト開催期間中、参加者のスコアのランキングが日々Slackで更新されるのが自分にとっては新鮮で面白かったです。他の参加者とスコアを比較したり(上位の人たちと自分のスコアに驚いたり)、アルゴリズムを変えたことによるスコアの向上を見れたりなど楽しかったです。

また、Slackで気軽に質問することもでき、フィードバックも早かったのでとても助かりました。

コードはブラウザ上の特定のサイトで実行・提出するのですが、実行時テストケースがどれだけあっているのかが見やすかったです。(ファイルを分割して実行することもできたようですが、やり方が最後まで分からなかったです…)

 

反省

工夫した点は

  • 小数を10倍して整数で管理(すべての入力で小数点以下は1桁なので)
  • 球とポリゴン間の距離を比べるとき、距離をsqrtで算出しない
  • 座標をVec3クラスで管理(演算子のオーバーライドも定義しコードを簡略化)
  • 8分木で空間全体を分割し、球に近いポリゴンしか判定を行わないようにする

コンテストの結果は9位でした。ここまで高い順位になるとは思ってなかったのでとても嬉しかったです!

 

反省点は

  • 8分木で空間分割をしたとき、球が属する空間とそれに隣接する6つの空間も探索すればよかった(球と三角形が空間を隔てて接していた場合を判定できない)
  • 公開されていたテストケースのうち、一つ正答できていなかったので、原因を探りたかった

などなど…

他の参加者には自分では思いつかなかった工夫をしている人もいました。自分はまだまだ知識が足りないことを痛感しました。

 

さいごに

コンテスト終了後の参加者のランキング発表や懇親会はとても楽しく、有意義な話が聞けてすごい良かったです!このコンテストを提供してくださったバンダイナムコスタジオ様、本当にありがとうございました。

Asepriteというドット絵ツールの紹介

僕は2Dゲームを作っていることが多いので、ドット絵やイラストなんかを描くツールをよく使います。

 

ドット絵を描くとき便利なツールに「Aseprite」というものがあります。steamで2050円(2020/09/19現在)で購入できます。このツールはかなりすごいのでぜひ見てほしいです!

f:id:ky0ichi:20200919194909p:plain

このツールの何がすごいのかといいますと、値段がリーズナブルなのに高機能で動作が軽いところです。

主に使える機能として以下のものがあります。

  • レイヤー機能
  • ブレンディング(加算、乗算、オーバーレイなど計19種)
  • 透明度(0~255)
  • アニメーション
  • オニオンスキン(前後のフレームの絵を薄く表示)
  • ブラシ、ぼかし
  • 投げ縄、矩形選択、バケツ選択(マジックワンド?)
  • bmp, ico, gif, jpgなど様々なファイルの対応
  • トーンカーブ、色相・彩度・明度変換
  • 文字入力

f:id:ky0ichi:20200919201142p:plain

レイヤー分けができたりフレームをタブで分けたりできる

これ以外にもたくさんの機能がありますが、詳しくはAsepriteのホームページで確認してみてください。

www.aseprite.org

 

このツールを使うメリットとして透明度の対応があります。Windows標準のペイントとかだと透明や半透明ピクセルをそのままpngファイルとして出力することができないので、Asepriteはかなり便利です。

f:id:ky0ichi:20200919200940p:plain

背景を透明にしたままエクスポートができる

 

またAsepriteはアップデートの頻度が高く、新機能が続々追加されているのでバグや不具合が修正されないままということもないです。

f:id:ky0ichi:20200919201719p:plain

頻繁に行われるアップデート

 

ぜひ、公式ホームページやSteamでチェックしてみて下さい!