LoginSignup
3
2

More than 3 years have passed since last update.

システムとアニメーションの理想の関係

Posted at

本記事について

この話は、サーバーエージェント様で開催された平成最後のハッカソン

でアプリ作った時の反省とか、改善点とかをまとめたものです。

何が問題になったか

まず、私たちが作ったのは、「平成を振り返る人生ゲーム」という物でした。

私は、人生ゲームのシステム担当・後の二人がUI・アニメーションを担当していました。

まず起こった問題

しばらくバラバラに開発を進めており、さあくっつけるか!となった時に

以下のような問題が発生しました。

class GameController {
  ...
  func spinRoulette(min:Int, max:Int) -> Int
  ...
}

ゲームシステム側にこのような定義がされていたのですが、

この関数を実行すると、プレイヤーの場所の変更・アイテムの獲得などが一度に行われてしまい、

その間にアニメーションが実行できないという問題です。

なので、以下のような関数をGameControllerに追加しました。

func animationDidEnd()

アニメーションが終わったら読んでね、的なやつです。

この間 GameController は実行を中断し、その間にViewがアニメーションを行えるようにしました。

次に起こった問題

さらに止まったマスがアクションマス(2マス進む)などがあった場合は、

GameController は2回に分けてプレイヤーの位置を更新する必要があります。

なので、以下のようにしました。

/// 移動が終わったら毎回呼んでください。
func animationDidEnd()

さらに起こった問題

今度は、止まったマスでアイテムがゲットできる場合があることがわかりました。

この場合はさらにアニメーションを行います。

なので、以下のようにしました。

/// 移動が終わったら毎回呼んでください。
/// アイテムがゲットアニメーションが終わったら呼んでください。
/// ...
func animationDidEnd()

結局何が問題か

まず、ここまで進めてきて起こった問題は、

意図しないタイミングで、イベントが発火してしまうというものです。

この問題はルーレットとマップの両方から、 animationDidEnd() という簡単なものだったのですが、

以降も似たような問題が多発しました。

なぜ起こったか

この問題が起こった理由は animationDidEnd() を呼ぶタイミングが

呼び出し元にとって明確でないことです。

アニメーションと言ってもゲームの中には多種あり、

複数人で開発している場合には、この認識の違いが問題になりました。

どうすべきだったか?

この問題はアニメーションのような、非同期処理一般に言えることだと思います。

呼び出し元からわかりやすい名称をつける

まずはこれが重要になってくると考えます。(命名規則の基本ですね...)

特に今回はルーレットからの呼び出しなのか、マップからの呼び出しなのか

などを分ける必要がありました。

func rouletteAnimationDidEnd()

func mapAnimationDidEnd()
...

のようにするだけで、かなりわかり易くなるはずです。

特殊な処理はシステムを分ける

また、今回システムが複雑になった理由として、

「2マス進む」などのアクションがあります。

ドメイン設計を念頭にこのシステムと、プレイヤーの位置などの管理は

クラス分けすべきだったと考えます。

非同期処理では、これをやると後処理は勝手にやってくれるのではなく、

実はいちいち呼び出して実行した方が良さそうです。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2