0
\$\begingroup\$

Intersecting colliders

The bottom part of the player capsule collider is going inside the ground collider. I am using a raycast for detecting whether the plauer is grounded; an object (sphere) that is present on the bottom bound of the capsule collider is responsible for firing the raycast.

Player jumping with red ray extending below

I think when the bottom part of the collider (including) the sphere is going inside the ground, my isGrounded variable is getting set to false, and the player character is transitioning from the landing to falling animation instead of running, which is not the desired behavior of course. I don't know why this is happening. I have been trying to find the solution for 2 days now and I can't seem to find the solution or reason behind the problem

  • I am updating the size and center of the collider at runtime during different animations like jump, slide, and land (back to default size). I can provide code if needed.

  • I am also moving the object responsible for the ray according to the size of the box collider using a collider.bounds and extents — will provide code if needed.

More details and code about how ground detection works

These two methods in the character control script are responsible for spawning and repositioning the object that fires ray on runtime. rayEmitter is a GameObject variable where prefab is added and Emitter is another GameObject variable. As you can tell RayEmitter object is spawning on the collider position.

  public void IntialSetup_of_RayEmitter()
    {
        Emitter = Instantiate(RayEmitter, Vector3.zero, Quaternion.identity);
        Emitter.transform.parent = transform;
        Reposition_RayEmitter();
    }

    public void Reposition_RayEmitter()
    {
        float bottom = cCollider.bounds.center.y - cCollider.bounds.extents.y;
        float side = cCollider.bounds.center.x - cCollider.bounds.extents.x;
        float front = cCollider.bounds.center.z + cCollider.bounds.extents.z;

        Emitter.transform.localPosition = new Vector3(side + 0.3f, bottom + 0.03f, front - 0.3f) - this.transform.position;
    }

these two methods are responsible for recentering and resizing the capsule collider at runtime, here I am using a bool RepostionEmitter as it turns true I am calling the reposition method Above on FixedUpdate, initially variable starts as false as it becomes true after updating size and center call reposition.

 private void UpdateCenter()
    {
        if (!UpdateNow)
        {
            return;
        }
        else if (Vector3.SqrMagnitude(cCollider.center - targetCenter_C) > 0.01f)
        {
            cCollider.center = Vector3.Lerp(cCollider.center, targetCenter_C,
                Time.deltaTime * CenterUpdate_Speed_C);
            RepostionEmiter = true;
        }
    }


    private void UpdateSize()
    {
        if (!UpdateNow)
        {
            return;
        }
        else
        {
            cCollider.height = Mathf.Lerp(cCollider.height, targetHeight,
                Time.deltaTime * SizeUpdate_Speed_C);
            RepostionEmiter = true;
        }
    }


 private void FixedUpdate()
    {
        if (StartRun)
        {
            if (isGrounded())
            {
                Grounded = true;
            }
            else
            {
                Grounded = false;
            }
        }

        ApplyGravity();
        RepostionEmiter = false;
        UpdateCenter();
        UpdateSize();

        if (RepostionEmiter)
        {
            Reposition_RayEmitter();
        }
    }

This bool method just a fire ray and detects the Grounded variable, I was also checking grounded or not using Rigidbody velocity but I had to remove it due to Dashing mechanisms during the dash especially if performed after the jump or double jump means in the air I don't want any different kind of velocity like gravity, etc to affect the dashing and it's forward force character just need to move forward during dash i am using AddForce for that, so you can imagine when I was doing that grounded variable was becoming true as i was messing with velocity during dash and due to that player was able to perform countless dashes in air and some other problems too.

 public bool isGrounded()
    {
        //if (Mathf.Abs(RIGIDBODY.velocity.y) <= 0.01f)
        //{
        //    return true;
        //}

        RaycastHit hit;

        if (Physics.Raycast(Emitter.transform.position, Vector3.down, out hit, rayDistance))
        {
            if (hit.collider.CompareTag("Ground"))
            {
                //Debug.Log(hit.collider.gameObject.tag);
                return true;
            }
        }
        return false;
    }

