DEMO
※1
Build.hoge.unitywebのdataなどが重いので、
Wi-Fi接続またはLAN接続のPCで確認ください。
※2
判定部分とは実質無関係ですが、
OnGUI()を画面表示に使用しており、かつ、
OnGUI()の関連処理で文字列処理を多用しています。
そのため上記処理が起因のGCのスパイクが発生します。
※3
時間精度の引き下げが行なわれる事があるようなので、
処理時間がミリ秒の精度に丸められることがあります。
同処理が施されたブラウザでは処理時間が正確に計測出来ません。
Firefoxであれば、
Firefoxの設定エディターにて、自己責任の上、
privacy.reduceTimerPrecisionをfalseにすれば、
処理時間の丸めなしにはできないようですが、
処理時間の丸めの精度は変更できるようです。
はじめに
Unityの存在を先日知り、
Unity及びC#のお勉強も兼ねて、
波動拳の入力受付をしてみよう、
という思いに何故か至りました。
Unity及びC#を今回初めて触る、
オブジェクト指向恐怖症のIT業界外の人間で、
html,css,JavaScriptやPythonを、
休日等に少々触る程度の素人ですので、
本内容に間違いや勘違いが見受けられるかもしれません。
カプコン社のストリートファイター等の技名を使用していますが、
あのコマンドね、と認識が伝わりやすいだろう、という意図です。
解説前書
冒頭のDEMOから以下処理を削除した波動拳(強)のみの入力判定で、
冒頭のDEMOから以下処理を削除した入力判定の中核部分のコードになります。
・波動拳(強)以外の技の削除
・溜め時間取得用処理の削除
・同時押し判定緩和用処理の削除
・本解説に不要なinput処理の削除
・本解説に不要な処理時間低減施策削除
・Inspectorへのデバッグ表示用処理削除
・GameViewへのデバッグ表示関連処理削除
※Consoleに入力判定の成否を出力
一口解説
詳細はコードを見て貰うものとして、
全体のざっくりした流れは以下です。
・各種enum設定
・技のコマンドのクラスとそのList …①
・十字キーとパンチキックの状態取得用のクラス
・キー履歴保持のクラスとそのList
・void Start()
・技のコマンドのListの反転 …②
・キー履歴保持のためのインスタンス生成
・フレームレートの設定
・void Update()
・今フレームのキーの状態をキー履歴保持のListに追記
(ある程度の量になったら古い履歴情報から順次削除)
・foreach
・foreach
・技のコマンドのひとつひとつを順次判定処理 …③
(波動拳は下⇒右下⇒右⇒Pなので4回判定)
(foreach1回目はP の判定)
(foreach2回目は右 の判定)
(foreach3回目は右下の判定)
(foreach4回目は下 の判定)
①技のコマンドのList
private List<List<MoveCommand>> MoveCommandList = new List<List<MoveCommand>>()
{
new List<MoveCommand>()
{
// 波動拳 状態は押している キーは左 次の入力は 6フレーム以内 次の入力同時押し不可NextFrame判定
new MoveCommand { DoFinger = Finger.Hold, InputKey = Key.J2, NextTime = 6, SlipTime = 1 },
// 波動拳 状態は押している キーは左下 次の入力は 6フレーム以内 次の入力同時押し不可NextFrame判定
new MoveCommand { DoFinger = Finger.Hold, InputKey = Key.J3, NextTime = 6, SlipTime = 1 },
// 波動拳 状態は押している キーは右 次の入力は 7フレーム以内 次の入力同時押し可能ThisFrame判定
new MoveCommand { DoFinger = Finger.Hold, InputKey = Key.J6, NextTime = 7, SlipTime = 0 },
// 波動拳 状態は押した キーはP 最後なので 0に必ずする 最後なので 0に必ずする
new MoveCommand { DoFinger = Finger.Pressed, InputKey = Key.HP, NextTime = 0, SlipTime = 0 },
},
};
以下の条件をListに設定。
1つ目の入力:
キーの下 を押している、
次の入力は6フレーム以内、
次の入力の判定とは同一フレーム不可。
2つ目の入力:
キーの右下を押している、
次の入力は6フレーム以内、
次の入力の判定とは同一フレーム不可。
3つ目の入力:
キーの右 を押している、
次の入力は7フレーム以内、
次の入力の判定とは同一フレーム可能(右とPの同時押しOK)
4つ目の入力:
キーのP を押した。
②技のコマンドのListの反転
foreach (List<MoveCommand> MoveCommandData in MoveCommandList) MoveCommandData.Reverse();
波動拳は下⇒右下⇒右⇒Pだが、
処理順はP⇒右⇒右下⇒下の順序で判定を行なうため反転。
③技のコマンドのひとつひとつを順次判定処理
foreach (List<MoveCommand> MoveCommandData in MoveCommandList)
{
// 中略
foreach (MoveCommand record in MoveCommandData)
{
// 中略
InputGetKeyTinyHistoryDataRow = record.DoFinger switch
{
Finger.Hold => InputGetKeyTinyHistoryList.FindLast(row => ((StaticFrameCount - StaticNextTime) <= row.FrameCount) && (row.FrameCount <= (StaticFrameCount - StaticSlipTime)) && ((row.Hold & StaticInputKey) == StaticInputKey)),
Finger.Pressed => InputGetKeyTinyHistoryList.FindLast(row => ((StaticFrameCount - StaticNextTime) <= row.FrameCount) && (row.FrameCount <= (StaticFrameCount - StaticSlipTime)) && ((row.Pressed & StaticInputKey) == StaticInputKey)),
_ => null
};
// 中略
}
// 中略
}
キー履歴保持のList内に条件に合うキーが存在するかを判定。
以下の全ての条件判定が成立していれば波動拳入力受付承認。
波動拳のみなので、
外側のforeachは1回のみ。
内側のforeachの1回目:
現在のフレームに、
Pを"押した"、
という条件に合うキーが存在するか判定。
内側のforeachの2回目:
(P の成立フレーム-7)から
(P の成立フレーム-0)の間で、
右 を"押している"、
という条件に合うキーが存在するか判定。
内側のforeachの3回目:
(右 の成立フレーム-6)から
(右 の成立フレーム-1)の間で、
右下を"押している"、
という条件に合うキーが存在するか判定。
内側のforeachの4回目:
(右下の成立フレーム-6)から
(右下の成立フレーム-1)の間で、
下 を"押している"、
という条件に合うキーが存在するか判定。
備考情報
Debug.Logに関する備忘録。
Debug.Logは結構重いようで、
環境によって違うかもしれませんが、
1回で0.1msとか持っていかれるので、
処理時間計測時は使用しない方がよいです。
WebGLのBuildに関する備忘録。
WebGLのBuildすると日本語が表示されません。
等幅フォントを使用したいので、
NotoSansMonoCJKjp-Bold.otfを、
Assets/Resourcesに配置して表示しています。
動作方法
Unityを触られている人なら不要とは思いますが、念の為。
Unity Hub での工程
Unity Hub でプロジェクトを新規作成。2D(または3D)で作成。
※1 Unityのバージョンは[Unity 2020.3.33f1]や[Unity 2021.3.0f1]以降であれば大丈夫かと...
※2 プロジェクト名と保存先はお任せします。
↓
{ Unity 起動 }
↓
Unityでの工程
GameObject⇒Create Empty
InspectorウインドウでAdd Component⇒New script⇒Nameをscriptにして⇒Create and Add
ProjectウインドウのAssetsに追加されたscriptをダブルクリック。
↓
{ Visual Studio Community 起動 }
↓
Visual Studio Community での工程
冒頭のリンク先のコード、または、
中段のリンク先のコード、どちらかをコピペ。
エンコードをUnicode(UTF-8シグネチャ付き)の形式に変更してscript.csを上書き保存。
Visual Studio Community を終了。
↓
{ Unity をアクティブウインドウにする }
↓
Unityでの工程
File⇒Save
File⇒Exit
↓
{ Unity Hub をアクティブウインドウにする }
↓
Unity Hub での工程
上記で作成したプロジェクトをクリックしてUnityを再度起動。
↓
{ Unity 起動 }
↓
Unityでの工程
( HierarchyウインドウのGameObjectをクリック )
( Consoleウインドウをクリックした後 )
Edit⇒Play
再度起動理由
Unityを再起動しないと、
当方の環境での話なのかもしれませんが、
Input Manager で同時押しのキー取得できない、とか、
Input Manager の動作が何故かもっさりしたり、とか、
Input Manager が正常に動作をしてくれません。
References
Unity 初心者入門講座
Unity
Unity Profiler
Unity Font
Noto CJK fonts
C#
Local Web Server