かさたな日記

主にUnityを使った制作記録。書いてる人は初心者です。一緒に頑張ろう。

Unity1week:Space編

Unityroomさんの1週間ゲームジャム、通称Unity1weekに参加しました。
無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう
参加は今回で3回目となります。
提出できなかった時も作ってはいたのですが、
間に合わないことが多かったのですよ、よよよ。。。

さて、今回のお題は……「space」!
この単語からは宇宙、空間、スキマ、あるいはspaceキー、バナナなんかが連想できました。
......我ながら発想が貧困。

しかしまあ、奇をてらってまた間に合わないというのもよろしくないので
ここはシンプルに宇宙ネタ、そしてシューティングで行くことにしました。

ただ、シューティングは実は前回も作っています。
しかも現在まさに制作中のシューティングもあったりします。
なので今回はちょっと趣向を変えて、
「宇宙」からの連想で惑星の引力を利用するものにしてみました。
そんなわけで作られたのが今回の「Swing By Me」です。
URLはこちら:https://unityroom.com/games/swingbyme
地球の引力で月を振り回すアクションシューティング。
よかったら遊んでくださいな。


制作するにあたって、ケプラーの法則を調べたりしてたのですが、
月が吹っ飛んだり地球(自機)が勝手に引っ張られたりでゲームにならないので
簡単なウソ引力で行くことにしました。コードは以下のような感じです。

//引っ張る方
public class GravityAttractor : MonoBehaviour {

	public float gravity = -10;

	public void Attract(Transform moon) 
	{
		Vector3 gravityUp = (moon.position - transform.position).normalized;
		moon.GetComponent<Rigidbody>().AddForce(gravityUp * gravity);
        }
}

地球から月への方角ベクトルを求めてその方向と逆に力を加えています。
地球が動くとうまいこと周囲を回転してくれます。Unityすごい。
このメソッドを月の側のUpdateで呼び出します。

[RequireComponent (typeof (Rigidbody))]
[RequireComponent(typeof(LineRenderer))]
public class Moon : MonoBehaviour {

    public GravityAttractor attractor;
    private Transform myTransform;
    private Rigidbody myRigidbody;
    private LineRenderer myLine;

    [Range(-360, 360)]
    public float rotateSpeed = 30;

    [Range(0, 5f)]
    public float minDistance = 0;

    [Range(0, 20f)]
    public float maxDistance = 5.0f;

    public bool isLookAtAttractor = true;
    public bool isLine = true;

    void Start () 
    {
        myTransform = transform;
        myRigidbody = GetComponent<Rigidbody>();
	myRigidbody.useGravity = false;
        myLine = GetComponent<LineRenderer>();
        
    }

    void Update()
    {
        transform.RotateAround(attractor.transform.position, Vector3.up, rotateSpeed * Time.deltaTime);

        float distance = Vector3.Distance(attractor.transform.position, myTransform.position);
        if (distance < minDistance)
        {
            Vector3 angle = (myTransform.position - attractor.transform.position).normalized;
            myRigidbody.MovePosition(attractor.transform.position + angle * minDistance);
        }
        else if (distance > maxDistance)
        {
            Vector3 angle = (myTransform.position - attractor.transform.position).normalized;
            myRigidbody.MovePosition(attractor.transform.position + angle * maxDistance);
        }

        if (isLine)
        {
            if (attractor.gameObject.activeInHierarchy)
            {
                myLine.positionCount = 2;
                myLine.SetPosition(0, myTransform.position);
                myLine.SetPosition(1, attractor.transform.position);
            }
            else
            {
                myLine.positionCount = 0;
            }
        }

        if (isLookAtAttractor)
        {
            Quaternion targetRotation = Quaternion.LookRotation(transform.position - attractor.transform.position);
            transform.rotation = new Quaternion(0, targetRotation.y, 0, targetRotation.w);
        }
  }

