Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

[Released] Kinematic Character Controller

Discussion in 'Assets and Asset Store' started by PhilSA, Sep 29, 2017.

  1. ryanflees

    ryanflees

    Joined:
    Nov 15, 2014
    Posts:
    27
    Hi, I have trouble with character may get pushed by other rigidbodies while slowing down. When I stop my character in front of a enemy, he uses a attack with RootMotion(which will be transfer to Kinematic movement) and pushes my character back a little bit.
    See, I kinda make a similar character controller like your example, I use the sharpness as acceleration to make a transition between fully stopped and moving. And I don't want my character can be pushed by other characters when he tries to halt before his speed reaches 0.
    Seems that the velocity passed into UpdateVelocity function is already changed while he gets pushed. I can use larger sharpness but the accelerating effect will be gone too.
    I tried different Rigidbody Interaction Type, Simulated Mass, Preserve Attached Rigidbody Momentum but they don't seem to work for my need. So any idea to actually avoid the push away interaction temporarily?
     
  2. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    could you provide a gif or video of what's happening? I'm having trouble understanding what happens
     
  3. BasementApps

    BasementApps

    Joined:
    Nov 26, 2017
    Posts:
    1
    Hey @PhilSA just a few questions about the controller.

    1. Can you adjust how steep you can climb up walls and on terrain, as well as the climbing speed on how steep it is.
    2. Is this controller efficient when it comes to networking and online play (around 100 players).
     
  4. ryanflees

    ryanflees

    Joined:
    Nov 15, 2014
    Posts:
    27

    sure, here's a video, I use the playground scene see how the character get pushed around :-|
     
  5. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    oh I see. This is actually a bug.

    I'll include the fix in the next update, but in the meantime, you can simply go in KinematicCharacterMotor.StoreRigidbodyHit() and add the condition under the "// HERE" comment:
    Code (CSharp):
    1.  /// <summary>
    2.         /// Remembers a rigidbody hit for processing later
    3.         /// </summary>
    4.         private void StoreRigidbodyHit(Rigidbody hitRigidbody, Vector3 hitVelocity, Vector3 hitPoint, Vector3 obstructionNormal, HitStabilityReport hitStabilityReport)
    5.         {
    6.             if (_rigidbodyProjectionHitCount < _internalRigidbodyProjectionHits.Length)
    7.             {
    8.                 // HERE
    9.                 if (!hitRigidbody.GetComponent<KinematicCharacterMotor>())
    10.                 {
    11.                     RigidbodyProjectionHit rph = new RigidbodyProjectionHit();
    12.                     rph.Rigidbody = hitRigidbody;
    13.                     rph.HitPoint = hitPoint;
    14.                     rph.EffectiveHitNormal = obstructionNormal;
    15.                     rph.HitVelocity = hitVelocity;
    16.                     rph.StableOnHit = hitStabilityReport.IsStable;
    17.  
    18.                     _internalRigidbodyProjectionHits[_rigidbodyProjectionHitCount] = rph;
    19.                     _rigidbodyProjectionHitCount++;
    20.                 }
    21.             }
    22.         }
    Basically, we just avoid storing rigidbody hits if it has a KinematicCharacterMotor on it
     
    Last edited: May 8, 2018
  6. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    Yes, you have control over the max slope angle. As for the slope speed, handling this would be the responsibility of your own custom character controller that you'd make using KCC

    On my computer (Intel Core i5-4690k and a GTX 970), I can have 1000 characters moving around at 60-70 fps. For 100 characters, I get about 450 fps. Adding networking usually adds a bit of a performance hit to that, but that really depends on which networking solution you're using. The character controller itself doesn't come with built-in networking, but it does have all the characteristics to support networking (manual ticking of simulation, as much determinism as possible, GetState/ApplyState, etc....). A networking example is provided with the package
     
  7. silentneedle

    silentneedle

    Joined:
    Mar 14, 2013
    Posts:
    280
    Did anyone manage to implement KCC to photon bolt?
     
  8. luispedrofonseca

    luispedrofonseca

    Joined:
    Aug 29, 2012
    Posts:
    860
    @PhilSA I'm sorry if you already replied this, but I couldn't find it. What's the recommended way of doing one-sided (one-way) platforms?

    I'm currently doing something like this on the "IsColliderValidForCollisions":
    Code (csharp):
    1. if (OneWayPlatform == (OneWayPlatform | (1 << coll.gameObject.layer)) && _deltaMovement.y > 0)
    2.         {
    3.             return false;
    4.         }
    5.        
    6.         return true;
    It works, but it's slightly clunky and I'd like the one-way platforms to ignore collisions if the character collides with the sides as well.
     
  9. Guerrilla705

    Guerrilla705

    Joined:
    Jan 23, 2014
    Posts:
    7
    I'm missing something really silly here I'm sure, but I'm experiencing an issue where the controller fails to successfully get ground hits after upgrading from 2017 to 2018 and KCC 1.2 to current.

    I have traced it down to the CharacterGroundSweep CapsuleCastNonAlloc call not actually returning collisions. I have checked that the capsule positions, direction, and distance for the cast are correct and don't seem to be the issue, and the layers are both set to "Default" and marked to collide in the layer matrix, but there still is never a valid hit return. With safe movement off, the capsule jitters slightly inside of the ground, while with safe movement on it stops a short bit above the ground. However, in both cases the CharacterGroundSweep fails, so ProbeGround does not correctly trigger the OnGroundHit callback and set the stability etc.

    Has anyone bumped into a similar problem?

    EDIT: Re-tested with a backup and an upgrade -- it stopped working upon the upgrade from 2017.3 to 2018.2. Anyone else had upgrade issues?

    EDIT2 electric bugaloo: I made a small test script running a CapsuleCastNonAlloc and put it on a capsule with a collider. It correctly reports the number of hits, but all of the hit results have a null collider and no distance. If I use CapsuleCastAll instead it correctly stores the hits. Could this be a Unity bug in 2018.2? Also odd: I am always seeing 2 hits from the nonalloc call in KinematicCharacterMotor, both saying the collider is the Capsule on the object, even though there is only one collider. It doesn't seem to get 3 hits when hitting the ground.

    EDIT3: I was able to fix the issue by replacing CapsuleCastNonAlloc calls in KinematicCharacterMotor to CapsuleCastAll calls. RaycastNonAlloc seems to function fine for me.
     
    Last edited: May 9, 2018
  10. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    190
    I'm almost certain that this is indeed a bug on Unity's side because I had similar issues with OverlapBoxNonAlloc vs. OverlapBox in the SteamVR plugin. Here's the thread I've started:

    https://forum.unity.com/threads/overlapboxnonalloc-vs-overlapbox-most-probably-a-bug.520495

    Unfortunately I wasn't able to create a simple test scenario to reproduce the bug, so I had to provide the big scenario that even required the QA team to use a VR System. However, they still weren't able to reproduce the bug on their side so they dropped my bug report.

    Can you reply in my thread and create another bug report, please?
     
  11. Guerrilla705

    Guerrilla705

    Joined:
    Jan 23, 2014
    Posts:
    7
    I'll put in a bug report! Seems something must be bugged indeed, don't know how I got into this state so unfortunately my repro steps will be somewhat vague, but what can ya do. These are the times I wish I could debug into the actual capsule cast function!
     
  12. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    Sorry for the late reply. This is indeed a bug in 2018.2, but it has supposedly been fixed in beta 3.
    See bug report thread here: https://forum.unity.com/threads/cas...ysics-queries-dont-return-any-results.527651/
     
  13. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    That's an interesting situation that I haven't thought of before... I think the way I'd handle this would be something like this:
    • we start with the assumption that your one-way-platform's transform's forward is the blocking side
      ...in other words, if we are going in the same direction as the object's forward, we can go through it.
      And if we go against its forward, we are blocked by it
    • In IsColliderValidForCollisions, we only ignore those colliders if one of these two conditions are met:
      • the Dot product between Motor.Velocity and coll.transform.forward is > 0f
      • a Physics.ComputePenetration between the character capsule and the coll returns true (meaning we are currently overlapping with it, so we don't want to be de-colliding from it)
    This is untested, but it would be my approach I think
     
  14. Coffein

    Coffein

    Joined:
    Jan 22, 2016
    Posts:
    19
    We've been considering this for our server auth top-down 2D game - is this supported, considering the dependencies to the capsule collider? Or this mainly geared towards 3D controllers?
     
  15. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    Unfortunately this works for unity's 3D physics/colliders only
     
  16. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    34
    Hey hi! Your character controler looks great, though I have a question as a fellow developer: does it prevent phasing on low framerates (or better, frame drops safe)?
    I've written some CC myself and had this kind of issue sometimes, low fps = big deltaTime = big movement delta = phasing. I've always solved it by subdividing the movement delta over multiple iterations to mitigate the issue by making it a distance problem instead of a time problem.
    You seem pretty knowledgeable about the matter so I was curious if you have a similar implementation too.
    Thanks!
     
  17. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    KCC operates entirely on a fixed timestep, so everything is framerate independant. On top of that, it uses swept collision detection, which means it does not go through colliders regardless of the speed (except for extreme cases where you ram into an angled corner between two mesh colliders at ridiculous speeds)

    for example, here's me testing with the application forced at 5 fps and running into a wall at a speed of 999: https://i.gyazo.com/01104b5f81a5ddba26df7d5cfdf47da4.mp4

    Due to the algorithm used, the character will never phase through those colliders, even if it's moving so fast that it looks like it's teleporting
     
    Bonfi_96 likes this.
  18. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    My suggestion:
    In your character's "ProcessHitStabilityReport", set the hitStabilityReport.IsStable to false if a hitCollider.gameObject.GetComponent<KinematicCharacterMotor>() doesn't return null
     
    Roy927 likes this.
  19. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    It'll make it so that this particular hit on a character cannot make your character be considered stable, but it won't prevent a grounding hit that touches the ground in the same frame to make the character stable
     
  20. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    34
    What if a big object, like a kinematic platform going up and down or a wall moving, tries to push the object at low framerate? The kcc interpolates "being pushed around" too? I'm asking this because the controller knows where it should go, so in that case you can sweep its movement and do checks indipendently from the framerate (as the video clearly shows), though I'm not sure if it knows if the others are trying to push him unless they are intersecting during the collision checks. I don't know if it makes sense to you
     
  21. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    That's right; other objects like moving platforms do not do continuous collision detection (sweeps) like the character does. But this could be accomplished by creating a moving platform script that does a Rigidbody.Sweep() on every update with a distance representing its displacement for the frame. If it hits a CC, it would store a Vector3 representing the distance that the CC has to be pushed. And finally, once the CC updates its velocity, it adds this vector to its regular velocity

    However, once the CC detects that it is grounded on a moving platform, it'll follow it even if the platform is going at ridiculous speeds:
     
    Yokogeri and Bonfi_96 like this.
  22. Bonfi_96

    Bonfi_96

    Joined:
    Oct 2, 2013
    Posts:
    34
    Thanks a lot for the insight, your KCC is the best generic purpose controller I've seen to date in unity!
     
  23. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Okay i have a question. I bought your controller and it is great. However, I want to use a different camera controller, ootii camera controller, found here, https://assetstore.unity.com/packages/tools/camera/camera-controller-13768. However, i have been racking my head trying to figure it out. The Ootti controller uses its own inputs for mouse. Is there a way to implement this controller instead of using the camera in your controller?
     
  24. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    You can just basically take ExamplePlayer and remove the camera-related stuff in there. The only thing you need to worry about is when we do SetInputs() on the character, the ExamplePlayer needs to pass the camera rotation of the new camera system you're using
     
  25. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Thank you i will try that out.
     
  26. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Btw if figured it out. Had to splice a few things together but now its working exactly how i want. Thank you.
     
  27. Bubsavvy

    Bubsavvy

    Joined:
    Sep 18, 2017
    Posts:
    43
    Hello all,

    I was wondering if there is anyway to move a character in the scene view that has the motor on it without it resetting its position when I unpause the game. If not is there any way you could add support for it. The motor is very useful and this is one of very little downsides i have encountered.
     
  28. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    I see what you mean. Try dropping this attached script into your project (it auto-initializes itself so you don't have to do anything else). Just make sure you put it in an "Editor" folder
     

    Attached Files:

  29. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Hello im back again. i have two questions, both dealing with swimming.
    1. When swimming, how can i make my character move up and down with ONLY the jump and crouch keys and NOT the camera orientation?
    2. Is there a way to make my character jump once he reaches the top of the water so that way he can jump out of it? if so how?
    Thanks.

    Edit: Scratch the first one. I figured it out
     
    Last edited: May 25, 2018
  30. faolad

    faolad

    Joined:
    Jan 27, 2013
    Posts:
    107
    Unity 2018.1. keeps crashing on clicking play when using "Physics Mover" and "Example MovingPlatform" in an object on a scene. Any ideas why?
     
  31. nyghor

    nyghor

    Joined:
    Jun 12, 2017
    Posts:
    3
    Hello! I've read a question about your controller handling fast speeds and as I saw in your answer, it does it with no problem at all. But I have another question regarding this subject. How does it handles fast speeds when it has a hill in front of it, and a thin wall on the top of the hill? Something like this for example:
    upload_2018-5-27_4-25-8.png
     
  32. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    For the surface jumping, there is a point in the swimming character controller where we have this:
    Code (CSharp):
    1.  
    2.                             // if our position would be outside the water surface on next update, project the velocity on the surface normal so that it would not take us out of the water
    3.                             if (closestPointWaterSurface != resultingSwimmingReferancePosition)
    4.                             {
    5.                                 Vector3 waterSurfaceNormal = (resultingSwimmingReferancePosition - closestPointWaterSurface).normalized;
    6.                                 smoothedVelocity = Vector3.ProjectOnPlane(smoothedVelocity, waterSurfaceNormal);
    7.                             }
    At that point, after the smoothedVelocity = Vector.projectOnPlane(...), if you add an upwards velocity to smoothedVelocity, it'll make the character jump out of the water
     
  33. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    Could you share your Editor.log found in
    C:\Users\[your_name]\AppData\Local\Unity\Editor

    It gets overwritten everytime you start unity, so make sure you wait until unity crashes, and then get the .log file

    Also make sure you are not using a beta version
     
  34. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    Thin walls will never be a problem for fast speeds, but hills can be a problem. This is because the only way to do continuous collision detection is directly towards your movement. There is no proper way to detect hits perpendicularly to your movement in a continuous way

    What this means is that if you go over hills at high speeds, you'll eventually fly off the hill despite the fact that the CC is trying to do ground snapping. I'm trying to illustrate this here:


    There might be ways to solve this by detecting that if you're over a certain velocity, you make your character update at a faster rate, but this could cause all sorts of problems with character and moving platforms interactions.
     
    nyghor likes this.
  35. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Thanks you, your awesome.
     
  36. dennisrsd

    dennisrsd

    Joined:
    Sep 18, 2013
    Posts:
    13
    He man I bought your plugin and I love it. I can do all what I wanted to do but there was one thing that I was curious how to solve.

    The problem is when standing on a rigid-body ( that is not kinematic but dynamic) the platform seems to shift a little bit under the character. Offset.gif see gif.

    What I did is made a script that uses addforce (every fixedupdate) in a certain direction. I told the dynamic moving platform (through physics Physics.IgnoreCollision) to ignore the player so the rigid-body platform wont move, when the character bumps or steps on it. With this I can ride the platform and when the platform bumps into terrain it reacts nicely and the player stays on the platform until the angle becomes to great (what is good). But as you can see in the gif when the speed picks up the platform shifts under the character ever so slightly, its not a big problem for me but maybe there was an easy solution to it. Or maybe this is not the way the controller was intended.
     
  37. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Sorry for bothering you again. I found the part of the code you were talking about. However, i am an idiot you cant seam to figure it out. Could you elaborate a bit or give me an example or something. Again, sorry for bothering you.

    For the record i dont expect you to write all the code for me, i just have a hard to understanding things sometimes
     
  38. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    Only two things to add in order to get you started:

    First, in MyCharacterController.SetInputs, remember that jumping is requested in the swimming state like this:


    Then, in the chunk of code mentionned previously, do the velocity add if the jump was requested:


    the " - Vector3.Project........" part is just so that the jump height doesn't vary based on the velocity you already had as you were reaching the surface
     
  39. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    The only thing that comes to mind is the rigidbody interpolation bug that was present since 2017.2, but is (supposedly) fixed in 2018.2 beta. There would be 2 things to try:
    1. Try 2018.2 beta
    2. Try setting KinematicCharacterSystem.InterpolationMethod to "Unity" on start. This won't solve the actual interpolation hiccups, but it'll at least make the character be affected too, so it won't be as obvisous
     
  40. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Thank you, works perfectly. I even figured out how to reset the jumping so i can double jump out of the water.
     
  41. dennisrsd

    dennisrsd

    Joined:
    Sep 18, 2013
    Posts:
    13
    He PhilSA,

    Tried both solutions, and both solution it brought it back to a minimum. But still is there, but its really not an issue for me right now.

    Thanks you for your answer.
     
  42. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    New question. How can i tell whether my character is moving down (falling). I want to implement a glide so i need to reduce gravity after i double jump but if i reduce gravity right after the double jump he will fly into the air. This with also help when implementing a ledge grab.
     
  43. B0M

    B0M

    Joined:
    Jun 22, 2017
    Posts:
    5
    Alright I'm back after a long time and decided to test out the updated version. The getting stuck when scraping against a stuck moving box glitch was fixed, but not the bug where if you move on the edge of a surface, you get stuck. stuck-png.270748
     
  44. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    378
    Hello, perhaps I can help.

    Code (CSharp):
    1. // check if we are moving up or down. Up is considered to be the character's up direction.
    2. float sign = Mathf.Sign(Vector3.Dot(motor.BaseVelocity, motor.CharacterUp));
    3.  
    4. // determine speed of character along the vertical direction (again, determined by character up). multiply by sign so up is positive and down is negative.
    5. float vSpeed = Vector3.Project(motor.BaseVelocity, motor.CharacterUp).magnitude * sign;
    You should glide when the vSpeed is negative after doing your double jump.
    Please note that if your gravity direction is always set to be down on the y axis, then you can simplify all that code by just monitoring your y values instead (that is, you are falling when the character's y pos is lower than in the previous frame. In my game, gravity can be in any direction and can change at any time, and can be different per player, so I used the code above.

    Oh also, I used motor.BaseVelocity which will be different to world velocity if you are on a platform. You may not want this, kinda up to you. So if you are on an elevator for example, and that elevator is moving down very quickly, BaseVelocity will be zero if your character is standing still on the elevator.
     
    PhilSA likes this.
  45. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Thanks. ill look into this.
     
  46. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    GOT IT!! Thank you so much. While im here, do you know how to cancel out the current fall velocity when i start to glide, that way if im falling and then glide my current fall velocity wont be added to the glide. That way i can always start to glide at the same speed?
     
  47. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    to cancel out the falling velocity (but keeping the horizontal velocity):
    Code (CSharp):
    1. currentVelocity = Vector3.ProjectOnPlane(currentVelocity, Motor.CharacterUp);
     
    FenixOfGreen likes this.
  48. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,495
    are you sure you are on the latest release? That picture seems to be from an earlier version of the WebGL demo, and I haven't been able to repro the bug in the new one

    (new version would look like this)
     
  49. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    how do you prevent sticking to steep/slide/unjumpable surfaces. I have a glide and while im gliding if i touch a surface that too steep, i stick to it like im grounded.
     
  50. FenixOfGreen

    FenixOfGreen

    Joined:
    Oct 2, 2017
    Posts:
    22
    Quick question (for anyone). I am trying to implement a Super Jump to my character. However i want to make it its own state so i can have different movement for the super jump compared to the regular movement. My problem is im not sure how to approach it. Do i just copy and paste the jumping from the Default state or is there another way i can do it?

    This will also help me with a long jump
     
    Last edited: Jun 5, 2018
unityunity