Imaginantia

思ったことを書きます

メモ240312 旗の判定の話

色々考えてこうなったので、考えたことについて書いておきます。

前提

  • エンディングのアレがやりたかったので、3種類のインタラクションを用意する必要がある
    • 根本的にあのワールドは「体を動かす」ことに趣旨がある
    • 最後に手を自ら伸ばしてもらうための布石として、手を動かすことに慣れてもらう必要があった
  • それぞれで別物にする為に、判定方法の異なる3種を考えた
    • 叩くもの・振るもの・向けるもの
      • (それぞれ近距離・中距離・遠距離という意図)
      • 「盛り上げ隊」のイメージからビジュアルがアレになった
        • ちなみに各バトン形態の名称は特に決めてないです
          • 以後、便宜上青いやつを「旗」と呼びます
  • これをうまく実現する為に必要なこと:
    • 何をすれば、何が起きるかをユーザに伝えること
    • 十分な精度で挙動をコントロールする能力をユーザに与えること
    • (逆に、例えば動作が直感的であることは、ゲーム一般においてあんまり必然性がない)
      • 補助として機能することはもちろんある
  • 一般に、連続操作を離散化するのは結構難しい (連続写像じゃないから)
    • 状況Aと状況Bの間を「切断する」のが離散化
      • 今回は「A: 動いてない状態」と「B: 素早く動いている状態」として捉えた
        • 実はこれが間違っていた (後述)
    • 特に今回はユーザに「切断」させるタイミングをコントロールさせる必要がある

どうなっていたか

判定

  • 「止まっている状態から、ある程度の事前動作を伴った状態で、旗の先端が一定速度を越えると、判定が入る」という実装
    • 厳密に言うと: 「先端位置 p のEMA*1と、p との距離」d のEMA \bar{d}閾値を超えたときに判定
      • EMAを使っているのはFPS非依存にする為
      • 加えて、次に旗の判定が入るためには \bar{d}閾値の3/4以下に落ちる必要がある (hysteresis)
      • ちなみに振った向きは「p のEMAから p へのベクトル」から判定
    • 何が起きるか?
      • 止まっている状態から急に位置が変わった場合、d は即座に大きくなるが、そのEMAはまだ小さいままなので、判定が入らない
        • つまり急激に移動させると、判定がちょっと遅延して入る
      • 手をぷるぷるさせて振りまくると、先端位置のEMAが平均点に収束するので d も一定以下にしかならず、判定が入らない
      • ゆっくり振り始めながら振り切ると、d もそのEMAもゆっくり大きくなりながら期待するタイミングで閾値を超え、判定が入る
      • 旗を振るように事前動作と事後動作を行うと、ほぼその中間のタイミングで判定が入る、という想定
  • 何故か?
    • 一番簡単な「叩く入力」に対し、もうちょっと丁寧に体を動かすようなインタラクションがほしかった
    • 振るたびに音が出るので多少の報酬として機能していて、ちょっと難しくても大丈夫という想定
    • ぷるぷるして判定が入りすぎると簡単になりすぎる可能性があるので、丁寧に入力を行うことを促すために判定が入らないようにした
    • 今思うと、旗の物理による「質量感」にもうちょっと期待していたかもしれない

チュートリアル

  • 各バトンの振る舞いを学習してもらう場として用意したもの
    • 学習とは何か?
      • ユーザの入力に対し、システムが応答を返し、その応答結果とユーザの期待の違いを元にユーザがシステムの挙動予測の精度を高めていく行為
    • 3種類のバトンはそれぞれ違うことに伴い、チュートリアルの内容もそれぞれ別物にした
      • タイミングの精度を高めるもの
      • 将来の行動予測を継続的に行うもの
      • 丁寧な動きを心がけるもの
  • しかしこれによって旗の学習が破綻していた
    • 余計な入力が入るとリセットされてしまうことで、メインの工場フェーズで過度に緊張させてしまった
      • 工場フェーズで余計な入力が無視されていることは白いやつを観察すればわかるのだけど、恐らく緊張している為にその余裕がない
    • 旗の入力タイミングを不問にしていたことで、タイミングよく旗の判定を入れる練習ができていなかった
      • (一拍ごとに入れるとちょうど良い間隔で入力し続けることができる想定だったが、システム (スコア表示のこと) がそれを示していない)
    • 丁寧に動かさせすぎたことで素早い入力に対応できなくなってしまった
  • どうしてこうなったのか
    • チュートリアルの内容を他と変えることに気を取られた
    • 最初から手首で私は振ってたので腕でしっかり振る人の想定をあんまりしていなかった
      • 多分ゲーム慣れしていると「判定さえ入れば良い」という意識から行動最適化が自動的に走るのだけど、そうでない場合は「形式」を優先してしまう様子?
        • もともとゲーム好きな人に向けたワールドではあるけども
      • 例えば私は精度上げる為に、頭でリズム取りながら、旗振るときに足も同時に動かしているのだけど、この辺の感覚は確かにそこそこの経験が要るかも
        • そこまでこのワールドで学習ができるとは思ってないわけで、そこまでの要求は要らない構造にするべきだった
          • とはいえ音を楽しもうとしてくれる人は結構そういう行動をしてくれてうまくいっている印象
        • 無意識にやっているから自分でわかんないんだよね…
          • テストプレイもっとしたかった…
    • 内部事情: エントランスだけBPMが違う (時間管理系が異なる) ので「タイミングを合わせる」ゲームを作る実装コストがちょっと高かった
      • なので判定は工場と同じ粒度で取っていて、これによって期待したタイミングとはちょっとズレて判定が出ていたはず
      • これを誤魔化すために緩めの判定処理 (向きオンリー) にしたという経緯もある

