Search Unity

[Released] Kinematic Character Controller

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

  1. FerdyHoefakker

    FerdyHoefakker

    Joined:
    Aug 17, 2019
    Posts:
    1
    I am running into an issue when implementing jumping. I tried making my own controller, as a learning experience, but slopes are such an intense pain in the ass I gave up and tried implementing this asset.

    One thing I did get right on my own version however, was the jump heights. I gave the controller 2 variables:
    • jump height in units
    • time to reach apex
    Using these 2 variables, I calculated the needed gravity and velocity. After that, when jumping, my capsule jumped up for the specified amount of units. The KCC implementation however, always seems to be off by some margin.How much this margin actually, differs on the set jump height and time to reach apex.

    At 1 unit, and .4s it's small but noticeable. But this offset increases the higher I set the jump hight. At a jump height of 2 units, it'll be closer to .25 units higher. And at 4 it's closer to .5 units higher. Same thing with the time to apex. The lower the value, the higher the discrepancy.

    In the UpdateVelocity method, I substract gravity * deltaTime from the Y velocity when not grounded. When a jump is requested, I set the Y velocity to my jump velocity.

    Code (CSharp):
    1. void Start()
    2. {
    3. _gravity = (2 * _jumpHeightInUnits) / Mathf.Pow(_timeToJumpApex, 2);
    4. _jumpVelocity  = _gravity * _timeToJumpApex;
    5. }
    6.  
    7. void Update()
    8. {
    9.         GetInput();
    10. }
    11.  
    12. private void GetInput()
    13.     {
    14.         _currentInput = InputManager.Instance.CurrentInput;      
    15.         if (_currentInput.jumpButtonPressed)
    16.             _state.JumpRequested = true;
    17.     }
    18.  
    19. public void AfterCharacterUpdate(float deltaTime)
    20.     {
    21.         if (_jumpConsumed)
    22.         {
    23.             _jumpConsumed = false;
    24.         }
    25.     }
    26.  
    27. public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
    28. {
    29. // Handle Jumping
    30.         if (_state.JumpRequested)
    31.         {
    32.             // check if we're allowed to jump
    33.             if (!_jumpConsumed)
    34.             {
    35.                 // Makes the character skip ground probing/snapping on its next update.
    36.                 // If this line weren't here, the character would remain snapped to the ground when trying to jump. Try commenting this line out and see.
    37.                 Motor.ForceUnground(0.1f);
    38.  
    39.                 currentVelocity.y = _jumpVelocity;
    40.  
    41.                 // reset jump stuff
    42.                 _state.JumpRequested = false;
    43.                 _jumpConsumed = true;
    44.             }
    45.         }
    46. }
    47.  
    I must be overlooking something (potentially/probably stupid), but I just can't figure it out. The screenshot shows what I'm talking about. Left capsule uses the KCC, right the Unity CC. Jump height is set to 2 units and time to apex to .4 for both.

     
  2. Marsunpaisti

    Marsunpaisti

    Joined:
    May 3, 2018
    Posts:
    22
    The store page did not contain much information about a few things, so I have a few questions before I buy.

    Is there something built-in for character-to-character and character-to-rigidbody interaction? I'd need to push objects (rigidbodies) with characters, and if all my entities are going to be using this controller I'd need large groups of AI entities not simply get stuck on each other but instead I need to something like a repulsive force between them to make them behave a little fluid-like when clumped up together. I suppose I cant use AddForce since its kinematic. Are there examples or design patterns for these use-cases?

    Also I'm probably going to need outside forces such as knockback effects on the entities and I'm wondering if such a thing is easy to implement with this controller. So that some knockback force applied on the player would not immediately get overridden by the controllers movement. For example if I'm moving north in a straight line, If I got knocked back south by some impulse-like force, it'd need to add together the effects of both forces so neither one simply overwrites the other. Is this feasible with this controller?
     
  3. w409544041

    w409544041

    Joined:
    Aug 3, 2017
    Posts:
    52
  4. Fr2

    Fr2

    Joined:
    Jan 19, 2013
    Posts:
    39
    In a couple of situations in my game I'd like to be able to make my KCC character follow a path (for example, a bezier spline divided into waypoints). It's the kind of situation where my character might walk around a desk to face a computer, or walk around a car to open the trunk.
    One option might be to use Motor.SetPosition() after using basic bezier utilities to determine the position and rotation at any given point along the curve.

    But is there a better way? The majority of movement is driven from an MLAgents AI which calls
    KinematicCharacterDriver.SetInputs() and ideally I'd like to use the same method when pathfinding to keep the design simple. I noticed there are a couple of mentions of Navmesh integration with KCC, but I couldn't find any examples.
     
  5. alexanderFabula

    alexanderFabula

    Joined:
    Sep 1, 2019
    Posts:
    22
    Hey

    I'm having trouble with step handling when going down from a step where the floor is at an angle or if there is a small gap between colliders. In both cases GroundStatus.IsStableOnGround is set to false.

    I can get it to work if I set Ledge and Denivelation Handling to false or if I set the Max velocity for ledge snap to something higher than my movement velocity. But both results in the character losing its forward velocity when running off a ledge and falling straight down.

    I have also played around with Ground Detection Extra Distance but I'm not sure I fully understand what it helps with.

    Is there any way to handle these cases, so that the ground detection becomes more stable? I have posted my controller settings below for information





     
  6. ioncannonstudios

    ioncannonstudios

    Joined:
    Apr 5, 2014
    Posts:
    2
    So I'm running into quite the odd bug when trying to transition over to KCC from my own character controller. When I run the scene, the character doesn't budge whatsoever. But, when I hit the keybinding I've set to reload the current scene, everything works perfectly. I have no idea what could be causing such an issue. Every reload works fine, but every single time I start the scene fresh, I get no character movement until I reload the scene during runtime, Any help on what could be wrong, even pointing me in the right direction, would be great. Thanks in advance!
     
  7. ioncannonstudios

    ioncannonstudios

    Joined:
    Apr 5, 2014
    Posts:
    2
    AH! I didnt realize I needed the motor running before the character controller. Then I saw all the onenable stuff in the motor script and guessed it was an ordering problem. Just letting anyone else who needs to loadscene before it works. Great controller thus far!
     
  8. BlackBunnyCrankn

    BlackBunnyCrankn

    Joined:
    Mar 21, 2020
    Posts:
    21
    In the example level there are blue boxes that are Is Kinematic = false with a box collider that he pushes around in the example video. When i play the level when you try jump on top of the Movable\pushable boxes the character gets kind of buggy and just falls through them.

    If you wanted to use this system and implement the same kind of style (boxes you can push) but can also jump on top of with weight\mass differences is it even possible with this controller? Or does it require significant coding\physics knowledge.
     
  9. thethirdkate

    thethirdkate

    Joined:
    Aug 17, 2014
    Posts:
    3
    Dynamic rigidbodies on moving platforms

    Hi, sorry if this has been asked previously, I searched the thread for posts relating to "moving platforms" and couldn't see it! I'm new to this stuff, so would appreciate pointing in the right direction.

    How do I make it so that a moving platform (e.g. as in the walkthrough scene) carries a dynamic rigidbody object (e.g. a crate or ball) along with it? It works perfectly fine with the player, but with other objects they get pushed by the platform but they don't stick to it, e.g. if it moves sideways with a crate on top. Is there a way to set it up so this works by default or do I need to write something custom for it?

    Thanks!
     
  10. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    If the ball or the crate aren't using a kinematic character controller, they will not be affected by the platform. You have to write something custom for it, I havent tried it but maybe this helps

    If your player also has a rigidbody make sure to ignore it in the oncollisionenter and exit part of the tutorial script by comparing the tag or something
     
  11. jndev1

    jndev1

    Joined:
    Jun 26, 2021
    Posts:
    1
    I figured I'd share it since the switching between orientation modes is not built to work at runtime,
    requiring instead that you change the orientation mode in the editor.

    I made a few modification and commented explaining them on the scripts to make the camera more WoW like:

    Left Mouse orbits around the character moving with keyboard input
    right mouse button rotates the character to the camera look direction, for strafing or walking 'backwards'
    It works with the modification I made, if anyone knows a better method I'd love to read it!

    What I havent figured out is how to make the left Mouse orbit not turn the player if held down while running forward without breaking things, if anyone can share a fix Id appreciate it!

    Set Character Controller Orientation Method to Towards Movement by default in the Unity inspector, then:

    Changes to Update() on Player script:
    Code (CSharp):
    1.  
    2.         private void Start()
    3.         {
    4.             //change cursor lock to None at start
    5.             Cursor.lockState = CursorLockMode.None;
    6.          }
    7.  
    8. private void Update()
    9.         {
    10.  
    11.             //Lock cursor on left mouse down, this will trigger camera orbit
    12.             //but does not rotate character forward with camera
    13.             if (Input.GetMouseButtonDown(0))
    14.             {
    15.                 Cursor.lockState = CursorLockMode.Locked;
    16.  
    17.             } else if (Input.GetMouseButtonUp(0))
    18.             {
    19.                 Cursor.lockState = CursorLockMode.None;
    20.             }
    21.  
    22.             //lock cursor on right mouse,
    23.             //this will rotate character with camera orbit direction
    24.             //also see HandleCharacterInput() method in this script for CharacterController update on right mouse click event.
    25.             if (Input.GetMouseButtonDown(1))
    26.             {
    27.                 Cursor.lockState = CursorLockMode.Locked;
    28.             } else if (Input.GetMouseButtonUp(1))
    29.             {
    30.                 Cursor.lockState = CursorLockMode.None;
    31.             }
    32.  
    33.             HandleCharacterInput();
    34.         }
    Changes to HandleCharacterInput() in Player script:
    Code (CSharp):
    1.         private void HandleCharacterInput()
    2.         {
    3.             PlayerCharacterInputs characterInputs = new PlayerCharacterInputs();
    4.  
    5.             // Build the CharacterInputs struct
    6.             characterInputs.MoveAxisForward = Input.GetAxisRaw(VerticalInput);
    7.             characterInputs.MoveAxisRight = Input.GetAxisRaw(HorizontalInput);
    8.             characterInputs.CameraRotation = CharacterCamera.Transform.rotation;
    9.             characterInputs.JumpDown = Input.GetKeyDown(KeyCode.Space);
    10.             characterInputs.CrouchDown = Input.GetKeyDown(KeyCode.C);
    11.             characterInputs.CrouchUp = Input.GetKeyUp(KeyCode.C);
    12.  
    13.             //updates CharacterController script when right mouse is pressed down,
    14.             //to change camera orientation to rotate with mouse while pressed
    15.             //see PlayerCharacterInputs structs and SetInputs() method in CharacterController script
    16.             characterInputs.MouseLookRot = Input.GetMouseButton(1);
    17.  
    18.             // Apply inputs to character
    19.             Character.SetInputs(ref characterInputs);
    20.         }
    Add the new MouseLookRot to PlayerCharacterInputs on CharacterController script:
    Code (CSharp):
    1.     public struct PlayerCharacterInputs
    2.     {
    3.         public float MoveAxisForward;
    4.         public float MoveAxisRight;
    5.         public Quaternion CameraRotation;
    6.         public bool JumpDown;
    7.         public bool CrouchDown;
    8.         public bool CrouchUp;
    9.  
    10.         //added boolean to check if right mouse button is pressed,
    11.         //used to change orientation see SetInputs()
    12.         public bool MouseLookRot;
    13.     }

    Then in SetInputs() method in Charactercontroller add this if else statement inside the switch:
    Code (CSharp):
    1.             switch (CurrentCharacterState)
    2.             {
    3.                 case CharacterState.Default:
    4.                     {
    5.                         // Move and look inputs
    6.                         _moveInputVector = cameraPlanarRotation * moveInputVector;
    7.  
    8.                         //if right mouse button is held down inverts the Orientation method
    9.                         //this will make right mouse turn the character while held
    10.                         if (inputs.MouseLookRot)
    11.                         {
    12.                             switch (OrientationMethod)
    13.                             {
    14.                                 case OrientationMethod.TowardsCamera:
    15.                                     _lookInputVector = _moveInputVector.normalized;
    16.                                     break;
    17.                                 case OrientationMethod.TowardsMovement:
    18.                                     _lookInputVector = cameraPlanarDirection;
    19.                                     break;
    20.                             }
    21.                         }
    22.  
    23.                         //else if right mouse button not held Orientation is keyboard bound
    24.                         else
    25.                         {
    26.                             switch (OrientationMethod)
    27.                             {
    28.                                 case OrientationMethod.TowardsCamera:
    29.                                     _lookInputVector = cameraPlanarDirection;
    30.                                     break;
    31.                                 case OrientationMethod.TowardsMovement:
    32.                                     _lookInputVector = _moveInputVector.normalized;
    33.                                     break;
    34.                             }
    35.                         }
     
    Last edited: May 30, 2022
  12. thethirdkate

    thethirdkate

    Joined:
    Aug 17, 2014
    Posts:
    3
    Thanks, I was hoping there would be an easier way as this side of coding is a bit new to me (hence looking for a character controller asset in the first place!). That tutorial looks useful though, I'll check it out.
     
    Vincent454 likes this.
  13. minkee5004

    minkee5004

    Joined:
    May 20, 2020
    Posts:
    2
    This can be easily solved by enabling "Edit -> ProjectSettings -> Physics -> Auto Sync Transforms".
     
  14. unity_3aKtbgwtjko-Ww

    unity_3aKtbgwtjko-Ww

    Joined:
    Jun 2, 2020
    Posts:
    1
    Hey y'all,

    Hope you're well! Just wanted to ask a question a straightforward question. Firstly, I really love using it, phenomenal job. Though, I had a question regarding applying gravity (Forces perpendicular to surfaces in general I suppose). I shared my set-up below, where I just pass in various acceleration functions and integrate them in the UpdateVelocity. I noticed that gravity would always contribute some lateral movement, say for example I jump, land, and then theres a slight push to some direction on the XZ-plane (When gravity is only applied when IsOnStableGround == false). This happens for any arbitrary downwards vertical force. I couldn't quite figure out what the issue was, so my temporary solution, as to continue applying gravity while grounded to give some feeling of momentum on slopes, was just apply its component tangent to the slope.

    I don't know if this is expected behavior or not, I noticed that in the example controller, gravity is only applied when not on stable ground, so thought I might as well ask here.

    Code (CSharp):
    1.     public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
    2.     {
    3.         float currentVelocityMagnitude = currentVelocity.magnitude;
    4.  
    5.         Vector3 effectiveGroundNormal = Motor.GroundingStatus.GroundNormal;
    6.  
    7.         // Reorient velocity on slope
    8.         if (Motor.GroundingStatus.IsStableOnGround)
    9.         {
    10.             currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) * currentVelocityMagnitude;
    11.         }
    12.  
    13.         // Calculate target velocity
    14.         Vector3 inputRight = Vector3.Cross(moveInputVec, Motor.CharacterUp);
    15.         Vector3 reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized * moveInputVec.magnitude;
    16.  
    17.         moveInputVec = reorientedInput;
    18.  
    19.         // Velocity Setters
    20.         if (_shouldSetVelocity)
    21.         {
    22.             currentVelocity = _setVelocity;
    23.             _shouldSetVelocity = false;
    24.         }
    25.  
    26.         // Velocity Clean Ups (Like Setters but methods)
    27.         if (velocityCleanUpCallbacks != null)
    28.         {
    29.             currentVelocity = velocityCleanUpCallbacks(currentVelocity);
    30.         }
    31.        
    32.        
    33.         // Force ungrounding when adding external forces (accumulates in _internalVelocity)
    34.         if (_internalVelocity.sqrMagnitude > 0f)
    35.         {
    36.             if (Vector3.Dot(_internalVelocity, movementData.Gravity) > 0)
    37.                 Motor.ForceUnground();
    38.             currentVelocity += _internalVelocity;
    39.             _internalVelocity = Vector3.zero;
    40.         }
    41.        
    42.         // Gravity is applied here, velFunc for gravity returns just the gravity vector
    43.         foreach (var velFunc in velocityCallbacks)
    44.         {
    45.             currentVelocity = Integration.RK4(currentVelocity, transform.position, velFunc, deltaTime);
    46.         }
    47.        
    48.         // After everything, clamp velocity - normal acceleration will only get you to the max values, but any wacky movement might increase it
    49.         // so we don't wanna set a hard limit, instead allow some wiggle room hence the 1.5, could be adjustable
    50.         Vector3 lateralMax = Vector3.ClampMagnitude(PlanarVelocity(currentVelocity), 1.5f * movementData.maxLateralMovementSpeed);
    51.         Vector3 verticalMax = Vector3.ClampMagnitude(VerticalVelocity(currentVelocity), 1.5f * movementData.maxVerticalMovementSpeed);
    52.  
    53.         currentVelocity = lateralMax + verticalMax;
    54.  
    55.     }
     
  15. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    Im not sure if this solution works, but if it does it should be noted that auto sync transforms has a big impact on performance if you have a lot of physics objects in your scene
     
  16. minkee5004

    minkee5004

    Joined:
    May 20, 2020
    Posts:
    2
    Another way is to edit KinematicCharacterSystem.cs inside the Core file.

    delete the following line
    #174 - mover.Transform.SetPositionAndRotation(mover.TransientPosition, mover.TransientRotation);
    #206 - mover.Transform.SetPositionAndRotation(mover.TransientPosition, mover.TransientRotation);

    And you also need to enable the "MoveWithPhysics" bool value in the PhysicsMover component.
     
  17. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    I bought this as the demo was superb; very robust. Looking through the code to understand it, I see scaling has to be (1,1,1). And indeed, trying this in demo by changing a character's scale, errors are logged (although it appears to run). This firstly means everything has to be sized in bake. You can't use a Goblin model and scale it large for 2 or 3 varieties of goblin. It also means scaling has to be static and you can't scale an object in game to make it larger or smaller - no size-changing games.

    Are there any workarounds? If not, this should be highlighted as a requirement of the engine.
     
  18. Deleted User

    Deleted User

    Guest

    Hey there.
    I need to retain the Motor.BaseVelocity and move the player additively with rootmotion and it's last controller velocity.
    But instead of the expected behaviour, the character constantly shoots/skyrockets out of the scene.
    Anyone know how to set currentVelocity to ADD onto the baseVelocity in a correct way?

    Code (CSharp):
    1. currentVelocity =  _rootMotionPositionDelta / deltaTime;
    This above ^ is causing the motor velocity to be null when it's driven by animation. But I want both.

    Okay.. I think I solved it. So currently I'm using this:

    Code (CSharp):
    1. if (Mathf.Abs(_rootMotionPositionDelta.magnitude) > 0)
    2.             {
    3.                 //Last velocity gets set to currentVelocity in the code above.
    4.                 var targetVelocity = lastVelocity + _rootMotionPositionDelta / deltaTime;
    5.                 currentVelocity = targetVelocity;
    6.             }
    And in the 'After character update, I reset the last Velocity to be Vector3.zero once more.'
     
    Last edited by a moderator: Jun 17, 2022
  19. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    If your model is a child of the character controller instead of them sharing the same object, you can scale the child model and change the character controller colliders size which should work. If you have a size changing game, you can change them individually from script that way too
     
  20. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    That works, thanks.
     
    Vincent454 likes this.
  21. ParadoxSolutions

    ParadoxSolutions

    Joined:
    Jul 27, 2015
    Posts:
    325
    I have an issue where I can have my hands off the keyboard and mouse and the character slides in a direction until the left mouse button is clicked. I'm using the example controllers with an orientation toward movement. In the same loops as the HandleCameraInput() and HandleCharacterInput() functions, I have some additional inputs to do things with mouse clicks that seem to interrupt the controller (code inside doesn't touch it). I can't seem to reproduce when this happens but I did squash a bug when stopping the input functions where I had to pass an empty PlayerCharacterInputs() struct to the controller that solved a very similar sliding issue. I've also tried moving my mouse input code into the LateUpdate() after the camera input is handled but the sliding bug still happens occasionally.

    Should I move all other Input calls to another monbehaviour? What might be creating a desync in the example controller inputs?
     
  22. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    I think you should always pass an input struct with the input vector being zero, even when the player doesnt do anything.
    Maybe double check if you are always passing one (Personally I am passing it even when the game is paused, just to make sure).
    I don't know how you are handling input, but it should be done in update, not fixedupdate.
    Also there was an issue with the editor that had keys get "stuck" until they were pressed again, but it was fixed a few months ago, maybe update to the newest Unity version and see if it helps.
    And try to unplug any controllers if you have any.

    If whatever clicking your mouse does in your game is completely unrelated to movement, maybe this isnt related to the character controller either. If these ideas dont help, maybe post some of the code here
     
  23. xealgo

    xealgo

    Joined:
    Dec 30, 2012
    Posts:
    12
    Hi Phil. Super happy with the character controller. However, while I was able to get it working really well in a single player scene, I haven't had such luck getting it to work with Mirror (networking). All game objects and components have to be owned by the player, so splitting the character apart from the player hasn't been working. However, when I add the motor and controller to the player object along with the player script, everything get super jittery. Is there a way to combine everything on a single game object?? I don't really understand why the separation of character from player :/ I've tried several approaches also such as nesting a character/player game object under the network player object, but for whatever reason, I could no longer update the player even though I could see inputs were working and everything was wired up correctly.

    Edit: I assume the kinematic character system isn't picking up the motor when it's nested.
     
  24. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    445
    Have you tried writing a PlayerNetworkController script that, depending on ownership, delegates player-control behaviour-enable/disable-states (like for example specific kinematic character controller components) respectively? For example, if you are not the owner, the script will search for the given components and disable them. The synchronization for non-owned client-objects is therefore handled separately by scripts like TransformSync and the likes (depending on your game and needs). This way, you don't have to modify the character controllers codebase at all.
    Btw, my advice here is a general purpose recommendation and is independent from your network-framework.
     
    xealgo likes this.
  25. xealgo

    xealgo

    Joined:
    Dec 30, 2012
    Posts:
    12
    Yeah, I actually am already doing this for things such as the player camera, inputs, etc. I'll give it a try and see. Thanks for the advice.
     
  26. xealgo

    xealgo

    Joined:
    Dec 30, 2012
    Posts:
    12
    Well, unfortunately after changing everything, following the documentation exactly, I'm still getting constant jerky motion. I've gone through every property, reset my physics settings, played with the network sync timing, ensure there were no other colliders on the character, etc. Just grasping at straws at this point.
     
  27. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    445
    In general, if you don't have jerky motion when being 100% offline without network synchronization, you shouldn't experience jerky motion when the only thing you move is only one player character. The easiest way to do network snychronization is to write client-authoritative code. In this case, the owner ignores all transform synchronizations when the data is coming from the server. Here the owner forwards the positions/rotations to the server. The server/host forwards the received data to the other clients. The other clients do the same for their owned character. For characters that are not owned by the respective client, positions/rotations are only applied in regard to the received server data - therefore their transforms shouldn't be affected by any other character-controller effector. It is recommended to use interpolation to achieve smooth transitions inbetween received data-packages.
     
  28. xealgo

    xealgo

    Joined:
    Dec 30, 2012
    Posts:
    12
    Yeah, I'm using Mirror's network transform sync with client authority, and it's been working fine with my old character controller, so I'm sure it's something stupid I'm doing with the KCC.
     
  29. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    445
    Have you made sure that KCC components + Input components are only active on the client that owns the player object?
    Have you made sure that all KCC + Input related components are getting disabled when you are not the owner of the ojbect?
    Have you made sure that if you are the owner, all transform-sync data for your owned player object are ignored? (I always have written my own transform-syncs so I implemented this step myself, but I guess the transform sync you are using should handle this as case as well - as long as it is configured right)
    Have you tested the exact same case without KCC but with a custom super short and simple script that just moves left and right (using a kinematic rigidbody component) and checked if the issue disappears if done so?
     
  30. xealgo

    xealgo

    Joined:
    Dec 30, 2012
    Posts:
    12
    All super great things to try. The input one actually caught my attention. I have debugged everything and it looks right, but it would have been easy to overlook a few things if I wasn't looking for it. I'll run through this awesome list of things to check as soon as I have time again. Worked 12 hour days for work work these past few days Q_Q
     
  31. pjbaron

    pjbaron

    Joined:
    Jan 12, 2017
    Posts:
    53
    EDIT: looks like I didn't read back far enough https://forum.unity.com/threads/released-kinematic-character-controller.497979/page-31#post-7917940 there's a possible approach here. Is this near ready for use? I get the general idea but it feels like it might be quite tricky to implement perfectly.

    SECOND EDIT: there was mention of a discord in some of the reviews, but I can't find a link to it here, or on the github or in the docs. Can someone point me in the right direction please?

    ORIGINAL:
    My question has been asked a few times before but I don't see an answer to it at the moment.

    Is there a way to allow the KC character to land on a box which is movable, without pushing it through the ground (which is what happens if the rotation is locked) or making it twist and tip her off?

    I've read the docs and looked through all of the example scripts, but I don't see anything that will enable this behaviour which is (unfortunately) critical to my game concept.

    My best idea so far is to toggle the crates to static when they're collided with, but that won't work correctly in a variety of situations (large horizontal landing velocities should impart rotation to the crate, crates that are balanced should act like see-saws, external forces should affect the crate taking into account the weight of the player on top of it)

    This question duplicates parts of:
    https://forum.unity.com/threads/released-kinematic-character-controller.497979/page-32#post-8158004
    https://forum.unity.com/threads/released-kinematic-character-controller.497979/page-32#post-8139545
     
    Last edited: Aug 19, 2022
  32. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    133
    Just found a weird inconsistency between Mono and IL2CPP.

    When the character goes up a slope that leads to a flat surface:
    On Mono it works exactly as in the editor and the character stays flush with the surface all the way through.
    On IL2CPP the character overshoots at the end of the slope and arcs above the flat surface.

    Does not seem to happen with the ExampleCharacter in the CharacterPlayground scene.

    The movement code:
    Code (CSharp):
    1.  
    2. public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
    3. {
    4.    currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, Motor.GroundingStatus.GroundNormal) * currentVelocity.magnitude;
    5.  
    6.    currentVelocity.x = Agent.MovementVectorInput.x * Agent.MaxStableMoveSpeed;
    7.    currentVelocity.z = Agent.MovementVectorInput.y * Agent.MaxStableMoveSpeed;
    8. }
    9.  

    Edit.: Moving Motor.GetDirectionTangentToSurface() below the setting of the x and z of currentVelocity seems to have worked around the issue.
    Still, weird inconsistency.
     
    Last edited: Aug 24, 2022
  33. philsa-unity

    philsa-unity

    Unity Technologies

    Joined:
    Aug 23, 2022
    Posts:
    115
  34. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    Congrats :)

    Just one question - I believe there were some fixes in the works (mentions on Discord, DM somewhere or something like that, it's been a few months, so not sure). These will be released still?

    I would love to migrate to Rival, but we can't migrate over to DOTS completely.
    We are too far into the project now and completely dependent on PhysX etc.
     
    Vincent454 likes this.
  35. Gigoorin

    Gigoorin

    Joined:
    Mar 5, 2018
    Posts:
    2
    Hi Everyone

    I hope you are all well!

    Sorry if this has been asked before but I'm wondering if anyone can help.

    I’ve trying to converter the Crouch system that is provided in the walk-through to smoothly transition between the Crouch/standing sizes.

    My current method for transitions looks like this (It's being called in the AfterCharacterUpdate and I'm passing the local deltaTime variable).

    Code (CSharp):
    1.     public void CrouchHandle(float deltaTime)
    2.     {
    3.         MeshRoot.localScale = Vector3.SmoothDamp(MeshRoot.localScale, _isCrouching ? endPos : startPos, ref _crouchScaleRef, deltaTime * _crouchTransitionSpeed);
    4.     }
    EDIT - I've also tried lerping. Not sure if I'm calling the method in the wrong loop.

    Any help will be super appreciated.
    Thanks,
    Jon
     
  36. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    I used to change the size gradually as well but that caused some slight stuttering during the transition. So what I am doing now is I change the kcc size instantly but move the camera smoothly instead. But if you really want to do it that way, I believe I called it in update velocity
     
  37. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    hey, do you maybe have any tips to avoid jitter like these when using BonusOrientationMethod.TowardsGroundSlopeAndGravity from the example character controller? GIF 20-09-2022 10-08-03.gif
     
  38. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    Try adjusting rotation smoothness. Can't verify the exact name now, but it's some Smoothness field in the Motor or CC inspector.
     
  39. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    do you mean the "Bonus Rotation Sharpness" by any chance?
    this sadly only slows the rotation, so now the slope adjustment will be super slow

    upload_2022-9-20_11-51-4.png
    to me it looks like the character is tring to align itself to this plane here? or?
    is there somehow a way to say dont align to straight up walls?
     
  40. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    You could try disabling step handling. To rule out the possibility that it interferes with the slope based orientation.
     
    RobertOne likes this.
  41. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    that was exactly it. thanks a lot :)
     
  42. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    okay, my journey kinda continues :D
    ive set the "BonusOrientationMethod" to"TowardsGroundSlopeAndGravity"
    and the "Step Handling" to "None"

    but now i get stuck on every little hump on the floor

    GIF 20-09-2022 18-19-05.gif

    and when i set the step handling to "standard" or "extra", this is what will happen:

    GIF 20-09-2022 18-23-38.gif

    would it be possible to let the character hover a bit over the ground?

    edit: yeah so the more i think about it: hover a bit over the ground would solve a lot of my problems
     
    Last edited: Sep 20, 2022
  43. forestrf

    forestrf

    Joined:
    Aug 28, 2010
    Posts:
    230
    Thank you a lot for this asset!
    Should this be in github now that it's free? The only reason I'm asking is to make pull requestes (thought that will probably take you more time than expected by dealing with those pull requests and issues and all).

    In KinematicCharacterMotor.cs changing
    if (colliderAttachedRigidbody.gameObject.GetComponent<PhysicsMover>())

    with
    if (colliderAttachedRigidbody.gameObject.TryGetComponent<PhysicsMover>(out var _))

    will remove several allocations in several situations. All instances of GetComponent where the component may not exist should be replaced with TryGetComponent to avoid generating garbage (or I think it was GetComponents with an array if TryGetComponent isn't available).

    In release mode (but still in the editor), for about 40 characters the profiler went from 1.64 ms to 0.65 ms when staying on a static mesh collider (o_O)
     
    Last edited: Sep 25, 2022
  44. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    I don't think the performance improvement is caused by allocation. No reason for this call to allocate.
    Doing this
    Code (CSharp):
    1. if (colliderAttachedRigidbody.gameObject.GetComponent<PhysicsMover>())
    is the same as writing this
    Code (CSharp):
    1. if (colliderAttachedRigidbody.gameObject.GetComponent<PhysicsMover>() != null)
    since Unity has the equality operators overloaded for all UnityEngine.Objects.
    These are actually expensive, since not only do they check reference for null, but they also check whether the Unity Object has been destroyed.
     
  45. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    hey, so setting currentVelocity.z = 0; in UpdateVelocity() set the WORLD Z to 0
    how can i set the LOCAL Z to 0?
     
    Last edited: Sep 30, 2022
  46. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    You should change Motor.baseVelocity or Motor.velocity I think
     
  47. Vincent454

    Vincent454

    Joined:
    Oct 26, 2014
    Posts:
    167
    According to this https://docs.unity3d.com/ScriptReference/Component.TryGetComponent.html GetComponent only allocates in the editor, so maybe there is no difference in the built game? Thats a big improvement though thanks for sharing!
     
  48. forestrf

    forestrf

    Joined:
    Aug 28, 2010
    Posts:
    230
    Oh I didn't know that. If it's only in the editor then it's not really a problem. It's still a small win at least, the editor can be quite slow.
     
    Vincent454 likes this.
  49. LooksCozyLabs

    LooksCozyLabs

    Joined:
    Feb 18, 2021
    Posts:
    2
    Hi there, want to report a bug and a workaround for it! If you change the layer of the Game Object which contains the script, CollidableLayers in KinematicCharacterMotor is not updated so you'll still interact or not with physics layers as if you never changed the layer.

    Workaround is you just need to manually run the bit of code in KinematicCharacterMotor's Awake function after you change the layer:
    Code (CSharp):
    1.  
    2. myKinematicCharacterController.gameObject.layer = someNewLayer;
    3. ...
    4. for (int i = 0; i < 32; i++)
    5. {
    6.     if (!Physics.GetIgnoreLayerCollision(myKinematicCharacterController.gameObject.layer, i))
    7.     {
    8.         myKinematicCharacterController.myKinematicCharacterMotor.CollidableLayers |= (1 << i);
    9.     }
    10. }
    11.  
     
    Vincent454 likes this.
  50. Mirath

    Mirath

    Joined:
    Aug 5, 2012
    Posts:
    14
    @PhilSA or anyone else who's dealt with Animated moving platforms
    Replying to this way after the fact, but have run into the same issue in a new project. I'm trying to implement moving platforms controlled by animations, initially following the approach used in the included samples. This worked for basic animations on a single collider, but became problematic with a more complex collider setup.

    Based on previous posts I've seen detailing approaches, I have a component on each relevant collider that on Start creates a new game object with a collider, PhysicsMover and IIMoverController. This object then orients to the position and rotation of the initial GameObject in IMoverController.UpdateMovement. This seems to get close to working, but at higher speeds/distances on the animated object the pose starts to drift, and standing on the platform creates an intense jitter.

    Here's a video showing the issue.


    I've tried several solutions:
    - controlling the Animator Update manually like the sample
    - resetting some of the positional values like InitialTickPosition after the Animator update
    - disabling Interpolation
    - disabling camera logic and locking a cinemachine to the player to ensure its not camera jitter instead of the collider, it persisted.
    None have worked. Though strangely the interpolation one seemed to get the closest, but wasn't viable with how it combined with other aspects of character movement.
    Any ideas that might address the jitter?