  void FixedUpdate () 
 {
	if (attractor)
	{
		attractor.Attract(myTransform);
	}
 }

}

決定稿では0になっているのですが
最近距離(minDistance)を設定しておくと、
その距離だけ地球を迂回するように動くようになります。

rotateSpeedも最終的に0にしておくことにしました。
ので、月はプレイヤーの操作による地球の位置の変動によってのみ
動かせることになります。

ここは上手いこと重力感というか、
「振り回している」手ごたえを感じてもらえるように
操作スクリプトの方で微調整をしております。

その他、当たり判定等は普通のシューティングの作り方ですが
何分、オブジェクトが大量に出てくるので弾からパーティクル、
敵キャラまですべてプーリングしつつ、
マネージャから座標を監視しています(これはループさせるため)
あとアイテムも……

そう、ホントはコインが出てきて集めると月のほかにも
太陽系の兄弟たちを振り回せる予定だったのですが
残念ながら時間切れとなりました。1週間って意外と短い。

敵を倒したときの効果音やエフェクトのタイミングに
こだわりたかったのでそこに時間を使ってしまいました。
でも爽快感があるという評価をいただいたので
時間を割いて調整したことは間違ってなかったと思います。


反省点としては難易度の調整ですね。
操作感が独特になるので、初めて触れるプレイヤーには難しい、ハズ。
なので、そこは慎重にならなくてはいけなかったのですが……
もとい、慎重になっていたつもりだったのです、が。
やっぱり難易度が高いという感想をいくつか頂きました。

一応、スコアに応じて徐々に強い敵が出るようになっているのですが
そんな調整だけでは小手先の小細工もいいとこ......

反芻になりますが、やはり操作に慣れが必要であることが大きかった。
大量の作品が投稿されている中で、1作品の操作練習に時間を割いてもらうのは
やっぱり難しいですね。 うーむ、考えが甘かったなぁ。

人気のある作品を見るに操作がシンプルで、瞬時に理解できるものが多いですしね。
次回はその辺、もう少し考えようと思います。
ほかにも細かい反省点は尽きないですが、
久しぶりに完成品を提出できたことは間違いなく「よかった」と思えます。


さて、今回のプロジェクトにはストアのアセットを
結構たくさん使用させて頂いているので
その紹介をしたいと思います。


■PlayMaker
定番のステートマシンアセットです。
ゲームのフローの制御から敵キャラのAIまで色々使えます。
今回は専ら前者で全体のフローに使用しています。
ボクの場合、主に使うのはCallMethodアクションで、
ゲームごとのマネージャに記述したステート処理を呼び出すようにしています。
拡張も比較的カンタンなので汎用アクションもほとんど自作したものを使ってます。

公式のドキュメントが充実していて、
エディタも日本語化されているのがありがたいです。
FSM入門はこのPlayMakerか、Arbor2がおススメ。(個人の感想です)
今セールやってるみたいです。


■Odin - Inspector and Serializer
お気に入りのアセット。
これはインスペクタを拡張するためのアセットです。
Attributeをちょっと記述するだけでこんな感じに出来ます。
f:id:kasatanet:20171120171623p:plain:w240 f:id:kasatanet:20171120173040p:plain:w240
グループ化したりタブをつけたり折りたたみ(FoldOut)したり
プロパティを表示したり、特定boolがtrueの時だけ表示したり
dictionaryをシリアライズできたりします。
機能性はもちろんなのですが単純に触るのが面白い。
拡張沼にハマるのもわかる気がする....。
これについてはもしかしたら、解説を別に書くかもしれません。

あっ、これも今セールやってるみたいですよ! (2017/11/20)


■Curved World
お気に入りの曲面シェーダ。
マリオギャラクシーのような雰囲気や
どうぶつの森のようなドラムロール式の演出が出来ます。
(アセットの説明文でも例に挙げられていました)
あくまでシェーダなので曲がっているのは見た目だけです。
物理的な座標はそのままなので物理挙動の計算式を変える必要もありません。
マテリアルに張り付けるだけでいつものマップがちょっと新鮮に。
あとモバイルでもあんまり負荷がかからない感じです。

