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

[RELEASED] Easy Character Movement

Discussion in 'Assets and Asset Store' started by Krull, Apr 21, 2016.

  1. Krull

    Krull

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

    No problem, glad i was able to help :)

    About your questions:
    The stepOffset is used to set the height of a step a character can walk over.

    One method to implement footsteps if you are using an animator to perform your headbob walk animation (like the included headbob example), is to use animation events to add sound effects like footsteps, since you have your 'walk' animation curve, you can set an event on the animation curve where character 'hit the ground' and then use this event to trigger a sound effect in your custom controller.

    To implement a toggle crouch please use the following code:

    Code (csharp):
    1.  
    2. if (Input.GetKeyDown(KeyCode.C))
    3.     crouch = !crouch;
    4.  
    This will toggle the crouch behavior, negating its current state.

    Regards,
    Oscar
     
  2. my_little_kafka

    my_little_kafka

    Joined:
    Feb 6, 2014
    Posts:
    87
    Hello! Currently I'm in a search of a fairly simple Character Controller for both Player Character and NPCs. I need my CharacterControllers to follow these rules:

    • The controllers never push each other
    • The NPCs use root motion to drive their movement, but even if there's an animation of an NPC lunging forward with a sword towards someone, this animation won't move that someone (be it PC or NPC), as in the first rule
    • The NPCs are confined on the NavMesh and can't leave it.

    What I'm doing now with the out of the box solutions in Unity is that I use NavMeshAgent to calculate the path and rotate the NPC towards the closest point while the root motion moves the NPC forward with CharacterController's Move(), I use the same method on PC and it provides me with the "no pushing" behaviour that I require.

    The problem is, if an NPC makes a certain move, like a dodge to the side, for example, the CC and NMA can get desynced - NMA is still on the navmesh, while CC is out of navmesh, because it dodged out of it.
    So I need to explicitly tell the CC to assume the NMA's position, even if I use NMA just to rotate the NPC towards the closest navigation point, I don't use it to move, because Unity's CharacterController is handling the movement.
    I had use some hacky solutions to achieve that, but, ultimately, I encountered a lot of problems with CC which I can't fix at all, mainly - if the NPCs CC radius is too high (and I need bigger CCs for giant enemies, for example), it will randomly fly up when colliding with other smaller CCs, including PC's CC, which is not very good for my game.

    I'm interested in this asset, but I would like to know - is it possible to lock NPCs that use this CharacterController to a navmesh, so it won't desync with a NavMeshAgent, but so they still maintained proper physical interactions - no pushing each other, no flying up the slopes or when colliding with other smaller CharacterControllers?
     
  3. Krull

    Krull

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

    About your questions:

    ECM is a physics based rigidbody, eg a regular rigidbody acting as a character controller, and while it works really well, the character's can push each other at some degree, for example based on its mass the one with bigger mass will push the other easier and vice versa.

    Having said that, this wont be as 'bad' as it sounds, because when using root motion, the animation's velocity takes full control over the rigid body's velocity so the pushing will be minimal.

    A more advanced solution, is cast a capsule towards its target position, and if it will hit another character, update its velocity to stop pushing the other, make it kinematic on idle state, toggle its position contraings, etc.

    The BaseAgentController included with ECM, works different than using a regular NavMeshAgent, with ECM, its the ECM character controller the one responsible of move and sync the NavMeshAgent, not the other way, basically ECM uses the agent as a navigation helper, just as you do, it gives us the desired velocity (direction towards the closest point), and we feed this velocity to the CharacterMovement Move method to move ECM character, as a last step, ECM will update the Agents properties to match the character's current state (eg: position, velocity, acceleration, etc).

    No out of the box, however just as abovem, a possible solution is to sample your future position (position + velocity * deltaTime), using the NavMesh.SamplePosition function and check if it lies within the NavMesh, if not, update's the character's velocity to prevent leaving the NavMesh.

    Hope this helps you, however if have further question, please do not hesitate to post it here, or email me.

    Regards,
    Oscar
     
    my_little_kafka likes this.
  4. anpShawn

    anpShawn

    Joined:
    Oct 1, 2012
    Posts:
    18
    Hi Oscar- I've been using ECM for a while now and it works great. I had one question though: do you have a preferred method to implement slow motion? Slow motion with rigidbodies can be tough because you need to consider current move velocity, gravity, and mass. I played with some of these values but always received inconsistent results (absolute movement of the character varied while slow motion was active).

    Just wondering if I should continue to tweak these values or if you had experience doing this already. Thanks!

    Edit: I've had the best luck so far by simply picking a speed value (such as .5) and applying it to both Time.timeScale and Time.fixedDeltaTime. I am continuing to look for unseen issues.
     
    Last edited: May 22, 2020
  5. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Afro-Ninja

    Yes, as your updated test, modifying Time scale (Time.timeScale) is the easiest and suggested way to perform slow motion. I suggest you leave the FixedTimeStep to its default value 0.02f as it could affect the performance.

    Another way, however its more complicated is to scale the character's velocity (eg: multiply it by 0.5f) and also its animation speed, however the only advantage of this method I can think over the timeScale, is with this method you control what character is slowed.

    Let me know if have any further questions.

    Regards,
    Oscar
     
  6. anpShawn

    anpShawn

    Joined:
    Oct 1, 2012
    Posts:
    18
    Performance isn't a huge concern at the moment, I don't believe I'll have a ton of ECM controllers in the scene at once. I currently have FixedTimeStep set to .016f (60fps) to make the sync between update and fixed update as smooth as possible.

    Unity's docs do recommend updating fixedDeltaTime if you decide to change the timeScale, but I can see why it would be problematic. I really just want to avoid any situations where changing to slow motion at an unexpected time means a character could end up in a slightly different place than they should be (or rather, wishing to preserve the game's ability to be deterministic)
     
  7. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Afro-Ninja

    Yes, definitely should not be an issue, I suggest you choose and set your desired FixedTimeStep for your project, based on your game needs, and update the Time.timeScale and Time.fixedDeltaTime when slowmotion is needed.

    At great sight, to move our character ECM basically will accelerate / decelerate its current velocity (given by PhysX) to match our given desired velocity (input, ai, etc), so this slow motion should not cause any troubles.

    Cheers,
    Oscar
     
  8. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    485
    @Krull Noticed what might be a small bug. I was trying to use some sort of magnitude or something to control my animator and noticed in BaseFirstPersonController::GetTargetSpeed() that the targetSpeed is initialized to forwardSpeed. This presented a problem since you cannot detect if the Player is moving or standing still. Changed line 151 to initialize targetSpeed to 0. Everything is working as expected.
     
  9. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @jnbbender, Thank you for report it, and yes actually it defaults to forwardSpeed value. I will add this change to the upcoming v1.8 version.

    Take care,
    Krull
     
  10. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    485
    Please help. I am fighting with the Crouch/Scaling problem. I am trying to use this for a FPS with the basic idea of having 2 cameras (one for the player view and another for the camera). My problem is that if I make my WeaponCamera (which is the parent for all weapons) a child of the Camera_Pivot, all the weapons get squashed but the firing line is good. (see video).



    If I don't, the weapon camera still views the weapons at the correct size but the weapons are not moved with the scale so they fire inappropriately (see video).

     
  11. Krull

    Krull

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

    I see, this behavior is caused because by default the BaseFirstPersontCharacterController in its AnimateView method, to handle the crouch state, it will modify the pivot scale, thus affecting your other camera.

    This can easily be modified if using a custom controller extending the BaseFirstPersonCharacterController, simply override its AnimateView and add your code in there if no, well simply modify the AnimateView directly as follows:

    This is the default implementation and is just for 'example purposes':

    Code (csharp):
    1.  
    2. protected virtual void AnimateView()
    3. {
    4.     // Scale camera pivot to simulate crouching
    5.  
    6.     var yScale = isCrouching ? Mathf.Clamp01(crouchingHeight / standingHeight) : 1.0f;
    7.  
    8.     cameraPivotTransform.localScale = Vector3.MoveTowards(cameraPivotTransform.localScale,
    9.         new Vector3(1.0f, yScale, 1.0f), 5.0f * Time.deltaTime);
    10. }
    11.  
    As you can see, it will modify the pivot scale causing your issues, to solve this you can move the pivot position or the camera as needed by your game code, for example this shows how move the pivot when crouched:

    Code (csharp):
    1.  
    2. protected virtual void AnimateView()
    3. {
    4.     // Modify camera pivot local position to simulate crouching state
    5.  
    6.     Vector3 targetPosition = isCrouching
    7.         ? new Vector3(0.0f, crouchingHeight, 0.0f)
    8.         : new Vector3(0.0f, standingHeight, 0.0f);
    9.  
    10.     cameraTransform.localPosition =
    11.         Vector3.MoveTowards(cameraTransform.localPosition, targetPosition, 5.0f * Time.deltaTime);
    12. }
    13.  
    You can use the same approach to move the camera's position if needed, or simply leave the AnimateView method empty and handle the crouch animation externally simply queering the isCrouching state and animate your camera rig as needed.

    Best regards,
    Oscar
     
    jnbbender likes this.
  12. Amadeu

    Amadeu

    Joined:
    Dec 11, 2014
    Posts:
    9
    Hi Oscar! I hope this message finds you and you loved ones safe and well.

    I use to visit easy character movement's asset store web to see if there's any update and also I like to check the reviews, and I have noticed a review from compurugu that tells how he managed to make his character swim with your help, and how this also can be applied to make the character climb and fly. As this are some features I want to add in short, I was wondering if you can post here the solution he was mentioning. Thanks in advance and a big hug from BCN!
     
  13. Krull

    Krull

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

    Thank you and sincerely hope you and your family the same :)


    About your question, yes,sure thing, however first I would like to share with you (and all of you :D), I have finally completed the ECM v1.8 and as part of this update I added a walk-through guide with the examples you requested an many more!

    The complete ECM v1.8 change log is as follows:

    - Character can now be arbitrary rotated, previously the character was required to remains upright (+Y Aligned).

    - Gravity is now a vector and allows arbitrary gravity direction.

    - Added support for root motion based rotation.

    - New position based snap to ground method, previously was speed based.

    - CharacterMovement DisableGrounding method now allows set disable duration time, this ease the character to leave the ground. Previously was just 1 frame of tolerance.

    - Added a new CharacterMovement ApplyImpulse method, this allows an arbitrary impulse direction.

    - Updated jump behavior. Added Jump Post-Grounded Tolerance Time and Jump Pre-Grounded Tolerance Time (previously serialized as _jumpToleranceTime) This allows to achieve a jump even when character is not grounded.

    - OrientModelToGround helper component has been deprecated.

    - Updated Documentation.

    - Added walk-through guide with following examples:

    - Custom Character Controller
    - Custom Input
    - Movement Relative To Camera.
    - Slide On Steep Slopes.
    - Jumping.
    - Fall Damage.
    - Crouching.
    - Platforms.
    - Orient Towards Ground Normal.
    - Toggle Gravity Direction.
    - Flying.
    - Swimming.
    - Climbing Ladders.
    - Wall Grab / Wall Jump.
    - Smoother FPS Rotation.
    - Over The Shoulder Camera.
    - Visualize 'Walkable' Ground.

    - Minor bug fixes.

    *** v1.8 is not released yet, however Ill do my best to make it available the next week (Monday 20).

    Having said that, yes, actually the climb, swim, fly, etc. are somewhat related as those 'states' require the use of the vertical component of the given desired velocity, which by default is discarded, as the default ECM character movement is planar, so in order to allow those movements, you must explicitly set the BaseCharacterController allowVerticalMovement property to true when your character's need to move vertically.

    Hope this helps you, however if need any further help, please do not hesitate to message me back.

    Take care,
    Oscar
     
    Bartolomeus755 likes this.
  14. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603


    I'm enjoying ECM, but I seem to be having a problem with it sometimes snapping down into the ground when getting close to the platform. This is with default settings on ECM>Character.




    I set up another test with Capsule Dummy and 1.3m height and noticed the problem especially prominent when clipping the edge. it also happens when crossing the threshold from above.

    How can I prevent this?
     
    Last edited: Jul 28, 2020
  15. Krull

    Krull

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

    First of all thank you for purchasing ECM!

    About your current issue, while I honestly can not reproduce it (yet), first, please make sure your capsule collider's center is correctly set, for example for you 1.3m character, its center must be 0.0, 0.65, 0.0.

    If the above does not help, it could be an issue related to the new position based snap to ground method, in order to fix this please add the following code to the CharacterMovement LateFixedUpdate (line 1570) method:

    In the line 1587, please add this conditions right before the SnapToGround and SnapToPlatform methods:

    Code (csharp):
    1.  
    2. // If enabled, attempt to snap to ground
    3. if (snapToGround && isOnGround)
    4.     SnapToGround(ref p, ref q);
    5.  
    6. // Attempt to snap to a moving platform (if any)
    7. if (isOnGround && isOnPlatform)
    8.     SnapToPlatform(ref p, ref q);
    9.  
    Please let me know if this helps.

    Regards,
    Oscar
     
  16. mookfasa

    mookfasa

    Joined:
    Dec 21, 2016
    Posts:
    46
    @Krull
    I am setting up a custom character controller where if I press shift the player will start to run in that direction from either idle and moving. Right now I am setting the moveDirection.z to 1. How do I make it run in the the forward facing direction?

    Code (CSharp):
    1.  
    2. protected override void HandleInput()
    3. {
    4.     if (runInputPressed)
    5.     {
    6.         moveDirection = new Vector3
    7.         {
    8.             x = Input.GetAxisRaw("Horizontal"),
    9.             y = 0.0f,
    10.             z = 1
    11.         };
    12.     }
    13.  
    14.     else
    15.     {
    16.         // movement
    17.                  
    18.         moveDirection = new Vector3
    19.         {
    20.             x = Input.GetAxisRaw("Horizontal"),
    21.             y = 0.0f,
    22.             z = Input.GetAxisRaw("Vertical")
    23.         };
    24.     }
    25. }
     
  17. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hey @mookfasa

    To move your character towards its current view direction, simply set its moveDirection = transform.forward, this transform.forward is the character's current facing direction. However, make sure you are no transforming the moveDirection vector in the CalcDesiredVelocity method.

    Let me know if need any further help.

    Regards,
    Oscar
     
  18. mookfasa

    mookfasa

    Joined:
    Dec 21, 2016
    Posts:
    46
    I think maybe what I am looking for is a way to accelerate in the the players in the forward facing direction while still having the movement relative to the camera. So just adding speed basically. But since the moveDirection inputs are 0, 0 times speed will still be zero.
     
    Last edited: Aug 4, 2020
  19. YannickTriqueneaux

    YannickTriqueneaux

    Joined:
    Apr 9, 2020
    Posts:
    4
    Very Nice, I'll try it at home :)
     
  20. Krull

    Krull

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

    Oh I see, you mean like an auto run, to accomplish it, simple add the transform.forward to your moveDirection once its been transformed to be relative to camera's view direction, as follows:

    Code (csharp):
    1.  
    2. protected override void HandleInput()
    3. {
    4.     // Input code
    5.  
    6.     moveDirection = new Vector3
    7.     {
    8.         x = Input.GetAxisRaw("Horizontal"),
    9.         y = 0.0f,
    10.         z = Input.GetAxisRaw("Vertical")
    11.     };
    12.  
    13.     jump = Input.GetButton("Jump");
    14.  
    15.     crouch = Input.GetKey(KeyCode.C);
    16.  
    17.     runInputPressed = Input.GetKey(KeyCode.LeftShift);
    18.  
    19.     // Make moveDirection relative to camera's view direction
    20.  
    21.     var mainCamera = Camera.main;
    22.     if (mainCamera != null)
    23.         moveDirection = moveDirection.relativeTo(mainCamera.transform);
    24.  
    25.     // If auto-running, move character's in its forward direction
    26.  
    27.     if (runInputPressed)
    28.         moveDirection += transform.forward;
    29. }
    30.  
    Let me know if need any further help.

    Regards,
    Krull
     
    Willbkool_FPCS likes this.
  21. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    Sorry for the delayed reply, but fixing the capsule collider center fixed my problem! thanks!!
     
  22. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    No problem, thank you for the update! Glad I could help. Regards
     
  23. mookfasa

    mookfasa

    Joined:
    Dec 21, 2016
    Posts:
    46
    @Krull moveDirection += transform.forward; works perfect thank you!
     
  24. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Thats great! Thank you for the update.

    Regards,
    Krull
     
  25. mookfasa

    mookfasa

    Joined:
    Dec 21, 2016
    Posts:
    46
    @Krull

    I am trying to have the player ride along top a custom nave mesh controller. When the character is on top of it just seems to slide off. It seems to work fine with the kinmaticMover, not sure why it wouldnt work with a controller. Does it have something to do with the velocity of the player not matching on player vs the velocity of the agent?
     
  26. larry2013z

    larry2013z

    Joined:
    Apr 14, 2020
    Posts:
    36
    Hi Oscar- Great product! I am currently integrating your flying code into my character controller. I am using root motion to move my character ('Use Root Motion' is checked on). The flying does not work when that box is checked ON but works perfectly when it is not checked. What happens is that after double jumping to get him in fly mode he is stuck in the air. The code to raise him up and lower him down is getting called but he is not moving up or down.

    The only difference between working and not working is the Use Root Motion checkbox.

    I would really like to use root motion. Any advice you could offer me to get the two (root motion and flying) working together would be greatly appreciated.

    Oh, and I am using moveDirection = moveDirection.relativeTo(mainCamera.transform); if that makes any difference.

    Thanks,
    -Larry
     
  27. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    By default an ECM character can only use as platform a kinematic rigidbody, as internally it use kinematic rigidbodies as platforms, so as long as you set your other as kinematic rigidbody it should work.

    However, depending on how you animate it, you need to make it comply with physics, for example when using an animator to move a platform you need to set the animator update mode AnimatePhysics, the same applies when using for example tween libs and so on.

    Regards,
    Krull
     
  28. Krull

    Krull

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

    Thank you for purchasing ECM and glad to know you like it!

    About your current issue, yes, by default ECM disables root motion when character is not grounded (eg: jumping), basically this is related the used Ethan animator not having root-motion jump animations, so in order to support root-motion jump, fly, climb etc (actually any vertical movement), you'll need modify its Move method.

    For example, if your controller is using exclusively root motion, in your custom controller, you can override its Move method, and simplify it as follows:

    Code (csharp):
    1.  
    2. protected override Vector3 CalcDesiredVelocity()
    3. {
    4.     // If using root motion exclusively, you can simplify this method to return animation velocity only
    5.  
    6.     return rootMotionController.animVelocity;
    7. }
    8.  
    9. protected override void Move()
    10. {
    11.     // If using root motion exclusively, you can simplify this method to just move the character with given animation velocity
    12.  
    13.     Vector3 desiredVelocity = CalcDesiredVelocity();
    14.  
    15.     // Root-Motion movement (not affected by character's accel / decel, frictions, etc. as animation takes full control)
    16.  
    17.     movement.Move(desiredVelocity, speed, !allowVerticalMovement);
    18.  
    19.     // Regular Jump logic (if needed)
    20.  
    21.     Jump();
    22.     MidAirJump();
    23.     UpdateJumpTimer();
    24. }
    25.  
    This should solve your current issue, however if still have issues or need any further help, please do not hesitate to message me back.

    Cheers,
    Oscar
     
  29. larry2013z

    larry2013z

    Joined:
    Apr 14, 2020
    Posts:
    36
    @Krull
    Shoot, it didn’t work. With MidAirJump(); in there, he just double jumps and ‘flying mode’ never activates. I commented that line out and I have the same problem I did originally. He jumps and freezes in mid air and won’t move up or down. I’ll keep plugging away…If you have any more ideas let me know. I may contact you by email if I can’t get anywhere.
     
  30. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    Hi! A few questions!

    1. Is there any way to prevent characters from sliding around non-flat walls if they continue to press into them? They stop moving but eventually slide sideways without turning.It only happens on walls with a slight slope, such as rockfaces.


    2. You mention a walkthrough for Ladders, but I can't find anything in the PDFs or code. Do you have plans to add this?

    3. Is there any way to access how long the character has been in the air for? I'd like to limit rotation speed on jumping and falling characters after a short while, but right now I only have 'isGrounded'.

    4. How can I make jump landing more generous? I often have the character bounce off and get pushed backwards.


    Thanks!
     
  31. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    The code I pasted assumes you are using root motion for all, meaning your animations handles the walk, run, jump, fly, etc, supplying the correct velocity (lateral, vertical, etc) to ECM character, for each state.

    In the attached package I modified the Fly example to solve the issue you are getting, to use it, simply import the package into a project with ECM installed on it, and please refer to the Support/RootMotion Flying Example/Scenes/RootMotion Flying scene.

    The modified Move method is as follows:

    Code (csharp):
    1.  
    2. protected override void Move()
    3. {
    4.     // Apply movement
    5.  
    6.     // If using root motion and root motion is being applied (eg: grounded),
    7.     // move without acceleration / deceleration, let the animation takes full control
    8.  
    9.     var desiredVelocity = CalcDesiredVelocity();
    10.  
    11.     if (useRootMotion && applyRootMotion)
    12.         movement.Move(desiredVelocity, speed, !allowVerticalMovement);
    13.     else
    14.     {
    15.         // Move with acceleration and friction
    16.  
    17.         var currentFriction = isGrounded ? groundFriction : airFriction;
    18.         var currentBrakingFriction = useBrakingFriction ? brakingFriction : currentFriction;
    19.  
    20.         movement.Move(desiredVelocity, speed, acceleration, deceleration, currentFriction,
    21.             currentBrakingFriction, !allowVerticalMovement);
    22.     }
    23.  
    24.     // Jump logic
    25.  
    26.     Jump();
    27.     UpdateJumpTimer();
    28.  
    29.     // Fly logic
    30.  
    31.     EnterFlyState();
    32.     ExitFlyState();
    33.  
    34.     // Update root motion state,
    35.     // should animator root motion be enabled? (eg: is grounded)
    36.  
    37.     applyRootMotion = useRootMotion && movement.isGrounded;
    38. }
    But please refer to the include package for a working example.

    Regards,
    Krull
     

    Attached Files:

  32. Krull

    Krull

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

    About your questions:

    1.- This depends of your character settings, mostly the GroundDetection GroundLimit and the CharacterMovement SlideOnSteepSlope setings (enabled / disabled, Slope Limit and Slide Gravity Multiplier).

    I suggest you setting the GroundDetection Ground Limit property to 89 (max value) and limit the walkable areas using the CharacterMovement Slide On Steep Slope settings (eg: SlopeLimit 60).

    Another consideration is to make sure your collision geometry geometry complies with character settings. This can be accomplished using the included walk-through example - Visualize walkable ground.

    2.- Yes, unfortunately this was left out of the v1.8 for time constraints, however I have planned to add the stair climb and wall climb examples by the end of this month.

    3.- By default it exposes isGrounded, isFalling and isJumping, states, and while it includes a _jumpTimer, this is mostly to handle the variable height part of its jump and not what you are looking for.

    In order to add a 'flight time' you can follow an approach similar to the one used in the fall damage example, as follows:

    Code (csharp):
    1.  
    2. private float _airTime;
    3.  
    4. protected override void Move()
    5. {
    6.     // Call ECM Default Move method (movement, jump, etc)
    7.  
    8.     base.Move();
    9.  
    10.     // Compute time on air
    11.  
    12.     if (!movement.wasGrounded && movement.isGrounded)
    13.     {
    14.         // Character has just landed, report and reset timer
    15.  
    16.         Debug.Log("Air Time: " + _airTime);
    17.         _airTime = 0.0f;
    18.     }
    19.     else if (!movement.isGrounded)
    20.     {
    21.         // If character is not grounded, update air time counter
    22.  
    23.         _airTime += Time.deltaTime;
    24.     }
    25. }
    26.  
    4.- This can be tuned using the Ground Detection Ledge Offset, where a value of 0.5 (for default 2m ECM Character) allows the character to walk 'out of the ledge' almost all its radius, and easing the landing on ledges.

    Worth note ECM being a Rigidbody based character controller, will take the velocity given by Physics engine and basically will accelerate / decelerate its velocity to match our desired velocity (the one passed to the CharacterMovement Move method), so this effect is eased or accentuated by the Character current Acceleration, Deceleration and Friction values, where higher values will slows down the character faster and vice-versa.

    Last but not least, you can try limiting the Rigidbody max de-penetration velocity, which by default is unlimited and can result in strong hard contacts. To limit you can add the following code to your custom controller:

    Code (csharp):
    1.  
    2. private void Start()
    3. {
    4.     movement.cachedRigidbody.maxDepenetrationVelocity = 1;
    5. }
    6.  
    Kind regards,
    Krull
     
  33. larry2013z

    larry2013z

    Joined:
    Apr 14, 2020
    Posts:
    36
    Thanks Krull! It's working the way I want now. Your example code was a huge help.

    Looks like my main issue was not using this line: applyRootMotion = useRootMotion && movement.isGrounded;
    which turns off applyRootMotion when the character is not grounded.

    P.S. Just posted a 5 start review of ECM. Well deserved!
     
    Last edited: Aug 20, 2020
  34. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    603
    @Krull Thanks for your suggestions. Unfortunately none of these work for me, especially because the ledge offset technique doesn't work unless the player is already at the ledge height.


    I'd love better support for edge scrambing/mantling and dangling in future. This is when a ledge is slightly out of reach so their hands land, typically prompting a very fast leg lift anim/motion.
     
  35. Amo-deus

    Amo-deus

    Joined:
    Jul 27, 2015
    Posts:
    21
    Hello! Amazing kit!

    I think I've found a small bug though. When the player jumps against Rigidbodies that use gravity they seem to get snagged and limits jump velocity, almost as if the box has a high friction physics material attached or something. Increasing the Character Movement Gravity makes this much more noticeable. This is from a clean import with nothing changed. Also this seems to happen when the Rigidbody is moving and the player is against it/pushing it.
     

    Attached Files:

    Last edited: Aug 20, 2020
  36. Krull

    Krull

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

    Thank you for the update, and happy to know I could help you.

    Yes, you are correct, this is needed to disable root motion when character is flying as the root motion is not providing the fly velocity, thous causing the previous issue.

    Thank you, I really appreciate it!

    Take care,
    Krull
     
  37. Krull

    Krull

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

    Ah I have a better understanding of your current issue, as I see it what you are looking / needing is a kind of 'ledge perch' system, which unfortunately ECM does not support.

    Based on your latest picture an ECM character expects its capsule be enclosing the character's whole body, the ledge detection occurs at the character's foot area (capsule bottom's sphere), based on current ledge offset setting, the character will be allowed to climb the ledge or slide of it, this is a typical behavior for capsule based characters.

    Back to the perch system, this could be achieved simply down-casting in front of the character (forward view direction) at a fixed height, this way when the regular ECM ledge detection slides the character off the ledge, the perch system will catch the hit, allowing to react to this case.

    Having said that I have planned a major upgrade for ECM 2.0, and while not incorporating a fully perch system as I aim to leave ECM as a general purpose character controller, it will feature a more robust collision detection system and the ability to climb higher steps, which in the current version are limited to the capsule's radius.

    Best regards,
    Krull
     
  38. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Amodeus-S

    First of all thank you for purchasing ECM!

    About your issue, Thank you for report the possible bug, Ill take a look at it as it seems to be related to the snap to ground feature, causing the character to get stuck to the non-kinematic rigidbody.

    In the meantime if need any help with ECM, post it here or feel free to write me to support email.

    Kind regards,
    Oscar
     
  39. larry2013z

    larry2013z

    Joined:
    Apr 14, 2020
    Posts:
    36
    Tip: This might save someone else some trouble. I had a death/dying/trip animation I was using from Mixamo. When it would run, the character would lie down about 3' in the air instead of on the ground as desired.

    At first I suspected the collider was holding him up (and it probably is) but instead of messing with the collider you should 'Bake into Pose' the Root Transform Position (Y). Make sure to set the 'Based Upon (at Start) to Feet.

    After that it works perfectly.


     
    Last edited: Aug 21, 2020
    Willbkool_FPCS and Krull like this.
  40. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Amodeus-S

    Sure, you can compare the angle between the character's velocity (which is accessed in the BaseCharacterController using movement.velocity) and the current input move direction vector (moveDirection property), if this is greater than a threshold the character did a quick turn.

    A simple dot product could work, for example:

    Code (csharp):
    1.  
    2. var speed = movement.velocity.magnitude;
    3. if (speed > speedThreshold)
    4. {
    5.     if (Vector3.Dot(velocity, moveDirection) < 0.0f)
    6.     {
    7.         // velocity and move direction are completely opposite!
    8.     }
    9. }
    10.  
    Let me know if need any further help.

    Regards,
    Krull
     
  41. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Excellent! Glad I could help :)
     
  42. mookfasa

    mookfasa

    Joined:
    Dec 21, 2016
    Posts:
    46
    @Krull is there a way to make it so when you are on a slope that is past the ground limit it wont disable all player input? Right now once i am on a slope it starts to slide but I cannot us the horizontal/vertical input any more.
     
  43. Krull

    Krull

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

    Yes, but no by default, so a little modification to CharacterMovement component is needed.

    First in the CharacterMovement ApplyMovement method (line 1299), modify its first if (line 1302) as follows:

    Code (csharp):
    1.  
    2. bool shouldSlide = slideOnSteepSlope && groundAngle > slopeLimit;
    3. if (isGrounded && !shouldSlide)
    4. {
    5.     ApplyGroundMovement(desiredVelocity, maxDesiredSpeed, acceleration, deceleration, friction,
    6.         brakingFriction);
    7. }
    8.  
    This will change the code path when character should slide to air movement path, last we need to add the following code to the CharacterMovement ApplyAirMovement method on the 'On Invalid Ground' section (line 1215), as follows:

    Code (csharp):
    1.  
    2. if (isOnGround)
    3. {
    4.     // If moving towards invalid 'ground', cancel movement towards it to prevent climb it
    5.  
    6.     if (Vector3.Dot(desiredVelocity, _normal) <= 0.0f)
    7.     {
    8.         var maxLength = Mathf.Min(desiredVelocity.magnitude, maxDesiredSpeed);
    9.  
    10.         var lateralVelocity = Vector3.ProjectOnPlane(velocity, up);
    11.  
    12.         desiredVelocity = Vector3.ProjectOnPlane(desiredVelocity, _normal) +
    13.                           Vector3.Project(lateralVelocity, _normal);
    14.  
    15.         desiredVelocity = Vector3.ClampMagnitude(desiredVelocity, maxLength);
    16.     }
    17.  
    18.     bool shouldSlide = slideOnSteepSlope && groundAngle > slopeLimit;
    19.     if (shouldSlide)
    20.         velocity += gravity * (slideGravityMultiplier * Time.deltaTime);
    21. }
    22.  
    This will enable a little lateral movement while character is sliding down of a steep slope IF slide on steep slope is enable.

    Regards,
    Krull
     
  44. Heckers

    Heckers

    Joined:
    Jan 22, 2015
    Posts:
    2
    Hi @Krull and thanks for such an easy to use package that just works.
    I also look forward to your demo of how you would do ladder climbing ever since you mentioned it in your post ;).

    There is also something else I hope you have a suggestion for.
    I would like to make my character be able to walk over debris or up steps that are higher than the radius of the collider.
    I updated the Clamping in the properties and tried to increase the values for Step Offset and Cast Radius but it didnt seem to have any effect.
    As per this screenshot, it really feels like the character should be able to climb these steps but I dont want to make a big fat collider that doesnt fit the character.
    upload_2020-9-1_18-15-45.png
     
    Last edited: Sep 1, 2020
  45. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hi @Heckers
    Thank you for purchasing ECM and glad you like it! About the ladder example, yes I hope to make it available this week (heavy busy days), so I appreciate your patience an understanding.

    Yes, I agree with you on this, unfortunately the current ECM grounding implementation, only allow to walk over steps as high as the capsule radius, unfortunately it is a current limitation, as internally ECM walk over steps simply projecting its movement over the ground surface, and in order to walk over higher steps, it requires a modification of it.

    The good news (without disclosing its newest features yet ;) ) is I am working in a BIG ECM update, actually is a complete rewrite of the package, and definitely will solve this step issues and improve many things.

    In the meantime, let me know If need any help.

    Regards,
    Krull
     
    Shiskebab, Heckers and Willbkool_FPCS like this.
  46. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    762
    Hello,

    As promised here attach the Ladder Climbing Example. To use it simply import the attached package into a project with ECM installed.

    I commented most of the code, however if you have any questions, please feel free to post it here or message me to support email.

    Regards,
    Krull
     

    Attached Files:

    my_little_kafka and Heckers like this.
  47. Heckers

    Heckers

    Joined:
    Jan 22, 2015
    Posts:
    2
    That is awesome @Krull !
    Even angled ladders, wow thank you so much.
     
  48. Krull

    Krull

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

    Great, Happy to know you like it, and sure will help others too!

    Kind regards,
    Krull
     
  49. ShiftedClock

    ShiftedClock

    Joined:
    Sep 12, 2012
    Posts:
    18
    Using Unity 2020.2.0b2 I get this Warning dialogue when clicking Import in the Package Manager window.

    The install instructions don't mention this part. Is this a known bug or possibly something new with 2020.2? I haven't tried it with older versions.
     
  50. Krull

    Krull

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

    Yes, it is normal, as it being distributed as a complete package in the unity asset store, and thus it includes a copy of project settings, however worth note this settings are not really required by ECM and can be ignored.

    Here I attach you the updated documentation to show how can easily import into existing projects.

    Best regards,
    Krull
     

    Attached Files: