unity1weekお題「当てる」に参加したゲームの開発話
2ヶ月ぶりの更新です。
サイト unityroom にて2/19~開催された一週間ゲームジャム #unity1week に「魔物討伐」で参加させていただきました。
魔物討伐 | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう
このタイトルの開発話を書いてきます。
お題「当てる」
当てるというお題で、悩んだ挙句にひねらずに弓矢を使うゲームにしようと考えました。
開発毎に再利用を行うために部品化やライブラリ化はしているものの、今回は着手が遅くなったこともあり開発中だったランゲームをベースにして、以前作成したものを色々流用しつつ開発を進めました。
各要素について
- キャラクタ操作処理:
キー + マウス操作については、以前のunity1week「2017/07/24〜 お題:夏」で作成したビーチバレー[仮]他からの処理を使用しています。 キャラクタは物理で動作させているので、そのあたりの処理や設定値も使いつつ調整しました。 - キャラクタの動き:
敵キャラに使用したスケルトンは以前のお題でも使用していたものを今回も使用しました。
キャラクタはボーンを埋め込んだポリゴンをfbxに出力してUnityでAnimationをつけています。
キャラクタドットは新規に作成することも多いのですが、動きのAnimationは同じものを使用しています。 タイトル毎に都度調整をしているので、最新作になるごとにアクションが増えていきます。 - 弓矢の処理:
以前作成していたものからの流用です。弓もドットテクスチャのボーン在りポリゴンです。
ドット絵的には邪道かもしれませんが、スケルタルアニメーションでの動作はドットパターンを描かない分工数が少なく済みます。
融通が利きにくい面もありますが。
ステージについて
- 背景、地形:
作成中のランゲームで多重スクロールを実装していたので流用、地形ではFerr2DというAssetを使用させていただきました。
樹木は以前作成したL-System2Dの生成処理を使用、楽ちんです。(GitHubにて公開中、更新してませんが)
描画ではMeshRenderer、SkinnedMeshRenderer、SpriteRendererが混在している状態です。うまく管理しないとカオスに・・・。 - ポストエフェクトシェーダー:
本作も含め作成した大体のゲームには、画面を曲面の様にゆがませる自作のシェーダーを適用しています。
ちょっと変わった画面効果が得られるかなと思ったためです。「地球も丸い、画面も丸い」な感じで。 ただ、シェーダーは理解不足なところもあるため、効率が悪かったり間違っている部分もあるかもしれません。
UIについて
- uGUIの利用:
Unity uGUIを使用したものは、unity1week「2017/08/21〜 お題:フロー」のあたりから作成したものを調整しつつ利用しています。
最初はuGUIのButtonを拡張していましたが、MonoBehaviour に IPointerClickHandler 等のインターフェイスで拡張したコンポーネントを使用しています。
これも回を重ねるごとに改良しつつ使用しています。
本作ではボタンやポップアップのイージング等も少し対応。最初はDOTween等のAssetを使うことを考えたのですが、単純なものでしたのでコードで実装しました。 - ツイート/ランキング機能:
これはunity1week期間以降に追加した機能です。
いずれもunityroom運営のnaichi (@naichilab) さんが提供されているライブラリを使用させていただきました。
特にランキング機能は以前からつけてみたかったので、今回(期限後ですが)実装できたのはよかったです。
これで次回以降も組み込めるかなと。
キャラクタ操作について補足
ADキーでの横移動、マウスでエイム、左マウス攻撃、右ジャンプという、FPSやテ○リア等のタイトルによく見られる操作かと思います。
個人的にスペースでのジャンプが苦手で、それよりも右クリックジャンプが楽な気がしているため、この操作方法が増えると良いなという思いもあります。
マウス併用はUI操作もしやすいですしPCでは標準的なデバイスなので、PC向けのタイトルを作成するなら、こういう構成が良いかなと考えていました。
ランキングについて
今回引っかかった部分を補足します。
使用させていただいたライブラリのスコア送信は double 型なのですが、スコア送信処理の際にタイムアタックの時間(float型ミリ秒)をそのまま使用していました。
ゲーム中はfloatだったため、何も考えずに値をセットしていたところ、ハイスコア更新判定で浮動小数精度による比較の問題が発生してしまいました。
(同数値のハズなのに、比較で一致しない)
結局、小数3位までの使用として、満たない桁を切り捨ててからdouble変換して使用しました。
切り捨て計算で誤差出るのも嫌なので、下記の様に一旦文字列にしてから対応にしました。(冗長かもしれません)
RankingLoader.Instance.SendScoreAndShowRanking( double.Parse(string.Format("{0:N3}", playTime)));
unity1weekについて感想
期限とお題が決まることで、普段なかなかできない「捨てる」判断が磨かれる気がしています。 また、回を重ねるごとに知見やコード、リソースが蓄積されていくので、いずれそれらを利用した集大成的なタイトルに仕上げることができればと思っています。 奇しくも今回はそんな感じになってしまいましたが。
作成したゲームがどなたかに遊んでいただけるというのも、非常にうれしいことです。
直接プレイヤーさんの反応を見ることはできませんが、様々な意見や感想をいただけるのは非常にありがたく嬉しく思いました。
謝辞
ゲームをプレイしていただいた方、感想・意見いただいた方、ありがとうございます。
また、開催・運営されているnaichi (@naichilab)さんにはこの場を借りて感謝申し上げます。
Unity uGUI TextにSpacing機能を~その2:複数行対応
以前作成したTextSpacing機能では複数行対応できていませんでした。
garakuta-works.hatenablog.com
修正した版を下記に作成しました。
- クラス名をUITextSpacerに変更しています。
- 残念ながらpivot.xが0.5以外やAnchors設定によっては配置がおかしくなる問題は解決していません。
- 2018.01.13 Wrapした場合の動作でずれた為修正しました。
※追記 - 2018.01.07:
どうやら車輪の再発明だった様で、下記Unityフォーラムに既に該当処理が掲載されている様です。
https://forum.unity.com/threads/adjustable-character-spacing-free-script.288277/#post-2524726
調べ方足りなかったなー。
※更新 - 2018.01.13:
Text.horizontalOverflowはOverflowにして、UITextSpacerに追加したhorizontalOverflowをWrapにしてください。
コンポーネント的に美しくない感じですが、色々妥協しました。
Unity uGUI TextにSpacing機能を付ける
UnityのuGUIのTextでフォントの文字間隔を調整する機能を作成してみました。
(行方向はText.LineSpacingがあるのですが、文字間隔の調整パラメータが無かったので)
Textがアタッチされているゲームオブジェクトに下記のUITextEffecterをアタッチして、TextSpacingを調整します。
TextSpacing = 0
TextSpacing = 5
開発環境:Unity2017.3.0f3
追記:
- Pivot.xが0.5以外の場合に位置がずれる問題があります。
- 複数行の文字列に対応できていません。
・・・色々ダメだな。
2018.01.07 複数行対応版を下記に登録しました。 garakuta-works.hatenablog.com
作成にあたっては、下記記事を参考にさせていただきました。
というかModifyTextSpacingメソッド以外はほぼ参考記事からの引用です。
tsubakit1.hateblo.jp
nn-hokuson.hatenablog.com
Unity Android タップ処理での IsPointerOverGameObject検出
Android タップ処理で Update FixedUpdate で動作が異なっていたのでメモ
- 開発環境:Unity2017.3.0f3
- 動作環境:Android7.0 XPERIA SO-02J
uGUIでのタップを検出する処理
private static bool IsPointerOverUI() { if (EventSystem.current == null) { return false; } #if UNITY_IOS || UNITY_ANDROID int tcount = Input.touchCount; if (tcount > 0) { for (int i = 0; i < tcount; i++) { if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(i).fingerId)) { return true; } } } return false; #else return EventSystem.current.IsPointerOverGameObject(); #endif }
uGUI入力検出処理
if (!IsPointerOverUI()) { #if UNITY_IOS || UNITY_ANDROID if (IsTouch()) { switch (GetTouch()) { case TouchPhase.Began: //入力開始 break; case TouchPhase.Moved: case TouchPhase.Stationary: //入力移動・維持 break; case TouchPhase.Ended: case TouchPhase.Canceled: //入力終了・取り消し break; } } #else if (Input.GetButton(InputJump)) { //入力 } #endif }
上記の入力確認を FixedUpdate で実行すると TouchPhase.Began 時点でのuGUI入力検出が出来ない。
Update で実行すると TouchPhase.Began でのuGUI入力検出も出来た。
物理処理を行うために FixedUpdate で使用する場合は入力処理のみ Update に実装を分けるか、TouchPhase.Began での入力を除外する等の対応が必要かもしれない。
※iOSでの挙動は不明、また、Androidの機種による差異の可能性もある。
入力確認処理のソースコード(AppInput.Check()で入力状況確認、IsInputで各アクションの入力判断)
Unity L-System 2Dについて
以前作成したL-Systemを使用した2D樹木作成についての記録です。(Blogの記入練習を兼ねて)
- Unityプロジェクトのソースコード一式はGitHubに格納しています。
- L-System(Lindenmayer system)については、どこかに詳しい情報が記載されていると思いますので、そちらを参照願います。
概要
2D Platformゲーム等でプロシージャルなステージ生成に使うことを目的として、樹木mesh生成を行う処理を作成しました。 設定された生成ルール定義ファイルを元に、MeshRendererまたはSkinnedMeshRendererに生成したmeshを登録します。
- 乱数生成にはXorShiftを利用(XORandomクラス)
- L-Systemルール定義ファイルはPlantConfigクラスをScriptableObject登録して使用
- Spriteをmeshのuv情報として使用します。
使い方
詳細はUnityプロジェクトファイルのSampleシーンを参照
- GameObjectにPlantクラスをアタッチします。
- Assets > Create > Custom > Create Plant Config でルール定義ファイルを作成、L-SystemルールやSprite参照を登録します。
- 登録したルール定義ファイルはPlantクラスInspectorのRef Configにセットします。
- MeshFilter/MeshRendererまたはSkinnedMeshRendererをアタッチして、PlantクラスInspectorのRef Mesh FilterかRef Mesh Rendererへ参照をセットします。 (Sampleでは子GameObjectにセットしていますが、Plantと同じGameObjectへのアタッチでも構いません)
- MeshFilter、SkinnedMeshRendererにはマテリアルをセットします。
- 実行時のStartイベントや、Inspectorの「Create L-System Plant」を実行することで、樹木meshが生成されます。
- PlantのRandom Seedが0の場合は実行毎にランダム生成されますが、0以外の場合はシード値として使用し同じ生成がなされます。
L-Systemルール
キーワード | 動作 |
---|---|
F | Forward 枝を伸ばす |
G | Generate Fと同じ、生成時のキーワード置き換えに利用 |
+ | Left 左に回転する |
- | Right 右に回転する |
[ | Push 分岐作成 |
] | Pop 分岐終了 |
meshにはボーン参照情報も含んでいるため、将来的には時間とともに樹木が成長していくような要素も組み込みたいところです。