実態

  • うっかり旗の判定処理がバグっていて、EMAになってなかった (しょうもないミス)
    • lerpの左右が逆だった (aveD = lerp(aveD, D, exp(-dt)) になってた)
    • FPSが高い場合は d\approx\bar{d} になり (迅速な判定が入る)、極端に低い場合は d\approx 0 になっていた (全然判定入らない) はず
      • ごめんなさい
      • エンディング、人数多いとなんか判定入らないな~とは思ってたけど普通に凡ミスで悲しい気持ちになった
        • ちなみにこれは叩くやつも同じ仕組みだったりするので、多分叩くやつで判定入らないと感じてた人も居るはず (私もそう)
  • モチポリが腕を大きく動かしてるのでユーザも腕を大きく動かしたくなってしまう
    • 「旗の動き」は真似すべき点があるのだけど、腕まで真似するとすぐ疲れちゃうんですよね (モチポリの腕は強靭なのかな?)
    • 疲れるからもっと楽な方法を探そう、ってなってくれることを期待していたけど難しいですよね
      • ポップコーンも同じことが起きててまぁそうだなあっていう感じ (うまい人はこのフェーズをすぐ越えられるんですよね)
  • 素早い動きの入力を入らないようにしたことで、エンディングのシナモンルートがほぼ不可能になっていた
    • BPMだいぶ上がるので… (多分理論上は可能なんだけど人間に可能かどうかは別問題)
      • つまり「2連続の入力をするとき、途中に動いていない状態は存在しない」ということがわかっていなかった
    • 毎回全然できね~~~って笑えるのはまぁそれはそれで良かったんだけど、パフェ取れないのは普通に問題
      • 別に得点を取れなくても全体の流れは何も変わらないので体験はギリギリ成立しているけど…
    • 何よりも自分が悪いのかシステムが悪いのか判断できないあたりがつらい (そのせいで原因究明が遅れた)
    • 一応書いておくと、エンディング以外の旗判定は私はほぼ確実に正確に入力を入れられます
      • そこまで行くと逆に面白くなくてどうしたものかな~と悩んでいたくらい

どうしたか

  • 判定
    • 2段階目のEMAを消した
      • これによって素早く動かしたときに即座に判定が出るようになった
      • 多分大体の人が感じていた不満はここ
        • 丁寧に旗を振らせるように誘導するというのも考えたけど、それをあのチュートリアル形式で説明できる気がしなかったのでやめた
        • というかチュートリアル無しでもちゃんと遊べるべきなので、まぁこうするのが筋という感じ
    • 安定状態になったと判断する閾値を0.75から0.95に上げた
      • 2連続で旗を振ったとき (上右とか) に、きっちり途中で止めなくても判定が出るようになった
        • ただちょっと方向は意図してないことがあるかも (先端のEMAがまだ収束してないから)
        • 途中で気持ち止まるようにするくらいにすれば大丈夫
      • シナモンルートがパーフェクトできるようになった
        • パーフェクト自体を取ったことはまだ無いけど最後の6つを全部取れたので大丈夫だと思う
  • チュートリアル
    • タイミングを判定に入れ、余計な入力を無視するように変更
      • 実は前と「理想的な方針 (拍に合わせて入力)」は一切変わってないのだけど、点数の増え方が変わることで意識が多分変わる (ことを期待している)
    • 紆余曲折
      • もっとゲーム的にする (ユーザを積極的にさせる) 案
        • どう判定を入れればいいのか・快適に入力するにはどうすればいいのかを探ってもらう意味合い
        • でも元々旗のチュートリアルは「メガホンのチュートリアルでちょっと盛り上がっちゃう気持ちを落ち着けさせる」意味合いがある (工場への静かな廊下に繋げる為) のであんまりよくない
        • ちなみに今のを倍速にして一回やってみたんだけど全然できなかったのでやめた
      • 手首で振らせることを示唆する案
        • 素早く2連続入力することを要求することで、腕では間に合わないことを悟ってもらう
        • これも結局楽しくなっちゃうので却下
        • 今の「リズムを判定する」方式だと必然的に素早い動きをしたくなるので、まぁ、大丈夫ではないかという気持ちもある
      • 頭や足でリズムを取ることをもうちょっと説明する案
        • 言語無しでやるにはちょっと無理がある
        • 代わりにスクロールする画面の方にはたまに出てくるようにした

これで本当にプレイしやすくなってるかは正直わかんないです。よかったら感想もらえるとわかりやすいです。

まとめ

こういうの難しいよねっていうのは昔からずっと言ってましたので、まぁ難しいなという感じですね。

結局複雑な処理でどうにか判定をするよりは「単純な処理」のほうがユーザもわかりやすいみたいな話が普遍的にありますよね。メタ的に捉えてるわけでは無いと思うんですが、結局そういうものが (人間に取っても) 単純なのかしら。

ただ今回の問題の4割くらいはチュートリアルの設計の失敗だと思っていて、ここは大きな反省点です。まだまだ「無知の人間」になるシミュレーションが足りないですね。

あと修正が遅れたのはいろいろやってて忙しかったからです。はい。

残りそんなに期間もありませんが、ぜひ楽しんでいただけると嬉しいです。

おわり。

*1:exponential moving average, 気持ちは low-pass filter