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
    ah... I must've added the option to set it only recently in my current WIP version. You can do the change yourself manually in KinematicCharacterMotor.

    In your version it should look like this:


    ...but you can modify it to look like this and gain the ability to set it


    This'll be part of the next update
     
    thestrandedmoose likes this.
  2. thestrandedmoose

    thestrandedmoose

    Joined:
    Jul 21, 2015
    Posts:
    70
    Perfect, thanks dude! It works now
     
  3. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I'm not actually familiar enough with the nav mesh components to give you a precise answer, but I can give you some tips

    Since this is a physical character controller and not a typical static nav mesh agent, it'll require quite a bit of AI programming to get this right, and it'll depend heavily on your specific use case. NavMesh.CalculatePath does detect NavMeshLinks properly, so it'll try moving towards them if there are any. The problems you must solve are
    • how to detect when to jump
      • For this, you can use box triggers over your NavMeshLinks that will inform your character that it has to jump. Maybe there is a cleaner way to detect that your calculated path goes through one with the API, but I don't know about it
    • how to align your character properly for a jump
      • Depending on if your character has a lot of "movement smoothing" or not, this can get complicated. You need to make sure your character is moving in the proper NavMeshLink direction when jumping, but also at an appropriate speed. Let me try to represent this with a picture:

      • Case A is how the agent would behave by default. It goes straight to the navMeshLink, and tries to traverse it. In our case this will be problematic because the character will probably end up jumping diagonally across the gap and fall into the hole. What you want to do is Case B. You need to predict the trajectory in advance so that at the moment of jumping, you'll be properly aligned and at max speed. However, I don't have a ready-made solution to that problem right now
    • how to calculate how far you can really jump
      • Your character's jumping distance can be calculated precisely based on your top speed, your jump impulse, your gravity, etc, etc... With this, you can know if the jump is possible or not
     
  4. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I did a build with the CharacterPlayground scene, on my Nexus 5x, with fixed timestep of 0.02, and Application.targetFramerate of 30, and I was unable to repro the problem.

    Can you confirm that the exact same setup works well in PC mode, but not in android mode?
     
  5. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    505
    Great character controller, left a 5 star review well deserved.
    I do have one query though :).
    When setting opposite gravity while standing on a relatively thin floor, the character rotates around the pivot (feet), ends up through the ground, and then the physics pushes it out under the floor. So in an house analogy, I end up walking under the floor, instead of on the ceiling.

    What would be the best way to avoid this problem?

    Cheers.

    Edit: I made my character smaller and now when reversing gravity he gets stuck in the floor. The floor is made of a bunch of box colliders. Different symptom but same cause: pivoting around feet into the floor.

    Can I suggest/request that the rotation towards gravity is smooth over frames with a sharpness value and still respects colliders?
     
    Last edited: Jan 2, 2018
  6. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    I have a small problem with rotation. I want rotation updated to be applied instantly, so first I removed the rotation smoothing completely (so no more RotationSharpness).
    But somehow this doesn't seem to be enough. After setting the rotation in UpdateRotation(ref...), the character will smoothly rotate over a few frames. Its really fast but still noticable and when I turn down timeScale to 0.01 I can clearly see how the character takes a second or so to rotate completely.

    I checked the code and it doesn't seem like there's any other rotation going on anywhere, so I guess this has to do with the rigidbody interpolation.

    Now my question is: Is there some safe way to apply the rotation instantly (to the transform directly, instead of the rigidbody)? Or will that cause problems somehow (most likely yes, no?)?
    What can I do to bypass the interpolation?
    I want to keep the interpolation for translation/movement.

    I tried adding this third line here in KinematicCharacterMotor.cs
    Code (csharp):
    1.  
    2.  
    3.             CharacterRigidbody.position = TransientPosition;
    4.             CharacterRigidbody.rotation = TransientRotation;
    5.  
    6.             CharacterRigidbody.transform.rotation = TransientRotation;
    7.  
    It fixes the rotation (its instant now), but breaks everything else, you can't move anymore while turning the camera (which instantly applies the rotation from camera to character).
    Is there some other way? What can I do?
     
    Last edited: Jan 2, 2018
  7. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    It seems like gaining the ability to rotate the capsule around its center would solve the issue. I'll think of a clean way to accomplish this for the next official update, but in the meantime, you can do this quick fix:
    1. Go in KinematicCharacterMotor.cs
    2. Find the "SetCapsuleDimensionsAuto" method
    3. Do this change:
    Now the capsule will be centered on the transform, and the problem you described shouldn't happen anymore

    yes, it is due to the fact that character updates run on FixedUpdate (and, in most cases, it's important that it stays like this). However, there are two ways to solve the issue:
    1. Only rotate the "mesh" child object of the character; not the whole character object. If your character up direction always remains the same, there is actually no point in rotating the capsule itself. A capsule that rotates along its length will always have the same collision. So just don't do anything inside UpdateRotation, and instead rotate the child mesh manually on Update or LateUpdate
    2. Do both rotations. You can keep rotating the character object in UpdateRotation as usual, but also add additional logic that will rotate the child mesh object every frame to match the rotation exactly.
      Just be careful not to end up in a situation where you modify the child's rotation by X, and then modify the parent's rotation by X. At the end of the frame, this will cause the child to have rotated by 2*X, because its parent rotated too
    Do you have more information about the exact line that causes the error? Or which object is actually null? Also, does it only happen in builds, or does it also happen in editor when the platform is Android?
     
  8. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I'll be looking into this, but I doubt I will be of much use until I am able to repro the problem. Right now the default CharacterPlayground scene running on android hasn't shown any problems in my basic test (character falls on the ground and moves forward automatically against walls, etc...). Does it always happen, or only sometimes when moving against corners?
     
  9. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Sure, you can send it in private messages
     
  10. davidseth8

    davidseth8

    Joined:
    May 8, 2016
    Posts:
    13
    In your example Character Controller, Gravity is referenced in each state (swimming, climbing, default, etc). What if I want to be on the planet walking and then climb a ladder? Would some sort of shared reference to Gravity be a better implementation or do I need to take this into consideration for each state?
     
  11. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    You're right, it would probably better to have a shared gravity
     
  12. cyzada

    cyzada

    Joined:
    Jun 24, 2013
    Posts:
    3
    Hello PhilSA,

    You've produced a fantastic solution, which I'm currently porting over to support VR (Vive/SteamVR, specifically), and I've run into a bit of an issue.

    I have two individual(siblings, not parent/child) GameObjects:
    1. KinematicCharacterMotor/Controller
    2. The CameraRig (this is the SteamVR playspace)
      1. This contains the actual player camera as a child.
    Everything is working well, except that when the player moves around within the playspace, without initiating movement via input, I need to move the KinematicCharacter/Rigidbody to the location of the camera within the playspace to facilitate accurate collisions for falling/sliding.

    I've found reference to the KinematicCharacterMotor.CharacterRigidbody.MovePosition is some of the previous posts, and in the documentation, but I have so far been unable to make use of it (getting no result).

    Can you give me any tips for moving the rigidbody to the location of the camera? I've tried to do this within both the Before and AfterCharacterUpdate with the same result.

    Any help would be greatly appreciated.
     
  13. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    For a variety of reasons, I've established that the character should only be moved with velocity, in the UpdateVelocity callback. This seems like a bizarre design decision to a lot of people, but it's mostly it's because otherwise, there would be too many ways for users to shoot themselves in the foot by trying to do a Move that isn't precisely at the right time or done in the right way.

    But there is a way to do what you want to do. Consider the following code:
    Code (CSharp):
    1. public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
    2. {
    3.     currentVelocity = KinematicCharacterMotor.GetVelocityForMovePosition(KinematicCharacterMotor.TransientPosition, targetPosition, deltaTime);
    4. }
    this gives the character a velocity that places it at "targetPosition" over the next FixedUpdate. It's an equivalent of doing MovePosition(targetPos) on a rigidbody on every FixedUpdate. With this you can move the character to a specific position, with all collisions being processed properly

    PS: Nevertheless, I'm still investigating ways to have a KinematicCharacterMotor.MovePosition() that will be user-friendly and won't conflict with the current UpdateVelocity workflow. No promises, but it might come in a future update
     
  14. cyzada

    cyzada

    Joined:
    Jun 24, 2013
    Posts:
    3
    Thanks for the quick reply,

    I found the GetVelocityForMovePosition right after making my post, and it seems to be doing the trick with a little Vector3.Distance evaluation to prevent constant, and slow, movement. Unfortunately, it doesn't appear that I will be able to both move the rigidbody to the position of the camera, and then move the entire camera/playspace to the position of the collider when receiving input without getting a little clever.

    I appreciate your help, thank you.
     
  15. dslyecix

    dslyecix

    Joined:
    Sep 29, 2017
    Posts:
    8
    Hi Phil, appreciate all you've done here. Hopefully a quick question, relatively new to the whole Unity/C# thing.

    I'm actually working on an ability system that's completely unrelated to your controller - which has been nothing but awesome so far - and wanted a quick example ability to test it out. My mind went to a knockback effect, and I tried to quick-and-dirty up a Rigidbody.AddForce effect on the player. Of course (it didn't work and) I recalled that since I was using the KCC, I am only supposed to move the character through the UpdateVelocity() method.

    I will be trying to craft the ability system so that any combination of effects can be chained together, and it would be nice to not need them to handle physics separately based on hitting the player or another entity. I'm basically just trying to work out the differences between applying physics forces to this character controller, and blasting other entities around with regular ol' AddForce(). It would be ideal if I could affect the player with the exact same system I affect everything else with.

    Of course overcoming this directly isn't a huge problem, I could write a method to detect a physics impulse and translate it into the velocity where required (edit - I've since rediscovered AddVelocity which is clearly the right place to add my impulse velocity), but I was just wondering if there's something I'm missing that might be easier or more direct. Maybe there's a simple way of just extracting all the 'regular' forces the readonly rigidbody is subjected to but simply ignores since it's readonly? If the best solution is to write my own physics detection, perhaps you can help me come to the 'correct' way of structuring that. I haven't come across it in this thread yet so I hope it hasn't been addressed anywhere.
     
    Last edited: Jan 7, 2018
  16. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Unfortunately it isn't possible to affect both rigidbodies and KCC characters with the same AddForce method call. I'm pretty sure this would actually be impossible to accomplish unless we had Unity's sources and we could modify Rigidbody to our liking

    So the solution here would be to stick to AddForce on rigidbodies, and use an equivalent of "AddVelociy" (see Walkthrough section 5 for an example) for characters
     
  17. dslyecix

    dslyecix

    Joined:
    Sep 29, 2017
    Posts:
    8
    Awesome, thanks! I kept revisiting all the resources looking for clues but it seems to point in this direction.

    Would it not be possible to overlay a second collider to detect the regular physics forces, automatically translate them, and provide them to AddVelocity? Trying to think through the implications of the timing between the systems it seems to me like this could work.

    Thanks for giving me something to think about (and amazing response time, holy cow).
     
  18. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Hmmm... it's possible that this could work, but I'd be worried about all the unexpected consequences of it. I don't have any in mind right now, but my spider sense is tingling :D
     
  19. FunnyDevJS

    FunnyDevJS

    Joined:
    May 3, 2016
    Posts:
    7
    Hello.

    I had a question about KinematicCharacterMotor.cs

    Line 1366 ~ 1374 Function name : CharacterCollisionsOverlap

    // Filter out invalid colliders
    nbHits = nbUnfilteredHits;
    for (int i = 0; i < nbUnfilteredHits; i++)
    {
    if (!CheckIfColliderValidForCollisions(overlappedColliders))
    {
    nbHits--;
    if (i < nbHits)
    {
    overlappedColliders = overlappedColliders[nbHits];
    }
    }
    }

    I don't understand this code. Why do you assign overlappedColliders[nbHits] to overlappedColliders ?

    if overlappedColliders[nbHits] is invalid for collision, Does invalid collider information includes calculation?

    Please tell me the reason.
     
  20. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Code (CSharp):
    1. nbHits = nbUnfilteredHits;
    2. for (int i = 0; i < nbUnfilteredHits; i++)
    3. {
    4.     if (!CheckIfColliderValidForCollisions(overlappedColliders[i]))
    5.     {
    6.         nbHits--;
    7.         if (i < nbHits)
    8.         {
    9.             overlappedColliders[i] = overlappedColliders[nbHits];
    10.         }
    11.     }
    12. }
    Here's the explanation:
    • We first do an OverlapCapsule which fills the "overlappedColliders" array
    • Lets say for example that overlappedColliders now contains colliders A, B, C and D
    • Now we go through each one with the for loop, checking if they are collidable with CheckIfColliderValidForCollisions
    • Lets say we determine that B is not valid.
      • We will then replace B with the last element of the array (D). Our new array will be A, D, and C. This is what the "overlappedColliders = overlappedColliders[nbHits];" line does
        [*]We will decrement the "nbHits" to 3 instead of 4

    So we end up with an array containing filtered colliders without having done any evil GC Allocs. (
    without having created any new arrays for containing the filtered colliders, or having used a List.Add/Remove). This way of handling arrays is similar to how Physics.RaycastNonAlloc works

    EDIT: Actually wait..... I just noticed there's a potential flaw in this. In my example, if D wasn't a valid collider, it'll never be detected with this algorithm. Instead I should be iterating backwards from the end of the array. I'll make sure to add that fix to the next version
     
    Last edited: Jan 9, 2018
    FunnyDevJS likes this.
  21. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I am hoping before the end of january
     
  22. FunnyDevJS

    FunnyDevJS

    Joined:
    May 3, 2016
    Posts:
    7
    Thank you PhilSA.
    I fully understood about non CG Allocs.
    I'm going to develope character with kinematic Character Controller.
    I'm learing about Kinematic Character Controller. It is very useful.
    I'm looking forward to next version.
     
  23. MikeFish

    MikeFish

    Joined:
    Oct 24, 2015
    Posts:
    12
    Hey there, I'm struggling implementing the mario style jump method into the example character controller script.
    You know: holding space short = small jump, holding space long = bigger jump. I was previously working with a way similiar to this https://forum.unity.com/threads/mario-style-jumping.381906/ , but somehow am stuck wrapping my head around how to set it up with the example. Any hints are aprreciated.

    ---
    never mind, figured it out. sorry for the interruption.
    Great asset, am very happy with it.
     
    Last edited: Jan 10, 2018
    PhilSA likes this.
  24. sharksharkshark

    sharksharkshark

    Joined:
    Apr 27, 2015
    Posts:
    13
    Any chance you feel like sharing your solution? I'll be implementing something similar using KCC soon and wouldn't mind seeing how other people have built this feature.
     
  25. MikeFish

    MikeFish

    Joined:
    Oct 24, 2015
    Posts:
    12
    sure, but it's most probably not the most elegant way.
    first of all I added this if block to ExamplePlayer.cs script

    Code (CSharp):
    1.  
    2. if(Input.GetKeyUp(KeyCode.Space))
    3.                 {
    4.                     Character.JumpCancel();
    5.                 }
    6.  
    in the ExampleCharacterController.cs i added these three to the list of variable declarations
    Code (csharp):
    1.  
    2. public float JumpTime = 0.25f;
    3. private float _curJumpTime;
    4. private bool _jumpHeldAndValid = false;
    5.  
    same class, where it starts with //Handle jumping I got // Handle jumping i got "Vector3 jumpDirection = KinematicCharacterMotor.CharacterUp;" out and above of the if(_jumpRequested) block so i can reuse it later on.

    same block i changed the following lines
    Code (csharp):
    1.  
    2. // Add to the return velocity and reset jump state
    3.                     _jumpHeldAndValid = true;
    4.                     _curJumpTime = JumpTime;
    5.                     //currentVelocity += (jumpDirection * JumpSpeed)- Vector3.Project(currentVelocity, KinematicCharacterMotor.CharacterUp);
    6.  
    so, as you might guess i handle the actual jump in another if block, that's why i commented the currentVelocity part out.
    I am doing all this because I didnt want to break the handling of how jumps are blocked, grounded, and especially to not break my favourite function of the pre-ground grace period. It is all handled very nicely in that construction.

    so, after this whole if block is closed i added a new one

    Code (csharp):
    1.  
    2. //Operate Mario Like Jump
    3.             if (_jumpHeldAndValid && _curJumpTime > 0f)
    4.             {
    5.                 currentVelocity += (jumpDirection * JumpSpeed ) - Vector3.Project(currentVelocity, KinematicCharacterMotor.CharacterUp);
    6.                 _curJumpTime -= Time.deltaTime;
    7.             }
    8.  
    And last but not least added the function called by the spacebar release
    Code (csharp):
    1.  
    2. public void JumpCancel()
    3.         {
    4.             _jumpHeldAndValid = false;
    5.         }
    6.  
    If anyone comes up with a less "hacky" way, please let me know.
    Also, this is just the rough concept, I recommend working on the arc of the jump. it is pretty linear this way, and doesnt look or feel very nice, so you might want to damp down the up velocity while holding down space in the //Operate Mario Like Jump block.
     
    JauntyBearGames likes this.
  26. sharksharkshark

    sharksharkshark

    Joined:
    Apr 27, 2015
    Posts:
    13

    Thanks for sharing! This will at least get us started in the right direction.
     
  27. davidseth8

    davidseth8

    Joined:
    May 8, 2016
    Posts:
    13
    @PhilSA I'm looking to integrate a climbing system into KCC. It is based on the great tutorial at https://sharpaccent.com/?c=course&id=21.

    Essentially it is based on raycasts towards a climbable object. If character can climb it attaches and then uses IK re-targetting to move the hands and feeet up/down & left/right. I have it mostly working in a new test scene with no KCC code.

    My question is what is the best way to model a climb sytem into KCC? I'm thinking about the velocity, etc methods such as: SetMoveVectorInput & SetVerticalInput in particular.
     
  28. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    In my opinion, the best way to approach this would be something that's very similar to how climbing ladders is done in the Walkthrough.

    Basically, you turn off the main KinematicCharacterMotor movement collision solving by calling "HandlePhysics(false,true)", and you make a completely separate velocity handling specifically for your climbing state. At that point, the problem becomes very simplified; you have a kinematic capsule that doesn't actually collide with anything and you just have to think about what velocity you must give it to accomplish your climbing. It's as if you now had just a regular kinematic rigidbody and you had to think about how to move it with MovePosition (except you'd still be working in UpdateVelocity). No need to worry about fighting the motor's default behaviour while you are climbing anymore
     
    Last edited: Jan 11, 2018
    davidseth8 likes this.
  29. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    seems like a pretty good way to go about it!
     
    MikeFish likes this.
  30. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Progress update:

    I am currently putting the finishing touches on the features and documentation of the next release of the package. If all my testing goes well, I should be able to submit it to the asset store before the end of january. It'll contain:
    • Tons of optimization, cleanup, minor bugfixes and refactoring of the "core" components
    • A new optional step-handling method that is much more powerful than the basic one (video), although it's a bit more expensive for performance
    • optional custom interpolation to counter the rigidbody interpolation bug in recent Unity releases
    • the fix for this problem
    • Ability to give the capsule an arbitrary center around the transform pivot
    • new walkthrough section demonstrating how you can achieve frame-perfect rotation even though the character operates on interpolated fixedUpdate
    • MoveCharacter/RotateCharacter methods that allow you to move it with full collision handling, without having to rely on UpdateVelocity and UpdateRotation (although both methods of moving the character can be used together)
    • ...and more
    ___________________

    A note on networking:

    I think by now the networking example is officially becoming my own "nested prefabs" due to how long it's taking and how wrong my predictions were... However, this next update introduces changes that should make it much easier for people who already know how to handle networking in general to get started. Most importantly:
    • KinematicCharacterSystem.autoSimulate and KinematicCharacterSystem.Simulate: Essentially works just like Physics.autoSimulation and Physics.Simulate(), but for the character controller system (character motors and moving platforms). With this, you can easily re-simulate inputs in the past.
      There will also be a variant of the Simulate() method that can be used to only simulate specific characters or moving platforms (or a subset of them). It takes arrays and counts as parameters to work well with no-GC approaches
    • KinematicCharacterMotor.GetState/ApplyState: Returns or applies a "KinematicCharacterMotorState" struct that represents the state of a KinematicCharacterMotor that is pertinent for simulation (pos, rot, velocities, grounding, etc....). Use this to save the state at a specific time, or apply a past state instantly.
      • KinematicCharacterMotor.SetPosition/SetRotation: Sets the character's position/rotation instantly, in the correct way, and without interpolation. This is used internally by the ApplyState() method, but can be useful on its own nonetheless
    • KinematicCharacterSystem.Handle[Pre/Post]SimulationInterpolation: An easy-to-use mecanism to allow you to handle character interpolation correctly even if you call Simulate() several times within a same frame (as it will often be the case with networking)
    With these new tools, implementing networking for KCC should become much clearer. Upon receiving a past world state, you basically do this:
    - KinematicCharacterMotor.ApplyState(pastState) for all character motors
    - KinematicCharacterSystem.HandlePreSimulationInterpolation (this will remember the positions to interpolate from)
    - For each network tick until present tick:
    - Apply the player inputs you saved for that tick
    - KinematicCharacterSystem.Simulate​
    - KinematicCharacterSystem.HandlePostSimulationInterpolation (this initiates the interpolation from the positions saved in HandlePreSimulationInterpolation)​

    Rest assured, though. A proper UNET LLAPI networking example is still coming (I swear!)
     
    Last edited: Jan 21, 2018
  31. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    505
    That sounds like a pretty sweet update. I'm personally particularly excited about the steps as I couldn't get my character to be able to step up heights of 0.5 and fit through widths of 1 at the same time. I think this new system will solve that. Also happy to see the option pivot point adjustment. :)

    Nice one.
     
  32. JustinLarrabee

    JustinLarrabee

    Joined:
    Feb 3, 2013
    Posts:
    13
    The new update sounds great. Refactoring the data to make it easy to capture the state of the controller will make proper networking much, much easier. Looking forward to it!
     
  33. Dysse_D

    Dysse_D

    Joined:
    Jan 11, 2017
    Posts:
    2
     
  34. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    You have the right idea, but you might be missing a few details. Here's how I think the full procedure should go (with explanations, just in case) :
    • KinematicCharacterMotor.enabled = false
      this unsubscribes the motor from the KinematicCharacterSystem, meaning it won't receive any movement updates anymore
    • KinematicCharacterMotor.HandlePhysics(false, false)
      the first "false" is probably unnecessary since the character is disabled as a whole, but the second one is necessary for disabling the actual capsule collider
    • KinematicCharacterMotor.SetPosition(targetPos)
      This is a method of KinematicCharacterMotor that will become available in the next update for setting the position/rotation in the correct way. I'll just paste the code here so you can add it in the meantime:
      Code (CSharp):
      1. /// <summary>
      2.         /// Sets the character's position directly
      3.         /// </summary>
      4.         public void SetPosition(Vector3 position)
      5.         {
      6.             CharacterRigidbody.interpolation = RigidbodyInterpolation.None;
      7.             CharacterTransform.position = position;
      8.             CharacterRigidbody.position = position;
      9.             TransientPosition = position;
      10.             CharacterRigidbody.interpolation = RigidbodyInterpolation.Interpolate;
      11.         }
      12.  
      13.         /// <summary>
      14.         /// Sets the character's rotation directly
      15.         /// </summary>
      16.         public void SetRotation(Quaternion rotation)
      17.         {
      18.             CharacterRigidbody.interpolation = RigidbodyInterpolation.None;
      19.             CharacterTransform.rotation = rotation;
      20.             CharacterRigidbody.rotation = rotation;
      21.             TransientRotation = rotation;
      22.             CharacterRigidbody.interpolation = RigidbodyInterpolation.Interpolate;
      23.         }
    • KinematicCharacterMotor.BaseVelocity = Vector3.zero and KinematicCharacterMotor.StableInteractiveRigidbodyVelocity = Vector3.zero
      You are right to return Vector3.Zero in your UpdateVelocity, but you should do the above just in case there is a one-frame delay between the time when you disable+move your character and the time your new state enters into action
    • When you want to reactivate it, HandlePhysics(true, true), and KinematicCharacterMotor.enabled = true
    And finally, it's probably a good idea to avoid doing this disable+move in the middle of the character update (in the UpdateVelocity, UpdateRotation, OnCharacterHit, etc... callbacks). Make sure you do it in AfterCharacterUpdate(), or BeforeCharacterUpdate(), or just in a regular Update()

    This sounds like it may be a framerate problem rather than a plaform problem. With rigidbody interpolation and the new "autoSyncTransforms" thing thrown into the equation, it's easy to get problems like these if you try to move a while it is already trying to interpolate to a new position. This problem should be solved by using the procedure described above

    But do let me know if you still get these problems even with the new procedure

    setting the Time.timeScale = 0 will work. But if that's not suitable for you, you can also call KinematicCharacterSystem.Instance.enabled = false

    (actually, I think in the version you have, it's KinematicCharacterSystem.GetOrCreateInstance().enabled or something like that )
     
    Last edited: Jan 17, 2018
    Streamfall likes this.
  35. rad1c

    rad1c

    Joined:
    Feb 26, 2016
    Posts:
    21
    hi Philippe,

    First off, thank you again for all the help you gave me in PMs before, STILL much appreciated :)

    Commenting to ask you a thing for the new version: I integrated your system in my app, would be great however to work with the new version (especially the strafe/slope issue addressed), so if I may, could you please add a short note to how to upgrade from the last version the least painful way?

    I.e. a short list of what modules ("cs files") were changed in what way as of usage (a file compare is never as chatty as the devs' description).

    Would be amazing!

    Thanks in advance!

    [EDIT: OH! Before I forget again. If I add three collision layers which don't collider with each other, the character can get stuck very easily. E.g. one has a "ground", a "wall" and a "walkableDebris" (for playing different audio when walking on debris) layer. None of these collide with each other or self. Adding a 'walkableDebris' to the ground which reaches inside a wall ==> the char. randomly gets stuck at the edge of the wall & the debris. I sorted this out by pixeling out collider dimensions to never touch, but can be frustrating and the source of the issue might be bigger. Thank you again :) ]
     
  36. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Absolutely, I'll probably add this to the User Guide and also post it here. Do expect some pretty big changes, though. It is a massive update, but it solves countless flaws and weaknesses that the package had, so overall it's well worth it. I think all .cs files under the "Core" folder have been modified, and most of the example/walkthrough character controllers have had very minor changes as a result.

    However, I think the upgrade should be pretty simple. When it comes to your custom character controllers, the only things that have changed is that OnMovementHit() has a struct instead of a bool as its last parameter, and perhaps 2-3 KinematicCharacterMotor methods were renamed (I don't have the exact count).

    The only thing I won't be able to provide is an upgrade guide for those who modified KinematicCharacterMotor.cs and want to add the new changes manually. There have been so many changes in that class that it might as well be a new class entirely:

    But rest assured; it is still used in the exact same way by the BaseCharacterController class, so it won't break anything

    Interesting... do you think you could send me a .unityPackage containing just a simple scene with the geometry that has the problem? (either here or via the support email) No need to have the character controller or any other scripts in the package. I'd definitely want to test this before sending the update
     
    Last edited: Jan 18, 2018
  37. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I tried this and didn't see the problem: https://i.gyazo.com/a503067a4dbd99ede8b0b1f143af539a.mp4
    I probably don't understand the test case well enough though. Could you give me a screencap of what you mean?
     
    Last edited: Jan 18, 2018
  38. MikeFish

    MikeFish

    Joined:
    Oct 24, 2015
    Posts:
    12
    Sorry to interrupt for a short praise.
    Man, I'm into KCC for one week now, and it already became such a huge fun to write new movement states. It really is like you advertised, everything I imagined so far was easy to implement. And the walkthrough delivers enough examples to look stuff up, when I got stuck. I'm not a pro coder, coming from the design side, and I'm so glad I didn't get scared off by your "Important Note" on the asset store, tho I understand it, it's probably not the right asset for folks who don't want custom solutions and just plug-in some gameobjects in the inspector.
    When I find the time, be assured that I will drop a longer in depth review on the asset store.
    Thank you for your excellent work!
     
    PhilSA likes this.
  39. rad1c

    rad1c

    Joined:
    Feb 26, 2016
    Posts:
    21
    Sure. I tried to create an area as simple as possible (attached the package, 7zipped).

    All you need to do is run around here a little bit. Either you get stuck next to the wall in the corner, or when you walk off the ledge from the corner, or when you walk off the ledge from the boxes. I also attached some "test stucks" so you can see how it goes (stuck_clips.7z)

    As for the last file, this is my KCC config.

    From what I learned so far, it helps a lot sorting out the issue by not allowing colliders to overlap, but TBH there's a lot to do for me now, so I didn't experiment too much with it. Solved for my "special corner" and the stairs and moved on.
     

    Attached Files:

    PhilSA likes this.
  40. Duusty

    Duusty

    Joined:
    May 14, 2013
    Posts:
    56
    would it be possible to get access to your prototype of the physical sensitive motor/controller?

    "Investigate the feasibility of adding a "non-kinematic" mode where you lose a bit of snappiness and precision but gain much better physics interactivity in return" <--

    As i bought this asset in hope that it interacts a little bit more with the physics, i would be very thankful to have a look at your progress here. And on the other hand i could maybe add some improvements. (did you had a look at this asset regarding the interaction with physics? https://forum.unity.com/threads/fau...cs-character-controller-v1-0-released.488874/)

    Thanks Sir!
     
  41. MikeFish

    MikeFish

    Joined:
    Oct 24, 2015
    Posts:
    12
    need a helping hand, any hint in the right direction is much appreciated.

    my character shall use a simple melee weapon (a big cartoon hammer). What would be the best way to implement this and set this up? first i thought triggers, but it would be nice if the hammer wouldnt clip through things.

    in a different scenario i would be using a rigidbody, but here this clashes with the controller system.
     
  42. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Oh, yes that's good. I forgot this was a new thing
     
  43. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Thanks, I'll be looking at this shortly
     
  44. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I've since then realized that there are issues with the dynamic rigidbody prototype that makes it not a viable option right now. They're not particularly difficult issues to solve (I think), but I'd have to take the time to solve them. This will probably be done after the next update and after the networking example is done.

    However, there's an important flaw in making your character a non-kinematic rigidbody: its movement becomes non-deterministic and so it is not idea for networking. This is why I'm not so sure it is a good idea afterall.

    The current kinematic character does have physics interactions that resemble the ones in the demo you linked, though. You can push things around, stand on things, etc, etc....
    https://i.gyazo.com/bba2e16b8108ef7d1526645b7db08794.mp4
    https://i.gyazo.com/2e778d50acb74df52b91576f1a2607b8.mp4

    If you have a certain physics interaction in mind... it may be doable with the current one. The kind of physics interaction this character controller is not good for is when your character needs to be pulled by physics constraints for example. So games like Gang Beasts would not be a good place to use Kinematic Character Controller
     
  45. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    for melee weapons, I think the best is to not rely on OnCollisionX() callbacks, but instead do continuous "sweeps" to detect collisions.

    So, for example, you'd place a sphere collider on the "damaging" part of the hammer, and when you swing the hammer, at each frame you could do this:
    • Physics.OverlapSphere() to see if anything is colliding with it right now
      • If there is an overlap, Physics,ComputePenetration to find the normal of the overlap
    • Physics.SphereCast() from your hammer's previous position to the next to also detect hits in-between frames
     
    MikeFish likes this.
  46. Duusty

    Duusty

    Joined:
    May 14, 2013
    Posts:
    56
    So in the example scene wich comes with the project (the big one)

    You'll have the cube launcher, interaction actually works quite fine as long as your standing on a physical mover or rigid body. (like in the video you've attached to your link)

    But i cant easily get the character to be pushed by the rigid body cubes. The mass of the cubes doesnt matter, if im blocked from the opposite direction of the launcher by another cube im notgetting pushed back by the cube at all. (here it should push the CharacterMotor as well as the cube behind me.

    What i actually want to achieve is beeing pushed around by rigidbodies as well as pushing other rigidbodies around in the same time (if beeing hit by an object with an high velocity/mass for an example)


    I already tried attach a custom mover/mover controller to the cubes, wich takes the rigidbody velocity/rotation into account for the UpdateMovement function. Wich kind of worked as your character motor is resolving every mover collision in a different way then the one of the rigidbodies. Still i wasnt able to push other cubes if i was beeing pushed by my custom mover based one.

    Another attempt was to overwrite the CharacterMotor logic to "ForceUnground" the character as soon as it got hit by a rigidbody and let it also be pushed back even if stabilized. This worked until the character motor figures out mhm im stabilized again after a frame or so, so i additionally added a small upwards boost to the velocity to keep him from snapping back into the stabilized mode. (i could probably do better here by having a coroutine or flag for a few frames wich keeps him destabilized)


    example 1:
    https://gyazo.com/2a1f18b922f2c89620f78b2e5a885704
    example 2 (here you can see that the cube behind me isnt affected at all, as well as its blocking any kind of affecting impact from the cube wich is shot at the character:
    https://gyazo.com/6905997f50cc42f80171194229cd438c


    Hopefully you can come up with a cleaner and more reliabable solution.

    I know about the multiplayer networking concerns you have, especially if its a game there the replication and prediction needs to be reliable. Still i would be super thankful if you would have an example of your physic based rework for testing purpose, from wich i can maybe adapt some changes over.
    otherwise i think i still can get off with modifing the character motor. to switch into a "full rigidbody" mode as soon as the character gets hit by the rigidbody for some time and then figure out a kind of interpolation to smoothly blend into control mode again.

    Thanks! (Btw i love your class design)
    And do you have a clue then your next update will be available?
     
    Last edited: Jan 19, 2018
  47. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    oh ok, I see what you're saying, and you're right about it being a limitation of the current KCC. You could make the rigidbodies apply some kind of impulse on the character upon impact, but it'll be a bit weird because they'll get stopped instantly. I wouldn't see easy ways of implementing this while the rigidbody stays kinematic. The fully dynamic character will come eventually...

    Right now, my prototype has trouble with moving platforms, step handling and staying grounded on another rigidbody, but it does do what you're talking about: https://i.gyazo.com/18f3b4aa2e4cb12aa8a5b3f4e568cb53.mp4

    I am currently correcting a bug I found while testing, and after that all that's left is some more testing and writing documentation. I'm hoping to submit it to the store before the end of january, but no guarantees :D
     
    Last edited: Jan 19, 2018
  48. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I tested this for a while but couldn't manage to repro the problem (I tried it with the version 1.2.2 of KCC)
    At this point, if you can allow it, it may be best if you could zip a full project where this is reproductible
     
  49. Duusty

    Duusty

    Joined:
    May 14, 2013
    Posts:
    56

    i'm quite sure i could help you out with those issues "https://forum.unity.com/threads/fau...cs-character-controller-v1-0-released.488874/" <-- this character controller solved the issues quite easily.

    By parenting a kind of a "probe" transform to the rigidbody, with the position and rotation from the controller, those are then moved and rotated against thes velocity of the rigidbody they are attached to. This delta is then used to correct the position of the character controller as long as its "grounded" to that rigidy body. (this solution is about 20 lines long)

    Not that i want to beg, to have a look at your progress.. but i really would love to use and improve your rigid body based controller. :rolleyes:
     
  50. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    I think the main source of the issues I'm having with my "dynamic" controller is that I'm trying to implement it as an option in the KinematicCharacterMotor. And it turns out that this is a really bad idea because it just makes everything difficult to manage while keeping feature/API parity between both controllers.

    What I'll do next time is that I'll start a completely separate "DynamicCharacterMotor" class that will diverge from the other one completely. It'll make things much simpler

    But if you're really curious and want to play around with the prototype, I can send it to you. Just leave your email in my inbox