1.6K Views
October 27, 23
スライド概要
モバイル・コンシューマ「開発比較」勉強会 #1 インターフェイスと手触り【2D格闘ゲームにおけるユーザビリティとゲームデザインについて】の修正版資料です。
https://atnd.org/events/65421
当時の資料をこちらでも公開しました。
内容を追加した定版を準備中
SlideShareにアップロードしたものを共有+新規スライドをこちらも公開。 デジタルゲーム、Unity/UnrealEngine、ゲームデザインを中心のものをアップします。 アニメ・ゲーム・映画大好きオジサンです
2D格闘ゲームにおける ユーザビリティと ゲームデザインについて プログラマー/ディレクター 2015/5/15 朝比奈むかで ※加筆修正2015/5/18
自己紹介 朝比奈むかで(Twitter @asahina_mukade ) ゲーム開発を続けて24年目ほど 現在も現役。プログラマー/ディレクター職 アーケード、コンソール、モバイル等タイトル開発者
!注意点1 今回は2D(対戦型)格闘ゲームが対象 開発関係・リリースしたタイトルでの事例 ゲームデザインは7年程前までの内容 説明の不足、質疑応答の内容は反映しました →もし漏れや質問がありましたらTwitterまでご連絡を!
!注意点2 用語統一をさせて頂きますm(__)m 十字キー、十字ボタン 8方向レバー ABXYボタン パッドボタン 押しボタン レバー ボタン
アジェンダ ユーザビリティとは? “学習のしやすさ”と入力制御 “効率性”とキャラクター制御 “主観的満足度”とコマンド入力 まとめ
ユーザビリティとは?
ユーザビリティとは?(1) “ユーザビリティ”って? ・一般的な定義として、ソフトウェアの使用感を指す ・操作感、手触りの意味に近いと考えてもよい ヤコブ・ニールセン「5つのユーザビリティ特性」 ユーザインターフェースのユーザビリティは、ある一面からだけの特性 ではなく、5つのユーザビリティ特性からなる多角的な構成要素を持っている ・学習のしやすさ ・効率性 ・記憶のしやすさ ・間違えにくさ ・主観的満足度
ユーザビリティとは?(2) 5つの特性の詳細 学習のしやすさ ユーザがそれを使って作業をすぐ始められるよう、 簡単に学習できるようにしなければならない 効率性 一度ユーザがそれについて学習すれば、あとは高い生産性を 上げられるよう、効率的な使用を可能にすべきである 記憶のしやすさ 不定期利用のユーザがしばらく使わなくても再び使うときに 覚えなおさないで使えるよう、覚えやすくしなければならない 間違えにくさ エラー発生率を低くし、ユーザがシステム利用中にエラーを 起こしにくく、致命的なエラーが起こってはいけない 主観的満足度 ユーザが個人的に満足できるよう、また好きになるよう楽しく 利用できるようにしなければならない
ユーザビリティとは?(3) ゲーム開発で重要だと考える項目(主に業務用ゲーム) 出来るだけ直感的に操作できること 学習のしやすさ 操作やデザインを可能な限り一貫性を保つこと 効率性 短時間で面白さが感じられること 主観的満足度 これらを今回2D格闘ゲームの事例で紹介
2D格闘ゲームとは? 2D格闘ゲームとは? アクションゲームの一種でプレイヤーが操作するキャラクターが CPU、別のプレイヤーの操作するキャラクターと1対1で戦うゲーム 敵キャラクターを殴る蹴るするゲーム 操作系 8方向キー(レバー)、4〜6ボタンを使用 レバーでキャラ移動・コマンド入力、ボタンで攻撃 代表タイトル ストリートファイターシリーズ、ギルティギアシリーズ キングオブファイターシリーズ
“学習のしやすさ”と入力装置
“学習のしやすさ”と入力装置(1) ビデオゲームではレバー・ボタンが入力装置 レバーは、方向入力装置 →傾けた方へ移動 →元は航空機の操縦桿 ボタンは、ON/OFFスイッチ →自動復帰型スイッチ →押している間だけON
“学習のしやすさ”と入力装置(2) 2D格闘ゲームの場合、レバーでプレイヤーが動かせる →入力方向と動作が一致している 入力方向 移動方向 前進 後退 (防御) レバーに合わせ動きが遷移 “How to Play”やデモ動きや操作は確認 実際に操作して数分でなんとなく理解可能 しゃがみ ジャンプ 画面での動き
“学習のしやすさ”と入力装置(3) ボタンがON状態になると攻撃 →押され続けるとOFF扱い 入力方向 移動方向 小攻撃 大攻撃 しゃがみ 小攻撃 1ボタン、1攻撃 押せば相手に攻撃をする事を理解 攻撃している最中は他に遷移できない しゃがみ 大攻撃 ジャンプ 攻撃 画面での動き
“学習のしやすさ”と入力装置(まとめ1) “学習のしやすさ” ユーザがそれを使って作業をすぐ始められるよう、 簡単に学習できるようにしなければならない “レバー操作” レバー操作で、画面上のキャラクターが動く “ボタンON” 1ボタン、1攻撃。レバーとの組み合せがある 機能ごとに役割が決まっているので、迷うことが少なく レバー=キャラ、ボタン=攻撃と、触れれば理解ができる また最小限これらだけでユーザーがプレイな点も重要
“学習のしやすさ”と入力装置(まとめ2) 直感的な操作方法は、説明不要でシンプルになる 同じ入力で同じ結果が得られることは非常に重要 →一度覚えれば似たシステムの場合、再学習が不要 短時間で操作方法を理解してもらえるシステムである
“効率性”とキャラクター制御
“効率性”とキャラクター制御(1) 2D格闘ゲームのキャラクター制御で重要なポイント レバー操作・ボタン押下でキャラクターをストレスなく動かせること レバー操作で移動・ジャンプ、ボタンを押せば攻撃 移動やしゃがみ、 ジャンプ、攻撃等々 ストレスなく、って具体的にはどういうこと?
“効率性”とキャラクター制御(2) レバー操作で状態が変化=“State“を理解 レバー方向を動きが変化=“State”を遷移が理解 ボタンを押下=攻撃を実行と操作の中断を理解 待機(Idle) しゃがみ (Crouch) 移動 (Move) デザインとしても把握しやすくわかりやすい →但しそのままだと問題点がある “キャラクターアニメーション”と レバーとの連動性における問題 ジャンプ (Jump) 攻撃 SP攻撃
“効率性”とキャラクター制御(3) 例えばレバーを下方向に入れ続けると“しゃがみ”状態になる場合 ただ遷移している途中、アニメーション遷移による Stateが曖昧な状態が起こる 待機 (Idle) しゃがみ (Crouch)
“効率性”とキャラクター制御(4) 例えばレバー下方向に入力を開始する (即座にStateが遷移する条件の場合) 時間経過 Step1 State 遷移 立ち待機 (Idle) 入力 見た目
“効率性”とキャラクター制御(4) しゃがみに遷移し、中間アニメーションが再生される (即座にStateが遷移する条件の場合) 時間経過 Step1 Step2 State 遷移 立ち待機 (Idle) しゃがみ (Crouch) 入力 見た目 しゃがみへ Stateはしゃがみ遷移 待機→しゃがみの中間 アニメーションになる
“効率性”とキャラクター制御(4) 遷移途中に、レバーをニュートラルにする (即座にStateが遷移する条件の場合) 時間経過 Step1 Step2 State 遷移 立ち待機 (Idle) しゃがみ (Crouch) 入力 見た目 しゃがみへ 待機→しゃがみ遷移 アニメーション途中で レバーを離す
“効率性”とキャラクター制御(4) “しゃがみ“を中断して“待機”に戻る処理が実行される (即座にStateが遷移する条件の場合) 時間経過 Step1 Step2 Step3 State 遷移 立ち待機 (Idle) しゃがみ (Crouch) 立ち待機 (Idle) 入力 Stateは立ち待機へ遷移 しゃがみ→待機の中間 アニメーションになる 見た目 しゃがみへ 立ち待機へ
“効率性”とキャラクター制御(4) “待機”に戻り中でレバー下方向と攻撃ボタン同時押下 (即座にStateが遷移する条件の場合) 時間経過 Step1 Step2 Step3 State 遷移 立ち待機 (Idle) しゃがみ (Crouch) 立ち待機 (Idle) 入力 見た目 しゃがみへ 立ち待機へ レバー下方向と 攻撃ボタンを同時に 入力
“効率性”とキャラクター制御(4) 入力に従って遷移すると“攻撃(しゃがみ)”になる (即座にStateが遷移する条件の場合) 時間経過 Step1 Step2 Step3 Step4 State 遷移 立ち待機 (Idle) しゃがみ (Crouch) 立ち待機 (Idle) 攻撃 (しゃがみ) 入力 見た目 しゃがみへ 立ち待機へ
“効率性”とキャラクター制御(4) えっ?お前さっき 立とうしてたじゃん! 入力に従って遷移すると“攻撃(しゃがみ)”になる おかしくない? (即座にStateが遷移する条件の場合) 時間経過 Step1 Step2 Step3 Step4 State 遷移 立ち待機 (Idle) しゃがみ (Crouch) 立ち待機 (Idle) 攻撃 (しゃがみ) 入力 見た目 しゃがみへ 立ち待機へ
“効率性”とキャラクター制御(5) 先程の問題は入力するタイミングにも依存するので 曖昧さが解決できない ・ユーザーがレバー下方向とボタンが同時入力される保証がない ・入力が断続的に行われ、一貫性がなく、挙動がおかしく見える 遷移が安定せずユーザーが混乱しストレスを感じる 毎回同じ(に近い)入力で、同じ結果なる必要がある為 State間遷移の対応が必要
“効率性”とキャラクター制御(6) State間の対応は、もうひとつStateを追加し、 どこに遷移するかを明示化する(1次、2次State) →原始的な方法だが、管理情報が増えてしまうが追加コストは安い 概念的には1次Stateは2次Stateを経由して 遷移することで、入力の変化にも対応可能になる 待機(Idle)-1次Sate 待機(Idle)-2次Sate 待機(Idle) Toしゃがみ (Crouch) しゃがみ (Crouch) 待機(Idle) ※ゲームデザイン次第でこの限りではない。アニメーションを2次Stateに合わせて分離したタイトル有
“効率性”とキャラクター制御(7) State遷移の概念図はこのような形になる 1次State ジャンプ (Jump) 攻撃 SP攻撃 2次State To 待機 (Idle) Toしゃがみ (Crouch) To 移動 (Move) To 攻撃 (Attack) 待機(Idle) しゃがみ (Crouch) 移動 (Move)
“効率性”とキャラクター制御(8) 先程の内容を再現し、レバー下方向に入力を開始する 時間経過 Step1 1次State 立ち待機 (Idle) 2次State None 入力 見た目
“効率性”とキャラクター制御(8) “しゃがみ”に遷移せず、”To Crouch”へ遷移 時間経過 Step1 Step2 1次State 立ち待機 (Idle) 立ち待機 (Idle) 2次State None To Crouch 入力 見た目 しゃがみへ
“効率性”とキャラクター制御(8) 遷移途中に、レバーをニュートラルにする 時間経過 Step1 Step2 1次State 立ち待機 (Idle) 立ち待機 (Idle) 2次State None To Crouch 入力 見た目 しゃがみへ
“効率性”とキャラクター制御(8) 2次Stateの遷移から、“しゃがみ“の”To Idle”へ 時間経過 Step1 Step2 Step3 1次State 立ち待機 (Idle) 立ち待機 (Idle) しゃがみ (Crouch) 2次State None To Crouch To Idle 入力 ここで1次Stateが 変化している! 見た目 しゃがみへ 立ち待機へ
“効率性”とキャラクター制御(8) “待機”に戻り中でレバー下方向と攻撃ボタン同時押下 時間経過 Step1 Step2 Step3 1次State 立ち待機 (Idle) 立ち待機 (Idle) しゃがみ (Crouch) 2次State None To Crouch To Idle 入力 レバー下方向と 攻撃ボタンを同時に 入力 見た目 しゃがみへ 立ち待機へ
“効率性”とキャラクター制御(8) 2次State遷移は一度“しゃがみ”を経由し… 時間経過 Step1 Step2 Step3 Step4 1次State 立ち待機 (Idle) 立ち待機 (Idle) しゃがみ (Crouch) しゃがみ (Crouch) 2次State None To Crouch To Idle To Attack 立ち待機へ しゃがみへ 入力 見た目 しゃがみへ
“効率性”とキャラクター制御(8) 入力に従って“しゃがみ攻撃”になる 時間経過 Step1 Step2 Step3 Step4 Step5 1次State 立ち待機 (Idle) 立ち待機 (Idle) しゃがみ (Crouch) しゃがみ (Crouch) 攻撃 (しゃがみ) 2次State None To Crouch To Idle To Attack From Crouch 立ち待機へ しゃがみへ 入力 見た目 しゃがみへ
“効率性”とキャラクター制御(8) 入力に従って“しゃがみ攻撃”になる しゃがみを経由して から下段攻撃だね! 時間経過 Step1 Step2 Step3 Step4 Step5 1次State 立ち待機 (Idle) 立ち待機 (Idle) しゃがみ (Crouch) しゃがみ (Crouch) 攻撃 (しゃがみ) 2次State None To Crouch To Idle To Attack From Crouch 立ち待機へ しゃがみへ 入力 見た目 しゃがみへ
“効率性”とキャラクター制御(8) 入力に従って“しゃがみ攻撃”になる 時間経過 Step1 Step2 Step3 Step4 Step5 1次State 立ち待機 (Idle) 立ち待機 (Idle) しゃがみ (Crouch) しゃがみ (Crouch) 攻撃 (しゃがみ) 2次State None To Crouch To Idle To Attack From Crouch 立ち待機へ しゃがみへ 入力 先程と違って、入力と 動作イメージが一致! 見た目 しゃがみへ
“効率性”とキャラクター制御(まとめ1) “効率性” 一度ユーザがそれについて学習すれば、高い生産性を上 げられるよう、効率的な使用を可能にすべきである State遷移の整理 想定される様々な入力を2つのStateで生理 動作の一貫性 多少曖昧な入力であっても同じ挙動になる 色々なアクションをするゲームなので回数を繰り 返せば、安定した動きになるようにシステムを提供 感覚的になるとわかれば、自然と操作がそれに近づく
“効率性”とキャラクター制御(まとめ2) ゲーム開発のキャラクター制御は例外処理に傾きがち →挙動がおかしくなりやすく、エンバグも多くなる State遷移2つ分けて遷移の流れを整理 →入力タイミングによる、違いが少なくなるようにロジックを定義 →また2次Stateからの遷移をスクリプトでも対応可能 ユーザーが同じ(に近い)入力で同じ結果になる →タイミングを覚えれば同じ行為を再現できる →入力と動作に一貫性をもってシステムにすることでストレスを軽減
“主観的満足度”とコマンド入力
“主観的満足度”とコマンド入力(1) コマンド入力とは? 特定の順序でレバーを入力しボタンを押下すると、“必殺技”と呼ばれる 強力な技を発動することができる。 指定された入力を行うことから“コマンド入力”と呼ばれる コマンド入力は発動技ごとに難易度を変えることができ、 入力が成功し技を出せれば、ゲームを有利に進められる
“主観的満足度”とコマンド入力(2) コマンド入力は最重要・要素 2D格闘ゲームにおいてコマンド入力=強力な技とされる 正確な“コマンド入力”を行えば、必ず技を発動させる ユーザーの見せ場・プレイ能力の高さを証明 ユーザーに納得してもらう“コマンド入力”のデザイン →コマンド入力は仕様のまま実装しても上手くいかない事が多い ユーザーがコマンド入力を成立できる為に 上手に補助・補完するシステムが必要
(補足)レバー・ボタンの入力情報について レバー(8方向)・ボタンはビット情報 キー ↑ ↓ → ← A B X Y On◯ Off✕ ◯ ✕ ◯ ✕ ◯ ✕ ✕ ✕ 入力値: 0xA8 入力値にはいくつか種類があり、用途によって使い分けられている →ボタンは通常“Trigger”を参照、キャラの移動は“Direct”等 入力値の種類 種類ごとの情報内容 Direct 現在のレバー・ボタンの入力値 Old 1フレーム前のレバー・ボタン入力値 Trigger レバー、ボタン別々に変化した入力があった場合の値 Repeat 同じ入力値を一定時間継続した場合に、反映される入力値
“主観的満足度”とコマンド入力(3) コマンド入力を判定する方式 複数の方式があり、今回はコマンドシーケンス検索方式を紹介 名称 処理内容 “コマンド入力”ごとに検索する入力を配列化 レバー・ボタンの入力を順番通り比較検索する コマンド シーケンス 検索方式 検索順番 一連のコマンド列 ① ② ③ ④ 検索キー
“主観的満足度”とコマンド入力(4) 検索テーブルの情報設定について コマンド列/検索キーごとに様々な設定があります ・コマンド列ごとの設定 コマンド列 受付時間 コマンド全体の入力受付時間(コマンド1つとは別) これも時間オーバーするとコマンド全体が失敗 リフレッシュ時間 コマンド列入力成功後に無効になるまでの時間 コマンド列の優先順位 他のコマンド列と同時成立した場合の優先順位付け数値 検索キーテーブル “検索キー”の全配列 ・検索キーごとの設定 判定するコマンド チェックする入力値 コマンドマスク レバー情報をマスクする入力値(不要な入力を許す/許さない) 入力値の参照タイプ 入力値を指定(Directのみ、Triggerのみ、Trigger + Old等) コマンド受付時間 1コマンドを受付時間、オーバーするとコマンド全体失敗に
“主観的満足度”とコマンド入力(5) コマンド列情報のサンプル(配列はコマンド技の数だけ定義) ID コマンド1 (波動拳) コマンド2 (旋風脚) 受付時間 0.4ms 0.4ms リセット 時間 0.3ms 0.3ms 検索キーテーブル 優先順位 3 4 検索キー コマンドマスク 入力値の参照タイプ コマンド受付時間 ↓ 0x20 Trigger 0.13ms ↘ 0x60 Trigger + Old 0.13ms → 0xF0 Trigger 0.13ms Aボタン 0x0F Trigger 0.5ms 検索キー コマンドマスク 入力値の参照タイプ コマンド受付時間 ↓ 0x20 Trigger 0.13ms ↙ 0x60 Trigger + Old 0.13ms ← 0xF0 Trigger 0.13ms Xボタン 0x0F Trigger 0.5ms
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 入力(Trigger) 0x00:- 入力(Old Trigger) 0x00:- チェック対象 コマンド1 参照キー Trigger 1:↓ コマンド1 入力受付時間 0.3ms マッチング ✕ 入力経過時間 0.0ms (8/60フレーム)
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 Step2 入力(Trigger) 0x00:- 0x40:↓ 入力(Old Trigger) 0x00:- 0x00:- Trigger Trigger 1:↓ 1:↓ チェック対象 コマンド1 参照キー コマンド1 入力受付時間 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) マッチング ✕ ◯ 入力経過時間 0.0ms 約0.06ms 入力値とチェック する参照キーが一致。 次回から2番目の 参照キーをチェック
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 Step2 Step3 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x00:- 0x40:↓ Trigger Trigger +Old 1:↓ 2:↘ 入力(Old 0x00:どのハードでも Trigger) 斜め入力は反応 Trigger が悪い為、対応 コマンド1 1:↓ が必要とされる 参照キー チェック対象 コマンド1 入力受付時間 0.3ms 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) (8/60フレーム) マッチング ✕ ◯ ◯ 入力経過時間 0.0ms 約0.06ms 約0.10ms 1つ前のTrigger値は Old Trigger値として保存 2番目の参照キーは↘だが OldとTriggerを論理和した 数値がチェックする 参照キーとなるので成立
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x60:↘ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ Trigger Trigger Trigger +Old Trigger 1:↓ 1:↓ 2:↘ 3:→ チェック対象 コマンド1 参照キー コマンド1 入力受付時間 マッチング 入力経過時間 Trigger値が、意図しない値 0.3ms になることもある。 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) (8/60フレーム) またこの場合、Trigger値と ✕ ◯ ◯ 参照キーの比較のために 不成立となっている。 0.0ms 約0.06ms 約0.10ms 0.3ms (8/60フレーム) ✕ 約0.13ms
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x60:↘ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ 0x60:↘ Trigger Trigger Trigger +Old Trigger Trigger 1:↓ 1:↓ 2:↘ 3:→ 3:→ チェック対象 コマンド1 参照キー コマンド1 入力受付時間 マッチング 入力経過時間 Trigger値が変わって、 0.3ms 参照キーと同じ値になり 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) (8/60フレーム) 次の参照キーに移動。 Step5 0x20:→ 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) ✕ ◯ ◯ ✕ ◯ 0.0ms 約0.06ms 約0.10ms 約0.13ms 約0.15ms
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x60:↘ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ 0x60:↘ 0x20:→ Trigger Trigger Trigger +Old Trigger Trigger Trigger 3:→ 4:Aボタン チェック対象 コマンド1 参照キー 1:↓ 1:↓ Trigger値が変わって、 2:↘ 3:→ 参照キーと同じ値になり 0.3ms 0.3ms 次の参照キーに移動。 (8/60フレーム) (8/60フレーム) (8/60フレーム) コマンド1 入力受付時間 0.3ms マッチング ✕ ◯ ◯ 入力経過時間 0.0ms 約0.06ms 約0.10ms (8/60フレーム) 0.3ms Step5 0x20:→ Step6 0x28:→A 0.3ms 0.5ms (8/60フレーム) (8/60フレーム) ✕ ◯ ◯ 約0.13ms 約0.15ms 約0.19ms
“主観的満足度”とコマンド入力(6) コマンドシーケンス検索方式のロジック(成立例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x60:↘ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ 0x60:↘ 0x20:→ Trigger Trigger Trigger +Old Trigger Trigger Trigger 1:↓ 1:↓ 2:↘ 3:→ 3:→ 4:Aボタン チェック対象 コマンド1 参照キー Step5 0x20:→ Step6 0x28:→A コマンド1 入力受付時間 0.3ms 0.3ms 0.3ms 0.3ms 0.3ms 0.5ms (8/60フレーム) (8/60フレーム) (8/60フレーム) (8/60フレーム) (8/60フレーム) (8/60フレーム) マッチング ✕ ◯ ◯ ✕ ◯ ◯ 入力経過時間 0.0ms 約0.06ms 約0.10ms 約0.13ms 約0.15ms 約0.19ms
“主観的満足度”とコマンド入力(7) コマンドシーケンス検索方式のロジック(失敗例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x20:→ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ 0x20:→ 0x20:→ Trigger Trigger Trigger +Old Trigger Trigger Trigger 1:↓ 1:↓ 2:↘ 3:→ 3:→ 1:↓ チェック対象 コマンド1 参照キー Step5 Step6 0x40:↓ 0x60:↘ コマンド1 入力受付時間 0.3ms 0.3ms 0.3ms 0.3ms 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) (8/60フレーム) (8/60フレーム) (8/60フレーム) (8/60フレーム) マッチング ✕ ◯ ◯ ✕ ✕ ✕ 入力経過時間 0.0ms 約0.16ms 約0.3ms 約0.32ms 約0.48ms 0.0ms
“主観的満足度”とコマンド入力(7) コマンドシーケンス検索方式のロジック(失敗例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x20:→ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ 0x20:→ 0x20:→ Trigger Trigger Trigger +Old Trigger Trigger Trigger 3:→ 3:→ 1:↓ チェック対象 コマンド1 参照キー コマンド1 入力受付時間 マッチング 入力経過時間 Step4までに 1:↓ 1:↓ 2:↘ 入力時間がかかっている。 0.3ms 思ったように入力が 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) (8/60フレーム) 上手くいっていない。 Step5 Step6 0x40:↓ 0x60:↘ 0.3ms 0.3ms 0.3ms (8/60フレーム) (8/60フレーム) (8/60フレーム) ✕ ◯ ◯ ✕ ✕ ✕ 0.0ms 約0.16ms 約0.3ms 約0.32ms 約0.48ms 0.0ms
“主観的満足度”とコマンド入力(7) コマンドシーケンス検索方式のロジック(失敗例) 時間経過 Step1 Step2 Step3 Step4 入力(Trigger) 0x00:- 0x40:↓ 0x20:→ 0x20:→ 入力(Old Trigger) 0x00:- 0x00:- 0x40:↓ 0x20:→ 0x20:→ 0x20:→ Trigger Trigger Trigger +Old Trigger Trigger Trigger チェック対象 コマンド1 参照キー 1:↓ コマンド1 入力受付時間 0.3ms マッチング ✕ 入力経過時間 0.0ms (8/60フレーム) Step5 Step6 0x40:↓ 0x60:↘ コマンド列 受付時間を 1:↓ オーバーしてしまった為、 2:↘ 3:→ 3:→ キー検索がリセットして 0.3ms 0.3ms 0.3ms 0.3ms (8/60フレーム)しまう。 (8/60フレーム) (8/60フレーム) (8/60フレーム) 1:↓ 0.3ms (8/60フレーム) ◯ ◯ ✕ ✕ ✕ 約0.16ms 約0.3ms 約0.32ms 約0.48ms 0.0ms
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー システムからのレバー・ボタンを受け取る システムから入力値を受け取る。 ※プラットホームにもよるが、 “Direct”、”Trigger”、”Repeat”は 取得できるが“Old Trigger”等は自前 で実装する。
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー システムからのレバー・ボタンを受け取る 検索テーブル上のコマンドすべてチェック コマンドシーケンス検索方式のロジックを 操作キャラクターすべてで行う
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー システムからのレバー・ボタンを受け取る 成立したコマンドは実行されるまで 検索テーブル上のコマンドすべてチェック リスト化して保存しておく コマンド列毎の入力の成否・リセット
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー システムからのレバー・ボタンを受け取る 検索テーブル上のコマンドすべてチェック コマンド列毎の入力の成否・リセット
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー システムからのレバー・ボタンを受け取る コマンド入力の チェックは管理のみ 検索テーブル上のコマンドすべてチェック コマンド列毎の入力の成否・リセット
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー レバー・ボタンからの入力を検索テーブルとは別に情報を保持 成立したコマンドは、リセットタイムが0になると“不成立”となる コマンドの優先順 位 コマンド名 成立・不成立 リセットタイム 優先1 コマンド1 ✕ 0.0ms 優先2 コマンド2 ◯ 0.4ms 優先3 コマンド3 ◯ 0.4ms
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー レバー・ボタンからの入力を検索テーブルとは別に情報を保持 成立したコマンドは、リセットタイムが0になると“不成立”となる コマンドの優先順 位 コマンド名 優先1 コマンド1 成立・不成立 リセットタイム 優先2 ✕ 0.0ms コマンド列の内容は 最後のコマンドが重複しがちで コマンド2 定義順に成立することが多い ◯ 0.4ms 優先3 コマンド3 ユーザーの努力が無駄にならない ◯ 0.4ms ようにより複雑なコマンド列を 優先して成立・発動させる
“主観的満足度”とコマンド入力(8) コマンド入力のチェックのフロー レバー・ボタンからの入力を検索テーブルとは別に情報を保持 成立したコマンドは、リセットタイムが0になると“不成立”となる コマンドの優先順 位 コマンド名 コマンド列全体の入力受付時間は 優先1 コマンド1 最終的にコマンド列が成立後も 有効になっている 優先2 コマンド2 成立後も時間経過・あるいは 優先3 コマンド3 他のコマンド入力と共に リセットされる 成立・不成立 リセットタイム ✕ 0.0ms ◯ 0.4ms ◯ 0.4ms
“主観的満足度”とコマンド入力(9) 成立したコマンド入力と、キャラクター制御 成立したコマンドがある場合、キャラクターの1次Stateをチェック 成立したコマンド入力 優先1 コマンド1 優先2 コマンド2
“主観的満足度”とコマンド入力(9) 成立したコマンド入力と、キャラクター制御 成立したコマンドがある場合、キャラクターの1次Stateをチェック 成立したコマンド入力 優先1 コマンド1 優先2 コマンド2 コマンド入力の必殺技 が発動できるか確認 1次State 待機(Idle) 移動 (Move) しゃがみ (Crouch) ジャンプ (Jump) 攻撃 (Attack)
“主観的満足度”とコマンド入力(9) 成立したコマンド入力と、キャラクター制御 キャラクターの1次Stateを必殺技に変更する 成立したコマンド入力 優先1 優先2 1次State 待機(Idle) コマンド1 発動できる状態であれば コマンド2 Stateを必殺技に遷移 しゃがみ 1次State 必殺技 (Special Attack) (Crouch) 移動 (Move) ジャンプ (Jump) 攻撃 (Attack)
“主観的満足度”とコマンド入力(9) 成立したコマンド入力と、キャラクター制御 State遷移できないと判定した場合は、次の入力タイミングを待つ 成立したコマンド入力 優先1 コマンド1 優先2 コマンド2 次の入力タイミングまで コマンド情報を保持 1次State 待機(Idle) 移動 (Move) しゃがみ (Crouch) ジャンプ (Jump) 攻撃 (Attack)
“主観的満足度”とコマンド入力(まとめ1) “主観的満足度” ユーザが個人的に満足できるよう、また好きになるよう 楽しく利用できるようにしなければならない コマンド入力補助 物理入力が難しいものは補助 優先順位とタイミング ユーザーがイメージしたコマンド入力を システム側でサポートし、強い技を入力した 結果が反映されるような仕組みを提供 ユーザーが上手く出来た!と思ってもらう為、 システムでサポートすることで、満足度を向上させる
“主観的満足度”とコマンド入力(まとめ2) コマンド入力が出来ることを良い体験であるように →ユーザーがより楽しくなる遊びのスパイス ユーザーが入力した入力を技術的でサポートする →ユーザーが入力した情報を曖昧さを含めて加工して利用する →システムによって、練度が上がるように技術でサポート ユーザー利益となるゲームデザインを考える →コマンド入力の練度や努力が無駄にならないようにする →ユーザーがイメージする結果に近づけていく
まとめ ユーザビリティは、昔からゲーム開発をする過程で重 視されるべき要素のひとつであり、現在もそうである 今回2D格闘ゲームでの事例を紹介しましたが、 入力に関するプロセスは、ストレス軽減だけじゃなく ユーザーの満足度に大きく影響します プレイするユーザーが遊びをより楽しむ仕組みを 紹介しましたが、今度皆さんがゲーム開発する際の ヒントになれば幸いです
ご清聴ありがとうございました 質問等はTwitter(リプライ・DM)でご連絡ください