Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How do I give my agent the ability to jump and check if grounded?

Discussion in 'ML-Agents' started by Yanannie, Mar 3, 2022.

  1. Yanannie

    Yanannie

    Joined:
    Mar 29, 2021
    Posts:
    4
    I have been following this tutorial on ml-agents and everything is working fine:


    Now I want to give my agent the ability to jump and check if it is grounded or not. The jumping part works, but it will just fly. I have been trying many different approaches and in a previous game I made, using feet to check if it collided with the ground worked perfectly, but it won't work now for some reason.

    This is the code I have to check if grounded:
    public bool isGrounded()
    {
    Collider[] isGrounded = Physics.OverlapSphere(feet.position, 0.5f, groundLayers);

    if (isGrounded != null)
    {
    return true;
    }
    return false;
    }

    This is the code for the actions:
    public override void OnActionReceived(ActionBuffers actions)
    {
    float moveX = actions.ContinuousActions[0];
    float moveZ = actions.ContinuousActions[1];
    int jump = actions.DiscreteActions[0];

    transform.localPosition += new Vector3(moveX, 0, moveZ) * Time.deltaTime * moveSpeed;

    if (jump == 1 && isGrounded())
    {
    rb.AddForce(Vector3.up * jumpStrength);
    }
    Debug.Log(jump);
    AddReward(-0.005f);
    }

    (full code is in the attached file)

    If there is any better approach to checking if grounded or a fix for my current code, please let me know.
     

    Attached Files:

  2. ChillX

    ChillX

    Joined:
    Jun 16, 2016
    Posts:
    145
    Is Gravity enabled on the Rigid Body ? If not then where is the downward gravity force to bring the agent back down to the ground?
     
    Yanannie likes this.
  3. Yanannie

    Yanannie

    Joined:
    Mar 29, 2021
    Posts:
    4
    Thank you for your reply, gravity is enabled on the Rigid Body and the agent will fall down. The thing is that it can jump while in the air, causing it to fly. I want it to only be able to jump while grounded.
     

    Attached Files:

  4. ChillX

    ChillX

    Joined:
    Jun 16, 2016
    Posts:
    145
    In that case the issue does not make sense because:

    Code (CSharp):
    1.  
    2. public bool isGrounded()
    3. {
    4. Collider[] isGrounded = Physics.OverlapSphere(feet.position, 0.5f, groundLayers);
    5.  
    6. if (isGrounded != null)
    7. {
    8. return true;
    9. }
    10. return false;
    11. }
    12.  
    Assuming:
    1) That groundLayers is only the actual ground layer and not the feet or any other object that might be around.
    2) That feet is a transform whose position is actually the feet of the character and not some other object or some other characters feet.
    3) That the ground somehow does not magically fly with the character.

    Then the above code (although not the most performant) should always work when the characters feet are within 0.5 meters from the ground.

    Which means that one of the three assumptions or something similar to that does not hold true.
     
    Yanannie likes this.
  5. Yanannie

    Yanannie

    Joined:
    Mar 29, 2021
    Posts:
    4
    The groundLayers is indeed only the platform, the feet is a transform with a position on the character and the ground does not magically fly.

    I have added two Debug.Logs to see if it is grounded or not:
    public bool isGrounded()
    {
    Collider[] isGrounded = Physics.OverlapSphere(feet.position, 0.5f, groundLayers);
    if (isGrounded != null)
    {
    Debug.Log("The agent is grounded");
    return true;
    }
    Debug.Log("The agent is not grounded");
    return false;
    }

    This is what I get in the console (0 means no jump input and 1 means jump input), for some reason whenever I jump, the code thinks that the agent is grounded: upload_2022-3-6_15-44-29.png
     
  6. ChillX

    ChillX

    Joined:
    Jun 16, 2016
    Posts:
    145
    Makes absolutely no sense. Even asked my cat and it just said MuWaw maw waw

    So if I may suggest. Instead of the overlap sphere. for grounding try use a raycast
    from feet position + new vector3(0f,1f,0f)
    with a distance of 1.5f

    If ray hit and (rayhit.point - feet.positon).magnitude > 0.99f
    Then you are grounded.
     
    Yanannie likes this.
  7. Yanannie

    Yanannie

    Joined:
    Mar 29, 2021
    Posts:
    4
    It is finally working, thank you and your cat a lot for your help :D

    This is the code that I am using for if it can help anyone:
    public bool isGrounded()
    {
    RaycastHit hit;

    if (Physics.Raycast(transform.position, -transform.up, out hit, 1f))
    {
    return true;
    }
    else
    {
    return false;
    }
    }

    Full code attached as a file
     

    Attached Files:

  8. ChillX

    ChillX

    Joined:
    Jun 16, 2016
    Posts:
    145
    My cat says your most welcome :)

    p.s. There are a few differences between OverlapSphere and Raycast.

    OverlapSphere will detect 0 to N colliders within the sphere. Raycast will detect 0 to 1 colliders and stops with the first collider that it hits.

    OverlapSphere is kind of like a thick ray cast meaning it has volume. Raycast is a thin line technically with infinitely small width.

    Basically OverlapSphere is bounding volume intersection between the OverlapSphere shape and any other collider shapes. Raycast is intersection between a line and the first bounding volume that it encounters.
     
    Yanannie likes this.