Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Character Controller Pro

Discussion in 'Assets and Asset Store' started by lightbug14, Jan 15, 2020.

  1. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi,

    EDIT: Obviously, i totally ignored the "character graphics" part lol ------------------

    It is possible. You could create a new monobehaviour and do something like this:
    Code (CSharp):
    1. graphicsTransform.up = CharacerActor.GroundContactNormal;
    It is very important to re-assign the "gravity-based" up direction (e.g. Vector3.up) every time your character goes unstable (or not grounded):
    Code (CSharp):
    1. graphicsTransform.up = CharacterActor.IsStable ? CharacerActor.GroundContactNormal : Vector3.up;
    As a bonus, you can also lerp between the current up and your "target":
    Code (CSharp):
    1. Vector3 targetUp = CharacterActor.IsStable ? CharacerActor.GroundContactNormal : Vector3.up;
    2. graphicsTransform.up = Vector3.Lerp(graphicsTransform.up, targetUp, someValue * dt);

    By the way, I've implemented this using the body (collider) for a sticky walls mechanic with good results. The results depend heavily on the geometry (as you can see in the video).
     
    Last edited: Dec 1, 2021
    flashframe likes this.
  2. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    Thanks so much for this example, this is great!
     
  3. rojbarak

    rojbarak

    Joined:
    Nov 17, 2021
    Posts:
    16
    No problem.

    #1
    yes that is really odd since I also can't see any difference on character. Maybe because of animator's animations? Because capsule and player are located on same spot and just switching on and off.


    #2
    Sliding still highly exist even when MaxGroundVelocityChange is 300. That setting doesn't affect at all. I just need to find who's lerping the player rigidbody velocity to zero, so I can make it instant when we land.


    #3
    Yes, as I stated it has a perfect matched convex collider. The more speed, the more it sinks. And everything scaled as 1 (both vehicle and player). Step ups are 0.35 & 0.4
     
  4. rojbarak

    rojbarak

    Joined:
    Nov 17, 2021
    Posts:
    16
    Ok did the #2 as well.



    Here I'm detecting the exact landing time and setting PlanarVelocity to zero (it is just one frame). Btw what is the deal with pre and post simulations? Can you explain them a bit? I guess PhysicsActor is responsible and doing two updates for them.
     
  5. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    @lightbug14

    I'm not using Unity Animators to control the animation of my characters, which is fine in general. I've just written my own states and added my custom functionality for that.

    But in the implementation, the CharacterStateController requires an Animator component to run Pre/PostCharacterSimulation. I'm happy to rewrite those functions, but just aware that this makes updating the asset to latest version a bit trickier in the future.

    Is there anyway to decouple that logic slightly more to remove the dependency on Unity Animators? Either moving the null checks to the States themselves, or a bool to indicate that I'm using a custom solution, or maybe even an overridable container class for the Animator.

    EDIT: After I wrote this, I realised that Pre/PostSimulation are events in the CharacterActor class, so I could register to those events in my custom states. (Incidentally, is there a reason not do the null check before registering to the events in the StateController?)
    I think it would still be a nicer to be able to just not use the Animator and have those functions run in the CharacterStateController regardless.
     
    Last edited: Dec 2, 2021
  6. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    What i meant before is that collider and graphics (animator) go on separate ways, especially when the graphics controller is working. Since the camera follows the "Graphics" object, it is ok to see that jitter.

    Oh i see what you mean. Indeed, i think that deceleration (from NormalMovement) is causing that. Using a "stable deceleration" of >100 may do the trick as well.

    Thanks for sharing that. Still, this need to be re-implemented using CharacterActor. The good news is that i think i know how to solve it.
    Basically, this is caused by a mix between velocity projection and handling position directly (what i like to called "simulated friction"). When you kill planar velocity (what you're doing now) you are effectively simulating infinite friction.

    PreSimulation: collider and rigidbody get prepared for the simulation (size and linear velocity are important).
    PostSimulation: Here i'm working with position/rotation directly (I don't care about physics anymore since the simulation is done). Also, i set up the interpolation data.
     
  7. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    I must admit that you are right. Having a method called "Pre/PostCharacterSimulation" that hides that null check (Animator) from you is bad, especially if you are not using the Animator component. I will fix this for the next patch (very soon).

    All those suggestions should work. Moving the null check to the state (as a little helper method) should be the best option, and also the most straightforward.

    For example, i could make this:
    NormalMovement.cs
    Code (CSharp):
    1.  
    2.        public override void PreCharacterSimulation(float dt)
    3.         {
    4.             if (!GetAnimatorStatus())
    5.                 return;
    6.  
    7.             // ...
    8.         }
    9.  
    10.         public override void PostCharacterSimulation(float dt)
    11.         {
    12.             if (!GetAnimatorStatus())
    13.                 return;
    14.  
    15.             // ...
    16.         }
    17.  
    CharacterState.cs
    Code (CSharp):
    1.        public bool GetAnimatorStatus()
    2.         {
    3.             if (CharacterActor.Animator == null)
    4.                 return false;
    5.  
    6.             if (CharacterActor.Animator.runtimeAnimatorController == null)
    7.                 return false;
    8.  
    9.             if (!CharacterActor.Animator.gameObject.activeSelf)
    10.                 return false;
    11.  
    12.             return true;
    13.         }
    Obviously, the original null checks must be removed from the state controller.
     
    flashframe likes this.
  8. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    That's great, thank you. Yes I think that's a clean solution
     
    Last edited: Dec 3, 2021
  9. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    ---> Input system bug <---

    Hello,
    This has been discussed already. For those using the input system (with this asset or not), please note that version 1.1 is broken. I've added this problem to the "Known issues" section (a separate page now):
    https://lightbug14.gitbook.io/ccp/package/known-issues#unitys-new-input-system-doesnt-work

    Changelog (from 1.2.0):
    - Fixed action.ReadValue and others returning invalid data when used from FixedUpdate or early update when running in play mode in the editor.

    Here is the official forum post:
    https://forum.unity.com/threads/inp...d-ps5-controller-support-for-desktop.1192894/
     
  10. rojbarak

    rojbarak

    Joined:
    Nov 17, 2021
    Posts:
    16
    @lightbug14
    Thank you. Can you help me with this one?



    Also I created the flow diagram of Character Controller Pro. Here is my contribution if anyone else interested.
     
    jasonMcintosh and lightbug14 like this.
  11. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Yes of course. I'm working on it :)

    Wow, great job! :cool: Thanks for sharing.

    Btw, Is that LucidChart?
     
  12. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    Hey @lightbug14

    I'm trying to make a CharacterState for Pushing / Pulling objects. (note, my game is 2D, so all of this is in 2D with Rigidbody2Ds)

    To enter this state, the player stands next to a "movable" object (which gets added to the CharacterActor Triggers) and holds down a button.

    While the player continues to hold the button, I'd like the object to move forward/backward to match the player movement (as if it is being pulled/pushed). But ideally, I want the object to be a dynamic rigidbody to benefit from gravity etc (so if the player pushes the object off an edge or down a slope, it falls).

    Currently, I'm moving the player using the same code from the NormalMovement state (setting the PlanarVelocity), and then I'm applying the same velocity to the movable rigidbody. This works well when pushing the object, but when pulling, the character loses contact with the object (exits the trigger).

    Do you have any suggestions of the best way to move the object so that it stays aligned with the player's planar movement but still benefits from physics vertically?

    In my previous character controller I ended up just making the movable object follow a predefined path. I could return to that, but thought you might have some ideas of how to make this work.

    Thanks so much!
     
  13. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    Update on the above:

    I added a DistanceJoint2D to the other rigidbody. That keeps the objects connected while pushing and pulling. Seems to work well.
     
  14. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    Sorry to keep posting :)

    I wanted to enable "Apply Weight To Ground" but only for some layers. That way I can make dynamic terrain but avoid unwanted interactions with other objects.

    I've added this myself to CharacterActor component, but if you agree it's a good option to have, would be nice to have it built in to the Core.

    I added a layer mask:

    Code (CSharp):
    1. public LayerMask applyWeightToGroundLayerMask = -1;
    and then perform the check in ApplyWeight()

    Code (CSharp):
    1. if(!CustomUtilities.BelongsToLayerMask(GroundCollider2D.gameObject.layer, applyWeightToGroundLayerMask))
    2.     return;
     
  15. rojbarak

    rojbarak

    Joined:
    Nov 17, 2021
    Posts:
    16
    Great, looking forward to it.

    Yes it is lucid :)
     
  16. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Oh sorry, I read your post the other day but i forgot to answer :(. I was going to recommend to mirror the character velocity with your object velocity (classic push/pull mechanic).

    Sounds good, thanks for the suggestion, I'll add that.
     
    flashframe likes this.
  17. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    Would still be interested in how mirroring the velocity would work! I assumed the velocity would have to be the same (not mirrored) since the object needs to move in the same direction as the player?

    EDIT: I realise that mirror == copy. I did try this, but over time / distance, the character and the other object drift apart. Any idea why that might be?
     
    Last edited: Dec 16, 2021
  18. victorkin11

    victorkin11

    Joined:
    Apr 20, 2013
    Posts:
    175
    Because I use Move(Vector3 position) method in CharacterActor, but It look like it isn't work, I change to set CharacterActor.velocity then it work.
     
  19. flashframe

    flashframe

    Joined:
    Feb 10, 2015
    Posts:
    789
    In CharacterAIBehaviour, ExitBehaviour() is never called by the CharacterBrain.

    I'm switching between AI and Player control so it'd be good to be able to undo any changes I made to the state controller / character actor when switching.

    I'm adding this for now. Would you consider adding it? (didn't want to post too much of the source code, so have omitted the unchanged lines)

    Code (CSharp):
    1. public void SetBrainType(bool AI)
    2. {
    3.     // ...
    4.  
    5.     if (AI)
    6.     {
    7.         SetAIBehaviour(aiBehaviour);
    8.     }
    9.     else if (this.isAI && currentAIBehaviour != null)
    10.     {
    11.         currentAIBehaviour.ExitBehaviour(Time.deltaTime);
    12.         currentAIBehaviour = null;
    13.     }
    14.  
    15.     // ...
    16. }
    17.  
    18.  
    19. public void SetAIBehaviour(CharacterAIBehaviour aiBehaviour)
    20. {
    21.     // ...
    22.  
    23.     if (currentAIBehaviour != null)
    24.     {
    25.         currentAIBehaviour.ExitBehaviour(Time.deltaTime);
    26.     }
    27.  
    28.     // ...
    29.  
    30. }
     
    lightbug14 likes this.
  20. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Copying the velocity is only the starting point, after that the body must deal with the physics simulation. Linear/Angular drag, static/dynamic friction, bouncing, mass ratio (between bodyA and bodyB), all that stuff will affect the body in some way.
    Another way to approach this is by moving the target object towards a specific point in space using either forces or velocity. I'm doing that with this asset.


    Oh yes, that has been fixed already. Thanks for reporting it!
     
    Last edited: Dec 18, 2021
    flashframe likes this.
  21. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    Hello,
    Is there an integration for the A.I. with a* pathfinding?

    Happy Christmas!
    Thanks
     
  22. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi there,

    There is no native integration with A*, although you should be able to use it without problems. A* will give you the path information which can be translated into whatever you want. For the demo scene, i use Unity's NavMesh to create a direction based on the path and the character position. Finally, I convert this direction into "movement" (=WASD input for the AI).
    Code (CSharp):
    1.        protected void SetMovementAction(Vector3 direction)
    2.         {
    3.             Vector3 inputXZ = Vector3.ProjectOnPlane(direction, CharacterActor.Up);
    4.             inputXZ.Normalize();
    5.             inputXZ.y = inputXZ.z;
    6.             inputXZ.z = 0f;
    7.  
    8.             characterActions.movement.value = inputXZ;
    9.         }
    Which A* pathfinding solution are you using?

    Happy Christmas to you too!
     
  23. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    Hello, thank you for the reply.

    Currently im trying the free version.
    Altough im heavily thinking in buying it as im very interested in the avoidance part, which unity fails..

    Well actually i've been trying to implement character controller pro, and a*, but for some reason
    character controller doesn't recognize the a* types. I believe there is a conflict in the namespace or something related.

    Regards!
     
  24. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi,

    Not sure what's happening there. Could you share the error messages? Also, check if your IDE is the one causing trouble (a.k.a not recognizing types).
    CCP is encapsulated in a dedicated assembly definition + custom namespaces, although that doesn´t mean there won't be conflicts.
     
  25. Lunarthewolf

    Lunarthewolf

    Joined:
    Feb 10, 2019
    Posts:
    10
    I'm trying to set CharacterActor.Forward to change the rotation, but it seems like it only works if I do it during the FixedUpdate function. Is there a way to get it to update the rotation in other function calls?
     
  26. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi,
    Sorry for the late reply.
    There is no way to do that unless you reset interpolation. With CCP's interpolation enabled the actor (PhysicsActor) will handle the Rigidbody/Transform position/rotation before and after the simulation. Even if you change Forward between simulations (e.g. Update), the body will go back to its previous position/rotation in the next FixedUpdate. In order to ignore this behaviour you need to call "ResetInterpolationRotation" and/or "ResetInterpolationRotation" which resets all the internal interpolation flags. Try this:
    Code (CSharp):
    1. CharacterActor.ResetInterpolationRotation();
    2. CharacterActor.Forward = something;
     
  27. Lunarthewolf

    Lunarthewolf

    Joined:
    Feb 10, 2019
    Posts:
    10
    I tried adding a call to ResetInterpolationRotation before setting the characterActor.Forward, but that still didn't seem to do anything.
     
  28. Lunarthewolf

    Lunarthewolf

    Joined:
    Feb 10, 2019
    Posts:
    10
    It's not a big concern if I can't get this working. Worst case I can probably get it working by setting

    characterActor.Rotation = Quaternion.LookRotation

    but I've had better results with setting characterActor.Forward and it seems like a cleaner solution
     
  29. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Oh wait, i think i made a silly mistake ‍*face palm*, try to change Forward before resetting the flag.
    Code (CSharp):
    1. CharacterActor.Forward = something;
    2. CharacterActor.ResetInterpolationRotation();
    3.  
    By resetting the flag the actor does store the current rotation as the starting/target rotation.

    Yes, that should work:
    Code (CSharp):
    1.        public Quaternion Rotation
    2.         {
    3.             get
    4.             {
    5.                 return RigidbodyComponent.Rotation;
    6.             }
    7.             set
    8.             {
    9.                 RigidbodyComponent.Rotation = value;
    10.  
    11.                 ResetInterpolationRotation();  //<-----
    12.             }
    13.         }
     
  30. Lunarthewolf

    Lunarthewolf

    Joined:
    Feb 10, 2019
    Posts:
    10
    Ah yup, this worked perfectly. In retrospect, I probably should have tried that myself lol

    Thanks!
     
    lightbug14 likes this.
  31. victorcharlie

    victorcharlie

    Joined:
    Jan 17, 2016
    Posts:
    3
    Hi, I have an working fps recoil system outside the CCP. Recoil makes the camera move sideways and rotate upwards. I want to make the CCP camera to be affected by other camera's recoil. Are there any ways to make it work? What kind of path should I follow? Should I disable the CCP camera and make the recoil camera the main camera?

    Edit: Hi again. I solved it by making the custom recoil camera lerp transform to the character body position and setting my custom camera as the Main Camera in the scene manager.
     
    Last edited: Feb 20, 2022
  32. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi there,

    In order to give you an answer i'll need to know How this recoil system is affecting the camera.
    Could you please share the main part of the code?

    CCP's Camera3D was never intended to be used as a camera system, so it might present some issues. Normally I would recommend to use a more dedicated camera system such as Cinemachine. That being said, i know users who have moved away from Cinemachine back to CCP's Camera o_O due to the collision detection part.

    Maybe i could improve the component a bit, it depends on how your system is handling things.
     
    Last edited: Feb 21, 2022
  33. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    Hey Juan, it's been a while :)
    Nice to see you're still working on this great asset!
    Here's what I think would be great for this asset (in order of importance).

    1)
    For your example scripts:
    Most people call Controller.Move(Vector3 velocity) and not Controller.Move(Vector3 normalized input) and then modify the max speed to make it go to the pace you want etc...
    It would be nice that you have this kind of setup added to your examples.
    It would also be nice if there were clear methods with which you can simulate Jump() instead of passing through the character brain.
    Essentially, it takes quite a bit of effort to have to adapt your examples to pre-existing project codes. Even though it says that the examples are there for demonstration only, realistically speaking, for the user to build his own system on your base would mean a lot of work so I think it would be nice if the implementation logic was made to be more flexible, and more accessible from scripts that are outside of the systems you have made.
    For example, it should be easier for me to remove parts of your code such as the character brain and use my own system on top. As it stands it's very "black box"-y where one has to work to make it work with a different system.
    Hopefully you see what I mean, just imagine more public methods that can do things like:
    Controller.ActivateCrouchMode(), Controller.Move(velocity), Controller.StartJump(), Controller.StopJump(), Controller.Dash(velocity, duration), Controller.ActivateCollisionsWithLayer() etc... (I'm just randomly imaging some methods here, not saying those are the ones that would be good)
    Thinking modular like this will tremendously help with implementation. It will make it sooo much easier to use for enemy AI, pathfinding etc... Please consider doing this.

    2)
    When the character has high deceleration in the air, it makes the character highly reactive for jumps etc... Which is necessary for action games.
    But having high deceleration also kills any accumulated speed the character can receive from the rigidbodies in the environment. And so it removes a part of the charm of the asset.
    It's a choice between cool physics movement and reactive input.
    To solve this, I think there should be 2 types of expulsions that would decelerate at different paces, the one given by the input and the one that's linked to the environment.
    This should also be made easy to access from outside scripts such as:
    CharacterController.Move(Vector3 movement) or CharacterController.Expulse(Vector3 expulsionForce)

    3)
    It would be cool to have a jump pad that makes you land at a designated location. with a Controller.JumpTo(position) and maybe even Controller.JumpTo(position, angle) -> that would have to change the gravity which the user can then reset to whatever he wants.

    4)
    Maybe you could create a trampoline (see gif here) in the example scene and make those jumps be more consistent: It seems sometimes the jump is killed? (not shown in the gif)
    It could definitely become a cool gameplay feature. Maybe I'm not timing the jump right.
    To reproduce: set max jump = 1 (not 2), jump apex to 5 and inherited ground vertical velocity multiplier to 2. rest is default.
    Probably that kind of thing would require to add some sort of capping on the velocity acquirable by the environment. That probably should be there already.


    Let me know what you think about those additional features :)

    This asset is one of the hardest to adapt to one's game code, but it's the most ambitious, the most complete asset in the store and I really enjoy seeing it in action. I hope it keeps getting great support as it has been for the past year.
     
    Last edited: Feb 21, 2022
  34. Vaeer

    Vaeer

    Joined:
    Feb 22, 2022
    Posts:
    8
    Hello lightbug14, that's a really great asset you've made. But I have problem to solve, a challenge, and don't know how to do it, or if your character controller would be suitable for such purpose.
    I need my character to be able to ride a vehicle (or spaceship) that makes it totally synchronized. What I mean is, all controllers at this moment just make it stick to the surface and if it moves, it gives its velocity to the controller. That causes launching into air or slowing down when jumping. But what I need is the character sticking to the surface even while jumping mid-air. If platform stopped at once, the jump should stop on planar axis as well (just continue it's normal movement). If it accelerated 1000m/s, character would still move only relatively to that surface, not affected by any momentum. So the vehicle (surface) should give no momentum, but simply sync the character to it's movement at all circumstances. If surface accelerates or rotates, character should just move across it normally, in perfect sync like it wasn't moving or rotating at all. Controller must also stick to the surface upside down and on any other angle, able to jump, like it was horizontal. No additional momentums, just that sync at all times, until dismissed by some switch.
    Is your controller able to do it? How would you implement it? I know that's not real physics, but maybe there's some hack or trick you know that would make it happen.
     
  35. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi @FeastSC2 , hope everything is ok. Thank you very much for the feedback, it is always great.

    All systems in v2 will be independent "mini assets" (e.g. the core (character controller), state machine, action system, utilities, etc).

    You should be able to remove/ignore them if you want.

    On the other hand, V1 systems are contained within the same "big asset" meaning everything exists under the same assembly. This doesn't mean they can't be independent systems (they aren't :(), nevertheless, it is possible to mess everything up.

    V2 Demo (included with the package) and the Demo project (separate project) both define its own layer on top of the existing systems. For example, the "Movement" action doesn't exist at all, it is something the Demo project defines along with the rest of the actions:

    Code (CSharp):
    1.     public class DemoActions : MonoBehaviour
    2.     {      
    3.  
    4.         public GenericAction<Vector2> MovementAction { get; private set; }
    5.         public GenericAction<Vector2> LookAction { get; private set; }
    6.         //....
    7.  
    8.         protected virtual void OnEnable()
    9.         {
    10.             brain.OnAssetChange += OnAssetChange;
    11.         }
    12.  
    13.         protected virtual void OnDisable()
    14.         {
    15.             brain.OnAssetChange -= OnAssetChange;
    16.         }
    17.  
    18.         void OnAssetChange(CharacterActionsAsset previousAsset, CharacterActionsAsset currentAsset)
    19.         {
    20.             MovementAction = brain.GetVector2Action("Movement");
    21.             if (MovementAction == null)
    22.                 MovementAction = new GenericAction<Vector2>();
    23.  
    24.             LookAction = brain.GetVector2Action("Look");
    25.             if (LookAction == null)
    26.                 LookAction = new GenericAction<Vector2>();
    27.  
    28.             //...
    29.          }
    30.     }
    31.  
    You can say the same for example states, AI behaviours, and so on.
    In summary, V2 will be completely transparent by drawing the line between where the asset ends and your code begins. Making the decision to use Demo content as part of your game should be pretty obvious.
    Originally, with V1 I intended to do that but unfortunately the example/tutorial went out of control (my fault).

    I totally agree, making the locomotion code as modular as possible is a very good thing. If i pull this off i need to do it right, and by that i mean creating a high level controller that does all that (another sub system or even a new asset). This HL controller cannot be just an extra state, like NormalMovement is, but instead a separate controller on top of the main asset. Concepts such as rotation, jump, gravity and things like that must be part of its vocabulary.

    When the actor becomes unstable, the platform velocity is added to its own velocity. If you jump while the bridge is going down, that means the jump will be reduced. Try to reduce the inherited vertical velocity multiplier (CharacterActor) to 0.

    I'm going to test that, thanks for the info.
     

    Attached Files:

    FeastSC2 likes this.
  36. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hello,
    Thanks for the nice words.

    What you are looking for is a way to parent the character to the ship in a physics-compatible way. Unfortunately, the asset (version 1.x.x = v1) does not support that, sorry. V2 will support that.


    Exactly, that's how it will work. This controller handles 80% of the situations in the same way a kinematic controller does (especially moving platforms).
    The current v1 system works in the same way but only when the character is contacting the surface (not exactly what you need right now).

    A trick? i guess you could jump from the platform and start to keep track of the "parent" frame by frame. Then, add the parent displacement (velocity changes) to the actor. It won't be pretty, but i think it could work. The issue here is that momentum might be affected in unexpected ways.
     
    hodgepodge2022 and Vaeer like this.
  37. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Since we are talking about moving platforms, @rojbarak i didn't forget about you. Those issues you reported back then have been ̶t̶h̶e̶ ̶s̶o̶u̶r̶c̶e̶ ̶o̶f̶ ̶m̶y̶ ̶s̶u̶f̶f̶e̶r̶i̶n̶g̶ ̶f̶o̶r̶ ̶t̶h̶e̶ ̶l̶a̶s̶t̶ ̶t̶h̶r̶e̶e̶ ̶m̶o̶n̶t̶h̶s̶ incredibly helpful, thank you. In addition to that, i also discovered three more problems associated with concave platforms and ground detection. Long story short, I've fixed them all:) but only v2 will get the good stuff :( (too many breaking changes).
     
  38. Broudy001

    Broudy001

    Joined:
    Feb 12, 2020
    Posts:
    72
    How is v2 coming along?
     
  39. partridge

    partridge

    Joined:
    Dec 8, 2014
    Posts:
    7
    Hi @lightbug14

    I'm trying to implement a setup where a character (based on your Demo Character 3D) has a twin that maintains the same movements, but with an offset position. The twin has the input and CharacterBrain disabled, and I have a simple Sync script set on the main character that looks at the main character's velocity and sets the velocity of the twin character (currently in FixedUpdate).

    First I tried to set the velocity direct:

    Code (CSharp):
    1. twinnedPlayerRb.velocity = thisPlayerRb.velocity;
    2. //twinPlayerRb.angularVelocity = thisPlayerRb.angularVelocity;
    3. twinnedPlayerCharacterActor.Rotation = transform.rotation;
    Worked ok-ish, the animation and movements are smooth, but the twin seems to leak speed when I move around with the main character, and over time loses the strict offset position I'd like it to stay in. The angular velocity didn't work, but I used CharacterActor.Rotation and this works well for the rotation part.

    I then tried using CharacterActor.RigidbodyComponent.Move(Vector3 position):

    Code (CSharp):
    1. twinnedPlayerCharacterActor.RigidbodyComponent.Move(transform.position + positionOffset)
    But as you can see from the following clip, the sync is very jittery:


    Is there a good method of getting the behaviour I want? I'm assuming FixedUpdate was the correct place to put the syncing (tried Update, but this was even more jittery).

    Thanks, Chris.
     
  40. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hello @partridge

    Yes, since your dealing with velocity, using FixedUpdate is the best place for this.

    My guess is that the twin copies the velocity just fine, however, since the "movement" action is <0,0> (brain disabled) NormalMovement is trying to decelerate the body (the execution order is important here).
    If you are applying your script after NormalMovement's FixedUpdate, then everything should work (i think). If not, NormalMovement will be the one handling velocity (something you don't want).

    If you want to run your script after NormalMovement (default execution order = 0), add this attribute to your monobehaviour class:
    Code (CSharp):
    1. [DefaultExecutionOrder(1)] //any value greater than 0 will do
    If you want to prevent NormalMovement from setting the velocity to a brain dead actor, go to the HandleVelocity method (NormalMovement.cs) and just do a simple check at the top:
    Code (CSharp):
    1. if(!CharacterStateController.CharacterBrain.isEnabled)
    2.       return;
    You can do the same thing to rotation as well.
     
    Last edited: Mar 1, 2022
  41. partridge

    partridge

    Joined:
    Dec 8, 2014
    Posts:
    7
    I set the execution order on the sync class as you suggested and that has definitely made a big improvement, though there seems to be an issue with animation states. Sometimes the twin is stuck on the walking animation even when not moving, and other times it is slipping into the run/boost animation (maybe exceeding a threshold since the twin will be very slightly behind the original character and so needs to catch up?).


    Also, I didn't mention this before but the twin is not doing very well when on a dynamic "ground":

    (plz ignore the news on the sound on this clip!)

    Is there some processing in NormalMovement relating to dynamic ground that is not executed because I'm setting the velocity manually in my sync script? How could I build that part back in?

    Note I tried overriding HandleVelocity in NormalMovement:

    Code (CSharp):
    1. protected override void HandleVelocity(float dt)
    2. {
    3.     if (!CharacterStateController.CharacterBrain.enabled)
    4.     {
    5.         // Debug.Log($"not handling velocity");
    6.     }
    7.     else
    8.     {
    9.         base.HandleVelocity(dt);
    10.     }
    11. }
    But this still was as jittery before, it didn't seem to solve the issue.

    Thanks for your help!
     
  42. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hello sir.

    v2 is progressing well, slow but steady:cool:. Most of the changes are structural ones, meaning that you won't get a ton of new features, although there are a few that are very important (and fixes).

    Making a character controller requires a lot of experimentation (especially when new toys arrive to the engine at the same time). So, even though only one project will be released to the public (v2), there will be 10 other branches collecting dust in my repository.

    I was going to write a big post about it, however, i think it will better to update the web page will all the changes. Twitter is too messy for this, i don't like it. That being said, If you have a specific question, please ask.

    Soon i will be posting a link to a survey that i'm making. Needless to say it will help tremendously with v2 development and future releases as well. I might post it on reddit as well.
     
    Last edited: Mar 3, 2022
    jasonMcintosh, FeastSC2 and Broudy001 like this.
  43. abandon_games

    abandon_games

    Joined:
    Sep 1, 2017
    Posts:
    38
    hi lightbug!

    hopefully a quick question about loading scenes with a first person player character at different positions and rotations, consider:
    • I have a scene with two potential spawn points for the player's first person character
    • each spawn point is a transform that specifies the desired position and rotation for the player's first person character when the scene loads with them at that spawn point
    • the position and rotation of the desired spawn point is applied to the player's first person character immediately after a
      yield return SceneManager.LoadSceneAsync(...)
      call
    what's the appropriate way of accomplishing this? I got it working by setting the position on the player character's rigidbody and setting the rotation on the player character's transform, i.e.:

    Code (CSharp):
    1. yield return SceneManager.LoadSceneAsync(...)
    2.  
    3. CharacterActor.RigidbodyComponent.Position = desiredPosition;
    4. CharacterActor.transform.rotation = desiredRotation;
    ...but it seems a bit odd/unintuitive to be specifying position on the rigidbody and rotation on the transform, so I was wondering if there's a better way of accomplishing this?

    thanks!
     
  44. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    Hey Juan, thanks the response, doing good :)

    Ah, I'm really looking forward to V2 then!
    I'll check out the V2 Demo later this week and tell you what I think.

    Would you care to go through these other 2 points? Is it something you could consider for future versions?

     
    lightbug14 likes this.
  45. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi @partridge,
    Really sorry for the delay! o_O
    Have you tried using the same actions source for both characters? In other words, duplicate the original character and do nothing to the clone. Sorry that i didn't mention this at first, it is probably one of the most commonly used fixes (hopefully) for this.

    The solution you originally proposed kinda works since you are dealing ONLY with velocity. However, that is clearly not enough since the character responds to other properties as well such as position, rotation, size, etc.

    Hi,
    The actor (rigidbody and transform) only cares about the rigidbody properties (Position and Rotation). Even the transform will get the body position/rotation values from the rigidbody right before going into the physics simulation (during FixedUpdate).
    Modifying transform data is not recommend.

    I assume you have encountered some issues with this and that's why you ended up using those specific lines (?). In any case, see if modifying the actor Position and Rotation properties does the trick. CharacterActor.Position/Rotation will automatically ignore interpolation (important when dealing with Transform data), so both rigidbody and transform will be modified at the same time.
     
  46. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi,
    Yes of course. In fact, both of these features are very relevant now to me since i am revisiting actions and implementing some high level stuff for v2.

    The "great control vs cool physics" war. The idea is pretty cool and will probably help with the implementation code a lot.
    I implemented something like that for a user (in fact, he was the first CCP user:)). In summary, the Actor was able to handle physics stuff normally like it always do, but at the same time it was capable of handling multiple "external velocities" based on animation curves (it was a little bit tricky). These velocities were not "readable" outside of the actor physics update at all (which is very important for this).
    For instance, you could call:
    Code (CSharp):
    1. CharacterActor.AddExternalVelocity(initialVelocity, Curve.Linear, duration)
    Pro: Your code will only handle input velocities based on Rigidbody.velocity.
    Con: You must set this "environmental influence" for all the possible sources you may have in your scene.

    This is why i might try to implement this the other way around, focusing on input velocities instead of external ones.

    Obviously, i would need to test this a lot before putting it in the asset.

    I've been playing a lot of Supraland Six Inches Under lately, and one of the coolest features it has (Supraland as well) is the jump pad system. This game implements two types of jump pads: red and blue ones.
    Red: The character follows a predefined path without being affected by anything. Basically, there is no way to deviate its trajectory.
    Blue: The character sets its initial velocity based on a predefined path. The jump trajectory can be affected by external forces and user inputs.

    I want to implement this, i think it will do what you want and allow some other interesting things (for AI as well).
     
    hodgepodge2022 and FeastSC2 like this.
  47. Loki18000

    Loki18000

    Joined:
    Apr 1, 2015
    Posts:
    75
    Hello,
    This may be a silly question. Can I stop the asset from editing the Animation component of GameObjects under graphics? I have a Melee weapon animated and it's giving the Object a new controller. Anyway to stop this?
     
  48. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Yes you can, go to the state (the one you want or even all of them) and disable the "override animator controller" boolean.
    upload_2022-3-28_14-2-46.png
     
    Loki18000 likes this.
  49. Loki18000

    Loki18000

    Joined:
    Apr 1, 2015
    Posts:
    75
    I have checked Override Animator Controller on Normal Movement, Dash, Ledge Hanging, and Ladder Climbing but it still adding in Animator Link script. Getting a lot of Warnings about missing parameters. Wouldn't matter to much but the animation won't run. Is there something else I have to disable?

    Thank you for your help.
     
  50. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    I forgot to mention that the override animator controller will only assign the controller to the animator. This can be useful if you want to handle one big animator for everything (many people do).
    The best way to handle this is by modifying the state your using. For example, in NormalMovement.cs i'm using PreCharacterSimulation and PostCharacterSimulation methods exclusively to update animator paraemters. You could either:
    A) Delete those lines if you don't need them... or
    B) Add a new public boolean called (for example) "UpdateAnimatorParameters" and use it with an if statement inside the state:
    Code (CSharp):
    1.        public bool UpdateAnimatorParameters = true;
    2. //...
    3.         public override void PreCharacterSimulation(float dt)
    4.         {
    5.             if (!UpdateAnimatorParameters)
    6.                 return;
    7.  
    8.             //...
    9.         }
    10.  
    11.         public override void PostCharacterSimulation(float dt)
    12.         {
    13.            
    14.              if (!UpdateAnimatorParameters)
    15.                 return;
    16.  
    17.             //...
    18.  
    19.         }
     
    hodgepodge2022 likes this.