Third Person Character Controller "OnGround" trigger bug

Hello,

Not sure exactly what lecture to post this on since I just notice it but I have no idea how long its been going on for.

Sometimes my zombie will “slide” instead of running, but after further examination I’ve discovered that the “OnGround” checkbox in the animator is randomly becoming unflagged, so I assume the sliding animation is actually a falling animation.

Any idea why this is happening? It seems to be on slopes, albeit it horribly gradual ones (5 degrees or less).

I can’t find any settings, and to fix it to be honest for now I’ve just commented out the code that affects the OnGround flag in the animator.

Halp pls

when you play your game try watching the zombie move and while he is sliding try adjusting in the inspector for the third person character script “ground check distance” slide this up or down and watch the zombie to see if he stops sliding.

I noticed this was occurring in the RPG course also. I spent some time looking into it and found that under the right conditions the raycast which comes out of the bottom of the model to determine whether the model is on the ground or not doesn’t quite work as expected.

The raycast has an original that is ever so fractionally within the character, if the origin of a raycast is actually inside another collider it won’t report it. What I observed was that often, on ground that was not flat, the origin of the raycast would not report back and as such the code set it to be “falling”… this gave the look of the invisible motorbike rider / sliding model. There was also a condition where by the character would jiggly / twitch / move uncontrollably when it should be stationary. This turned out to be related but was due to the animation actually moving the character and some conflicts between the code.

I don’t know whether it will fix your issue, but I tweaked the code in both the ThirdPersonCharacter.cs and AICharacterControl.cs scripts and was able to resolve the issue completely - at least within the confines of the testing I was doing. Below are the snippets from each of the two files which I had changed;


AICharacterControl.cs

        private void Update()
        {
            if (target != null)
                agent.SetDestination(target.position);
            else
                character.StopMoving();

            if (agent.remainingDistance > agent.stoppingDistance)
            {
                character.Move(agent.desiredVelocity, false, false);
            }
            else
            {
                target = null;
                character.StopMoving();
            }
        }

ThirdPersonCharacter.cs

        [Space][Tooltip("Minimum value 0.1f")][SerializeField] float m_GroundCheckDistance = 0.1f;
        /// <summary>
        /// Stops the character moving
        /// </summary>
        public void StopMoving()
        {
            // TODO: should maybe consider checking whether we are moving first

            CheckGroundStatus();

            Vector3 stop = Vector3.zero;

            m_TurnAmount = Mathf.Atan2(stop.x, stop.z);
            m_ForwardAmount = stop.z;

            UpdateAnimator(Vector3.zero);
        }
		void CheckGroundStatus()
		{
            // increased offset from 0.1f to 0.5f to place origin of raycast further inside the character
            float rayCastOriginOffset = 0.5f;

			RaycastHit hitInfo;
#if UNITY_EDITOR
			// helper to visualise the ground check ray in the scene view
			Debug.DrawLine(transform.position + (Vector3.up * rayCastOriginOffset), transform.position + (Vector3.up * rayCastOriginOffset) + (Vector3.down * m_GroundCheckDistance));
#endif
			// rayCastOriginOffset is a small offset to start the ray from inside the character
			// it is also good to note that the transform position in the sample assets is at the base of the character
			if (Physics.Raycast(transform.position + (Vector3.up * rayCastOriginOffset), Vector3.down, out hitInfo, (rayCastOriginOffset + m_GroundCheckDistance)))
			{
                m_GroundNormal = hitInfo.normal;
				m_IsGrounded = true;
				m_Animator.applyRootMotion = true;
			}
			else
			{
                m_IsGrounded = false;
				m_GroundNormal = Vector3.up;
				m_Animator.applyRootMotion = false;
			}
        }

Not sure if it will help but thought I would share on the off chance.

1 Like

Okay so I did a bit of investigative work following the two replies above.

Changing the “Ground Check Distance” did literally nothing. If you turn it to negative it makes the character permafloat (kinda makes sense when you think about it) and increasing it (even to rediculous levels) didn’t affect functionality, and didn’t fix the bug.

Rob’s solution got me on the right track, although in my instance a lot less editing was required to fix this specific issue.

In the CheckGroundStatus() function of the ThirdPersonCharacter.cs, I literally just changed the "0.1f"s to "0.5f"s. NOTE: The Debug.DrawLine function is just for debugging purposes (obviously), the line below is the functioning line.

This seems to have solved my issue completely. I have no doubt that, if I were using more of the Character Controller functions I would have to do more complex editing like Rob has, but in my instance this doesn’t appear to be hugely necessary. (I could be wrong, I’ll bookmark this post for future reference.)

As always, really appreciate the help on this one. I was actually a bit lazy with it, since I clocked the bug about 10 minutes before I was going to go to bed, so after a quick fiddle I basically just posted it here and then looked at the responses after work. My plan had I not got any responses would have been to disect the 3rd person controller scripts and the AI scripts, so honestly this really saved me a lot of time and I’m grateful.

1 Like

Glad to hear it has resolved the issue.

I think what happens is that the origin of the raycast ends up inside the very thing that you want to test against and as it ignores that the default is “I’m falling”.

The 0.5f is a bit arbitary in that I just wanted to ensure the original was more significant than it was, in effect it increases the tolerance, if the character for some reason was to go into the object it was standing on, eventually 0.5f wouldn’t be enough either.

The stop moving code was more for RPG course where we were using point and click to move the character. I wasnt entirely certain what your project looked like so gave you it all :slight_smile:

Privacy & Terms