Problem with state machine

I’m trying to implement a state machine for hand states in VR. I simply want the hands to remain in the ‘empty’ state when they are not holding an object, and when an object is grabbed, the hand state should transition to ‘grabbed.’ The problem arises when I grab the object – the states repeatedly go from ‘empty’ to ‘grabbed,’ and I don’t understand why this is happening

Original Post on Discord

by user 691445074055397447

Hello there – we have an experimental AI bot :robot: that might be able to help you with your question. Would you like to try this out?

How it works:
Reply to the messages of the bot that end with a thread_id to interact with it and ask follow-up questions. You can also mention the bot directly in this channel to get help.

Help requested: please wait a moment…

enum HandState {
    Idle,
    Grab,
    Release,
    Empty
}

 update() {
        this.checkAndUpdateVRStatus();
        this.grabbing();
      this.handleHandState();
    }
    private grabbing() {
        const rayDirection = new Vector3(0, 0, 1);
        const interactDistance: number = 1;
    
        const raycastResult = this.context.physics.engine?.raycast(
            this.gameObject.transform.position,
            rayDirection,
            interactDistance
        );
    
        if (raycastResult && this._webXR) {
            const hitCollider = raycastResult.collider;
            const handCollider = hitCollider.gameObject.getComponent(GrabController);
    
            const isLeftHand = this.handInput == this.handInputLeft;
            const controller = isLeftHand ? this._webXR.LeftController : this._webXR.RightController;
    
            if (handCollider) {
                if (controller?.selectionPressed && !this.isHoldingObject && this.handState !== HandState.Grab) {
                    // console.log("HandCollider detected, transitioning to Grab state");
                    this.onHandColliderDetected?.invoke(this, controller);
                    this.isHoldingObject = true;
    
                    // Check if the current state is Idle before transitioning to Grab
                    // if (this.handState === HandState.Idle) {
                    //     this.updateHandState(HandState.Grab);
                    // }
                }
            }
        }
    }

private handleHandState() {
    switch (this.handState) {

        case HandState.Idle:

        if(this.isHoldingObject) {
           this.handState = HandState.Grab;
         }

        break
        case HandState.Empty:
           
            break;
        case HandState.Grab:
         
            break;
    }
console.log(this.handState)
}

by user 691445074055397447

Here is what I found for you :brain: Discord

Hello boss15493, it sounds like you have an issue where the state of the hand is toggling between ‘empty’ and ‘grabbed’ states continuously when an object is grabbed. This could be due to the state change logic being called repeatedly, perhaps every frame or on a continuous input event.

To resolve the issue, ensure that the state change to ‘grabbed’ only occurs once when the grab action initiates, and similarly, the transition to ‘empty’ only occurs when the release action is performed.

Here’s a pseudocode plan, followed by a code suggestion:

  1. Define states for hand (e.g., EMPTY, GRABBED).
  2. Add event listeners/methods for grab and release actions.
  3. On grab action, check if current state is EMPTY before transitioning to GRABBED.
  4. On release action, check if current state is GRABBED before transitioning to EMPTY.
  5. Prevent any further state changes until a new action occurs.
export class HandStateMachine extends Behaviour {
  // Define the hand states
  private currentState = 'EMPTY';

  // Called when component is added to an object and is active in the scene
  awake() {
    // Add event listener for grab action
    this.addEventListener('onGrab', this.onGrab);
    // Add event listener for release action
    this.addEventListener('onRelease', this.onRelease);
  }

  // Method to handle the grab action
  onGrab() {
    // Check if the hand state is empty before transitioning to grabbed
    if (this.currentState === 'EMPTY') {
      this.currentState = 'GRABBED';
      // Additional code for when the object is grabbed
    }
  }

  // Method to handle the release action
  onRelease() {
    // Check if the hand state is grabbed before transitioning to empty
    if (this.currentState === 'GRABBED') {
      this.currentState = 'EMPTY';
      // Additional code for when the object is released
    }
  }
}

thread_PfVgCla8BAHbtjNO5xHTdORQ

Make sure that your event listeners for grab and release actions are properly implemented and not causing unintended repeated calls to your state transition methods.

If the issue persists, try adding some debug logs to track when state changes are occurring. This can help identify why the state is toggling unexpectedly.

1 messages left GPT 4
thread_PfVgCla8BAHbtjNO5xHTdORQ