last thing and I think I should mention just in case, I am using something called a Statemachine pattern to control the logic/behavior of the character For example; this scriptable object containing code is present on all the animation state that needs to check if player is grounded or not.

using UnityEngine;

namespace EndlessRunning
{
[CreateAssetMenu(fileName = "New Object", menuName = "ScriptableObject/Ability/GroundDector")]
public class GroundDector : ScriptableObjectData
{
    public override void OnEnter(PlayerStateBase playerStateBase, Animator animator, AnimatorStateInfo stateInfo)
    {
    }

    public override void OnUpdate(PlayerStateBase playerStateBase, Animator animator, AnimatorStateInfo stateInfo)
    {
        if (playerStateBase.characterControl.Grounded)
        {
            animator.SetBool(HashManger.Instance.DicMainParameters[AnimatorParameters.Grounded], true);
        }
        else
        {
            animator.SetBool(HashManger.Instance.DicMainParameters[AnimatorParameters.Grounded], false);
        }
    }

    public override void OnExit(PlayerStateBase playerStateBase, Animator animator, AnimatorStateInfo stateInfo)
    {
    }
}

}

enter image description here

That is how different player movements are being handled Overall my scene does not have anything related to that just objects that are responsible for cameraControl, and Spawning character according to the selected character from character select scene These systems are completely separate, and decoupled from movement and has nothing to do with it.

Character Inspector

enter image description here

enter image description here enter image description here

\$\endgroup\$
6
  • \$\begingroup\$ Have you tried starting your raycast from higher up, so even a small overlap won't cause the ray to miss the ground surface? \$\endgroup\$
    – DMGregory
    Sep 6, 2023 at 18:39
  • \$\begingroup\$ yes I have tried it, Setting the value high too much causes the landing animation to trigger too quickly checking different values 0.5 seems to work less than that cause the issue mentioned above more than causes land to trigger way too early in mid-air, i will run more tests \$\endgroup\$ Sep 6, 2023 at 18:59
  • \$\begingroup\$ You can also change the threshold at which you trigger the animation to counter any buffer space you add this way. \$\endgroup\$
    – DMGregory
    Sep 6, 2023 at 19:01
  • \$\begingroup\$ can you explain this threshold part a bit.. also maybe it has something to do with the speed of updating the box collider, I had the speed set to 5000 so it happens quickly, maybe this extra quickness pushes the collider into the ground without detecting collision. \$\endgroup\$ Sep 6, 2023 at 19:03
  • \$\begingroup\$ To help you with that level of detail, we'll need more information in your question. Please edit it to include a Minimal Complete Verifiable Example. That is, all the code and scene setup steps a reader would need to follow to reproduce a simplified version of this problem, starting from a new, empty project. Once we can reproduce the issue, we can confirm which specific code or inspector/animation configuration changes will successfully resolve it. \$\endgroup\$
    – DMGregory
    Sep 6, 2023 at 19:43

1 Answer 1

0
\$\begingroup\$
  1. I can't believe it took me 2 days to figure out what was the problem. solution is way too simple. All I had to do was to set the ray emitter object red sphere a bit higher so when the character hits the ground and the collider gets updated object does not penetrate the ground collider like it does in the picture above also have to increase the length of the ray.
  2. Another issue is with the updating of the collider If the update size and center speed are set to a very high value like 500 or 5000 then during the collider update emitter object gets pushed inside the ground.

enter image description here enter image description here

now when the character hits the ground sphere stays a bit higher from the ground and does not return isGrounded false.

For setting the sphere higher I just add 0.3 in the bottom position in the reposition method

 float bottom = cCollider.bounds.center.y - cCollider.bounds.extents.y;
 float side = cCollider.bounds.center.x - cCollider.bounds.extents.x;
 float front = cCollider.bounds.center.z + cCollider.bounds.extents.z;

 Emitter.transform.localPosition = new Vector3(side + 0.3f, bottom + 0.3f, front - 0.3f) - this.transform.position;

I hope it helps if anyone face similar issue in future

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .