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. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Thats great!

    Unfortunately ECM2 character is limited to a single capsule (vertically aligned), so one option for the spider is to set a big capsule for the center area, but it will prevent characters walking below it since the capsule can't float above ground.

    Another approach could be to use a capsule in the center but configured so other characters can't collide with it, so it serves to move the spider but will let other characters move below the spider but collide with the TCC colliders (spider bones).

    I think the best usage for TCC could be for rag-dolls since it requires a bone colliders structure but could work with second approach suggest above
     
    Last edited: Aug 17, 2023
  2. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    I was thinking of this as well but would also need to allow default objects to pass under unless I could pass through a custom stepUp height maybe?
     
  3. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    I am not following you sorry, could you clarify a bit, what do you refer to as default objects?

    With the proposed idea, the other characters will collide against the additional colliders created for each bone (using the TCC package) including the spider core, so they will serve as blocking colliders for each ECM2 character, while the spider capsule (ie: spider capsule) will collide against world obstacles to handle the spider movement but will be 'invisible' to other ECM2 characters.
     
  4. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    Like objects in the world, stones, boulders, the environmental objects the spider would be able to move over on the ground collision layer.
     
  5. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Ah, yes, mmm well you can use the CharacterMovement ColliderFilterCallback function to selectively filter small colliders that can pass below spider, probably using a tag or some other custom logic.
     
    Asarge likes this.
  6. JulienCornillon

    JulienCornillon

    Joined:
    Nov 17, 2022
    Posts:
    4
    Hello,

    I've been using your asset for a long time and it's great. However, I have a small issue I'm not able to fix.
    I'm using the CharacterMovement script, and I've made a custom controller that calls the move method.
    The issue is that my player is often "stuck" inside my AI collider. I've sent a screenshot where I display the colliders.
    Here, when I try to move forward, nothing happens. My player seems to be completely stuck.
    Here, my AI doesn't move since it's already in range. At first, I was using a capsule collider. I tried to change it to a small box collider, but I still have the same issue.
    It seems when I move toward the AI, before being stuck, my collider "enters" the AI collider, and I end up stuck inside.
    Is there a setting somewhere to prevent the collider from blocking the player like that?
    In the second screenshot, there are the settings I use for the CharacterMovement script.

    Thanks in advance for your answer.
     

    Attached Files:

  7. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @JulienCornillon ,

    You could use the AgentCharacter in your enemies so it correctly collides with your player character as the AgentCharacter works different than just using a regular NavMeshAgent, the AgentCharacter use the NavMeshAgent desiredVelocity property to navigate the world and move the NaveMeshAgent with us so it keep synced and correctly collide each other.

    To issue an AgentCharacter movement use its MoveToLocation method.

    You can use unity collision layers to disable character / enemy collisions, or use the CharacterMovement ColliderFilterCallback, in this callback function you can decide if the CharacterMovement should filter the other collider (returning true) based on your game logic, for example using tags, interfaces, etc.

    Example ColliderFilter callback function:

    Code (csharp):
    1. private bool ColliderFilterCallback(Collider collider)
    2. {
    3.     // If collided collider is a character (e.g. using CharacterMovement component)
    4.     // ignore collisions with it (e.g. filter it)
    5.  
    6.     if (collider.TryGetComponent(out CharacterMovement _))
    7.         return true;
    8.  
    9.     // Return false to allow collisions (e.g. not filter it)
    10.  
    11.     return false;
    12. }
    13.  
    14. .
    15. .
    16. .
    17.  
    18. void OnEnable()
    19. {
    20.     // Register to CharacterMovement callbacks
    21.  
    22.     characterMovement.colliderFilterCallback += ColliderFilterCallback;
    23. }
    24.  
    25. void OnDisable()
    26. {
    27.     // Unregister from CharacterMovement callbacks
    28.  
    29.     characterMovement.colliderFilterCallback -= ColliderFilterCallback;
    30. }

    Additionally you can find a working callbacks example in the included Character Movement v1.0.7 package, in particular Character Movement\Walkthrough\10.- Callbacks folder.

    Let me know if you need any further assistance
     
  8. JulienCornillon

    JulienCornillon

    Joined:
    Nov 17, 2022
    Posts:
    4
    Hello, Thanks for your answer.

    I have tested your solution using AgentCharacter, at first it was possible to push the AI even if I have all the push interaction checkbox uncheck.I fixed it by making the AI collision layer to don't collide with the player (the player still collide with my enemy collider) and it works.

    In the end, I realized it added a rigidbody component to the AI when I've added the AgentCharacter script and I don't really want that. I could have a lot of AI in my game and don't want the need of a rigidbody on all of them.

    What I would like is for the AI collider to work a bit like a wall, but it can move on the navmesh. I never got any issue with walls, but why even for AI that is not moving I run into the issue where I got "stuck" inside the collider? For testing, I have disabled the movement of the AI.

    About the CollisionFiltercallback, this is what I use for other stuff and it's great, but it's not relevant here. I don't want to be able to pass through the AI.

    Edit: While writing this I realized what was causing the issue. It's because the navMeshAgent always "teleport" the agent to be on the navmesh. When I was colliding with it I was probably pushing it a little bit or something and the navMeshAgent was "teleporting" the agent back at his place on the nav mesh and it ended inside my collider and then blocked me. I solved it by disabling the navMeshAgent when it was at range to hit me and it work fine.
    Thanks for the help.
     
    Last edited: Aug 24, 2023
    Krull likes this.
  9. Spazius

    Spazius

    Joined:
    May 22, 2018
    Posts:
    16
    Trying to create a high-accuracy first person shooter I noticed that the FPSCharacter's horizontal aiming is limited to the Rigidbody's interpolated rotation. This causes aiming to behave very weirdly on low timescales and as far as I can tell for the horizontal mouse movement to always lag behind of where it should be even without the slo-mo.

    Do you have advice how to get the "true" look direction that's decoupled from physics or to otherwise make horizontal aiming more responsive?
     
  10. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @JulienCornillon,

    Mmm, I think there's some issue in your setup, as by default a Character will consider another Character as an static obstacle unless (same code path as 'world') physics interaction is enabled and only if allowed will push other characters.

    In order to better help you, I created a basic example scene, this shows an NPC Agent chasing the player, actually the NPCAgent code is pretty straightforward, all is trying to do here is reach the player's position:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using EasyCharacterMovement;
    4.  
    5. namespace EasyCharacterMovement.Support.NPCAgentExample
    6. {
    7.     public class ChaseAI : AgentCharacter
    8.     {
    9.         [Header("ChaseAI")]
    10.         public Character playerCharacter;
    11.  
    12.         protected override void Update()
    13.         {
    14.             if (playerCharacter)
    15.             {
    16.                 MoveToLocation(playerCharacter.GetPosition());
    17.             }
    18.         }
    19.     }
    20. }
    As you can test in the attached package, both the Player Character and the NPC Agent respect each other without any penetration or push, even if the NPC is trying to reach the player position all the time (ie: trying to cause interpenetration).

    Is not the agent, but the CharacterMovement as it requires a Kinematic Rigidbody in order to correctly move the Capsule collider. Worth note this is a Kinematic Rigidbody, a much lightweight rb version, so it definitely should not be an issue, as you can see in above posts, the system is capable of handling a very large number of Characters without much impact.

    Additionally, you could add a NavMeshObstacle to your player character, but honestly speaking, this is not needed at all.
     

    Attached Files:

  11. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    The default ECM2 character operation is coupled with unity physics, where the character is simulated after the Unity internal physics update implementing a LateFixedUpdate (coroutine). This behavior requires interpolation since it's running at the physics engine fixed timestep.

    However as most with ECM2 it's not limited to it and can be easily modified, expanded or completely replaced.

    An easier way to accomplish this is do not rotate the character at all, and instead rotate a regular gameobject, for example, the Root (from the FirstPersonCharacter rig), this way it wont rely on character's interpolated rotation at all, so now, the rig will handle rotation as follows

    Character (no-rotation)
    -> Root (Yaw)
    -> Eye (Pitch)
    -> Camera

    I attached a custom script showing this approach, so you can try it.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using EasyCharacterMovement;
    4.  
    5. namespace EasyCharacterMovement.Support.SmootherFPSExample
    6. {
    7.     public class FPCharacter : FirstPersonCharacter
    8.     {
    9.         public override Vector3 GetForwardVector()
    10.         {
    11.             return rootPivot.forward;
    12.         }
    13.  
    14.         public void AddEyeYawInput(float value)
    15.         {
    16.             if (value != 0.0f)
    17.             {
    18.                 rootPivot.localRotation *= Quaternion.AngleAxis(value, Vector3.up);
    19.             }
    20.         }
    21.  
    22.         protected override void HandleInput()
    23.         {
    24.             // Movement input
    25.  
    26.             Vector2 movementInput = GetMovementInput();
    27.  
    28.             Vector3 movementDirection = Vector3.zero;
    29.  
    30.             movementDirection += Vector3.right * movementInput.x;
    31.             movementDirection += Vector3.forward * movementInput.y;
    32.              
    33.             movementDirection = movementDirection.relativeTo(cameraTransform);
    34.  
    35.             SetMovementDirection(movementDirection);
    36.  
    37.             // Look input
    38.  
    39.             Vector2 mouseLookInput = GetMouseLookInput();
    40.  
    41.             if (mouseLookInput.sqrMagnitude > 0.0f)
    42.             {
    43.                 // Perform 'Look' rotation with Mouse
    44.  
    45.                 if (mouseLookInput.x != 0.0f)
    46.                     AddEyeYawInput(mouseLookInput.x * characterLook.mouseHorizontalSensitivity);
    47.  
    48.                 if (mouseLookInput.y != 0.0f)
    49.                     AddEyePitchInput(mouseLookInput.y * characterLook.mouseVerticalSensitivity);
    50.             }
    51.         }
    52.     }
    53. }
     
    Spazius likes this.
  12. MichelVictor

    MichelVictor

    Joined:
    Apr 15, 2018
    Posts:
    8
    Hey there, there is anyway easy to change the capsule Center during runtime?
     
  13. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Not by itself, as it is relative to the Capsule's height, so the only way to modify it is adjusting the capsule size or its height for example, while crouching.

    You can use the CharacterMovement SetDimensions, SetHeight methods to adjust the capsule size.
     
  14. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    Hi @Krull
    I'm testing the networking example for Fishnet server authoritative. However I got this error after extracted the Unity package. Could you help?
    upload_2023-8-31_16-15-54.png

    Thanks.
     
  15. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi
    @Minzie,

    Yes, that's an issue in the FishNet example when using the new input system, since the networking example uses old input and the handleInput property is only available in the Character old input version. This will be fixed in the following update.

    In the meantime, you can comment out the line and make sure your Character inputActions remains empty (null), since the example uses the old input for simplicity.

    Code (csharp):
    1. private void CacheComponents()
    2. {
    3.     // Cache and initialize controlled Character
    4.  
    5.     _character = GetComponent<PlayerCharacter>();
    6.  
    7.     if (_character)
    8.     {
    9.         // Disable character local input management (within character class)
    10.  
    11.         //_character.handleInput = false;
    12.  
    13.         // Disable character auto simulation (i.e: its LateFixedUpdate).
    14.         // It will be managed here.
    15.  
    16.         _character.enableLateFixedUpdate = false;
    17.     }
    18. }
     
    Minzie likes this.
  16. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    Thanks @Krull. It will be great if there is a separate example for new input system as well to help newbies/ noncoders, if possible. hehe :D
     
    Last edited: Sep 2, 2023
  17. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Yes, I plan to update the examples in the following update so the new input version uses the Input System too.
     
    Minzie likes this.
  18. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    Hi @Krull
    Since you are in this, is it possible to request for the Fishnet networking example to have the camera e.g. cinemachine to follow player instead of static camera? I tried to change the code but it doesn't work well..:(
     
  19. FergJoe

    FergJoe

    Joined:
    Dec 28, 2016
    Posts:
    19
    Hello @Krull
    I've really enjoyed working with ECM2 so far! It's a must have in all my projects!

    I think I may have found a bug?

    Used the asset menu to create my character, tuned the ECM2 settings in the inspector to get the controls the way I wanted, then saved my completed character as a prefab. I instantiate a prefab for the player - all of my custom settings appear and work EXCEPT the gravity multiplier. To get the jump response I want, I'm using a jump impulse of 8 and grav multiplier of 2 (gravity Vector3 is the default 0, -9.8, 0).

    What I'm seeing: my tuned values all appear in the inspector as entered (grav mult of 2, jump impulse 8). However, the character behaves as if gravity were only multiplied by 1. I can get the correct behavior if I change the grav mult in the inspector to a new value, then return it back to 2. It seems like ECM2 isn't calculating final gravity including the multiplier until I change its value in the inspector?

    I will try editing gravity Vector3 manually and not using the multiplier tomorrow. :)

    UPDATE - Setting the gravity Vector doesn't stick, either. I've also tried setting the values in code when I init my character and even each time I jump...the only thing that gets gravity to reflect the numbers shown in the inspector is making a change in the inspector to the GravityVector or GravityMultiplier fields. I have to do this for each spawned player.
     
    Last edited: Sep 7, 2023
  20. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Sure, Ill update it
     
    Minzie likes this.
  21. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @FergJoe

    Thanks for reporting this issue, I'll check it this weekend and issue a fix.

    Thanks,
    Krull
     
  22. krou

    krou

    Joined:
    May 29, 2014
    Posts:
    22
    hello! Can somebody help and explain why
    Gizmos.DrawRay(transform.position, transform.InverseTransformDirection(Vector3.forward) * 10f);
    and
    Gizmos.DrawRay(transform.position, transform.forward * 10f);
    draw not the same direction? My expactation was that it should be the same
     
  23. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @krou,

    Yes, the transform.forward vector is a direction vector in world space, ie: the Character's forward direction vector.

    This are equivalent:

    Code (csharp):
    1. transform.TransformDirection(Vector3.forward);
    or

    Code (csharp):
    1. transform.position + transform.rotation * Vector3.forward;
    Since we want to transform the local forward direction vector to world space relative to the character's rotation.

    The posted code actually is transforming the given Vector3.forward to Character's local space (InverseTransformDirection) thats what there are different one in local space and other in world space.
     
    krou likes this.
  24. Quest_for_stuff

    Quest_for_stuff

    Joined:
    Nov 11, 2014
    Posts:
    11
    Hello! I really like the asset @Krull !

    I was wondering, Is it normal that OnCollisionEnter doesn't work when the character is standing on top of a collider? For example, you can go on the Example scene Physics Platform Example Scene and add a simple OnCollisionEnter script on one of the non-kinematic rigidbody Rotating Platform. If you collide with it, it will correctly register. But if you jump on top of it, OnCollisionEnter will not be detected. You need to collided with with the sides.

    If I put a OnCollisionEnter script on one of cube, OnCollisionEnter will never registered. But the event characterMovement.Collided is corectly getting triggered.

    TLDR I'm having trouble making a non-kinematic body work with collision. For example, how could you make a rotating object like in the game Fall Guys, that will amplify the impulse of impact to create a bouncy effect. Bouncy effect is pretty easy with OnTrigger with the character. But to amplify the impact I probably need to use the ContactPoints of OnCollisionEnter that I now don't have access.

    Is this intended behavior or am I missing something?

    Thank you!
     
    Last edited: Sep 10, 2023
  25. krou

    krou

    Joined:
    May 29, 2014
    Posts:
    22
    Thank you for help and example. But i still don't understand why if i rotate object 90 degrees around it's Y-axis and draw a ray with direction of transform.InverseTransformDirection(Vector3.forward), the local forward axis point in the direction of Vector3.left in world space instead of Vector3.right
     
    Last edited: Sep 10, 2023
  26. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi
    @Quest_for_stuff,

    Yes, the CharacterMovement component being a kinematic character controller keeps a tolerance distance from other objects in order to correctly resolve the movement, and a larger distance from the ground, this tolerance distance causes the behaviour you noticed as the physics engine (based on its default contact offset value) not register the collision.

    For example, you can change the Physics->Default Contact Offset from 0.01 (default value) to 0.001 and notice the OnCollisionEnter will be called.

    For this, just like unity's built-in CC, ECM2 includes its own collision related events, like OnCollided, OnFoundGround, OnLanded, etc. to handle your character collision events.
     
    Quest_for_stuff likes this.
  27. Kurjenpolvi

    Kurjenpolvi

    Joined:
    Nov 15, 2016
    Posts:
    14
    Heyoo! We've been using ECM1 for a long time and released a game using it so we have a bunch of custom code. ECM1 is an absolutely amazing asset. We are now starting another project, and I'm wondering, how much work is it to migrate to ECM2. I know it's impossible to give an accurate answer, and I have seen the notes that there's no direct porting from ECM1 to 2. But I would like to know how similar is the logic flow between the assets? Are the changes more that functions have been renamed, optimized and restructured, or are we talking about MAJOR changes to the flow which would require a lot of restructuring?
     
  28. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @Vera987,

    Thank you for your kind comments about ECM1 and for your interest in ECM2.

    It really depends if you have modified ECM1 or not, and adapt to the new changes, for example, ECM2 basically separates the ECM1 BaseCharacterController in two independent clauses, completely isolating the CharacterMovement which in ECM2 is analogous to built-in CC (I mean it can be used by itself) and the character related code like movement, flying, sprinting, etc is now handled in the Character class.

    In ECM2 the CharacterMovement is a very robust component capable of handling collision detection and response, physics interactions, moving platforms, first class ground detection, callbacks to customize collisions and response, etc. It is a AAA character controller.

    The Character class uses the CharacterMovement but adds a higher level layer implementing custom movement modes and mechanics for game characters, like walking, sprinting, jumping, falling, flying, swimming, crouching, etc.!

    In ECM2 you typically would extend a Character class and add your custom logic on top of its default functionality or if desired you can completely ignore the Character based clases, and just make use of the CharacterMovement so you are responsible of creating your character movement mechanics (or if have created it before) and use the CharacterMovement Move to move the character or the included SimplyMove which is very similar to the ECM1 move method.

    Worth noting the CharacterMovement package includes examples of a controller very similar to the BaseController found in ECM and definitely worth checking it out.

    Last but not least, another major difference is ECM2 is a completely kinematic character controller unlike ECM1 which is rigidbody based.

    I suggest you try it and get familiar with it, and if you decide to stay with ECM1, let me know to issue a refund.
     
  29. k3ndro

    k3ndro

    Joined:
    Dec 8, 2016
    Posts:
    28
    Hi, what's the setup if my game is in 2D?
     
  30. HustlaMasi

    HustlaMasi

    Joined:
    Aug 17, 2017
    Posts:
    4
    Hey hey,
    I have a rotating bar with a rigid body. It's rotating with the motor property of the HingeJoint.
    I want the player to be pushed by the bar. And/Or pushing the bar against the player is "harder" and slows the motor.
    But the player is always rock solid.
    I tried changing all the mass settings but nothing is working.
    Thx
     
  31. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @k3ndro,

    While it is 3D based (Rigidbody, Capsule, Sphere, Box, etc) it can be used for '2D' games, for example, for a top-down game, you basically need to set the camera view. Now for sidescrollers you would want to constrain its movement along the Z axis and modify the input to handle left / right movement. For this I suggest you take a look at the included Side Scroller template scene, as it includes a preconfigured Character and a custom Character class to serve you as a starting point.
     
    k3ndro likes this.
  32. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @HustlaMasi,

    For this please make sure to Enable Physics Interaction on your Character and set the Braking Deceleration Walking to 0 as this is a constant deceleration (when no input) which could interfere with this.

    Additionally I suggest you take a look at the included demo scene, in particular the green hinges for a working example.
     
  33. k3ndro

    k3ndro

    Joined:
    Dec 8, 2016
    Posts:
    28
    Thanks for getting back. Would a top-down '2D' possible in the XY plane? or XZ is preferred?
     
  34. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Sure it's possible, but would require a little more work since you need to modify the camera and input to be XY plane aligned, while XZ plane is practically seamless, all you need to do is set up a top-view camera perspective. I would recommend the XZ plane.
     
    k3ndro likes this.
  35. k3ndro

    k3ndro

    Joined:
    Dec 8, 2016
    Posts:
    28
    Another question, what method/approach should I call on if I want to use a magnitude and direction for movement?

    I only see AddForce and LaunchCharacter.

    And the only way I can move the character is to:
    1: SetMovementDirection()
    2: Simulate()

    I wonder if I could implement a Move(direction, magnitude) function to replace its movement.?
     
    Last edited: Sep 28, 2023
  36. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi,

    To move a Character all you need to do is set its movement direction vector using the SetMovementDirection method, internally it will calculate the velocity using its current properties, like MaxWalkSpeed, Acceleration, Deceleration, GroundFriction, etc. Please take a look at the Side Scroller Template for a minimal custom Character configured for a typical 2D SideScroller.

    A Character by default implements an auto-simulate, so you don't really need to call its Simulate or Move method unless you explicitly disable its 'auto-simulation' setting its enableLateFixedUpdate property to false. When disabled, you need to call the character's Simulate method to update the character.
     
    k3ndro likes this.
  37. chumomo

    chumomo

    Joined:
    Jun 30, 2017
    Posts:
    17
    Hello, in the TopDown template folder, the sample shows how to implement navmeshagent with keyboard input.
    How to restrain the character just moving IN the nav mesh Surface when I use keyboard input?
    In the sample the character will fall if moves through keyboard.
    Thks!
     
  38. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @chumomo,

    In ECM2 an AgentCharacter behaves differently than a regular agent. An AgentCharacter is the one that moves the NavMeshAgent and basically uses it as its 'brain' asking for a path to a location, and then using the NavMeshAgent desiredVelocity to feed the CharacterMovement Move method. Due this it does not support constrain the movement to a NavMesh.

    One possible approach to limit the movement, is sample the next character position (ie: nextPosition = transform.position + velocity * deltaTime) and determine if this is within a NavMesh, so you can stop the movement if it lies outside it.
     
  39. FergJoe

    FergJoe

    Joined:
    Dec 28, 2016
    Posts:
    19
    Any word on if you were able to replicate and fix this issue? I've still been unable to find a workaround. I've got plenty of other mechanics to work on in the meantime, but wanted to check in to see if you needed additional info.

    Thank you!!
     
  40. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @FergJoe,

    I performed several tests and honestly could not reproduce the issue, as you can see in source code, both fields are correctly serialized and only validate (OnValidate), so this led me to think the troubled prefab could be corrupted somehow.

    I suggest you recreate the prefab (if possible) and even test in an empty new project in order to isolate the possible cause.

    Worth noting, in order for gravity to be affected by the scale, the Character gravity property must be used, as this is where the _gravity * _scale multiplication occurs.
     
  41. rystills

    rystills

    Joined:
    Jan 4, 2013
    Posts:
    4
    Hi Krull,
    I just purchased ECM2. Overall, my first impressions of the asset are very positive. However, I noticed that the character will snap to the ground while still rising from a jump if they pass over a ledge from a sufficiently shallow angle. I've uploaded a video of the behavior here:
    https://drive.google.com/file/d/1fXBCDNHK7KPp69fTnxoXti_wXEl6RSF0/view?usp=sharing
    Are you aware of any way to prevent this behavior?
    Thank you!
     
  42. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @Risingstar64,

    First of all thank you for purchasing ECM2!

    About your question:

    Yes, that's normal behaviour as it's considered it landed on the upper ledge, no matter if moving up or down during a jump.

    Having said that, you can modify the jump implementation to add a greater time window for the pause constraint, since by default it's 0.1 seconds. Or instead of pause it for a fixed amount of time, disable when jumping up and enable it when falling down.
     
  43. rystills

    rystills

    Joined:
    Jan 4, 2013
    Posts:
    4
    Thanks for the quick reply! Your explanation made sense, and you pointed me in the right direction to adjust the behavior. In PauseGroundConstraint I set unconstrainedTime to a very high value, and in PostPhysicsUpdate I set it back to 0 if characterMovement.velocity.y <= 0.1f, and just those tweaks fixed the behavior. Thanks again for the help!

    Edit: Regrettably, this approach causes the player to lose their forward momentum when landing on an upwards slope, so I'll probably end up checking the ground normal before snapping rather than hijacking unconstrainedTime.
     
    Last edited: Oct 21, 2023
  44. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @rystills,

    For your particular case, you can simply modify the Character DoJump method and set an appropriate time to the PauseGroundConstraint method.

    You can compute an appropriate time using the jump physics formulas as shown here this way you can configure the timer to just the initial jump time.
     
  45. icanhazscreenid

    icanhazscreenid

    Joined:
    Jun 2, 2016
    Posts:
    14
    Hey @Krull,

    First off, this is the greatest asset ever and I love it. Thank you! Question: is there a way to prevent characters from walking off ledges? I saw some mention canWalkOffLedge as future functionality but I didn't see it in the package as of yet. Can you confirm? Thank you!
     
  46. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @icanhazscreenid,

    Thank you, happy to hear it!

    About your question:

    Yes, as commented before that's a planned feature, unfortunately has not been added to the package yet. The good news is I am currently working on an update and while I can not promise it, I definitely will try to add it in the following update.
     
    icanhazscreenid likes this.
  47. doiglebear

    doiglebear

    Joined:
    Dec 13, 2020
    Posts:
    3
    Hey @Krull - I've been using your character controller for a little bit but noticed in my use case that the characters don't move when the app window is not the focus, even when Application.runInBackground is set to true. Do you have a solution or workaround for this, or am I missing something obvious?

    Thanks!
     
  48. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @doiglebear,

    I think this is normal behaviour as the input (not ecm2 in particular) is only processed when the window is focused. Honestly not quite sure if this behaviour could be modified.
     
  49. doiglebear

    doiglebear

    Joined:
    Dec 13, 2020
    Posts:
    3
    That's strange as I'd written my own character controller previously using the new input system package and it works fine when the window isn't in focus. My use case is a unity based stream overlay for twitch so it's somewhat fundamental that I can use other applications simultaneously.

    This might narrow down where to look though, thanks!
     
  50. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    758
    Hi @doiglebear

    In order to better help you, could you provide me additional information:

    - Are you using ECM2 Character with a new input system and is your Character class handling input? I mean, have you assigned input actions to your Character?

    - Are you using the unity Player Input component? If not, I suggest doing a quick test using it in order to isolate the cause from the Character input actions management. For this case, please take a look at the example 1.3- PlayerInput Character Controller.

    I believe this, as I guess, could be related to Character enabling / disabling input actions. Another possibility is a disabled character sharing same input action asset as you can see here