「ガードステート 補足説明」の編集履歴(バックアップ)一覧はこちら
「ガードステート 補足説明」(2009/12/21 (月) 16:27:44) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
・ガードステートについて 最終更新 2008 2/17
&italic(){&u(){EnemyNear,HitDefAttr中心のステート}}
㍻㌢氏や⑨氏のAI講座においてガードステートのトリガーにP2StateTypeがよく使われています。
このままでも良いのですが、これだけだと立ち下段などの一部攻撃に対応できません。
そこでP2StateTypeだけではなくHitDefAttrも用います。
勿論自分のではなく相手のを参照するのでEnemy,もしくはEnemyNear,をつけて下さい。
ここではEnemyNearを用います。
なぜP2StateTypeだけではなくHitDefAttrも用いるかというと、
相手の攻撃の中にはStateTypeとAttr、そしてGuardFlagが一致していない場合があるからです。
簡易的に表してみると
StateType = S
HitDefAttr = S,AA(NAやSAの可能性もあるが立ち打撃という意味でAAで統一)
GuardFlag = MA(あるいはA)
これは立ち打撃で立ち、屈み、空中を問わずにガードできるというものです。
いわゆる上段というものです。(多分)
StateType = S
HitDefAttr = S,AA
GuardFlag = HA(あるいはH)
これは立ち打撃で立ち、空中状態のみガードできるというものです。
つまり屈み状態ではガード不可、中段という意味です。
これらの場合はP2StateType=SでもHitDefAttr=S,AAでも結果は変わりません。
ですが中にはこういったものもあります。
StateType = S
HitDefAttr = S,AA
GuardFlag = L
これが所謂「立ち下段」と呼ばれる形です。
StateType=S、つまりキャラが立ち状態で
HitDefAttr=S,AA、つまり立ち打撃であることが分かります。
この場合立ちガードの記述にP2StateType=Sを使っているとほぼ確実に立ってしまいます。
しかしGuardFlagがL、つまり屈みガードのみ可なので攻撃を喰らってしまいます。
またStateType=A(空中状態)なのにGuardFlagがLという場合も有ります。
そのためP2StateTypeではなくHitDefAttrを用います。
HitDefAttrは相手のHitDefに影響されます。
つまりHitDefAttrを用いると相手がSCAのどの状態であろうとどのような攻撃かを正確に読み取ってくれます。
それにHitDefはStateTypeとは別に設定できますからね。
とりあえず基本形を書いてみると
[屈み移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A(念の為)
Trigger1 = EnemyNear,HitDefAttr = C,AA || EnemyNear,HitDefAttr = SCA,AP
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time < *
[立ち移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A(念の為)
Trigger1 = EnemyNear,HitDefAttr = A,AA
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time >= *
となります。
ただしEnemyNear,HitDefAttr = SCA,APは保険用ですので注意して下さい。
EnemyNear,HitDefAttrではProjectileどころかHelperすら読み込んでくれません。
そこで飛び道具に対してはEnemy,NumProj > 0を使用することを薦めます。
まず屈み移行のTrigger1は&u(){「屈み打撃に対して屈む」}というものです。
つぎに立ち移行のTrigger1ですがこれは&u(){「空中打撃に対して立つ」}という意味です。
そして掲示板の方にも質問がありましたが、Trigger2のEnemyNear,Timeについて。
屈み移行も立ち移行もTrigger2に立ち打撃が条件となっていますが、EnemyNear,Timeの部分が違います。
これは&u(){「相手の立ち打撃が*フレーム未満の場合は屈み、*フレーム以上だと立つ」}という仕組みです。
通常中段は他の攻撃に比べて発生が遅くなっています。
そこでEnemyNear,Timeを用いて擬似的に中段かどうかを判断させています。
補足ですが*には任意の数字を入れて下さい。
目安とはして16~18ぐらいを入れるとベストかもしれません。
これで立ち下段に対するガードがほぼ完璧ですが、注意点があります。
AIにガードさせる記述、つまりChangeStateです。
この時にステート130や131などに直接飛ばすとガード不可能な攻撃もガードしようとするようです。
それを防ぐためにステート120や121に飛ばすことをおすすめします。
更に精密なAIを作ろうと思うのならばさらにトリガーを増やして条件を厳しくすることを薦めます。
例えば変数(Var)を用いて、相手の数フレーム前のStateTypeを判断したり、擬似的な学習システムを作成しそれによって確率を変化させたりなど。
簡単な例としてはTrigger2は中段対策なのですが、これを数種類に分けて判断させることもできます。
例えばEnemyNear,StateType!=Sを付け加えることによって「立ち状態以外での立ち打撃」という珍しい攻撃を判断することもできます。
この場合は相手が屈んでいるか空中にいるかなのですが、屈み状態ならば中段であることは滅多にありませんし、
空中状態での立ち打撃なんてものも滅多に有りません。
しかし念には念をということで一応それに対するためのトリガーも追加します。
それは&u(){EnemyNear,Vel Y < 0} と &u(){EnemyNear,Vel Y >= 0}です。
これらは&u(){「相手が降下攻撃してきているかどうか」}を判断します。
気晴らしに遊んでいた時に空刃脚を思い出しまして。
しかしこれでもまだメタじみている気がします。
もう少し記述を少なく出来ればそうは感じ無いのですが・・・。
例)
[屈み移行ステート]
Trigger1 = EnemyNear,HitDefAttr = C,AA || EnemyNear,HitDefAttr = SCA,AP
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time < *
Trigger2 = EnemyNear,Vel Y <= 0
Trigger3 = EnemyNear,StateType != S
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time >= *
Trigger3 = EnemyNear,Vel Y <= 0
[立ち移行ステート]
Trigger1 = EnemyNear,HitDefAttr = A,AA
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time >= *
Trigger2 = EnemyNear,StateType = S
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time < *
Trigger3 = EnemyNear,Vel Y > 0
Trigger4 = EnemyNear,StateType != S
Trigger4 = EnemyNear,HitDefAttr = S,AA
Trigger4 = EnemyNear,Time >= *
Trigger4 = EnemyNear,Vel Y > 0
屈み移行のTrigger2は立ち下段対策ですが、一応Velが入っています。
これの詳細は後述を参照してください。
立ち移行のTrigger2は中段対策です。
これは&u(){「相手の立ち打撃が*フレーム以上で立ち状態である」}ということで中段と判断させております。
次に屈み移行のTrigger3は&u(){「相手の立ち打撃が*フレーム以上で立ち状態じゃなく下降していない」}というものです。
これは後述するP2StateType中心のトリガーにおけるVel Y = 0に対する屈みと同じようなものです。
もし相手が屈み状態ならばVel Y = 0に当てはまって屈んでくれます。
相手が空中状態であっても下降攻撃以外は屈んで避けてしまえというものです。
といっても対応できる攻撃には限界がありますが・・・。
まさか昇竜に中段があるとは思えませんけどね。
そして立ち移行のTrigger3,4。
この2つは屈み移行のTrigger2,3に対応させています。
まずTrigger3の意味は&u(){「相手の立ち打撃が一定フレーム未満or下降中」}です。
下降中という場合ほとんどが空中状態になっているはずです。
空中状態で攻撃した場合は普通空中属性が付いた攻撃になります。
その場合は立ち移行ステートのTrigger1が反応して立ちます。
もし相手の攻撃が立ち属性の場合はまず屈み移行のTrigger2か3が反応します。
しかしそれは&u(){「相手が下降していない状態」}が条件となりますのでそれに対して&u(){「相手が下降している状態」}という条件のトリガーが立ち移行に必要です。
そのため屈み移行のTrigger2に対して立ち移行のTrigger3が、屈み移行のTrigger3に対して立ち移行のTrigger4があります。
以前は(EnemyNear,Time < *) || (EnemyNear,Vel Y > 0)という記述を使いこれ一つで両方に対応させようとしていましたが、
これだとまだ反応してくれない攻撃があるのでTrigger3と4の2つに分けました。
こちらの方が丁寧と言えば丁寧なんですけどね。
しかしこれでも対応しきれていないものもあります。
それは&u(){「地面と平行に移動する空中属性の攻撃には必ず立つ」}ということです。
これでは純粋な空中突進には屈んで避けるということはできません。
まあそこは同様に場合分けをすれば済む話ですが。
注意点としてはキャラの大きさ、特に高さを考慮してくださいということだけですかね。
そして最後に飛び道具対策ですが、現段階では完全には出来ません。
ただし無いよりはマシなのでそれを加えた暫定完成形は
[屈み移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A
Trigger1 = Enemy,NumProj > 0 || Enemy,NumHelper > 0 飛び道具が存在する時
Trigger2 = EnemyNear,HitDefAttr = C,AA,AP || EnemyNear,HitDefAttr = SA,AP
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time < *
Trigger3 = EnemyNear,Vel Y <= 0
Trigger4 = EnemyNear,StateType != S
Trigger4 = EnemyNear,HitDefAttr = S,AA
Trigger4 = EnemyNear,Time >= *
Trigger4 = EnemyNear,Vel Y <= 0
[立ち移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A
Trigger1 = EnemyNear,HitDefAttr = A,AA
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time >= *
Trigger2 = EnemyNear,StateType = S
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time < *
Trigger3 = EnemyNear,Vel Y > 0
Trigger4 = EnemyNear,StateType != S
Trigger4 = EnemyNear,HitDefAttr = S,AA
Trigger4 = EnemyNear,Time >= *
Trigger4 = EnemyNear,Vel Y > 0
となります。
ヘルパーにHitDefを載せた形に対してはInGuardDistが有効みたいです。
というわけで屈み移行ステートにEnemy,NumHelperも追加しました。
しかし途中で気付いたので修正したのですが、&u(){ガード移行ならともかく立ち屈み移行にInGuardDistって必要ないですよね?}というわけで修正しました。
これでもしっかりと動いてくれます。
もしInGuardDistが無効になってもそのときはガードを止めてくれますからね。
そして立ち移行からEnemy,NumProj = 0が無くなりました。
これは&u(){「飛び道具がある時確実に屈むから中段で崩される」}という弱点を無くすためです。
もしこれがあった場合、例えば波動拳キャンセル禊なんかくると確実に屈んでしまうため屈みガード不可である禊を受けてしまいます。
そういったものを防ぐために消しました。
&italic(){&u(){P2StateType中心のステート}}
皆さんが良く使うP2StateType(あるいはEnemy,~、EnemyNear,~)についてやってみます。
実はこれ&bold(){だけ}だと一部攻撃には対応できませんが、Timeなどの他のトリガーと組み合わせると対応可能です。
まずは&u(){「相手が空中状態の時のみ立ち他は屈む」}という風にすると
[屈み移行ステート]
Trigger1 = P2StateType != A
[立ち移行ステート]
Trigger1 = P2StateType = A
となります。
ただしこの状態だと立ち中段で余裕で崩されるのでそれに対する対策もします。
[屈み移行ステート]
Trigger1 = P2StateType = C
Trigger2 = P2StateType = S
Trigger2 = EnemyNear,Time < *
[立ち移行ステート]
Trigger1 = P2StateType = A
Trigger2 = P2StateType = S
Trigger2 = EnemyNear,Time >= *
ここまではEnemyNear,HitDefAttr中心のステートとほぼ同じです。
本来ならこれだけでも上等なのですが更にガチガチにしたいという人は
[屈み移行ステート]
Trigger1 = P2StateType = A
Trigger1 = EnemyNear,Vel Y = 0
Trigger2 = P2StateType = C
Trigger3 = P2StateType = S
Trigger3 = EnemyNear,Time < *
[立ち移行ステート]
Trigger1 = P2StateType = A
Trigger1 = EnemyNear,Vel Y != 0
Trigger2 = P2StateType = S
Trigger2 = EnemyNear,Time >= *
とすればOKです。
上との違いはP2StateTypeがAでも場合によっては屈むという条件が追加されている事です。
この場合は&u(){「相手が空中状態で地面と平行に移動している時は屈みそれ以外は立つ」}という条件が追加されています。
これに当てはまる攻撃は限られている気がしますが例としてはサイコクラッシャーとかですね。
ちなみにEnemyNear,HitDefAttrと比べて有利な点としては竜巻旋風脚に少しだけ対応しているということですかね。
というよりはそれに対して必要な記述が少ないという点でしょうか。
まあこれらは立っていてもガードできますが。
どっちかというと&u(){「空中突進とか屈んでスルーしようぜ」}というコンセプトでやりました。
役に立つかどうかは不明ですが・・・。
ちなみに普通に空中攻撃をしてもその技独自の動きか重力によってVel Y != 0になるので立ち移行は可能です。
あとこのステートは下段飛び道具とかには完全には対応していないので注意して下さい。
その対応度はEnemyNear,HitDefAttr中心より低いですがまあ気にするほどのものでもありません。
最後に途中までガードするけど途中からガードしなくなるなどの現象はガードに移る条件や
[State X]
Type = ChangeState
Trigger1 = (略)
Value = 140
となっている記述のトリガーをいじってみてください。
自分もこの辺はまだ完璧ではないのでこれ以上は何とも言えません。
・各トリガーの欠点 最終更新 2008 4/25
AIを作成する際にはトリガーは非常に重要です。
ですがトリガーにも色々な落とし穴があります。
それについて気付いたものを適当に書き連ねようかと思います。
&italic(){&u(){InGuardDist}}
ガードや回避の際にお世話になるトリガーです。
しかしこれにもいくつかの欠点があります。
&u(){「(Facing*(EnemyNear,Facing)*P2Dist X >0)の時、無効になる」}
というものです。
多分これだけだとよく分からないと思うので画像を用意しました。
&blankimg(InGuardDist区別.JPG,width=301,height=238)
この画像で言うと右側の状況が当てはまります。
つまりめくりとかそういったやつですね。
P2BodyDistだけでなくP2Distも役に立ちますよ、ということでしょうか。
あと勘違いされがちですが、互いに向き合っていない状態でも相手が後ろにいればInGuardDistフラグはしっかりと立ちます。その状態をトリガーで表すと
TriggerAll = P2Dist X < 0
Trigger1 = Facing = -1 && EnemyNear,Facing = -1
Trigger2 = Facing = 1 && EnemyNear,Facing = 1
ということになります。
あまり使うことは無いと思いますが、こんなものもありますよと思っていただければ嬉しいです。
二つ目は&u(){GuardDist=0を使用しているものには反応しない。}
これは主に突進系の攻撃によく見られます。
GuardDistとはガードステートに移行する距離のことですが、それが0の場合密着状態じゃないと有効になりません。
突進系の攻撃に対してほとんど対応できていない場合はこれが原因かもしれません。
他にGuardDist=0が用いられるとしたら投げぐらいでしょう。
&italic(){&u(){EnemyNear,~}}
これは自分が主に使っているものです。
勿論他にも使っている人は大勢居るでしょう。
この効果は&u(){自分に最も近い相手の~}です。
やはりこれにも欠点はあります。
それは&u(){ヘルパーに対応していない}ということです。
これについての実用例は後で詳しく説明します。
もしこれがヘルパー対応でしたらそれはそれですごいことになるでしょうが。
EnemyNear,IsHelperとかできたら良かったのになあ。
&italic(){&u(){EnemyNear,HitDefAttr}}
いうまでもなく相手のHitDefAttrを認識するトリガーです。
当身などには何かと便利なのですが地味にいやらしい欠点があります。
一つ目は&u(){攻撃判定が無いと無効になる。}
まあ実際はあまり関係無いのですが、これ中心の記述だと移行が遅れるみたいです。
当然ですよね。相手のHitDefが有効にならないと作動しないのですから。
が、逆を言えば&u(){HitDefが有効にならない限りという条件}がつけられる・・・かもしれません。
編集中に思いついただけなので期待しないで下さい。
それに実用方法が思いつきません。
移行が遅れるのを防ぐにはP2StateTypeだけにするとよいみたいです。
二つ目は&u(){Projectileには反応しない。}
これは実にいやらしいです。
これのせいでEnemyNear,HitDefAttrだけでガードを組むことができませんから。
また&u(){ヘルパーのHitDefAttrを認識できない}という欠点もあります。
ただプレイヤー属性のヘルパーならば認識できるようです。
・おまけ 最終更新12/1
ここでは愚痴みたいなものを書いていきます。
というよりは現状AIに認識不可能なものを少し。
&italic(){&u(){HelperにHitDefを載せた飛び道具の裏回り状態}}
これは本当に認識不可能です。
いや一応可能と言えば可能なのですが、それをやると今度は必要以上に固まってしまいます。
もしこれがProjectileならばEnemy,NumProj > 0と!InGuardDistによって認識することが可能です。
ProjectileならできてHitDefでは出来ない理由はHelperであることが最大の原因です。
トリガーの欠点について書いてある通りにヘルパーの存在を認識できても詳細は一切認識できません。
ここでProjectileならNumProjとInGuardDistの2つのトリガーによって認識できますが、HitDefだとInGuardDistでしか認識できません。
更にそのInGuardDistも裏回りが認識できません。
無論ヘルパーの存在はNumHelperで認識できますが、それが何かの処理を行うためのものなのか攻撃用のものなのかは認識できません。
そのためInGuardDistなどの相手が攻撃している状態を認識できるトリガーを一緒に組まない限り必要以上にガードするのです。
が、InGuardDistを組ませると裏回りが・・・というジレンマが発生します。
ですのでこれは現状諦めたほうが良いです。
情報提供:B9MW85qx氏
:EQbnUkn9氏
・ガードステートについて 最終更新 2008 2/17
//おまけのみの更新なので、最終更新日は書き換えていません
&italic(){&u(){EnemyNear,HitDefAttr中心のステート}}
㍻㌢氏や⑨氏のAI講座においてガードステートのトリガーにP2StateTypeがよく使われています。
このままでも良いのですが、これだけだと立ち下段などの一部攻撃に対応できません。
そこでP2StateTypeだけではなくHitDefAttrも用います。
勿論自分のではなく相手のを参照するのでEnemy,もしくはEnemyNear,をつけて下さい。
ここではEnemyNearを用います。
なぜP2StateTypeだけではなくHitDefAttrも用いるかというと、
相手の攻撃の中にはStateTypeとAttr、そしてGuardFlagが一致していない場合があるからです。
簡易的に表してみると
StateType = S
HitDefAttr = S,AA(NAやSAの可能性もあるが立ち打撃という意味でAAで統一)
GuardFlag = MA(あるいはA)
これは立ち打撃で立ち、屈み、空中を問わずにガードできるというものです。
いわゆる上段というものです。(多分)
StateType = S
HitDefAttr = S,AA
GuardFlag = HA(あるいはH)
これは立ち打撃で立ち、空中状態のみガードできるというものです。
つまり屈み状態ではガード不可、中段という意味です。
これらの場合はP2StateType=SでもHitDefAttr=S,AAでも結果は変わりません。
ですが中にはこういったものもあります。
StateType = S
HitDefAttr = S,AA
GuardFlag = L
これが所謂「立ち下段」と呼ばれる形です。
StateType=S、つまりキャラが立ち状態で
HitDefAttr=S,AA、つまり立ち打撃であることが分かります。
この場合立ちガードの記述にP2StateType=Sを使っているとほぼ確実に立ってしまいます。
しかしGuardFlagがL、つまり屈みガードのみ可なので攻撃を喰らってしまいます。
またStateType=A(空中状態)なのにGuardFlagがLという場合も有ります。
そのためP2StateTypeではなくHitDefAttrを用います。
HitDefAttrは相手のHitDefに影響されます。
つまりHitDefAttrを用いると相手がSCAのどの状態であろうとどのような攻撃かを正確に読み取ってくれます。
それにHitDefはStateTypeとは別に設定できますからね。
とりあえず基本形を書いてみると
[屈み移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A(念の為)
Trigger1 = EnemyNear,HitDefAttr = C,AA || EnemyNear,HitDefAttr = SCA,AP
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time < *
[立ち移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A(念の為)
Trigger1 = EnemyNear,HitDefAttr = A,AA
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time >= *
となります。
ただしEnemyNear,HitDefAttr = SCA,APは保険用ですので注意して下さい。
EnemyNear,HitDefAttrではProjectileどころかHelperすら読み込んでくれません。
そこで飛び道具に対してはEnemy,NumProj > 0を使用することを薦めます。
まず屈み移行のTrigger1は&u(){「屈み打撃に対して屈む」}というものです。
つぎに立ち移行のTrigger1ですがこれは&u(){「空中打撃に対して立つ」}という意味です。
そして掲示板の方にも質問がありましたが、Trigger2のEnemyNear,Timeについて。
屈み移行も立ち移行もTrigger2に立ち打撃が条件となっていますが、EnemyNear,Timeの部分が違います。
これは&u(){「相手の立ち打撃が*フレーム未満の場合は屈み、*フレーム以上だと立つ」}という仕組みです。
通常中段は他の攻撃に比べて発生が遅くなっています。
そこでEnemyNear,Timeを用いて擬似的に中段かどうかを判断させています。
補足ですが*には任意の数字を入れて下さい。
目安とはして16~18ぐらいを入れるとベストかもしれません。
これで立ち下段に対するガードがほぼ完璧ですが、注意点があります。
AIにガードさせる記述、つまりChangeStateです。
この時にステート130や131などに直接飛ばすとガード不可能な攻撃もガードしようとするようです。
それを防ぐためにステート120や121に飛ばすことをおすすめします。
更に精密なAIを作ろうと思うのならばさらにトリガーを増やして条件を厳しくすることを薦めます。
例えば変数(Var)を用いて、相手の数フレーム前のStateTypeを判断したり、擬似的な学習システムを作成しそれによって確率を変化させたりなど。
簡単な例としてはTrigger2は中段対策なのですが、これを数種類に分けて判断させることもできます。
例えばEnemyNear,StateType!=Sを付け加えることによって「立ち状態以外での立ち打撃」という珍しい攻撃を判断することもできます。
この場合は相手が屈んでいるか空中にいるかなのですが、屈み状態ならば中段であることは滅多にありませんし、
空中状態での立ち打撃なんてものも滅多に有りません。
しかし念には念をということで一応それに対するためのトリガーも追加します。
それは&u(){EnemyNear,Vel Y < 0} と &u(){EnemyNear,Vel Y >= 0}です。
これらは&u(){「相手が降下攻撃してきているかどうか」}を判断します。
気晴らしに遊んでいた時に空刃脚を思い出しまして。
しかしこれでもまだメタじみている気がします。
もう少し記述を少なく出来ればそうは感じ無いのですが・・・。
例)
[屈み移行ステート]
Trigger1 = EnemyNear,HitDefAttr = C,AA || EnemyNear,HitDefAttr = SCA,AP
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time < *
Trigger2 = EnemyNear,Vel Y <= 0
Trigger3 = EnemyNear,StateType != S
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time >= *
Trigger3 = EnemyNear,Vel Y <= 0
[立ち移行ステート]
Trigger1 = EnemyNear,HitDefAttr = A,AA
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time >= *
Trigger2 = EnemyNear,StateType = S
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time < *
Trigger3 = EnemyNear,Vel Y > 0
Trigger4 = EnemyNear,StateType != S
Trigger4 = EnemyNear,HitDefAttr = S,AA
Trigger4 = EnemyNear,Time >= *
Trigger4 = EnemyNear,Vel Y > 0
屈み移行のTrigger2は立ち下段対策ですが、一応Velが入っています。
これの詳細は後述を参照してください。
立ち移行のTrigger2は中段対策です。
これは&u(){「相手の立ち打撃が*フレーム以上で立ち状態である」}ということで中段と判断させております。
次に屈み移行のTrigger3は&u(){「相手の立ち打撃が*フレーム以上で立ち状態じゃなく下降していない」}というものです。
これは後述するP2StateType中心のトリガーにおけるVel Y = 0に対する屈みと同じようなものです。
もし相手が屈み状態ならばVel Y = 0に当てはまって屈んでくれます。
相手が空中状態であっても下降攻撃以外は屈んで避けてしまえというものです。
といっても対応できる攻撃には限界がありますが・・・。
まさか昇竜に中段があるとは思えませんけどね。
そして立ち移行のTrigger3,4。
この2つは屈み移行のTrigger2,3に対応させています。
まずTrigger3の意味は&u(){「相手の立ち打撃が一定フレーム未満or下降中」}です。
下降中という場合ほとんどが空中状態になっているはずです。
空中状態で攻撃した場合は普通空中属性が付いた攻撃になります。
その場合は立ち移行ステートのTrigger1が反応して立ちます。
もし相手の攻撃が立ち属性の場合はまず屈み移行のTrigger2か3が反応します。
しかしそれは&u(){「相手が下降していない状態」}が条件となりますのでそれに対して&u(){「相手が下降している状態」}という条件のトリガーが立ち移行に必要です。
そのため屈み移行のTrigger2に対して立ち移行のTrigger3が、屈み移行のTrigger3に対して立ち移行のTrigger4があります。
以前は(EnemyNear,Time < *) || (EnemyNear,Vel Y > 0)という記述を使いこれ一つで両方に対応させようとしていましたが、
これだとまだ反応してくれない攻撃があるのでTrigger3と4の2つに分けました。
こちらの方が丁寧と言えば丁寧なんですけどね。
しかしこれでも対応しきれていないものもあります。
それは&u(){「地面と平行に移動する空中属性の攻撃には必ず立つ」}ということです。
これでは純粋な空中突進には屈んで避けるということはできません。
まあそこは同様に場合分けをすれば済む話ですが。
注意点としてはキャラの大きさ、特に高さを考慮してくださいということだけですかね。
そして最後に飛び道具対策ですが、現段階では完全には出来ません。
ただし無いよりはマシなのでそれを加えた暫定完成形は
[屈み移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A
Trigger1 = Enemy,NumProj > 0 || Enemy,NumHelper > 0 飛び道具が存在する時
Trigger2 = EnemyNear,HitDefAttr = C,AA,AP || EnemyNear,HitDefAttr = SA,AP
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time < *
Trigger3 = EnemyNear,Vel Y <= 0
Trigger4 = EnemyNear,StateType != S
Trigger4 = EnemyNear,HitDefAttr = S,AA
Trigger4 = EnemyNear,Time >= *
Trigger4 = EnemyNear,Vel Y <= 0
[立ち移行ステート]
TriggerAll = AIフラグON
TriggerAll = StateType != A
Trigger1 = EnemyNear,HitDefAttr = A,AA
Trigger2 = EnemyNear,HitDefAttr = S,AA
Trigger2 = EnemyNear,Time >= *
Trigger2 = EnemyNear,StateType = S
Trigger3 = EnemyNear,HitDefAttr = S,AA
Trigger3 = EnemyNear,Time < *
Trigger3 = EnemyNear,Vel Y > 0
Trigger4 = EnemyNear,StateType != S
Trigger4 = EnemyNear,HitDefAttr = S,AA
Trigger4 = EnemyNear,Time >= *
Trigger4 = EnemyNear,Vel Y > 0
となります。
ヘルパーにHitDefを載せた形に対してはInGuardDistが有効みたいです。
というわけで屈み移行ステートにEnemy,NumHelperも追加しました。
しかし途中で気付いたので修正したのですが、&u(){ガード移行ならともかく立ち屈み移行にInGuardDistって必要ないですよね?}というわけで修正しました。
これでもしっかりと動いてくれます。
もしInGuardDistが無効になってもそのときはガードを止めてくれますからね。
そして立ち移行からEnemy,NumProj = 0が無くなりました。
これは&u(){「飛び道具がある時確実に屈むから中段で崩される」}という弱点を無くすためです。
もしこれがあった場合、例えば波動拳キャンセル禊なんかくると確実に屈んでしまうため屈みガード不可である禊を受けてしまいます。
そういったものを防ぐために消しました。
&italic(){&u(){P2StateType中心のステート}}
皆さんが良く使うP2StateType(あるいはEnemy,~、EnemyNear,~)についてやってみます。
実はこれ&bold(){だけ}だと一部攻撃には対応できませんが、Timeなどの他のトリガーと組み合わせると対応可能です。
まずは&u(){「相手が空中状態の時のみ立ち他は屈む」}という風にすると
[屈み移行ステート]
Trigger1 = P2StateType != A
[立ち移行ステート]
Trigger1 = P2StateType = A
となります。
ただしこの状態だと立ち中段で余裕で崩されるのでそれに対する対策もします。
[屈み移行ステート]
Trigger1 = P2StateType = C
Trigger2 = P2StateType = S
Trigger2 = EnemyNear,Time < *
[立ち移行ステート]
Trigger1 = P2StateType = A
Trigger2 = P2StateType = S
Trigger2 = EnemyNear,Time >= *
ここまではEnemyNear,HitDefAttr中心のステートとほぼ同じです。
本来ならこれだけでも上等なのですが更にガチガチにしたいという人は
[屈み移行ステート]
Trigger1 = P2StateType = A
Trigger1 = EnemyNear,Vel Y = 0
Trigger2 = P2StateType = C
Trigger3 = P2StateType = S
Trigger3 = EnemyNear,Time < *
[立ち移行ステート]
Trigger1 = P2StateType = A
Trigger1 = EnemyNear,Vel Y != 0
Trigger2 = P2StateType = S
Trigger2 = EnemyNear,Time >= *
とすればOKです。
上との違いはP2StateTypeがAでも場合によっては屈むという条件が追加されている事です。
この場合は&u(){「相手が空中状態で地面と平行に移動している時は屈みそれ以外は立つ」}という条件が追加されています。
これに当てはまる攻撃は限られている気がしますが例としてはサイコクラッシャーとかですね。
ちなみにEnemyNear,HitDefAttrと比べて有利な点としては竜巻旋風脚に少しだけ対応しているということですかね。
というよりはそれに対して必要な記述が少ないという点でしょうか。
まあこれらは立っていてもガードできますが。
どっちかというと&u(){「空中突進とか屈んでスルーしようぜ」}というコンセプトでやりました。
役に立つかどうかは不明ですが・・・。
ちなみに普通に空中攻撃をしてもその技独自の動きか重力によってVel Y != 0になるので立ち移行は可能です。
あとこのステートは下段飛び道具とかには完全には対応していないので注意して下さい。
その対応度はEnemyNear,HitDefAttr中心より低いですがまあ気にするほどのものでもありません。
最後に途中までガードするけど途中からガードしなくなるなどの現象はガードに移る条件や
[State X]
Type = ChangeState
Trigger1 = (略)
Value = 140
となっている記述のトリガーをいじってみてください。
自分もこの辺はまだ完璧ではないのでこれ以上は何とも言えません。
・各トリガーの欠点 最終更新 2008 4/25
AIを作成する際にはトリガーは非常に重要です。
ですがトリガーにも色々な落とし穴があります。
それについて気付いたものを適当に書き連ねようかと思います。
&italic(){&u(){InGuardDist}}
ガードや回避の際にお世話になるトリガーです。
しかしこれにもいくつかの欠点があります。
&u(){「(Facing*(EnemyNear,Facing)*P2Dist X >0)の時、無効になる」}
というものです。
多分これだけだとよく分からないと思うので画像を用意しました。
&blankimg(InGuardDist区別.JPG,width=301,height=238)
この画像で言うと右側の状況が当てはまります。
つまりめくりとかそういったやつですね。
P2BodyDistだけでなくP2Distも役に立ちますよ、ということでしょうか。
あと勘違いされがちですが、互いに向き合っていない状態でも相手が後ろにいればInGuardDistフラグはしっかりと立ちます。その状態をトリガーで表すと
TriggerAll = P2Dist X < 0
Trigger1 = Facing = -1 && EnemyNear,Facing = -1
Trigger2 = Facing = 1 && EnemyNear,Facing = 1
ということになります。
あまり使うことは無いと思いますが、こんなものもありますよと思っていただければ嬉しいです。
二つ目は&u(){GuardDist=0を使用しているものには反応しない。}
これは主に突進系の攻撃によく見られます。
GuardDistとはガードステートに移行する距離のことですが、それが0の場合密着状態じゃないと有効になりません。
突進系の攻撃に対してほとんど対応できていない場合はこれが原因かもしれません。
他にGuardDist=0が用いられるとしたら投げぐらいでしょう。
&italic(){&u(){EnemyNear,~}}
これは自分が主に使っているものです。
勿論他にも使っている人は大勢居るでしょう。
この効果は&u(){自分に最も近い相手の~}です。
やはりこれにも欠点はあります。
それは&u(){ヘルパーに対応していない}ということです。
これについての実用例は後で詳しく説明します。
もしこれがヘルパー対応でしたらそれはそれですごいことになるでしょうが。
EnemyNear,IsHelperとかできたら良かったのになあ。
&italic(){&u(){EnemyNear,HitDefAttr}}
いうまでもなく相手のHitDefAttrを認識するトリガーです。
当身などには何かと便利なのですが地味にいやらしい欠点があります。
一つ目は&u(){攻撃判定が無いと無効になる。}
まあ実際はあまり関係無いのですが、これ中心の記述だと移行が遅れるみたいです。
当然ですよね。相手のHitDefが有効にならないと作動しないのですから。
が、逆を言えば&u(){HitDefが有効にならない限りという条件}がつけられる・・・かもしれません。
編集中に思いついただけなので期待しないで下さい。
それに実用方法が思いつきません。
移行が遅れるのを防ぐにはP2StateTypeだけにするとよいみたいです。
二つ目は&u(){Projectileには反応しない。}
これは実にいやらしいです。
これのせいでEnemyNear,HitDefAttrだけでガードを組むことができませんから。
また&u(){ヘルパーのHitDefAttrを認識できない}という欠点もあります。
ただプレイヤー属性のヘルパーならば認識できるようです。
//・おまけ 最終更新12/1
//ここでは愚痴みたいなものを書いていきます。
//というよりは現状AIに認識不可能なものを少し。
//&italic(){&u(){HelperにHitDefを載せた飛び道具の裏回り状態}}
//これは本当に認識不可能です。
//いや一応可能と言えば可能なのですが、それをやると今度は必要以上に固まってしまいます。
//もしこれがProjectileならばEnemy,NumProj > 0と!InGuardDistによって認識することが可能です。
//ProjectileならできてHitDefでは出来ない理由はHelperであることが最大の原因です。
//トリガーの欠点について書いてある通りにヘルパーの存在を認識できても詳細は一切認識できません。
//ここでProjectileならNumProjとInGuardDistの2つのトリガーによって認識できますが、HitDefだとInGuardDistでしか認識できません。
//更にそのInGuardDistも裏回りが認識できません。
//無論ヘルパーの存在はNumHelperで認識できますが、それが何かの処理を行うためのものなのか攻撃用のものなのかは認識できません。
//そのためInGuardDistなどの相手が攻撃している状態を認識できるトリガーを一緒に組まない限り必要以上にガードするのです。
//が、InGuardDistを組ませると裏回りが・・・というジレンマが発生します。
//ですのでこれは現状諦めたほうが良いです。
//厨忍氏のAI作成に関するQ&A集内でhelper方式の飛び道具を識別する方法が公開されているのでコメントアウト
//ちなみにProjectile方式の飛び道具であっても、飛び道具側の設定に不備があると裏回りを認識できません(MUGEN豆知識内のInGuardDist=1になるタイミングと距離についての項目に解説があります)
情報提供:B9MW85qx氏
:EQbnUkn9氏