注意点としては、
あくまで平面を曲げて見せているだけなので
これだけで完全な球面(ループ構造)にはならない、ということです。
今回のゲームではマップ(と敵)の座標をループさせることで球面を演出しています。


■DOTween (HOTween v2)
定番のTweenです。
twitterでこれは良い、という話を見かけて今回初めて使わせてもらったのですが、
ホントにこれを無料で共有してもらっていいのかしらというくらい色々できます。
今回のゲームで使っているのはUI....ではなくて弾の軌道の制御です。
上に張ったシューターのコンポーネントで機能を利用していて、
先に設定したパスに沿って飛ばせるようになっています。
とはいえ、今回は難易度調整の関係で歪曲弾とか撃つ敵はいないんですけどね....。


■Clean & Minimalist GUI Pack
シンプル、フラットで扱いやすいUIテクスチャのセット。
このアセット作者さんがシリーズで出しているような素材感のあるUIもいいですが、
こういうシンプルなのも素敵です。
インスペクタから色を変えるだけで雰囲気を変えられるのも利点ですね。


■Dynamic Starry Sky
愛用させてもらっているスカイドーム用のシェーダです。
星や月の表示位置、グラデーションの開始位置をカスタマイズできます。
もちろん夜空以外を作成することも可能です。


■Hyperbit Arsenal
今回のジャムでの使用者も多かった気がするパーティクル集。
80年代のようなレトロ感を醸し出しつつも新しい、ステキエフェクト。
効果音まで付属しているのがとってもありがたいです。
制作中のシューティングでもお世話になっております。


■Game Music Pack - SUITE
高品質、かつあらゆるジャンルが取り揃えられた楽曲セット。
カジュアル系からEDM、ファンタジーRPGぽいのからSFシューティング風まで。
毎回お世話になっております。


■BGM Collection Volume 1 "Colorful"
今回ゲームシーンのメイン曲として使用させていただきました。
扱いやすい短めのループ曲の詰め合わせ。ジングルも入っています。
作曲者さんごとに雰囲気というか、傾向があるのが楽しいです。
Volume 1 とあるので 2 にも期待しております。


■Deportivo
日本のパブリッシャーさんが提供してくれているシリーズ。
ポリ数、頂点数ともに抑えめでモバイルでも使いやすいモデルです。
制作中のアクションRPGでも使用させてもらっています。


■Low Poly Ultimate Pack
様々な屋外場面を演出できるローポリモデルの詰め合わせ。
平原、雪原、森、砂漠、海岸、孤島、西部の荒野まで。
今回は汽車のモデルを銀河鉄道として使わせていただきました。
1000点以上で出現します。....キミは見ることが出来るか!?


■Planet Pack
デザインが好みだったので、今回のジャム用に買ったアセット。
カートゥーンな惑星モデルの詰め合わせです。
先にも書いたけど、ホントは月以外も振り回せる予定だったのさ。
今後の使用予定ももちろんあります。


■Space Theme Items and Props Starter Pack
隕石やロケット、砲台、UFO、宇宙飛行士などのモデルのセットです。
SF風の看板やゲート、信号機なども含まれています。
これだけでシューティング出来そうな勢い。低ポリでモバイルでも安心。
今回はほとんどの敵キャラをこの中から使用させていただきました。


■Planets with Space Background in Flat Style
惑星の2Dテクスチャの詰め合わせ。フリーアセットです。
今回は各種ボタンとして使用させてもらいました。


こうしてリストアップしてみると、かなり使ってますね。
なるべく汎用的な、色々なプロジェクトで使えそうなのを
選んで買っているつもりなのですが、
セールがあると気になってたのを衝動買いしてしまう癖が……。

そういえば、また今日からセールが始まってるんだっけ……。