対戦カードゲーム開発ブログ 【2019年秋リリース(ios,android)】

【Unity】カードゲームっぽい手札を作りたかった話

こんにちは、たかせです。カードゲーム作ってます。

twitter.com

先日、手札のカードをこんな風に表示していたら、デザイナさんに突っ込まれました。もっと シャドバ カードゲームっぽくしたいとのこと。

UIを円状に配置できるScriptを見つけたので試してみたものの、いまいちカードゲームっぽさが出ない。

やっぱこうじゃないと...!!!

 

ということで、SectorLayoutGroupを作成しました。

github.com

デモ

3D対応!アニメーション可能!

D&Dでラクラク設定!Gizmosによる補助機能付き!

使い方

スクリプトとプレファブをインポートすると使えます。UniRxというAssetに依存しているので、利用していない方はコチラからインポートしてください(無料です)。

  1. SectorLayoutGroup.csをインポート
  2. SectorTemplate.prefabをインポート
  3. 並べたいGameObjectをSectorTemplateの子供に子供として追加
  4. 完了!

パラメータの説明

  • Center
    • 必須。扇形の中心点となるGameObjectを指定します(図中の赤点)
  • Start
    • 必須。扇形の始点となるGameObjectを指定します(図中の青点)
  • End
    • 必須。扇形の終点となるGameObjectを指定します(図中の緑点)
  • ChildrenRotateOffset
    • 子供の向きを調整します。デフォルトではCenterを向きます
  • FrameCount
    • アニメーションの実行時間を調整します。最終的な時間はFrameCount * FrameIntervalにより決まります
  • FrameInterval
    • アニメーションの実行間隔を調整します。最終的な時間はFrameCount * FrameIntervalにより決まります
  • useSlerp
  • enable
    • Gizmosを使ってデバッグ用の扇形と点を描画します(予めGizmosをONにしておく必要があります)
  • freeze
    • 要素を並べる時、回転情報をリセットします

とりあえず動作確認してみたいという方へ

お試し用のプロジェクトを作成してあります。コチラからZipファイルをダウンロードして、UnityでSampleSolutionフォルダを開くと動作確認が可能です。

git cloneでもOKです

 

動作の解説(と苦労話)

要素を扇状に並べる手順をざっくり言うと、次のようになります。

1. 3点(赤点、青点、緑点)をもとに扇型を定義する
2. 扇型を曲座標変換して半径、xy平面上の角度、xz平面上の角度を取得する
3. 2つの角度をn等分し、その等分線を直交座標系に戻す
4. 等分線の終点にGameObjectを配置する
5. 中心点(赤点)を向くようにGameObjectを回転させる

文字数にして149文字の短い説明ですが、ベクトルの足し算ってどうやるんだっけ...?な状態だった僕にはなかなかしんどい実装でした。

 

いやほんとに。高校の数学、こういう動機を持って勉強したかったなぁ。

 

Unityの座標系はxyzではなくxzyであることに気づかず数時間悩んだり、気まぐれにWordScopeからLocalScopeに切り替えてみたらxyz座標系に戻って悩んだ時間が吹っ飛んだり、Quaternion.LookRotationの説明にあるspecified forward directionsがさっぱりイメージできなくて場当たり的に引数を設定してみたり...。もうさんざんでした。初めてUnityエンジニアらしい実装をした気がします。

 

わりと困ったのが「扇形の形が変化したら子供を並べ直す」実装で、3点(赤点、青点、緑点)のpositionの変化を検知したかったのですが、その時点で唯一知っていたOnValidateでは検知できませんでした。困った挙げ句、UniRxのObserveEveryValueChangedを使ってtransform.positionの変化を購読することで対応しました。動作上問題は出ていないものの、誰がもっと良い実装があれば教えてください...

 

また、どうせUniRxを使うなら...と思いたった結果、要素数の変化もObserveEveryValueChangedで行いました。これにより、LayoutGroupの継承をせずに済むようになり、uGUIではないLayoutGroupが完成しました。作った手前あれなんですが、非uGUIなLayoutGroupって嬉しいことあるんでしょうか...。継承を外せたのは嬉しかったんですが、使う側としても何か嬉しいことがあればぜひ教えてもらえると🙇‍♂️

 

2箇所もUniRxに依存してしまった現状、Vector3.LerpによるアニメーションにUniRxを使わない手はありませんでした。

 

こんなデータをクラスを作り、

こんなストリームを作れば、

あっと言う間にUpdateメソッドを使わないLerpアニメーションの完成です 。

 

Corotuineとか使ったほうがスマートかもしれません

おわりに

SectorLayoutGroupにより、こんな素敵な手札が完成しました。

 

カードゲームを作っているみなさんが少しでも楽になりますように!

 

こんな風に使えるともっと便利なんだけど...みたいなご提案、お待ちしております!!!