Page 1 of 1

FSMで状態遷移したタイミングだけで衝突をとりたい

Posted: 2020/01/14 13:41
by Einst
こんにちは、Arborはじめて2日目の初心者です。

状態遷移したタイミングでColliderに触れているかどうかを判断するのに良い方法はありませんか?
剣が握られる、握られてない(手離す)という状態で、離したタイミングでさやに触れていたらさやに
収めるなどを作る場合どうすれば良いでしょうか?

OnTriggerEnterTransitionなどで、さや格納状態に遷移させるのも考えたのですが。剣を落とした状態
で、さやを握って剣に触れさせるとさやに入ってしまします。

OnStateBeginのタイミングで衝突判定するとか
OnTriggerEnterTransitionを初回状態遷移時のみ有効にするとか
何か良い方法はありませんか?

Re: FSMで状態遷移したタイミングだけで衝突をとりたい

Posted: 2020/01/14 23:15
by caitsithware
ステートと衝突判定のタイミングに関するご質問ですね。
Einst wrote: 2020/01/14 13:41 剣が握られる、握られてない(手離す)という状態で、離したタイミングでさやに触れていたらさやに
収めるなどを作る場合どうすれば良いでしょうか?
「離したタイミング」という一瞬のみの判定でしたら、「鞘に収めるチェックステート」を作成し、OnTriggerEnterTransitionやOnTriggerStayTransitionとTimeTransitionを組み合わせてみるというのはいかがでしょうか。
  • OnTriggerEnterTransitionやOnTriggerStayTransitionではチェック対象のTagを鞘に限定し、触れているようであれば「収めるステート」に遷移。
  • TimeTransitionでは数フレーム分(ほぼ一瞬)待ってから「離したステート」に遷移。
という感じです。
Einst wrote: 2020/01/14 13:41 OnStateBeginのタイミングで衝突判定するとか
OnStateBeginのタイミングでの衝突判定については、Unityの仕様上の話となります。
Physics.Raycastなどの判定メソッドを使用したり、別途Trigger系イベントをプーリングするスクリプト(一旦フラグ立てておいて後からでも判定できるようにする処理)などを自作する必要があります。
こちらについては、Arborの範疇を超えているためこれ以上のサポートは致しません。
Unityマニュアルやチュートリアルを参考に、スクリプトを作成してみてください。
Einst wrote: 2020/01/14 13:41 OnTriggerEnterTransitionを初回状態遷移時のみ有効にするとか
何か良い方法はありませんか?
初めから組み込まれているスクリプトについては汎用性のため、お望みの機能がないことがあります。
StateBehaviour等のスクリプトを自作するのを推奨しておりますので、一度自作もご検討ください。

StateBehaviour | Arbor Documentation

Re: FSMで状態遷移したタイミングだけで衝突をとりたい

Posted: 2020/01/15 04:38
by Einst
回答ありがとうございます。基本、お教えいただいた通りで動きました。

1.チェック用のステートを設け、OnTriggerStayTtransitionで、収めるステートに飛ぶ
2.収めるステート内で独自処理
 2.1.カスタムのStateBehaviourを作成しOnTriggerStayTtransitionからColliderを受け取り。
 2.2.ColliderからさやのGameObjectを取得し、刀のParentに設定
 2.3.刀をisKinematecをTrueに設定


public class StoreNozzle : StateBehaviour {

public InputSlotCollider sayaCollider;

public override void OnStateBegin()
{
Collider collider = null;

if (sayaCollider.GetValue(ref collider))
{
gameObject.transform.parent = collider.gameObject;
gameObject.transform.localPosition = new Vector3(0f,0f,0f);

Rigidbody nozzleRigidBody = gameObject.GetComponent<Rigidbody>();
nozzleRigidBody.isKinematic = true;
}
}
}