Search Unity

[Released] Kinematic Character Controller

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

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    The most obvious first steps would be:
    • disable "Safe Movement". SafeMovement is just there in case you end up in a situation where your character runs into an extremely tight corner at a very high speed and tunnels through it, which will never actually happen if your velocities stay within "normal" values.
    • Set Step Handling to None. Step handling should be completely avoidable if you use ramp colliders instead of steps
    • Consider not using Ledge Handling on characters that are less important (like non-player characters)
    • Make sure Physics.autoSyncTransforms is set to false
    • Make sure your character's collision layers are arranged to collide against only what's necessary (the KCC uses the physics collision matrix from the gameObject's layer just like regular rigidbodies)
    If you already had those settings and really want to disable all collision checks aside from grounding, you should be able to do that by commenting out the highlighted code here (in motor.UpdatePhase2()):



    Aside from all this, since most of the performance cost comes from Unity's own Physics queries and SyncTransforms calls, I don't think this is something I can improve much for the time being. But eventually there will be a Pure ECS version of KCC that will surely improve performance by a whole lot
     
    Last edited: Apr 16, 2018
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    ya already doing the obvious stuff there.

    One thing I might try is setting a threshold for certain checks. On my kinematic boat controller I gate ComputePenetration and collision checks by time, because it doesn't do any good to run those 3 times within 10ms, which is what can happen when you get spikes of cpu activity somewhere else.

    Basically physics won't degrade gracefully with the rest of the system in a game where it's normal to range from say 35fps to 60fps. Which is completely normal in a game like mine, a mass combat focused mmo type game.

    In that case you need to gate some physics stuff by framerate, or it starts trashing the system. It ensures it keeps using the same amount of cpu time it did at 60fps, so you get this not nice scaling as framerate goes down from optimal.
     
  3. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Actually I just noticed the physics queries in the profiler pic you showed only account for about 10ms out of the 25ms total, so it looks like there's a 15ms of "other" stuff in there. Could you take a pic of what a deep profile of the fixed update looks like?

    As for what you describe regarding gating the physics, there's this: https://docs.unity3d.com/ScriptReference/Time-maximumDeltaTime.html
    But yeah it might be a better idea to handle this more manually
     
    Last edited: Apr 16, 2018
  4. nxrighthere

    nxrighthere

    Joined:
    Mar 2, 2014
    Posts:
    567
    I solved this problem with GPU-accelerated rigid bodies. All collision calculations are done in compute shader. It allows me to have hundreds of entities per frame in my simulations. 176 controllers are computationally expensive for Unity's built-in physics.
     
    Last edited: Apr 17, 2018
  5. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I think most of that extra time is just an accumulation of lots of little stuff, with accessing/setting transforms most likely being pretty heavy in comparison to the math involved. I still think the possible biggest gain is not running the stuff that takes obvious big chunks of cpu as often that I don't need for my specific environment.

    Physx is actually pretty fast and I know capable of far better performance, I think it's how Unity uses it. Like the sync points they have, that's Unity not physx and I'm sure it has a hefty impact on performance when force everything to update at once instead of spreading it out more. Plus physx is async by default and supports gpu acceleration.

    upload_2018-4-16_23-50-16.png

    upload_2018-4-17_0-8-14.png
     

    Attached Files:

  6. nxrighthere

    nxrighthere

    Joined:
    Mar 2, 2014
    Posts:
    567
    PhysX in Unity is not GPU-accelerated for about a century. At least, the last time when I did a simple test, it was not working.
     
    Last edited: Apr 17, 2018
  7. Yokogeri

    Yokogeri

    Joined:
    Oct 14, 2013
    Posts:
    21
    Greetings @PhilSA !

    I'm currently trying to implement this awesome character controller into my networked game, which uses Photon Bolt.

    As far as I understand, Bolt wants me to use "BoltNetwork.frameDeltaTime" instead of Time.deltaTime or Time.fixedDeltaTime.

    How would I switch this out when using this character controller?
     
  8. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I am not familiar enough with Bolt to give you a very specific answer, but you should take a look at the walkthrough section on networking (How to “Tick” the character movement simulation)

    Basically, you'd turn off KinematicCharacterSystem.Autosimulation, and you'd simulate it manually by calling KinematicCharacterSystem.Simulate(BoltNetwork.frameDeltaTime) at the same frequency that Bolt simulates its "frames". By passing "BoltNetwork.frameDeltaTime" as argument to the simulate method, this deltaTime will be transmitted to all functions of the KinematicCharacterMotor such as UpdateVelocity, UpdateRotation, etc.....
     
    Yokogeri likes this.
  9. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Unfortunately I'm not really seeing anything suspicious in that profiler. I doubt I could do much to improve things aside from the conversion to ECS+Burst+Unity.Mathematics+Jobs

    ...but on the bright side, Unity apparently just realized that Mono had some really unoptimal settings regarding float operations, and they've managed to make all float operations up to 4.4x faster (!!!)
    Source: http://tirania.org/blog/archive/2018/Apr-11.html

    It sounds a little bit too good to be true, but it seems like this is actually a real thing that is really happening and should be in an upcoming Unity release soon. Here's the twitter discussion, with Aras mentionning that we might get it in april at the end: https://twitter.com/Reedbeta/status/985986135196286976

    In the meantime, it might actually be interesting to build your game with IL2CPP instead of Mono, and see if there's improvements
     
    Last edited: Apr 17, 2018
  10. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    IL2CPP crashes my game on start. Not worth bothering with right now whatever it is will probably get fixed by the time I care.

    I think it's going to take a long time to get full jobified physics. Like I ran into some wtf bugs they missed with just the raycasting. Where it was stepping on particle updates to the physics system and crashing unity. They will have to get rid of the entire notion of sync transforms I think. I'm hoping for sooner but not counting on it.
     
  11. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    I am so sorry for the late reply, thought I would recieve email notifications :d

    Anyway - I tried to reproduce the bugs I had mentioned in clean project with kcc 2.1 and they disappeared completely. However, after I upgraded to 2.2.1 all of them came back. Maybe this somehow occurs when updating? They only appeared after I updated my other project with v1.2.2 to 2.0 so that might be it.

    As for the sliding bug, it still happens but less frequently I think. At least it is harder to reproduce. But it still happens.
     
  12. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    thanks for the info, I will try to do some tests with upgrading and see what I can find. When you upgraded, did you completely replace all files, or did you do a copy-paste of the new files over the old ones?
     
  13. silentneedle

    silentneedle

    Joined:
    Mar 14, 2013
    Posts:
    280
    @PhilSA It would be great if you could add a MoveCharacter method which accepts a velocity vector.

    p.s. Are there any drawbacks when setting the position/rotation directly instead of the UpdateVelocity/UpdateRotation overload?
     
  14. Homer-Johnston

    Homer-Johnston

    Joined:
    Nov 26, 2012
    Posts:
    46
    @PhilSA thank you so much for this asset!! I hope you do very well. I'm not sure if this could be my fault or not, but I might have a small "bug" (unexpected behaviour) when moving between platforms versus when moving from solid ground to a platform. Basically when you instantly walk from one platform to another, BaseVelocity doesn't reset and slowly adapt the way it does when you leave a moving platform (I think???) See slow-motion gif:

    https://gyazo.com/a71dd9d2ef92c4620776547fcd4cb3e9

    Green = Motor.BaseVelocity
    Red = Motor.AttachedRigidbodyVelocity
    Yellow = Motor.Velocity

    I can recreate the same effect in your CharacterPlayground scene with your example controller by placing two platforms side by side and walking or jumping between them. Wondering if there's a missing check to recalculate your BaseVelocity or something if your AttachedRigidBody changes without touching solid ground?

    Thanks again!!
     
  15. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    I completely replaced all of them
     
  16. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    There is a KinematicCharacterMotor.MoveCharacter() that takes a position. You could use this and simply pass [currentPosition + (velocity * fixedDeltaTime)] as argument

    Setting the position/rotation manually (not with MoveCharacter()) does has tons of drawbacks because it makes it impossible for the character controller to follow any continuous collision detection and velocity projection rules, so it'll almost always result in buggy movement if there's any collider in the way of the movement

    But even with MoveCharacter(), there is the drawback that the motor will not be able to calculate the resulting velocity from the movement if there were any obstructions. So in the end, UpdateVelocity() really is the recommended way to go about this
     
  17. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I think I see what you're saying (although I'm not completely sure). You mean there should be at least a little bit of "drifting" once you stand on the second platform doing in opposite direction?

    I did a quick fix and got this result (same color code you used): https://i.gyazo.com/6e98949ef71584415f70b63d63a17dd2.mp4

    I'll upload the fix in the next version, but if you want to fix it manually in the meantime....
    1. Find the place in UpdatePhase1 with the following comment:
      Code (CSharp):
      1. // Conserve momentum when de-stabilized from an attached rigidbody
    2. Simply replace the "if" condition under that comment with this:
      Code (CSharp):
      1. if (PreserveAttachedRigidbodyMomentum && _lastAttachedRigidbody != null && AttachedRigidbody != _lastAttachedRigidbody)
     
    Homer-Johnston likes this.
  18. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    So far, I haven't had any success with reproing the issue

    I tried creating a new project in 2017.3 and importing the KCC 2.1 package. I moved objects in the example scene and saved a few times (just in case), and played the scene. Then, I deleted the whole KCC folder and imported KCC 2.1.1 into the project, and tried the scene again

    Is there anything you notice you did differently so that I can try this again?
     
  19. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    Im using 2018.1.0b13, maybe thats the issue. Also I did not delete the entire KCC folder, since I thought overriding it would be enough - I'll try deleting and then importing it!
     
  20. baumxyz

    baumxyz

    Joined:
    Mar 31, 2017
    Posts:
    107
    Hi PhilSA, first thank you for this awesome asset.
    I'm currently trying to access these informations but I can't find them. Can you tell me how I can access these informations from my custom character controller? I want to check for "IsOnLedge" inside my SetInputs() method.
     
  21. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    For this, I would suggest getting the HitStabilityReport struct at every OnGroundHit, and caching it in your character controller so you can reuse it in SetInputs
     
  22. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    I'm trying to implement a dash (press a button, move quickly over the next few frames in the specified direction with a constant velocity then stop).
    I'm trying to use the AddVelocity(Vector3 velocity) in the ExampleCharacterController for that.

    First I tried to just add the velocity, but depending on the slope it was too slow, or too fast, or if I jump and do the dash it was WAY too fast. I tried adding a Vector3.up in there to get off a slope while doing it and I ended up becoming superman and flying away (whichw as kinda fun).

    I looked at the documentation and tried
    var directionTangent =
    Character.KinematicCharacterMotor.GetDirectionTangentToSurface((transform.forward+(Vector3.down*0.3f))*DashSpeed,
    Character.KinematicCharacterMotor.GroundNormal);

    And used that direction. That was a better result, but if I dash while going down a ramp I still get air-time and faster speeds...

    I tried
    Character.KinematicCharacterMotor.GetVelocityForMovePosition(
    transform.position + (transform.forward*DashSpeed), Time.deltaTime*10); but that also had similar problems...

    Is there a better way to do this?
     
  23. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Did you take a look at the Walkthrough section called "Charging State"? (try out the associated scene in the project to see what it does) I think this would be helpful to you. The approach used here is that we make an entirely new movement state in which we return a constant velocity for the dash in UpdateVelocity()
     
  24. Homer-Johnston

    Homer-Johnston

    Joined:
    Nov 26, 2012
    Posts:
    46
    @PhilSA thanks - this pointed me in the right direction. After staring at it for a while I made one more change... I just marked all the lines I added or changed with TODO comments:
    https://i.gyazo.com/36ee9ce2527b3737600dcc0b0cba5549.png

    I haven't checked every possible scenario yet to figure out if I'm breaking anything else with this, but seems OK and gives full conservation of momentum between platforms very nicely which is what we were looking for with our project :)
    https://i.gyazo.com/6e43a8dfa192739c306bab3d4686a819.mp4
     
  25. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Ah, you're right. The additional subtraction of the attached velocity is required. I'll make sure to include that fix as well!
     
  26. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Oh! Did not see that! Sorry! Thank you very much :D
     
  27. kindingerlek

    kindingerlek

    Joined:
    Jul 7, 2015
    Posts:
    10
    Hi @PhilSA

    I almost complete the migration from my legacy controller to your plugin, and man, I'm loving it! Seriously, all just worked as expected. Thank you so much!

    There only one missing feature in this migration, capsule orientation. Can you suggest me a workaround for this?

    My character has 2 types of Crouch: Idle and Moving. In the Idle state, I can get a fake "SphereCollider" just shrink down the capsule height. But when goes to moving, I can't set capsule orientation axis. If I change it at Motor.Capsule, the gizmos may show it properly, but collisions not.

    If I don't change the capsule orientation, two issues appear: If capsule radius is small enough to fit character local X axis (Arms), his head passthrough to the wall. However, if capsule radius is bigger enough to fit local Z axis (Head to Foot), he cannot pass between two obstacles.

    Anyways, I am so happy with your plugin!

     
    Last edited: Apr 23, 2018
  28. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    265
    Your character controller looks really impressive! I once tried to combine a somewhat 'dynamic' character controller with Edy's Vehicle Physics and had the problem that a car running over the player would slowly stop if the player moves towards the car, i.e. the controller was much more powerful than the car. This video shows what I mean:


    Can your character controller deal with rigidbody impacts more realistically, especially cars?

    I've got two more questions and then I will shut up :)

    - Does your controller handle curly stairs well?
    - Is there a video of the controller's swimming ability?
     
    Last edited: Apr 24, 2018
  29. kindingerlek

    kindingerlek

    Joined:
    Jul 7, 2015
    Posts:
    10
    In Walkthrough, there is one step which is swimming state. :)

     
  30. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    This is unfortunately not (directly) possible with KCC. The recommended way to approach this is more or less what's described in this post: https://forum.unity.com/threads/released-kinematic-character-controller.497979/page-10#post-3423777

    In short; you would have the KCC capsule stay upright and be scaled down to a sphere at the front of your character, and then you would have another sphere/capsule collider at the back of your character, whose job would only be to tell the KCC how to decollide from detected obstacles if any.

    Since this is often asked about, I am thinking about doing a walkthrough section on this in the near future
     
    LouisHong likes this.
  31. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Interacting physically with rigidbodies is not this character controller's strength. By default, if you were to ram a car into a Kinematic Character Controller at 100mph, the character would stay perfectly still and the car would stop dead in its tracks. Any movement it does has to be explicitly scripted by the user. In this case, it would involve turning the car into a "moving platform" (technically speaking) by adding the included "PhysicsMover" script to it. This would make the car push the character without ever losing momentum

    ... I think this is definitely the kind of thing that would require an example from me, because it could get a bit complex. I'll see if I can come up with something soon

    Do you mean spiral stairs, or rounded steps? Well, in both cases it does

    https://i.gyazo.com/098b05fdcdcc8ae8ac63a9e4ddb3ebd5.mp4
    here it is. As you can see, it is fairly basic and mostly serves as a way to point users in the right direction for implementing their own swimming
     
  32. sebsmax

    sebsmax

    Joined:
    Sep 8, 2015
    Posts:
    118
  33. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
  34. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    Wellllllll, I have fixed all of the issues I was having.

    For some reason the fixed timestep was set to 0.0008. I didnt touch this value since I had started my project almost 2 years ago so I have no idea what caused it. Also I loaded a backup project from before I upgraded the kcc and the value was at 0.0167 there. The weird part is that the same thing happened to my test project which had it set to 0.0008 as well. Using 0.0167 again solved all of my issues, so sorry for that, I've probably wasted a lot of your time.

    The sliding bug is also completely gone now, thanks a lot, you're the best!
     
    PhilSA likes this.
  35. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    265
    Thank you for your fast answer. Your response rate is remarkable!
    That would be really great! Please keep me posted. I am searching so desperately for a solution that I'm even considering migrating Unity's Physics Engine to BEPU Physics as soon as version 2.0 is released since this engine uses a dynamic character controller.
    I meant spiral stairs and it's great to hear that it works. All of the other character controllers in the Assetstore that I've tested so far can't handle them well.
    Nice! :) I'm really excited now to see your controller progress even further. I'm using a phrase now that has been used way too often but I really mean it: Please keep up the excellent work!
     
    Last edited: Apr 25, 2018
  36. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    Good looking controller. One thing I've been looking for in a CC is handling walls; like wall climbing/ledge hanging, and low wall vaulting. Are these things that KCC can handle?
     
  37. Petethegoat

    Petethegoat

    Joined:
    Jun 12, 2013
    Posts:
    39
    It doesn't do these things by default, but it makes it very simple to implement this stuff yourself. I loosely described my climbing/mantling here, and I think Phil has given some suggestions for ledge climbing elsewhere in the thread.
     
    PhilSA and LukeDawn like this.
  38. out-of-pixel

    out-of-pixel

    Joined:
    Mar 18, 2013
    Posts:
    3
    Hi @PhilSA, your KCC looks great so far, i'm thought about buying it but first a have a question.
    Will it work with variable time steps, to achieve a Slowmotion/Bullettime like Gameplay?
     
  39. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    Import with 2018.1.0b12 gives me 2 errors of unsafe code.

    Assets/KinematicCharacterController/Walkthrough/18- Networking example/Scripts/NetworkingFramework/SerializationBuffer.cs(527,16): error CS0227: Unsafe code requires the `unsafe' command line option to be specified. Enable "Allow 'unsafe' code" in Player Settings to fix this error.

    Assets/KinematicCharacterController/Walkthrough/18- Networking example/Scripts/NetworkingFramework/SerializationBuffer.cs(1255,16): error CS0227: Unsafe code requires the `unsafe' command line option to be specified. Enable "Allow 'unsafe' code" in Player Settings to fix this error.
     
  40. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    There's two different concepts here:
    • Variable time step: the notion of running the character movement code on Update instead of FixedUpdate (by default it runs on FixedUpdate)
    • Variable time scale: warping time to achieve slowmotion
    KCC supports both of these things, although I wouldn't recommend using a variable time step because you'd lose a lot of quality/precision when it comes to interaction with rigidbodies and moving platforms.

    But if you just mean slowmotion, then yes you can simply tweak Time.timeScale and it'll work. The only gotcha is that with Unity physics in general, you always have to scale the Time.fixedDeltaTime proportionally to the Time.timeScale. This means for example that if your default fixedDeltaTime is 0.02 and you decide to reduce timeScale to 0.1, you'll have to set your fixedDeltaTime to 0.002 for as long as the timeScale remains 0.1
     
    out-of-pixel likes this.
  41. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    ah, yes. Unity 2018.X requires a special tickbox to be enabled in Edit > Project Settings > Player Settings to allow unsafe code. It's called "Allow unsafe code" I think

    I should probably put the whole networking example in a package of its own to avoid getting the error upon import
     
    LukeDawn likes this.
  42. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    It's only the one script in the networking example on some bitwise operations. But could put some people off if they have to tick a box somewhere or rem out a line or two to make things compile from import.
     
  43. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    Looking through the walkthroughs with 2018.1.0b12 and I'm seeing FixedUpdate.PhysicsFixedUpdate spikes of 170ms to 300ms about once per second which of course is causing big lag jolts in playback. About to test again with 2017 to see if the problem exists there too.

    No, 2017 is fine. I'm now downloading the latest 2018.1.0f1 to see if that's ok or not.

    profiler.jpg


    Just as I'm testing with the latest 2018.1.0 beta, the final release is out. Downloading that now.
     
    Last edited: May 2, 2018
  44. superjayman

    superjayman

    Joined:
    May 31, 2013
    Posts:
    185
    Do you support SteamVR integration?
     
  45. luispedrofonseca

    luispedrofonseca

    Joined:
    Aug 29, 2012
    Posts:
    945
    Hi, just bought your plugin. Looks brilliant.

    However, testing out the included demo scene I'm noticing a 40/80B memory allocation every frame. Is there something you can do to prevent this?
     
  46. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    It doesn't come with a pre-made character controller for VR, but there wouldn't be any problems with making a VR character controller using KinematicCharacterController
     
  47. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    These allocs are editor-only. They are coming from the "Playable Director" that controls the boat's animation, but they disappear in a build

    I think you might also see other GC allocs from time to time while standing on moving platforms for example, but these are also editor-only (they come from internal warning message strings generated by unity when doing a GetComponent in editor and no component was found)
     
    luispedrofonseca likes this.
  48. kindingerlek

    kindingerlek

    Joined:
    Jul 7, 2015
    Posts:
    10
    Hey @PhilSA

    I just want to share a solution to an issue which I had. My problem was with RootMotion. My Character is heavily Root Motion based, and when I converted from my legacy code to your plugin, I had some strange motion behaviours. Looking for what causes it, I realized the animator Update don't match with the FixedUpdate used by Character Controller.

    To solve it, just place this line at Start or Awake calls:
    Code (csharp):
    1. animator.updateMode = AnimatorUpdateMode.AnimatePhysics;
     
  49. LukeDawn

    LukeDawn

    Joined:
    Nov 10, 2016
    Posts:
    404
    Those lag spikes don't appear in 2018.1.0f2 (the current release). Must have been a fixed bug from beta versions.
     
    PhilSA likes this.
  50. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    The only real difference is that in the new version, SetInputs takes a struct that contains all the inputs the character could need. You can look at ExampleCharacterController does in SetInputs when its "OrientationMethod" is set to "TowardsMovement" for reference