Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[RELEASED] Easy Character Movement 2

Discussion in 'Assets and Asset Store' started by Krull, May 5, 2021.

  1. zzzz789

    zzzz789

    Joined:
    Apr 11, 2022
    Posts:
    9
    Excited for the FishNet support coming for the Characters. Any update on how this is progressing @Krull ?
     
  2. TheMK-_-

    TheMK-_-

    Joined:
    Feb 8, 2018
    Posts:
    13

    Thanks Krull appreciated :) +1
     
    Krull likes this.
  3. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @FGRivera

    Could you develop a bit more on how this happens, as from the attached image I can see the character is far from the gray wall (ramp?) so it should not catch those as ground, but honestly the image does not provide me enough information to get a clue of the possible issue. But this leads me to think it could be a bug due to the character being rotated (not vertically aligned) and flat base.

    Regards,
    Krull
     
  4. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    HI @Asarge,

    Ah yes, your approach is correct, and looks very cool too!

    To offset your character make sure you assign your models root transform to the CharacterMovement Root Transform property and at runtime modify the Root Transform Offset, i.e: characterMovement.rootTransformOffset = new Vector3(0.0f, 1f, 0.0f);

    However, I noticed the Animator (I think is the culprit) prevents the model to be offseted, when the Animator is the Character's main GameObject and not as a child of it. I noticed the same issue with the model and animation included in the Unity Starter Assets - Third Person Character Controller where you can't alter the character's transform from editor.

    Cheers,
    Krull
     
  5. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    hmm that is the one I'm calling in the script and my animator is on the child object just like how it's set up in the ECM2 examples but the result in the video is the same. I'll try updating to a newer Unity & ECM2 version and see if it fixes the problem.
     
  6. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @zzzz789

    Will have to wait a bit, as unfortunately I have to delay the update due to my full time job and the lack of free time to work on it.
    Having said that, you can rest assured it will be released just a little later than I initially expected.
     
    zzzz789 likes this.
  7. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    I'll need to perform some additional tests with the starter assets package I commented on, as I guess this could be related to some animation (how it is authored) and not just the animator being on the root object.

    I'll let you know my findings.
     
  8. prestonjsawyer

    prestonjsawyer

    Joined:
    May 8, 2018
    Posts:
    14
    Hola I just purchased your controller I am enjoying it a lot. I have a quick question though: I am trying to implement a full body awareness system and the snafu that I have ran into is that their is no option for the first person camera system to adjust it's position according to the camera's yaw, meaning that if you look down the camera will move forward slightly so not to clip into the body. Is there a work around for this within the asset or is extra programming required? Asking as an artist trying to learn unity. Thanks!
     
  9. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Thank you!

    About your question:

    Unfortunately it is not something built in, as being a general purpose controller its expected users extend it to tailor fit to match their game needs.

    For this, In your custom controller, you can extend the UpdateRotation method and add the required code in there.

    Having said that, if you could provide me an example of this I can take a look and see if I can add it to the next update.

    Regards,
    Krull
     
  10. nicknick_

    nicknick_

    Joined:
    Mar 31, 2017
    Posts:
    11
    Hi Krull,

    First of all thank you so much for this awesome & versatile controller!
    I have a question about temporarily moving the character via code, to be able to implement vaulting/climbing.
    Can you push me in the right direction? I think you have to either use PauseGroundConstraint or disable it before moving? Or should you set the Movement mode to none?
    I tried different combinations and regardless having some difficulties to smoothly blend climbing and moving together and prevent small snapping, after the climbing to the right position has occured :)
     
  11. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    Hi Krull,

    What would be the smoothest way to add additional non-controller colliders to integrate into the ECM2 structure? For example a larger capsule around the character that can access the OnCollided() to add particle effects when going fast but not directly touching with your normal character push/pull algorithm. Or another example where you would want an additional collider to interact with the physics algorithm like having the character inside or on top of a sphere for certain abilities.
     
  12. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @nicknick_

    Thank you!

    An easier way is to set the Flying movement mode, this will disable gravity and ground constraint, but the most important it allows the full velocity vector be used (both, horizontal and vertical components) as when walking movement mode, the velocity vertical component is ignored . / discarded.

    A more 'advanced' approach is to implement a custom movement mode (ie: vaulting), this will let you have full control over the character and even implement sub-states like climbing_up, moving_foward, move_down, etc. The ladder climb shows an example of how to implement a complete custom movement mode, however I think the flying movement mode should be enough.
     
  13. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @Asarge,

    You can add a sphere trigger and subscribe to the Character CharacterMovement.Collided event, please take a look at the 3.2.- Character Controller Events to see how to subscribe to CM events from external scripts. However this will only be triggered where the character's capsule collides.

    For other colliders you can use regular unity OnCollision / OnTrigger events, or perform an OverlapSphere within your character's custom controller, to query surrounding objects, just make sure the character ignore those.
     
    Asarge likes this.
  14. nicknick_

    nicknick_

    Joined:
    Mar 31, 2017
    Posts:
    11
    Setting to Flying Mode did the trick, thank you!! Applying forces during this time is rlly smooth :)
    Currently I temporarily disable collisions for the controller during vaulting until the desired height is reached, this works really well, but not in situations where there is e.g. a wall shortly after the obstacle and the player is moving fast.
    I could simply disable collisions for this particular obstacle, but maybe there is a more elegant way?
    Is there some way to just disable collision checks only for the top and bottom and not for the “sides”?
    But maybe this is overcomplicating the problem… The best way I can think of would be to change the collider size and position to an area around the eye/camera position, but that also seems like a complicated task with many possible edge cases, no?
    Anyways, thanks for your support, this alone helped so much!
     
  15. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @nicknick_

    Happy to help :)

    To filter Colliders, you can make use of the CharacterMovement colliderFilterCallbackcallback.

    Code (csharp):
    1. /// <summary>
    2. /// Let you define if the character should collide with given collider.
    3. /// Return true to filter (ignore) collider, false otherwise.
    4. /// </summary>
    5.  
    6. public ColliderFilterCallback colliderFilterCallback { get; set; }
    This let you decide if a contact should be processed or not simply returning true to filter data based on your own logic, like filter based on tag, on layer, etc.

    Please take a look at the CharacterMovement 10.- Callbacks (Easy Character Movement 2\Character Movement\Walkthrough\10.- Callbacks) for a working example of this and other CM callbacks. A very powerful and easier way to tailor it.

    Regards,
    Krull
     
  16. unity_kNAkg40A_6Vxwg

    unity_kNAkg40A_6Vxwg

    Joined:
    Jun 26, 2020
    Posts:
    4
    I didn't quite understand how to get the collision that collided with the player. How can I write protected virtual void OnCollided(ref CollisionResult collisionResult); Is it correct to use this method?
     
  17. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    You can call this method into your own character script like so,

    Code (CSharp):
    1.     protected override void OnCollided(ref CollisionResult collisionResult)
    2.     {
    3.         base.OnCollided(ref collisionResult);
    4.  
    5.         Collider colliderHit;
    6.         colliderHit = collisionResult.collider;
    7.     }
     
    Krull likes this.
  18. unity_kNAkg40A_6Vxwg

    unity_kNAkg40A_6Vxwg

    Joined:
    Jun 26, 2020
    Posts:
    4
    thank you! It was very helpful!
     
    Asarge and Krull like this.
  19. Ologon

    Ologon

    Joined:
    Nov 16, 2014
    Posts:
    16
    Hi! I was interested in this package and I was wondering: if I buy ECM2, do I also get the "Character Movement" Asset with it? Or are there any differences with the one sold separately?
     
  20. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @Ologon ,
    First of all, thank you for your interest in ECM2!

    About your question:

    Yes, the ECM2 package includes the whole Character Movement package and uses it as its character controller (analogue to unity's built-in CC) building a feature-rich high level character class. This character class implements common movement modes for characters like walk, spring, crouch, fly, swimm, etc.

    You can see the Character Movement as a 'low level' component aimed to replace the unity's built-in CC, so users use this to implement their characters movement mechanics or port their current character controllers using the built-in CC, etc. While the Character(s) classes included in ECM2, already does this for you, plus many many more features.

    Regards,
    Krull
     
    Ologon likes this.
  21. Organik05

    Organik05

    Joined:
    Feb 15, 2016
    Posts:
    10
    I was wondering why is it when I edit the collider attached to the character the revisions revert back to the previous unmodified version. Is there somewhere in the character scripts where this is changed?
     
  22. Organik05

    Organik05

    Joined:
    Feb 15, 2016
    Posts:
    10
    Never mind I answered my own question and just changed the height and radius of the player. I have a small player so I need to alter those fields either on the fly or permanently
     
  23. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @Organik05 ,

    Yes, the character movement component controls your capsule dimensions, also if crouching is enabled, the character will update the character´s height from its current values.

    Additionally, you can use the Character Movement SetDimensons method to modify it at runtime if needed.
     
  24. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    Hi Krull,

    While boarding I move super slow up slopes that I can normally walk up and there is no collision on the board to catch it. I am however in falling movement mode while boarding so I assume this is causing the slope behavior. How could I fix this?

     
  25. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Yes, the falling movement mode does not reorient the movement along the ground surface, like the walking movement does. So using the walking movement mode seems more correct for this, could you please remind me why are you using the flying movement mode?
     
    Asarge likes this.
  26. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    There were a few various reasons while testing as the board is intended to be hovering off the ground. The friction and braking I couldn't remove enough to match the feel of taking off the PauseGroundConstraint(). Also I was unable to transfer from ground > air with the GroundConstraint when boarding off small slopes where PauseGroundConstraint() allows this behavior.

    characterMovement.AddForce(transform.forward * boardSpeed, ForceMode.Force);


    This is what drives the character forward when boarding with a boardSpeed ranging from 1-20 (mostly at 20 outside of drifting). I'm unsure if this was messing up the friction/braking tests when trying it in a grounded mode but I'll leave it here in case it's relevant.
     
  27. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    Krull likes this.
  28. baumxyz

    baumxyz

    Joined:
    Mar 31, 2017
    Posts:
    107
    Hi @Krull,
    A quick question. I want to use OnReachedJumpApex(). I set notifyJumpApex to true and have overwritten OnReachedJumpApex(). See code:

    Code (CSharp):
    1. protected override void OnStart()
    2.     {
    3.         base.OnStart();
    4.  
    5.         CharacterStateMachine.Data.CharacterController = this;
    6.         notifyJumpApex = true;
    7.     }
    Code (CSharp):
    1. protected override void OnReachedJumpApex()
    2.     {
    3.         base.OnReachedJumpApex();
    4.         CharacterStateMachine.Data.ReachedJumpApex = true;
    5.         Debug.Log("OnReachedJumpApex");
    6.     }
    The method OnReachedJumpApex() never gets called.
    And notifyJumpApex is false in every frame. I looked at the base Character script and found that notifyJumpApex is set to false in several places.
    For example in OnMovementModeChanged(...) and Jumping().
    How can I make OnReachedJumpApex work properly? Getting called on every jump when reaching the apex point.

    Thank you in advance!

    Okay, reading the user manual helps... x)
    Setting notifyJumpApex to true inside OnJumped() solves the problem.
     
    Last edited: Oct 5, 2022
    Krull likes this.
  29. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @Asarge,
    The character (CharacterMovement component) will only process 'steps' when in walking movement mode, or more specifically the CharacterMovement is constrained to ground (characterMovement.constrainToGround == true), so in your case I suggest you use the walking movement mode for the hoverboard.

    When in walking movement mode, the character's velocity is affected by the Max Walk Speed (character's maximum horizontal velocity), Max Acceleration, Braking Deceleration Walking, its current friction; mostly GroundFriction but can be overridden with braking friction when useSeparateBrakingFriction is enabled.

    While using the walking movement mode, you can 'model' your desired movement, tweaking these settings to model your desired movement, in your case, a hoverboard, later when exiting the hoverboard, you reset the modified walking movement mode settings to 'model' the regular walking state. As I commented in the manual, movement modes can be confused with character states but they are not, they just define the rules to move the character (i.e: modify its velocity).

    So in your case, while on board, you would want to set Braking Deceleration Walking to zero, possibly modify the Max Acceleration, and modify the Ground Friction, this is a case to make use of the Braking Friction talked earlier, when you set useSeparateBrakingFriction to true it will replace the current movement mode friction with the Braking Friction value letting you bypass the movement mode friction without having to directly modify its property!.

    Additionally, in your custom controller, you can make use of the GetMaxSpeed, GetMaxAcceleration, GetMaxBrakingDeceleration, etc. so you can override this methods and return a different value for your character's current logical state, transparently integrating in the character without having to modify properties, for example:

    public override float GetMaxBrakingDeceleration()
    {
    // Bypass braking deceleration when on hoverboard

    if (OnHoverBoard)
    {
    return 0;
    }

    // otherwise, return regular values

    return base.GetMaxBrakingDeceleration();
    }

    Then for the ground air, you can set a low slope limit, this will be your allowed slope limit to 'walk' (and be snapped to), but the character will still be able to step high surfaces if within the current slope limit., for example, setting a slope limit of 1, let the character walk on flat ground and climb, flat steps (up to its step offset) but won't be able to walk on slopes.

    Regards,
    Krull

    PS I tried your current game, and it is getting really fun, great job!
     
    Asarge likes this.
  30. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @baumxyz

    Yes :D, the notifyJumpApex should be enabled per usage, as it gets cleared after it report.

    Regards,
    Krull
     
    baumxyz likes this.
  31. baumxyz

    baumxyz

    Joined:
    Mar 31, 2017
    Posts:
    107
    I kind of assumed that it would work like ECM1. And I should have read the user manual. Absolutely my mistake :D
     
  32. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    Is there a discord for ECM2?

    What is the best way to move (teleport) a character which is using ECM2 directly? Cheers.
     
  33. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    I have found a Teleport example, which uses Character.SetPosition, I assume this is the recommeded method?

    Seems there is also a corresponding SetPosition in CharacterMovement. Am I on the right track?
     
  34. Predulus

    Predulus

    Joined:
    Feb 5, 2018
    Posts:
    90
    Well, it seems to work, so I guess - question answered! :)
     
    Krull likes this.
  35. baumxyz

    baumxyz

    Joined:
    Mar 31, 2017
    Posts:
    107
    Hey @Krull
    I have a new, more significant problem. My character does NOT use root motion. However, now I want to implement a ledge grab mechanic. For this I would like to use a root motion animation.
    What would you recommend how I proceed here? My character is based on a state machine. I thought that when I enter the state "Ledge Grab", I switch to Root Motion and play the animation. Also, since it is a vertical animation, I need to set the MovementMode to Flying, correct?
    But now comes the problem: What do I do with the collider? I have attached a link how the collider would partially clip through the wall. I can't and don't want to edit the animation. Can I temporarily turn off the collider until the target position is reached?

    Link to clip: https://imgur.com/a/inQDMA5

    What would you do in such a case?

    Thanks in advance!
     
  36. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Is there a discord for ECM2?

    Unfortunately not yet.

    About your question:

    You can simply modify the transform position, however if interpolation is enabled (defaults) you would want to disable rigidbody interpolation, update position, and re-enable interpolation. Something like this:

    characterMovement.interpolation = RigidbodyInterpolation.None;
    characterMovement.position = teleportPosition;
    characterMovement.interpolation = RigidbodyInterpolation.Interpolate;

    Having said that, I will add a direct Teleport option to the character in the following update which takes care of those settings internally.
     
    Predulus likes this.
  37. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    That's correct!

    Now for the collider part, yes, you can temporarily disable collisions setting the characterMovement.detectCollisions property to false, and true to re-enable. This will halt all collision and ground detection.

    Alternatively you can disable collisions per collider / rigidbody, using the CharacterMovement IgnoreCollision function.
     
  38. Rin-Dev

    Rin-Dev

    Joined:
    Jun 24, 2014
    Posts:
    571
    I've been having a bit of trouble implementing a wall slide/wall jump. I've looked through the examples of setting up a custom movement mode. I'm just having issues getting the character to behave properly.

    Has anyone implemented wall jumping previously that could provide some insight?
     
  39. Broudy001

    Broudy001

    Joined:
    Feb 12, 2020
    Posts:
    70
    I have both on mine, though I'm doing a 3d sides roller so my implementation might differ, what issue are you having?

     
  40. Rin-Dev

    Rin-Dev

    Joined:
    Jun 24, 2014
    Posts:
    571
    I'm doing a side scroller. Trying to figure out the best way to incorporate it. I'm sure making a custom mode out of it is the right way to go. I was trying to figure out how to detect the wall without constant raycasts and checking distances. I didn't even have time to mess with the "physics" portion of it too much.

    I found out though there's a OnCollided function from looking at the dash example. So I'm going to do a bit of rewriting using that and seeing how that goes.
     
  41. Rin-Dev

    Rin-Dev

    Joined:
    Jun 24, 2014
    Posts:
    571
    Code (CSharp):
    1.     protected override void OnCollided(ref CollisionResult collisionResult)
    2.     {
    3.         // Call base method implementation
    4.  
    5.         base.OnCollided(ref collisionResult);
    6.  
    7.         if (!IsGrounded() && !IsWallGrabbing() && !collisionResult.isWalkable)
    8.             SetMovementMode(MovementMode.Custom, (int)NewMovementMode.WallGrab);
    9.         if (IsWallGrabbing() && collisionResult.isWalkable)
    10.             SetMovementMode(MovementMode.Falling);
    11.     }
    12.  
    13.     public void WallGrab()
    14.     {
    15.         var yInput = GetMovementInput().y;
    16.         yInput = (yInput < 0) ? Mathf.Abs(yInput * 10f) : 1f;
    17.         var velocity = -transform.up * 20f * yInput * Time.deltaTime;
    18.         characterMovement.velocity = velocity;
    19.     }
    20.  
    21.  
    22.     protected override void CustomMovementMode(Vector3 desiredVelocity)
    23.     {
    24.         if (_customMovementMode == (int)NewMovementMode.WallGrab)
    25.             WallGrab();
    26.     }
    This is essentially the code I've been using. Has a slide down result. I haven't incorporated anything like jump off yet. Trying to get Update Rotation to work with me here before moving on to jumping. Just wondering how this looks compared to some other wall slide code. It isn't perfect and buggy but I feel like its going in the right direction.
     
  42. baumxyz

    baumxyz

    Joined:
    Mar 31, 2017
    Posts:
    107
    Thank you! This worked like a charm.
    I still have the problem that when I switch from root motion to non-root-motion, I always fall for a short moment because the character is not grounded. This causes my state machine to switch to the "fall state" and play a wrong animation for a few frames.
    Do you have any idea how I can stick the character to the ground directly after disabling root motion?
     
  43. Rin-Dev

    Rin-Dev

    Joined:
    Jun 24, 2014
    Posts:
    571
    I've switched to using OnTriggerEnter and Exit because it works better for me. I even have the jump in place.

    My issue now is I can't seem to stop rotation from happening. I've set it to a custom rotation mode and it still rotates based on input. Very confused why. Gonna keep fiddling around.

    *edit*
    I found the culprit. I was handling some rotation inside my HandleInput function. Moving that around and it works fine now :)
     
    Krull likes this.
  44. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Mmm, I think you can add some timer to trigger the falling state and not just the ground detection result, similar to how the Starter Assets - Third Person Character Controller handles the falling logical state.

    Another possibility is to use the OnMovementMode changed to handle the root motion on and off, actually this is how the included example (root motion toggle) handles it, enabling it when on grounded, and disabled when not. However I think the timer extra condition should work fine.
     
  45. AGregori

    AGregori

    Joined:
    Dec 11, 2014
    Posts:
    526
    Hello, ECM2 is pretty cool. It feels like a spiritual successor to FPC Pro, an awesome controller sadly abandoned 3+ years ago. My question: is there any hardcoded way that I missed that could switch between 3rd and 1st person characters? Or do we make our own container script that allows dynamic switching?
     
  46. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    757
    Hi @AGregori,

    Thank you for your kind comments, happy to hear you like ECM2!

    About your question:
    No by default, as the FirstPersonCharacter and ThirdPersonCharacter are developed to serve as a starting point for 'typical' first / third person games. However, as with almost anything with ECM2 it can be easily modified / replaced.
    here
     
  47. AGregori

    AGregori

    Joined:
    Dec 11, 2014
    Posts:
    526
    OK I can do the Cinemachine + scripting route. Although ECM2's competition (even if technically poorer) generally does include this in the box.
     
  48. Eternity774

    Eternity774

    Joined:
    Jan 30, 2018
    Posts:
    5
    Hello, is there a way to push dynamic rigidbodies without changing character speed? I need this for some small props and big objects.
    Thanks
     
  49. Rin-Dev

    Rin-Dev

    Joined:
    Jun 24, 2014
    Posts:
    571
    I seem to be having a weird physics interaction. I have 2 characters in scene. When one character pushes into another character, the first one will collide and slowly merge. I want a constant wall effect. I don't want my characters to ever merge. I don't know the reason for this effect. I have push bodies on and physics enabled on both bodies.
     
  50. wechat_os_Qy06U4-4WRqwOqeFdJSRbcG-I

    wechat_os_Qy06U4-4WRqwOqeFdJSRbcG-I

    Joined:
    Jan 11, 2021
    Posts:
    4