Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[DEPRECATED] Character Movement - Advanced kinematic character controller

Discussion in 'Assets and Asset Store' started by Krull, Jan 17, 2022.

  1. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Logo_White.png


    Character Movement has been developed as a comprehensive alternative to Unity's built-in Character Controller.

    It allows for more realistic character behavior, complete customization and robust ground detection following the same workflow (Move / SimpleMove) for seamless integration into existing projects.

    It can be used for any kind of character (player or AI controlled) and for a wide range of games like, platformer, side scroller, first person, third person, adventure, point and click, and more!

    It offers full control over the update and simulation timestep perfectly suitable for tick-based simulations.


    * If you are looking for a complete character movement package with Character Movement included, check out Easy Character Movement 2


    FEATURES
    • Kinematic character controller.
    • Work the Unity's way, simply call its Move, SimpleMove methods, just like Unity' Character Controller.
    • Cinemachine-based First and Third person examples.
    • Robust ground detection based on real surface normal.
    • Slope Limit Override lets you define walkable areas per-face or even per-object.
    • Configurable walkable area (perchOffset) lets you define the character's 'feet' radius.
    • Capsule-based with Flat Base for Ground Checks option. This avoids the situation where characters slowly lower off the side of a ledge.
    • Ground constraint, prevent the character's being launched off ramps.
    • Configurable Plane Constraint so movement along the locked axis is not possible.
    • Auto-stepping preserving character's momentum (i.e. Its stride).
    • User-defined gravity and up vector for mario galaxy like effects.
    • Physics interaction.
    • Character vs Character interactions.
    • First-class transparent (without further steps needed by you) platforms support, be it animated, scripted, physics based, or even fully simulated objects like vehicles!
    • Collision and Grounding events.
    • Network friendly. Full control over the update and simulation timestep, perfectly suitable for tick-based simulations.
    • Flexible and customizable behavior through callbacks.
    • Simple to use complete API.
    • Full source code included.
    • Garbage-Collector friendly, no GC allocations.


    FAQ

    What is a character controller ?

    A Character Controller allows you to easily do movement constrained by collisions without having to deal with a dynamic Rigidbody.

    A Character Controller is not affected by forces and will only move when you call the Move function. It will then carry out the movement but be constrained by collisions.

    In the past, games did not use a 'real' physics engine like the PhysX SDK (Unity’s underlying physics engine). But they still used a character controller to move a player in a level. These games, such as Quake or even Doom, had a dedicated, customized piece of code to implement collision detection and response, which was often the only piece of physics in the whole game. It actually had little physics, but a lot of carefully tweaked values to provide a good feeling while controlling the player. The particular behavior it implemented is often called the 'collide and slide' algorithm, and it has been 'tweaked for more than a decade'.

    The Character Movement is an implementation of such an algorithm, providing a robust and well-known behavior for character control.

    Who is this for?
    For developers who are familiar with programming and 3D math and want to build their own game mechanics using a comprehensive character controller as their foundation.

    For developers who are willing to replace Unity's Character Controller with a robust and feature-rich alternative but following the same Unity's workflow they know and love!

    For developers who want to learn how to build common character movement mechanics such as walk, jump, fall, crouch, first person, third person controllers and are already familiar with Unity and programming.

    What is the difference between Character Movement and Easy Character Movement 2 ?
    Character Movement is a general purpose character controller analogue to Unity's Character Controller aimed at developers who prefer to build their own character movement and game mechanics from scratch using a comprehensive character controller as their foundation.

    Easy Character Movement 2 adds a higher-level layer on top of the Character Movement component implementing a highly-featured Character-based classes and is aimed at developers who prefer a more complete character movement system out-of-the-box.

    Additionally, ECM2 includes over 40 examples, ranging from using the new input system custom actions, PlayerInput component, first person, third person, target lock, twin-sick movement, dash, slide, ladders, AI, Cinemachine, Bolt, and many more!

    Can I use URP/HDRP?
    Yes, Character Movement doesn’t do any rendering, it’ll work with any render pipeline. The demos are made using the Built-in Render Pipeline, as it’s still the most common denominator, but you can use any RP you prefer.


    HELP AND SUPPORT
    Getting Started Guide
    WebGL Demo
    User Manual
    Walkthrough
    API Reference Download
    Email

    IMPORTANT NOTE ON PACKAGE DEPENDENCIES

    The Character Movement component does not require any external package, however its Demo and the First/Third Person examples require the Cinemachine package to work.

    Please make sure to install the Cinemachine package into your project when importing demos and examples.


    SCREENSHOTS

    Screenshot_01.png

    Screenshot_02.png

    Screenshot_03.png


    ASSET STORE PAGE
    Character Movement
     
    Last edited: Jan 31, 2022
  2. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    It's live at Unity Asset Store, hope you like it!

    Please let me know if you have any questions.

    Cheers,
    Krull
     
  3. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Hey!
    I have a fully developed game using the Default Unity controller, which obviously isn't ideal, running into lots of limitations and wanna move away.
    How hard would it be to move an Existing full game using the Default controller to this controller? Are all the Forces and whatnot the same? Or am I likely gonna need to make a lot of adjustments to get it to work the same?
    I wanna replicate the same controller I already have, so same speeds, jump height, and so on as closely as possible.
     
  4. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @killer1171090,

    Thank you for your interest in Character Movement.

    About your question:

    Definitely, replacing the character controller with character movement is pretty easy.

    In your case, since you are computing all forces and movement code should behave the same, however with CC you pass the displacement vector (e.g: updatedVelocity * Time.deltaTime) to its Move function, while with CM you pass the velocity (e.g: updatedVelocity) to its Move function.

    Now depending on your game requirements you could need further changes in case you are updating your character controller in Update method and using / expecting heavy physics integration, in that case you will need to update your character in sync with the physics engine tick.

    All this is explained in the included walkthrough.

    To illustrate it better, please take a look at the attached script, this is Unity's Starter Assets third-person controller BUT replacing the character controller with Character Movement so you can get a better look of how easy it is to port.

    Let me know if you have any further questions.

    Regards,
    Krull
     

    Attached Files:

    Last edited: Jan 25, 2022
    killer1171090 likes this.
  5. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Well that was suprisingly easy, I changed the CharacterController on the player and the script to CharacterMovement, Replaced The CharacterController.Bounds with CharacterMovement.Collider.Bounds which seems to be the same.
    Removed all the Time.DeltaTime's and done.
    In my case i had to also move some movement code i had in Fixed update to the Update method to get the same forces, but thats specific to my project i have a fairly complicated and precise movement system.

    Still testing things, but it looks like that was it!
     
    Krull likes this.
  6. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    One other questions, does this controller support rotation? I think i saw it somewhere before but i couldnt find any documentation on it.
    like Can i have my character walking on walls and stuff?
     
    Last edited: Jan 25, 2022
  7. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @killer1171090,

    Great! Glad to hear you were able to replace the character controller with Character Movement!

    Sure, you can freely rotate the character and gravity to create a mario galaxy like movement, however please keep in mind to implement this, your movement should be relative to its new up axis.
     
    killer1171090 likes this.
  8. corjn

    corjn

    Joined:
    Feb 6, 2014
    Posts:
    168
    Hey,
    Does Character Movement supports interpolated physics ? I use it a lot in my projects to avoid flickering.
    Thanks :)
     
  9. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @corjn,

    Absolutely. As you can see in the demo scene, all green objects are real physics objects (Rigidbodies, Hinge Joints, Spring Joints, etc).

    However in order to make your character movement in sync with physics, you will need to move your rotation and movement code from Update to a LateFixedUpdate. This LateFixedUpdate is just like the Unity's MonoBehaviour FixedUpdate, BUT its executed AFTER internal physics update, so the character can read the world's current state.

    You can find a complete explanation and examples in the walkthrough and obviously included examples and walkthrough companion examples within the package.

    As part of the following v1.0.1 minor update, I'll add a helper component PhysicsUpdateBehavior that extends the MonoBehaviour adding a LateFixedUpdate so it will be even easier to do physics integrations.

    eg: PlayerController : MonoBehavior -> PlayerController : PhysicsUpdateBehavior

    And put the code you regularly put on FixedUpdate in the new LateFixedUpdate.

    Kind regards,
    Krull
     
  10. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Minor Update Released:

    VERSION 1.0.1

    - Added a 'Getting Started with SimpleMove' guide and example.

    - Minor bugs fixed.
     
  11. tsupra88

    tsupra88

    Joined:
    Dec 15, 2019
    Posts:
    6
    Would it be possible to offset the physics capsule from the root Transform instead of offsetting the root Transform in CharacterMovement similar to the CharacterController.center property? I took a look at the source code but couldn't find anything that would appear to do that. I use that particular property in order to shift the character body so that both the CharacterController's hidden collision capsule and the movement capsulecast are both located at an offset from the character's root transform during runtime.
     
  12. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @tsupra88

    I am afraid it's not possible, could you develop a bit about what you're trying to achieve? If willing to prevent collisions, there are several options included.

    Regards,
    Krull
     
  13. tsupra88

    tsupra88

    Joined:
    Dec 15, 2019
    Posts:
    6
    Current, I have a Player entity that can offset the Unity CharacterController component center property (local position offset from the Transform that the CharacterController component sits on. The internal CapsuleCollider generated by the CharacterController component as well as the Physics CapsuleCast that occurs during the sweep phases can be freely updated relative to the Transform pivot by providing the center property offset. This allows for the capsule to be spaced at any point within a box volume, but the capsule itself will dictate movement collisions as well as other objects falling and hitting that kinematic Rigidbody Collider. For example, if I have the capsule +1meter in front of the Transform's pivot point, it can run into a wall and prevent movement. If I move that capsule back to the 0,0,0 point, I can then move the character rig forward by 1 more meter. The Radius and Height on the CharacterMovement component work as I expected, but the Center property is critical to the project I'm working on.
     
  14. tsupra88

    tsupra88

    Joined:
    Dec 15, 2019
    Posts:
    6
    The rest of the code I have currently hooks into the CharacterController component and alters its center value at runtime where I can move the character capsule around a box platform. Shifting the center value about will determine what it is allowed to hit/dodge. This allows for both the platform to be controlled and moved, as well as the character standing on the platform. However, only the character will bump into walls when Move() is called. Maybe the attached image will make the issue more clear. The wireframe is offset from the Transform point and will handle collision when moving as well as represent what other objects will hit. The 2nd part with the objects being hit is not too much of an issue since I can just move the CapsuleCollider component center. The issue is the Move() command where I currently can't do that same offset with CharacterMovement (at least I can't find it if it is there).
     

    Attached Files:

  15. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    I see, while the current version does not support offset, it already includes a vast set of collision detection and ground detection (ie. Raycast, OverlapTest, CheckHeight, MovementSweepTest, ComputeGroundDistance, FindGround, etc), actually the same used internally by the system are exposed.

    Those functions are there to help to implement custom custom game mechanics like, mantle, vault, ledge grab, etc. and should help in your case.

    For example, to test 1m in forward direction from your current position you could use the MovementSweepTest, i.e:

    Code (CSharp):
    1. bool blockingHit = _characterMovement.MovementSweepTest(characterPosition, transform.forward, 1, out CollisionResult hit);
    The same to check if the target position is walkable you could use the ComputeGroundDistance or FindGround, the difference between this is the latter do a perch check while the former don't.

    All these functions let you test any arbitrary position just like if the character was moved.
     
  16. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Minor Update Released:

    VERSION 1.0.2

    - Added Assembly Definition.

    - Minor bug fixes.

    - Fixed. CharacterMovement.detectCollisions not re-enabling collider.
     
  17. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Noticing a bug that kinda just randomly started happening, seemed fine before.
    On Moving platforms the controller seems to "slip" the amount it sleeps seems to be tied to fps, the higher the fps the more it slips any ideas? It's weird though, sometimes it's completely fine, but if I click on a game object to inspect some components while the games running it might break again, but sometimes opening components up fixes it.
    So something weird probably related to performance could be Editor related. I tried on 2019.4.0f1 and 2019.4.35f1 same issue
     
    Last edited: Feb 11, 2022
  18. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Mmm thats strange, however:

    A cause for platforms slippery is due platform / character execution order. CM has been designed so the character is moved after the platforms have been updated, so he can read its current state. So if you are moving your character in Update, make sure you move your platforms in Update too, however when moving a platform in Update method, make sure you update its kinematic rigidbody position too or its collider will not be updated.

    While character movement can work in Update without any issues (as long as you follow the above guidelines), my recommended workflow is using the LateFixedUpdate (as commented in docs) as this will give you seamless and rock-solid platforms and physics integrations without you having to do any special setup or write custom scripts.

    Could you develop a bit about how you are implementing your platforms, I mean are you calling the Move function within your platform?
     
  19. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Im using the Moving platforms from your example scene specifically the Blue ones. I am updating in the Update function though.
    All my code and whatnot from the original project was all inside Update() Im not sure what would be required port over to LateFixedUpdate() Since all our movement math and everything has been created and fine tuned inside the Update method.
     
  20. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Ah I see, yes the demo scene updates the platforms in its FixedUpdate and the Character in its LateFixedUpdate method, so both are updated in-sync in a frame rate independent interval.

    In your case since you are using Update, you will need to update your platforms in its Update method but make sure those are updated before the character so both are updated using the same time.

    I attached the modified platform example code, basically uses the Update instead of the FixedUpdate to move the platform and adds a default execution order so the platform is moved before the character.

    Please take a look at the walkthrough guide from page 16 to 19 for a more in depth explanation of using update vs fixed update and how it affects game physics in general.

    Last but not least, let me know if need any further assistance

    Regards,
    Krull
     

    Attached Files:

    killer1171090 likes this.
  21. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Thanks, but the new script doesn't appear to fix the issue, he's still sliding quite a bit.
     
  22. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Well that tells there's another cause for it but hard for me to figure it out without access to the whole picture, as you commented it was not happening before.

    I created a test scene to let you simulate different frame rates and choose to update using a frame rate independent or frame rate dependent. Make sure to enable interpolation in platforms and characters when using fixed update, and disable it when using update.

    Having said that, I strongly suggest you move your character using a frame rate independent or at least a semi-fixed as it gives you many advantages as you can read here
     

    Attached Files:

  23. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Tried moving to Fixed update, surprisingly it seems it's become More FPS dependent, speed changes drastically based on fps now, It did fix some Physics interaction bugs we were having but also didn't fix the sliding.
    Do you have Discord? I can share some of the code and whatnot there to give you a better idea what were doing. The fact that it was fine before is really strange
     
  24. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    The sliding is really weird, it's not consistently sliding. Even at the same fps, sometimes it slides a lot, sometimes it's perfect.

    Sometimes it's perfect like this:
    https://gyazo.com/c7bb1bb1d1dc4e7001f70549de5a89fc.mp4
    But other times it's Jittery and sliding like this:
    https://gyazo.com/92aad4b61af20d9bae09cf56f72b0c1e.mp4
    While it's jittering if I stay on there long enough I do eventually fall off
    The Camera angle is different between the two but that's not the cause, To start the jittering I actually opened a Component on the Player in the inspector, that was enough to start the jitter for some reason. This issue exists in Builds as well.
     
    Last edited: Feb 16, 2022
  25. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @killer1171090,

    FixedUpdate is frame rate independent, it is called at a fixed rate more or less times per second as needed, but completely frame rate independent and provides rock solid physics interactions as you can see in demos and included examples.

    I suggest you try the demo character in your project to try to isolate your issue, also make sure you update your camera in the LateUpdate method and even try disabling the post processing effects.

    I don't have a discord server but you can contact me to support email, please share your player controller so I can get a better look at what could be causing your issue.
     
  26. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    I turned off everything in my character controller, The only interaction with CharacterMovement now is a Downward Force. using your LateFixedUpdate coroutine from the Demos. The camera is using Late Update with no Post Processing.
    https://gyazo.com/aa43f9a8f327078b97604c3744d65f07.mp4
    The jittering does appear to be something to do with the Camera updating since it doesn't do it in the Scene view at least not noticeably so ignore that.


    Code (CSharp):
    1.     private void OnEnable()
    2.     {
    3.         if (_lateFixedUpdateCoroutine != null)
    4.             StopCoroutine(_lateFixedUpdateCoroutine);
    5.  
    6.         _lateFixedUpdateCoroutine = StartCoroutine(LateFixedUpdate());
    7.     }
    8.  
    9.     private void OnDisable()
    10.     {
    11.         if (_lateFixedUpdateCoroutine != null)
    12.             StopCoroutine(_lateFixedUpdateCoroutine);
    13.     }
    14.  
    15.     private IEnumerator LateFixedUpdate()
    16.     {
    17.         WaitForFixedUpdate waitTime = new WaitForFixedUpdate();
    18.  
    19.         while (true)
    20.         {
    21.             yield return waitTime;
    22.             OnLateFixedUpdate();
    23.         }
    24.     }
    25.  
    26.     public void OnLateFixedUpdate()
    27.     {
    28.         // tried both of these
    29.         //CharacterController.Move(base.transform.up * m_gravity, Time.fixedDeltaTime);
    30.         CharacterController.Move(base.transform.up * m_gravity);
    31.     }
     
    Last edited: Feb 17, 2022
  27. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    I managed to reproduce the issue with one of your demo scenes by significantly dropping the fps using particles in the background. (It was Slightly noticable without dropping fps still)
    https://gyazo.com/e437828c9cbdc7158287f4371f297731.mp4
    The only difference here though as I was unable to make the character fall off the platform, in my scene he does eventually fall off.
     
    Last edited: Feb 17, 2022
  28. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    What you notice in the demo scene is unity interpolation as obviously the visuals lag behind, you can visualize it easier using the Physics debugger so it shows the rigidbodies and colliders correctly postioned while visuals lags behind that's why characters stay on platform, as you can see on image below:

    upload_2022-2-16_21-36-23.png

    Where blue objects are real positions (rigidbody, collider, etc).

    Honestly, as much as I tried to help you, it seems you are not satisfied with CM, and IMHO your issue is external to CM (widely tested and backed by a huge number of users) so all left to do on my side is offer you a full refund.

    Please contact me to support email with your invoice number and Ill issue the refund for you.

    Thanks,
    Oscar
     
    Last edited: Feb 17, 2022
  29. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
  30. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Do you even read what I commented?

    Right, obviously that's not right, that's your issue, the 'issue' does not happen on demo scenes or examples as you can try, nor reported before by any other user (thousands) or found during beta testings.

    Look at the following video, I jump on an edy vehicle fully simulated vehicle as a moving platform, ROCK SOLID, no slide, no issues at all.



    About your issue, I offered you several working examples and solutions and even to take a look at your controller in order to solve your issue, and just ignored my offering and kept repeating the same here on forums without ever reaching me through email, so I offered a full refund, as simple as that.
     
  31. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    Yes, I read what you said, and I asked after if what I was experiencing was normal, if so then i would have agreed and taken a refund, I didn't think Interpolation could cause that so I wanted to ask. I tried all your solutions, I moved platform updating to Update() I moved the controller to Fixed Update, which made things somehow more fps dependant, after adding a Time.FixedDeltaTime into the Move() call did improve things but its possible I messed up the implementation so I also Tried copy pasting your demo controllers code in, everything you told me to do hasn't worked, or at least my attempt at them didn't work. That snippet of code I sent IS the character controller that I used to reproduce the issue, it's just a copy-paste of your controller with only gravity. that reproduces the bug inside our scene it doesn't in your test scene. I would prefer not to take a refund, I would just like to figure out why our setup is behaving differently from your demo scenes. Email is kinda a pain for me I offered discord but you said you couldn't so I thought well just stick to talking on here.

    Well doesn't matter, I just figured it out, Rigidbody Interpolation on the Character controller caused it. I have no idea why even after deleting all my movement code having Rigidbody Interpolation on the character breaks Moving platforms but it works fine on your demo characters.
    I don't know what the difference is between My setups and your demo setup. I also don't understand why even though interpolation on the rigid bodies for both the Platform and Controller is set to None, does there still seem to be visible Interpolation still causing an apparent slide however it's at least not a physical slide just a visual one.

    Even that Edy's vehicle physics video I can't see any interpolation or anything it looks perfect, but the Demos in my project arent perfect the interpolation is obvious even when the moving platform is really slow.
     
    Last edited: Feb 17, 2022
  32. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Are you using root motion or OnAnimatorMove? What are your character components?

    Please do a quick test, set the fixed timestep to a low fps, like 0.05 (20 FPS) and completely disable the interpolation on platforms and character, and make sure both are moved using a fixed interval, i.e. FixedUpdate for the platform and LateFixedUpdate for the character. The result should be both moving really choppy as it's being updated at a 20 fps rate without interpolation. If you notice something smooth, then there is one script moving one of those in a Update, as Character Movement does not do any interpolation and completely relies on Unity's interpolation.

    By other hand, if you move both platforms and character(s) in Update, please make sure to disable interpolation as it definitely will cause some issues and is not needed at all.
     
    killer1171090 likes this.
  33. killer1171090

    killer1171090

    Joined:
    Feb 23, 2013
    Posts:
    145
    It does make it noticeably jittery, I think the demo I used before the might of been using an Update() which might explain why I was getting weird results. IM using the "7.- Physics Interaction" one now

    I have a lot in my project that could be interfering there, I have a few different animation components and systems on my character. as long as it's not a physical slide it's not really a problem for me, I can figure it out from here. thanks!

    I guess in Update() the rigid body interpolation throws off the controller's sense of location.
    Probably fixed it with all the things we tested multiple times, but there seem to be two types of "Sliding" the Physical one which is what I was getting, and a visual Interpolation which is what it is just now. Whenever I saw either of those I assumed it was still broken, didn't realize there were two and that moving to FIxedUpdate and stuff very well could have fixed the Physical one, didn't test it.
     
    Last edited: Feb 18, 2022
    Krull likes this.
  34. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Update Released

    VERSION 1.0.6
    • Added CharacterMovement State data. This is the data needed to sync across the network ensuring proper simulation continuity.
    • Added networking examples for Major Unity networking libraries like Photon Fusion, FishNet, Mirror, etc. Where both, the Photon Fusion and FishNet examples implement server authoritative movement with client side prediction and reconciliation.
    • Minor bug fixes.
     
  35. b1gry4n

    b1gry4n

    Joined:
    Sep 11, 2013
    Posts:
    146
    hello, i stumbled on this thread while searching for a character controller that handles client side prediction. i noticed that your controller handles moving platforms very well. i was wondering how this holds up while being networked. a common issue in networking moving platforms and syncing player positions is the desync/delay of the position being updated while a non local player is being updated. for example, when updating a non local client while youre not the server, the character appears to sink in or float above vertically moving platforms or slide on horizontal ones. i noticed your asset comes with some networking examples, do you include moving platforms in these examples?
     
  36. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hello @b1gry4n ,

    Thank you for your interest in Character Movement!

    About your question:

    While it includes full client side prediction and reconciliation examples for several networking solutions, it does not include (yet) networked platforms examples yet as the current implementation does not handle this special case (networking wise) mostly because as you comment it requires special handling and extra care to implement it well and sometimes the approach is even game dependent.

    Worth note the included example method "works" with networked platforms but not in a rock solid way as the non-networked version.

    Let me know if you have any further questions.

    Regards,
    Krull

    On and by the way :D, Here is a great video from the Photon guys, explaining moving platforms in a networking environment for those interested in this topic.
     
  37. Broudy001

    Broudy001

    Joined:
    Feb 12, 2020
    Posts:
    72
    Hi, @Krull, is there an existing method that tells me the collision is in front of the character? I can see hitlocation but not forward, only sides above below? I can do it with a raycast etc or use the movement sweep test, but figured if it was already somewhere that I could plug into would be easier. It's just to do wall sliding
     
  38. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Broudy001,

    It will report all contacts found during the last Move call through the CharacterMovement Collided event or iterative using the GetCollisionCount() and GetCollisionResult() methods. From there you can use the CollisionResult point and normal to determine the hit WRT to capsule.

    Worth noting these are hits found during the last movement (already resolved), so if you want to implement some kind of 'blind stick' behavior, it's better to handle it separately, using CharacterMovement Raycast, MovementSweepTest etc. methods to look ahead a given distance.
     
    Broudy001 likes this.
  39. Thunderik

    Thunderik

    Joined:
    Apr 28, 2020
    Posts:
    32
    Hi, what is the role of the Rigidbody component? I have no intention for one entity to push other entities
     
  40. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Thunderik,

    CM is a kinematic character controller, as such it is only moved when its Move method is called, pretty much like Unity's built-in CC. The kinematic rigidbody is there so we can update the capsule collider at our will, in this case each Move method call.
     
    Thunderik likes this.
  41. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Hi @Krull, quick question:

    How's perf? I'm looking for a simple character controller for ~1000 actors that does NOT use ECS (I'm kind of forced into Unity 2022.x so no ECS support for me for a while) and I'm coming up a bit dry. I've bought 4 different character controllers so far, the best performance I can get is from Ootii's Actor Controller, ~25ms for 1000 actors moving around. Not quite good enough for my needs but it's close.

    edit: I answered my own question. Perf is real good. ~3.5-5ms with 1000 characters in my simple test setup which was the Advanced Character Controller example (with a simple box instead of the Room mesh collider) with the SyntheticBenchmarkController spawning 1000 characters from the Performance example.

    Awesome stuff! Let's see if controller #5 works out eh? ;)
     
    Last edited: Oct 4, 2022
    Krull likes this.
  42. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @UnkelRambo,

    Thank you for purchase it, was about to answer your question but you already beat me hehe.

    Yes, on my dev machine (i7 + GTX 1080 TI), it can run 1000 characters at about ~130 FPS (~7.5) ms, 2000 characters at about ~65 FPS (15.4 ms) but worth note its a synthetic benchmark pretty much like the included in KCC and rendered with lowest quality to focus on characters performance only.


    Let me know if I can be of further assistance.

    Regards,
    Krull
     
  43. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Hi @Krull, quick question, but first some context:

    I'm using MLAPI (now Netcode for Gameobjects) and after switching to this movement controller I noticed my characters IsGrounded check is failing for remote clients. I've only dug into this for an hour or so before losing power yesterday (lol Washington weather) but I was curious if you had any suggestions? I was avoiding sending character state like "IsGrounded" or "Velocity" across the wire as they're easily derived on remote clients and my network bandwidth requirements are already pretty tight (for 1000 characters.)

    So far my attempt has looked a little something like so:

    1. Create a new "Non-Authority Update" method that gets called in a custom update loop on non-authority clients
    2. NonAuthorityUpdate() so far is doing almost exactly what SetPositionAndRotation is doing, without actually updating the transform.
    3. This *mostly* works, but the issue I'm seeing is that a remote character's "is grounded" state is slightly out of alignment with the server. I ended up disabling the call to PauseGroundConstraint() on remote clients because that looks like it's set again in the Move function, which isn't called on remote clients. It *works*, but I'm unsure of the consequences.

    Here's my *very simple* code to update remote clients:

    Code (CSharp):
    1.        
    2.         public void UpdateNonAuthority()
    3.         {
    4.             // Manually derive velocity and others here
    5.             velocity = (position - updatedPosition) / Time.deltaTime;
    6.             UpdateCachedFields();
    7.             FindGround(updatedPosition, out FindGroundResult groundResult);
    8.             {
    9.                 UpdateCurrentGround(ref groundResult);
    10.                 UpdateCurrentPlatform();
    11.             }
    12.         }
    13.  
    Like I said I'm only just now looking into this, but it works well enough for my needs. I also ended up deriving Acceleration and Velocity for remote clients (for animating walking and such) since those aren't set explicitly in the controller on remote clients.

    I was curious if you had any suggestions or things to watch out for? Or is there something obvious that will be missing/broken by doing this?

    Hopefully this is useful for anybody else using Netcode :D
     
    Last edited: Oct 11, 2022
    Krull likes this.
  44. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @UnkelRambo,

    Sorry for the late reply and thank you for sharing your solution with us :D!

    Well honestly my experience with MLAPI is very limited, however the way it works on other network solutions, is syncing the character state (something not possible in your case), this is required because while the Move method 'takes' from its current position, internally it re-orients the velocity along the last movement (its current) normal to ensure proper motion continuity.

    Now for your solution, I think it could work well but to some degree will be dependent on your 'ground', if mostly flat I don't think will cause any real issue because as I commented, the movement starts from the current transform position and rotation and moves along its velocity.

    Another possibility is to keep a local list of 'saved moves' (mostly grounding info, velocity, like CM State) including the server tick that generated this movement, later when new data from the server is received, do a roll-back using the current server tick to restore the saved move from your saved list, using the server tick as index.

    Regards,
    Krull
     
  45. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Thanks for the reply @Krull ! OK one more for you...

    I'm changing the scale of my objects at runtime and I've noticed the move controller doesn't consider scale when doing the capsule casts for checking movement.

    I literally just started looking into this, which I imagine shouldn't be too difficult a fix, but is this something you plan on officially supporting or am I missing something obvious?

    Thanks!
     
  46. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @UnkelRambo,

    Yes the scale is not supported and not recommended to modify it, instead you change the character dimensions (ie: radius, height, etc).

    You can use the CharacterMovement component height, radius properties, or its SetHeight, SetDimensions methods.

    Regards,
    Krull
     
  47. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Oh hey, I got this working *relatively* easily, it works for my needs anyway, and it only took a few hours (mostly debugging.) Though I haven't tested every little edge case, so user beware. The TLDR is that I added a "uniform scale" field that gets set in UpdateCachedFields(). I then went through and changed the "scale affected properties" (like radius, height, step offset, etc) multiply by that uniform scale and bob's your uncle! I had to go through several places that were using the underlying field and replace them with the properties, but it was all pretty simple in the end. Non-uniform scale isn't something I need so I'm not worried about it, but it would complicate matters with the capsule casts.

    Funny enough, doing this made me realize I was misinterpreting a couple fields on the CharacterMovement script so my ledge walking now feels MUCH better :D
     
    Krull likes this.
  48. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @UnkelRambo

    Thats great! I think one old unity controller (cant rememeber its name atm) did something similar to your approach in order to support scaling, so its a good approach :).

    Regards,
    Krull
     
  49. tomfulghum

    tomfulghum

    Joined:
    May 8, 2017
    Posts:
    78
    Hi @Krull
    I was wondering if you could help me with a small problem. As you can see in the video below, i have placed one of the dynamic cubes in the demo scene on one of the moving platforms. The only thing I've changed is disabling physics interactions on the first person player controller.

    What happens is that when the platform is moving in the direction the player is standing relative to the cube while the player is also giving input to move in the opposite direction, the cube is pushed off the platform.

    Do you have an idea on how to solve this, as in actually eliminate all physics interaction (except collision) between the dynamic body and the player?

    Thanks in advance!

     
    Last edited: Jan 25, 2023
  50. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @tomfulghum

    Hi,

    Yes, that's a hard case to solve and somewhat expected.

    The CharacterMovement component resolve its collision and overlaps as it moves and keeps a 'shell radius tolerance' away from objects trying to prevent, physical contacts (PhysX), while moved on the platform PhysX engine will register the contacts between the character's capsule and the green cube (dynamic rigidbody), and since internally kinematic rigidbodies (the character) are pretty much dynamic rigid bodies but with infinite mass, Physx will resolve the green cube (dynamic rigidbody) vs character's capsule collider (kinematic collider) contact.

    I am afraid there is not an easy solution for this case, you can somewhat 'minimize' this, making the cubes ignore the character's capsule, so physx do not resolve this contacts, and that's one of the reasons, the CharacterMovement includes two functions to ignore collisions, CapsuleIgnoreCollision and IgnoreCollision, the former will ignore collisions at PhysX level, while the later will cause the collide and algorithm to ignore specific colliders, or all colliders in a specific rigidbody.

    But as commented, it 'works' but it's not a 100% solution.