Search Unity

[RELEASED] Easy Character Movement 2

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

  1. dyadicgames-ericzou

    dyadicgames-ericzou

    Joined:
    Aug 30, 2022
    Posts:
    1
    Hello Krull,

    My character can't detect the collision between the ground and character by unity build-in collision enter and exit function, looks like there is a little offset from the ground make the character can't touch the ground.

    But there is only a OnCollided in Character class. But there is no something Like OnCollisionExit that I can use in collision detection mechanics.

    How do I detect the bottom collision enter or exit?
     
    Last edited: Feb 24, 2023
  2. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    Hey @Krull
    The swimming example doesn't seem to work, both in ECM2_Demo & example 5.8. Is this also the case at your side?
     
  3. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @jiajialin1975

    Thank you for the clarification.
    I have been performing several tests and honestly speaking I have not been able to reproduce the issue.

    Having said that, one possible culprit I can think of, could be the MathLib.Clamp0360 function (AddCameraYawInput method) causing the side to side camera issue.

    I attached a modified version for you to look at, this uses a different (more robust) method to keep the yaw value in the [-180, 180] range.

    Let me know if I can be of any further assistance.
     

    Attached Files:

    jiajialin1975 likes this.
  4. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @dyadicgames-ericzou

    Yes, that's correct, it maintains an offset around the character and the ground in order to smoothly resolve collisions.

    The OnCollided method / event works like Unity's built-in CC OnControllerColliderHit, which is called when the controller hits a collider while performing a Move.

    The CharacterMovement component offers a vast amount of ground related data, like wasGrounded, isGrounded, groundDistance, groundPoint, etc. or even more through the CharacterMovement.currentGround property.

    Additionally, you can use the CharacterMovements ComputeGroundDistance and FindGround methods, to sample any given position.

    The OnCollidedEnter / Exit, will only be called if the 'other' contains a non-kinematic rigidbody.
     
  5. Krull

    Krull

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

    I just tested it on both the old input and new input and both ECM2 versions works fine, however worth noting the demo and the 5.8 example works a little differently.

    By default, when a character enters a 'water volume' it will float and change its movement mode to swimming, but will not cause the character to jump out of water.

    This is where the example enters, it shows how to use the water related functions, ie, isSwimming, ImmersionDepth, etc. to implement a jump out of water mechanics.

    For swimming, a character uses the OnTriggerEnter / OnTriggerExit methods, so please makesure if your character override those methods, to call the base method implementation (ie. base.OnTriggerEnter...) otherwise it won't work.

    Additionally, please make sure your character can collide with the triggers and has its canEverSwim property enabled.
     
    Minzie likes this.
  6. jiajialin1975

    jiajialin1975

    Joined:
    Jan 20, 2021
    Posts:
    5
    Hi @Krull ,

    Thank you for testing.

    I replace the file with same name, but still camera change position between two position.

    I test vanilla (un-modified) Cinemachine example in an brand new project. It works perfectly fine.

    Could it be some settings in my old existing project cause this problem?

    But the porblem still happened after I re-install "Cinemachine" and "Input system" in my old existing project.
     
  7. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771

    Hi @jiajialin1975,

    Yes, there could be some settings causing the strange issue. You could try resetting your project settings:

    PLEASE BACKUP BEFORE TRYING THIS!

    Close the unity editor, and from your project's folder delete the ProjectSettings folder, additionally you can also delete the Library folder so your assets will be re-imported. This should reset your current project.

    Let me know if I can be of further assistance.
     
  8. wjf644045860

    wjf644045860

    Joined:
    Oct 14, 2019
    Posts:
    1
    in ladder Climbing Eample I grab but Icant input W when I release ladder then I can Move . i find it output (0,0); but release ladder i can move
     

    Attached Files:

  9. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @wjf644045860,

    Mmm, I think this could be some kind of binding issue on your side, please make sure the input actions are correctly assigned, or reset input settings if using the old input system.
     
  10. One_Learning_Man

    One_Learning_Man

    Joined:
    Sep 30, 2021
    Posts:
    81
    @Krull Does ECM2 support swinging/hanging on ropes?
     
  11. Asarge

    Asarge

    Joined:
    Jun 2, 2018
    Posts:
    26
    Hi Krull, if my grapple logic is called OnUpdate() the grapple runs quite smoothly but will not sync up with the hand bone. OnFixedUpdate() has the hand bone sync but the grapple becomes jittery in some situations. Is there a way I can get these synchronized?
     
  12. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771

    Hi @One_Learning_Man ,

    Not by default, but I think you can use the general approach using a joint, where your end point is a regular non-kinematic rigidbody (jointed) and your character will be 'attached' to this endpoint rigidbody using the CharacterMovement SetPlatform method, so the character is moved along with this rigidbody.

    Hope this makes sense
     
  13. Krull

    Krull

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

    Mmm, honestly not quite sure if I correctly understand your current issue, however if desired or needed, you can modify the default execution order (late fixed update by default), and perform the character movement in a regular Update method.

    For this, first disable its late fixed update coroutine, setting the Character enableLateFixedUpdate property to false and call the Character Simulate method in a regular Monobehaviour Update method.

    This basically modifies the execution order, so instead of being updated in a late fixed update (a WaitForFixedUpdate coroutine) you decide where to update your character (Simulate it) in your case an update method.
     
    Asarge likes this.
  14. my_little_kafka

    my_little_kafka

    Joined:
    Feb 6, 2014
    Posts:
    87
    Hi, @Krull !

    I started to implement behaviours for AI that are more complex than just finding and going towards their target. I'm using animations with root motion, and I implemented an animation controller from the examples provided for ECM2.

    Code (CSharp):
    1. float forwardAmount = _character.useRootMotion && _character.GetRootMotionController()
    2.                 ? move.z
    3.                 : Mathf.InverseLerp(0.0f, _character.GetMaxSpeed(), _character.GetSpeed());
    4.  
    5.             animator.SetFloat(a_forward, forwardAmount, a_walkingTransitionDumpTime, deltaTime);
    6.             animator.SetFloat(a_turn, Mathf.Atan2(move.x, move.z), a_rotatingTransitionDumpTime, deltaTime);
    This code works fine when I just tell an enemy character to move towards their target — the enemy stops and plays «turn in place» animation and rotates where needed (I don't use root rotation, as it is not as precise because of animation blending).
    I'm also using a blend state with idle, running and turning animations, driven by the «move forward» and «turn» parameters which I set in the code mentioned above.

    The problem is, I can't seem to turn the enemy when they're not moving anywhere. For example, in the pursuing state, when the enemy is close enough to their target, I want the enemy to just turn towards the target.

    I'm using
    Code (CSharp):
    1. actorCharacterController.RotateTowards
    2. (actorCharacterController.playerCharacterGO.transform.position - actorCharacterController.GetPosition());
    to rotate enemy, and the enemy does rotate towards their target (player character's game object), but the thing is, the turn parameter of the animation is not affected by this rotation, the enemy just stands still (it's not moving forward, so it plays an idle animation) and rotates.

    Using ECM's SetRotation command does affect the turn parameter, but I can't seem to find a correct quaternion to pass to this function so the enemy character turns steadily towards their target.

    Are there any specific ECM2 commands to sync character physics with animators?
     
  15. MichelVictor

    MichelVictor

    Joined:
    Apr 15, 2018
    Posts:
    8
    Hello again. Any news about new abilities like wall jump and ledge grabbing?
    I'm not a programmer but in my spare time I like to read the code and try to learn using the examples, I modified a lot of the examples to test if I'm learning something, and it seems that I think is working, but I feel like I need more knowledge to be able to fully comprehend some ideas. So it will be very useful if it has more examples on other types of movements.
     
  16. jiajialin1975

    jiajialin1975

    Joined:
    Jan 20, 2021
    Posts:
    5
    Hi @Krull ,
    I am trying to create a custom input action. I copy 'MyCharacter.cs' and create 'MyOwnCharacter.cs'. In this script I create an new input action "High Jump" copy from the "Jump" in 'Character.cs'. The only different between "High Jump" and "Jump" is 'Jump Impulse'. I make "High Jump" jump double higher than "Jump", but they still use the same jump animation.

    How to use two different animations for "High Jump" and "Jump"?

    I add "High Jump" animation in the 'Airborne Blend Tree' and setup "High Jump" animation play in value of Jump equal to 10 , but it always transform back to "Jump" animation because of "Jump" animation play in value of Jump equal to 5. It seems impossible to identify the different between "High Jump" and "Jump" in one value of blend tree.
     
  17. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @my_little_kafka,

    When using root motion (in general not only ECM2) basically you are controlling your animation with your given input, in case of a player controlled character its input vector, and in case of an AI a movement direction, in the end it is typically mapped to 0-1 range in the Animator.

    By default a Character (an an AgentCharacter too!) will rotate towards its given movement direction unless you modify its rotation mode or modify it by code (ie: custom rotation mode). In your case this is what you want, a custom rotation mode based on your character's logical state, as I think your rotation is being overriden someway (hard to tell without the whole code).

    So here you can simply ignore rotation modes and directly extend the UpdateRotation method and handle your character's rotation based in your logical state, for example:

    Code (csharp):
    1.  
    2. protected override void UpdateRotation()
    3. {
    4.     if (isMoving)
    5.     {
    6.         // Rotate towards movement direction
    7.  
    8.         Vector3 movementDirection = GetMovementDirection();
    9.  
    10.         RotateTowards(movementDirection);
    11.     }
    12.     else if (isCloseEnough)
    13.     {
    14.         // Rotate towards enemy
    15.     }
    16.     else ...                
    17. }
    18.  
    If not using a custom Character (ie: not extending a Character based class), makesure your character do not have input action assigned (so it wont process any input related code) and its rotation mode is None so it do not modify its rotation.[/code]
     
    Last edited: Mar 18, 2023
    my_little_kafka likes this.
  18. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @MichelVictor

    Unfortunately not yet, as the in the following update I am focusing in adding network support to the Character class, and while I could try to fit at least a wall jump example, probably will need to wait to next update, where I plan to add support for the 'canWalkOffLedge' option and more examples.

    Sorry for the inconvenience.
     
  19. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @jiajialin1975 ,

    Yes, consider a jump, it is a parabolic motion, where the vertical velocity goes from its initial impulse (ie: 5, 10, etc) towards zero (slowly decelerated by gravity) and zero means jump apex is reached, to start falling (negative value), so I think this should work only for 'short jump, since it will never reach the > 5 to 10 range, but the high jump will go from 10 to 0 passing from the short jump range.

    Mmm, If your jump(s) are triggered by different inputs, the easiest way (I think) is to use separate flags, ie: isJumping (regular jump), and isHighJump (new jump). You set this to true depending on your input and false on key release, etc.

    Later you will use these 'flags' (boolean vars) to feed your animator to triggering the corresponding animation.

    Now for the animator, you could use two separate jump states, regular jump, and high jump, and trigger accordly (based on jump), as the included example jump method is 'tailored' for a regular jump.

    It's common (in a more advanced setup) to even split jumps in sections, like jump start, jump apex, jump_falling, etc.
     
    Last edited: Mar 18, 2023
  20. One_Learning_Man

    One_Learning_Man

    Joined:
    Sep 30, 2021
    Posts:
    81
    Nice! So how will it work? Do you plan on having both:

    1) NetworkCharacterMovement.cs + NetworkThirdPersonCharacter.cs? Or will NetworkThirdPersonCharacter take care of all networking?

    2) Do you use Network Transform components offered by FishNet/Mirror?

    3) How do you plan on adding rollback/prediction offered by FishNet?

    4) Will you update your docs talking about implementing networking? I examined the example in CharacterMovement FishNet integration and wished it had a bit more comments.

    Keep up the great work Krull!
     
  21. my_little_kafka

    my_little_kafka

    Joined:
    Feb 6, 2014
    Posts:
    87
    Oh, so this is how the rotations should be handled, dully noted (I felt weird rotating the character in a completelly separate state script, this looks like a better idea). I extended this method in my ai agent controller script, made it like that:

    Code (CSharp):
    1.         protected override void UpdateRotation()
    2.         {
    3.             //base.UpdateRotation();
    4.             if (IsDisabled())
    5.                 return;
    6.  
    7.             if (currentState is States.ACS_Pursuing)
    8.             {
    9.                 if (pursuingState.isPursuing == true)
    10.                 {
    11.                     Vector3 movementDirection = GetMovementDirection();
    12.                     RotateTowards(movementDirection);
    13.                 }
    14.  
    15.                 if (pursuingState.isCloseToTarget == true)
    16.                 {
    17.                     Vector3 targetDirection = playerCharacterGO.transform.position - transform.position;
    18.                     RotateTowards(targetDirection);
    19.                 }
    20.             }
    21.           }
    And my state machine affects the isPursuing and isCloseToTarget booleans. It works fine when the enemy character pursues their target, but when they get close, they just rotate without affecting the «Turning» variable in the animator. Could it be that the StoppingDistance is interferring with it? The enemy character plays turning animations just fine when they're away (for example, if the target is behind them, they stop and turn to look at the target while playing turning at place animation), but not when they reached this stopping distance.
    I haven't extended the AgentCharacter script that much, so nothing else affects the turning or moving.
     
  22. jiajialin1975

    jiajialin1975

    Joined:
    Jan 20, 2021
    Posts:
    5
    @Krull
    Thank you for your help.

    I use your JumpLeg float value to seperate "jump" "high jump" animations in blend tree.
    And it works perfectly.

    I have another question about collision. I wirte a script on a cube(with rigibody and collider). I try the
    OnCollisionEnter event on the cube is not working.

    How do I let the cube know the cube was collided by the easy character?
     
  23. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Thanks @One_Learning_Man,

    About your questions:

    1) For the first iteration I would like to add support for character (in general) as this is the 'core' base and all other characters are just extending this, so the same approach could be followed for networking purposes.

    Additionally I am adding client-authority examples including Unity's Netcode for gameobjects, as this is a lot easier to implement (almost transparent) than server-auth client-side prediction, so beginners should appreciate it the most.


    2) Yes, this is already used in the CharacterMovement examples, as a CharacterMovement can continue simulating from the given transform position, in this case given by fishnet NetworkTransform or through CM network state.


    3) Similar to the one used with CM examples, however the Character class requires a lot more of data housekeeping, so possible adding a tick based histogram for relevant data (ie: SavedMove), this way when a rollback is issued, the histogram data is restored for the given tick and then apply the server received data (something like this) to complement it.

    4) Well for networking I assume higher programming skills, since networking in general definitely adds a difficult layer to game programming in general, however I could add a kind of tutorial / doc for the ECM2 networking part.

    Also, please keep in mind this will be added as examples, and while it definitely be production ready in movement related part, as ECM2 it is a general purpose solution, so it is expected to be modified adapted for each project
     
  24. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @my_little_kafka,

    Yes, that's the approach I suggested.

    Now for your rotation issue, you could add a kind of tolerance radius, similar to the Agent's stopping distance, so within this tolerance radius you can simply stop rotating or apply a falloff effect torotation rate.

    This is similar to the stopping distance used in order to prevent overshooting as the agent reaches its destination.
     
    my_little_kafka likes this.
  25. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771

    Hi @jiajialin1975

    Glad I could help :)

    About your question:

    For it to work, the cube's rigidbody should be non-kinematic, as you can see here.

    Also, please make sure your script is on the GameObject containing the rigidbody.
     
  26. my_little_kafka

    my_little_kafka

    Joined:
    Feb 6, 2014
    Posts:
    87
    Oh, the issue is in the fact that the turning animation doesn't play, the character is rotation towards their target in idle state.
    I figured out that the stopping distance wasn't an issue, the issue was my inability to get a suitable Vector3 variable so it would not only turn the character, but also would affect the Animator component so it would play the turning animation.

    The closest thing I got is:

    In my custom CharacterController script that I built upon AgentCharacter, I created this override for rotation (don't mind the sloppy usage of states, I will clean the code once I will understand the issue with the Animator):

    Code (CSharp):
    1.        
    2. public Vector3 targetDirection;
    3. protected override void UpdateRotation()
    4.         {
    5.         //    Debug.Log("Movement direction is:" + GetMovementDirection());
    6.             //base.UpdateRotation();
    7.             if (IsDisabled())
    8.                 return;
    9.  
    10.             if (currentState is States.ACS_Pursuing)
    11.             {
    12.                 if (pursuingState.isPursuing == true)
    13.                 {
    14.                     Vector3 movementDirection = GetMovementDirection();
    15.                     RotateTowards(movementDirection);
    16.                 }
    17.  
    18.                 if (pursuingState.isCloseToTarget == true)
    19.                 {
    20.             //        Debug.Log("Target direction is:" + targetDirection);
    21.                     RotateTowards(targetDirection);
    22.                     targetDirection = playerCharacterGO.transform.position - transform.position;
    23.                 }
    24.             }
    25.  
    26.         }
    If the state is pursuing, then it works the default way, by using GetMovementDirection(). But if the enemy character is close to their target, they're rotating towards it. I calculate the vector as Target Position minus Enemy Position, and this gives me the seemingly right vector.

    Then, in the script that handles the animation, I wrote this:

    Code (CSharp):
    1. private void AnimateCharacter()
    2.         {
    3.             float deltaTime = Time.deltaTime;
    4.  
    5.             if (pursuingState.isPursuing)
    6.             {
    7.  
    8.                 Vector3 move = transform.InverseTransformDirection(_character.GetMovementDirection());
    9.                 if (_character.useRootMotion && _character.GetRootMotionController())
    10.                 {
    11.                     forwardAmount = move.z;
    12.                 }
    13.                 else
    14.                 {
    15.                     forwardAmount = Mathf.InverseLerp(0.0f, _character.GetMaxSpeed(), _character.GetSpeed());
    16.                 }
    17.                 animator.SetFloat(a_forward, forwardAmount, a_walkingTransitionDumpTime, deltaTime);
    18.                 animator.SetFloat(a_turn, Mathf.Atan2(move.x, move.z), a_rotatingTransitionDumpTime, deltaTime);
    19.             }
    20.  
    21.             if (pursuingState.isCloseToTarget)
    22.             {
    23.  
    24.                 Vector3 move = transform.InverseTransformDirection(_character.targetDirection);      
    25.                 forwardAmount = 0;
    26.                 animator.SetFloat(a_forward, forwardAmount, a_walkingTransitionDumpTime, deltaTime);
    27.                 animator.SetFloat(a_turn, Mathf.Atan2(move.x, move.z), a_rotatingTransitionDumpTime, deltaTime);
    28.             }
    29.         }
    It is also a rework of a default third person character animator, where I did the same split based on the current state. Pursuing state — default animation behaviour. But in CloseToTarget state I give the system a different vector — the one I calculated in CharacterController script.
    So here's my problem, the vector I calculated doesn't give a large enough value to drive the animator's turn animations. There's this really wide angle, right in front of enemy character, where if the character will turn, it will not play the turning animation. But if the angle will be large enough, it will play the animation.
    I tried to manually multiply the results from Mathf.Atan2(move.x, move.z), but it results in some weird jerky changes of animation and generally it doesn't seem like it's the right way. Is there any way to naturally transform the value that I pass into the animator to be in the range of turning animations in my blend tree (it's -0.5 and 0.5 currently)?

    I'm not really good with vectors, and, God forbid, quaternions, so I'm not sure if it's a ECM2 issue, or it's unrelated. Here's the video so it would be easier to understand, I know it's all confusing, but I can't express all this in a more precise way.



    (The small blue sphere indicates the direction of enemy character)
     
  27. revanaii

    revanaii

    Joined:
    Jun 13, 2017
    Posts:
    11
    howdy @Krull
    a question: currently I can jump on top of enemies and stay there, which obviously breakes the combat. How to prevent that from happening?
    The enemy is not a CharacterController, but a capsule collider + kinematic rigidbody + navmesh agent.
    Thanks.
     
  28. revanaii

    revanaii

    Joined:
    Jun 13, 2017
    Posts:
    11
    Fixed by checking
    if(...GetCharacterMovement().groundRigidbody..) AddForce(...);
     
  29. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771

    Mmm I think your issue is due the expected values of the parameter your turn animation requires, as ecm do not use animation at all, so users are free to animate characters using 'plain' unity code, and use the character data (isGrounded? its speed, velocity, etc) to feed your animator parameters, so this leads me to think probably your animator requires data in degrees (just a guess) or in a different way used by example character.

    You can try the normalizing your your targetDirection since it is a direction vector (magnitude no matters), I suggest you normalize it so really smaller values do not affects it, also try feeding your isCloseToTarget turn in degrees, just mult by Mathf.Rad2Deg.
     
    my_little_kafka likes this.
  30. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Glad to hear you were able to fix it.

    Actually ECM2 includes a working example 5.15.- Prevent Standing On Other Character where the character is pushed off others when standing on it.

    Alternatively, you can make use of the CharacterMovement CollisionBehaviorCallback that lets you fine tune how a character should handle a collision.

    The CollisionBehaviorCallback it's a powerful mechanism to influence the character’s collision, or in other words how it should proceed when a collision occurs. Using a combination of bitwise flags you can fine tune the collision behavior overriding the default one in a performant and practical way.

    For example, making use of the CollisionBehaviorCallback function you can decide if the collided should be walkable or not independently of the character’s slopeLimit, allow / prevent the perch behavior, determine if the character can step on and even determine if can use it as a moving platform or not.

    You can find working examples in the included CharacterMovement package.
     
    revanaii likes this.
  31. HyunWol

    HyunWol

    Joined:
    Jan 27, 2021
    Posts:
    11
    Question: It's not smooth between dash and movement (including sprint).

    The character pauses at the end of the dash.
    I implemented the dash using the dash of the sample.
    How to get the character to move naturally (including sprint) without stopping at the end of the dash?
     
  32. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @HyunWol

    The included dash example implements it like the one from Doom Eternal, however this can easily be modified.

    Following the Dash example, in the StopDashing method, simply remove the latest line (SetVelocity(Vector3.zero)) so the velocity is not cleared at the end of the dash, so the character conserves the momentum.

    A dash can also be implemented adding an impulse to a character, after all that's what a dash / boost is, a sudden change in the character's velocity.

    This can be accomplished using the LaunchCharacter function, the AddForce, or directly modifying the character's velocity, however worth noting all character's movement is affected by its current properties, ie: acceleration, deceleration, max speed, friction, etc. so this should be taken into consideration.

    Regards,
    Oscar
     
  33. One_Learning_Man

    One_Learning_Man

    Joined:
    Sep 30, 2021
    Posts:
    81
    Hey there Krull, do you have eta on next release window? I've been using a cobbled together networked character controller temporarily and excited to be using yours.
     
  34. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @One_Learning_Man,

    Currently working on it, and plan to release it by the end of this month (fingers crossed :D).
     
    One_Learning_Man and Pixelith like this.
  35. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    HI @Krull
    I notice that when character walks and then jump, the force of the landing is the same for when the character sprint and jump. It should have higher speed/ force (not sure if this is the correct term) when landing for when character is sprinting due to momentum from sprinting. How can I make the character exhibits this behaviour?
     
  36. PhuntasyProductions

    PhuntasyProductions

    Joined:
    Feb 6, 2023
    Posts:
    5
    Hi @Krull

    1. Does ECM2 work inside a non-kinematic rigidbody, e.g. a moving and rotating spaceship? Does it collide with the ground and effectively cause force on the ground, which would also move the spaceship?

    2. Is it possible to have a full body like in the third person view, but have the camera attached to the head where the eyes are? Of course there must not be any looking through own body.

    Thanks for your reply!
     
  37. Krull

    Krull

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

    The character movement is modeled based on its current properties, like acceleration, deceleration, friction, gravity, jump impulse, etc. So the movement is heavily dependent on its current settings.

    Its friction model it's pretty robust and can be tailored from a realistic behaviour to a very cartoony snappy movement as needed.

    For your case, you can start setting the deceleration to zero, since this is a constant value breaking the character, so to achieve a more visible momentum it's better lower this value or even set it to zero so the character breaks due its friction.

    When the character is falling, its movement is affected by gravity, MaxFallSpeed (ie: terminal velocity) Falling Lateral friction, AirControl and Braking DecelerationFalling, once again this behaves just like Braking Deceleration Walking.

    Also, worth noting by default (default values) it uses semi-realistic values and the jump is a variable height jump, if you want a fixed height jump, you can set the jump Max Hold Time to 0, so it does not trigger the variable-height part.

    I suggest you take a look at the following article about implementing a physically correct jump, it is for unreal, however ECM2 uses the same friction-based model used by UE, so the UE behavior is fully reproducible by ECM2!
     
  38. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Thank you for your interest in ECM2!

    About your questions:

    Sure, it will be used as a 'platform' without you having to code any special script. For example it can even use a fully simulated vehicle like Edy Vehicles to say something, as a moving platform without users having to code any script or do special handling code.

    While it does not include an example of this, definitely it's possible as ECM2 is a general purpose character controller not game-genre tied and very flexible. Its purpose is to serve as a very robust character controller where you (users) can build their game specific mechanics on top of its default functionality.

    Let me know if you have any further questions.
     
  39. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Lastly, I would like to let you know I have finished the latest ECM2 update to include the networking examples for major Unity networking libraries, and should be available pretty soon! :)

    In the meantime, let me know if I can be of any help.
     
    One_Learning_Man, Minzie and Pixelith like this.
  40. Minzie

    Minzie

    Joined:
    Jul 26, 2019
    Posts:
    77
    HI @Krull ,

    Thanks for your advice. Uhm, I'm not really trying to mimic realistic/ physically correct jump. My intention is to have different animation when character is falling, based on the speed/ force of landing :D I want it to be able to move forward after falling from sprinting. Thanks for providing the article too, although it feels so intimidating for non-coder like me :confused: I'll try to play around with the values & see if that's what I want though. Look forward to the networking update too! :)
     
    Krull likes this.
  41. PhuntasyProductions

    PhuntasyProductions

    Joined:
    Feb 6, 2023
    Posts:
    5
    Hi @Krull

    Thanks for your reply!

    I believe there are two major differences to "moving platform":

    1. The player is not on top (=outside) of the spaceship rigidbody. Instead the Player is inside! Of course standing on a floor gameobject (child of the ship itself) with a collider. It is rigidbody inside rigidbody what I need here. Further more, the player is not in direct control of the ship, so this is not a situation where the player sits down in some cockpit and effectively becomes the spaceship. The player and other networked players must be able to walk around while the ship is moving and rotating, driven by forces. I'm aware of the "static ghost ship solution", this is not what I'm looking for.

    2. While moving platforms are usually kinematic, the spaceship must be non-kinematic. The problem is, when the player collides with the floor, then the ship gets an impuls. This must not happen.

    Are you really sure that ECM2 can fulfil those requirements?

    Thanks
     
  42. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @C_B_S,

    A Character will use as a moving 'platform' any kinematic or non-kinematic Rigidbody the Character is standing on no matter if is kinematic or a fully simulated rigidbody, like a vehicle as you can see in the following video



    Alternatively it could simply attach the Character to a dynamic platform (once again kinematic or non-kinematic) using the CharacterMovement SetPlatform method, this will make the character follow the platform even if the character is not directly standing on it.

    The CharacterMovement component (ie: the character controller used by ECM2) keeps a safety distance from collisions, and another from the ground, can say the capsule floats a variable height above the ground, however in some cases PhysX can even with this safety tolerance can register contacts with the Character's Capsule Collider, for this cases you can use the Physics.IgnoreCollisions so the capsule does not collides with other physical objects, and let CM handle its collisions, additionally you can use the contacts modification to tailor fit it if needed.


    Having said that, please keep in mind ECM2 do not support moving platforms in a networking environment, not even in incoming update, since this is a very advanced topic (see attached video for a very complete talk about it by the Photon Fusion guys) and its implementation heavily depends on the game needs and tradeoffs.

     
  43. KutluKan

    KutluKan

    Joined:
    Feb 22, 2022
    Posts:
    3
    Hi Krull, I'm trying to use NetworkTransform to synchronize the transforms of two player prefabs, but ECM2 isn't letting me move the client player.

    I've made the Character and CharacterMovement classes extend NetworkBehaviour instead of Monobehaviour, and I've taken all the basic steps, but I don't know how to make this simple functionality work.

    Can you help me with this?
     
  44. One_Learning_Man

    One_Learning_Man

    Joined:
    Sep 30, 2021
    Posts:
    81
    Hello Krull! Awesome job on the new update release! That must not have been easy so hats off to you.

    If I really wanted to implement this, what script/function would I override to get started?
     
    Last edited: May 5, 2023
  45. Asarge

    Asarge

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

    How would you detect a dynamic (without specific layers or ledge object component) ledge checker to vault over objects you can't jump over but is within the characters upward arms length and has a clearing (not a wall jump). For example games like Genshin Impact or Sunset Overdrive do this and likely some form of cast checking as you can jump up at the clearing of any collision.

    The ECM2 collision checker can detect the front wall part but how would you do the above clearing check to see if you can initiate the addforce vault up?
     

    Attached Files:

  46. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @KutluKan,

    I just released an ECM2 update including networking examples for major networking engines (Netcode for GameObjects, Mirror, FishNet and Photon Fusion), so if I have not checked I suggest take a look at it, the examples source code is fully commented and discussed in the user manual too.

    In general when using a Character in a networking environment, it's necessary create a controller to 'possess' our character, this controller extends a NetworkBehaviour and is responsible for handling the user input and issuing character actions in response.

    Additionally, depending on your networking library you should set a few settings, but all of this is shown in more depth in the latest update, so please take a look at it, and let me know if you have any questions.
     
  47. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    I have implemented it using Photon Fusion (client side prediction and reconciliation) following the guidelines from the shared video, but only for fusion and not in a very 'production ready' state.

    At great sight, the Idea is that your platform should provide and synchronize its velocity, later the Character will use this platform velocity to correctly move your character, additionally you will need a way to handle what data the character uses to interpolate and the proxies too (ie: csp, snapshot, etc).

    So about what script to modify, it should be in the Character Move method, as this is the code which 'simulates' the character and calls the CharacterMovement.Move method.

    The ECM@ default platforms code do not comply well (at least on my tests) basically due it uses a verlet approach to compute the 'platform' velocity and this is dependant on last and current platform positions, something works in a regular simulation (ie: local, single player, etc) but not in a networking environment...
     
  48. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    For this you could use the CharacterMovement exposed collision detection functions, like CheckHeight, MovementSweepTest, FindGround and ComputeGroundDistance, this are the same functions used internally by the CharacterMovement so it will ensure proper simulation continuity and correct 'walkable ground' detection. Additionally, this functions can use an arbitrary position

    The general approach is first check if your character can move up up to its allowed vault height, if cant, well we are done; if can 'step up' check if can move forward, and lastly check step-down (from vaulted position) in order to prevent ending on not-walkable surfaces / objects.

    You should take a look at the CharacterMovement StepUp function as this uses a similar approach but with some additional checks needed in there.
     
    Asarge likes this.
  49. KutluKan

    KutluKan

    Joined:
    Feb 22, 2022
    Posts:
    3
    Hi @Krull

    Thank you for the quick response, as well as the opportunity to learn from your examples. I have a small question: you mention at the end of the documentation that advanced things such as platform movement aren't covered by the example scenes; may I ask, roughly, which features of ECM2 aren't in the networking examples? I'd like to know what your 'Player Controller' solution is capable of. (To be clear, I'm using Netcode for GameObjects)

    Again, thank you for the opportunity.
     
    Last edited: May 6, 2023
  50. Krull

    Krull

    Joined:
    Oct 31, 2014
    Posts:
    771
    Hi @KutluKan,

    The networking examples, in particular the client-side prediction ones, shows how to replicate the character and all its movement and additional mechanics like its variable-height jump, crouching, sprinting etc. However as commented in the user manual, it does not replicate platform movement as I previously commented, it requires a custom implementation, also other features, like current physics volume, ignored colliders, etc are not replicated in included examples.

    The goal of the examples is show a easy and practical way to use the Character class in networking games, and show a way how users can add / remove features based on their game needs, for example, if your game jump is fixed height (ie: not a variable-height one), you can completely remove (not replicate) the jump related fields from the networked state. The same way, you can add to the network state any fields / data your game might need.