Hello. Lately I was searching for perfect rigidbody collision script. What I mean by that is something to check where character is touching the ground and switch grounded properly. I have found many ideas with tags on the floor, which is no go since tagging everything will be kinda chaotic, second idea was to check for velocity but it doesn’t work. So I kept digging myself and well, I’ve found out about collision flags but I don’t know how to apply them properly.
It’s simply not working properly and I still get ground toggled back on even if touching side which makes my jump repeatable on a wall launching me off like rocket.
I temporarily calculate the raycast offset so I don’t have to do it every frame. The “Extra” variable is a float which is extra distance beneath your character’s feet which will register the player as grounded (so little bumps won’t cause missed jumps and such). Set it to about 0.2.
Also note that the maximum angle the player can climb is hard coded at 45 in this particular example. You can change that if you wish.
Edit (yet again, sorry): I forgot to include my optimized GroundAngle function…
The system works fine, however I am experiencing two problems. One is that When I run towards an object, be it cube for example I can’t Jump onto it. The second one is That holding space makes character to continue jump. Any ideas for changes?
You don’t even know how thankfull I am for your response. I’ve spent 20+ hours on searching for proper script like yours.
When you say you can’t jump onto the cube, do you mean when you land on it, you aren’t grounded on it? And for the continuing to jump problem, I’d have to see some relevant code to figure out why.
Hmm that’s a very interesting problem. Did you make any changes to the code I posted? If not, I am assuming the problem is the spherecast is detecting the wall and seeing the angle is greater than the maximum slope, and registering as ungrounded. This is odd, since in my game, this does not happen. Try this for the SphereCast:
if (Physics.SphereCast(transform.position + raycastOffset, collider.radius * 0.9f, Vector3.down, out hit, Extra + 0.05f) && GroundAngle(hit.normal) <= 45.0f)
The only difference in this line of code is “collider.radius * 0.9f” for the sphere’s radius. This will hopefully prevent walls from causing issues.
I can’t notice any difference in reaction of character. I think the problem must be somewhere else. I’ve done some research and what I’ve noticed is that changing material of rock to ice slightly fixes it. So it might be something with friction and gravity. Adittional bug I’ve found is that when you slide down without jumping grounded doesn’t toggle off (duh). So obvious fix was adding else in check:
You’re using GetButton which returns a boolean containing the state of the button. If you hold the button down, it will continue to jump because the state is always returning true. If you use GetButtonDown, it will return true ONLY the frame in which the button is pressed. The problem is, FixedUpdate does NOT sync with normal frames, so you will miss a lot of jumps. What you want to do is check if the user is jumping with GetButtonDown in the Update() method, then set a boolean to true. We’ll call this boolean variable doJump. So you set that to true if GetButtonDown(“Jump”). Then in FixedUpdate(), check if doJump is true. If so, set doJump to false. Then check if grounded. If so, apply jump forces. Something like this:
bool doJump = false;
void Update()
{
if (Input.GetButtonDown("Jump"))
doJump = true;
}
void FixedUpdate()
{
if (doJump)
{
doJump = false;
if (grounded)
{
// jump here
}
}
}
Please note I just typed this in and may have made typos! But this is the general idea of what you want to do. The reason I set doJump to false even if we are not grounded (and thus unable to jump) is to prevent arming a jump while you’re mid-air and then jumping as soon as you are grounded.
Are you moving GetButtonDown into the Update() function instead of the FixedUpdate(), as per my above example?
I’m not sure if I understand your second sentence. If you are having trouble creating the PhysicMaterial, you can create it programmatically in the Awake() function like this:
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Jump")) {
doJump = true;
}
}
void FixedUpdate ()
{
// Cache the inputs.
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
bool sneak = Input.GetButton("Sneak");
bool jump = Input.GetButton("Jump");
if (doJump)
{
doJump = false;
if (grounded)
{
grounded = false;
anim.SetBool ("Grounded", false);
rigidbody.AddForce(0, JumpForce, 0);
}
}
RaycastHit hit;
if (Physics.SphereCast (transform.position + raycastOffset, collider.radius * 0.9f, Vector3.down, out hit, Extra + 0.05f) && GroundAngle (hit.normal) <= 45.0f) {
grounded = true;
anim.SetBool ("Grounded", true);
//groundNormal = hit.normal;
} else {
grounded = false;
anim.SetBool ("Grounded", false);
}
MovementManagement(h, v, sneak, jump);
}
About the second: I meant that adding material didn’t solve the problem. But now after I’ve added info to awake the hero is like icecube, permamently sliding.
Is JumpForce perhaps too low? Try setting it to something absurdly high to see if it works.
The reason the player slides without friction is probably because of the way you are applying movement. You are probably adding acceleration forces, but not using deceleration forces to slow the player down and instead relying on friction. The problem with that is friction is applied to every part of the player, not just their feet. So jumping against a wall will cause friction and perhaps limit jumping. Rigidbody character controllers are really tough to create, which I’m sure you’re beginning to realize :P. I feel like they are really great though once you get them working correctly.
Despite the undesired sliding behavior, have you tried jumping against a wall to see if the physic material solved that issue? If it did not solve it, then friction is not the issue and something else is. If it did solve it, then we need to implement deceleration forces and not use friction anymore.