Search Unity

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 there, thanks!
    You can still use OnTriggerXXX with your character (assuming you are using some random script).
    The controller use that internally, collecting all triggers (and contacts), calculating some stuff, and putting them in a list called "Triggers".
    So, you can get those triggers by doing the following:
    Code (CSharp):
    1. foreach( var trigger in CharacterActor.Triggers )
    2. {        
    3.         if( trigger.firstContact )
    4.         {
    5.                //OnTriggerEnter
    6.         }
    7.        
    8. }
    That event you mentioned was just a "helper", basically its job was to hook up the OnTriggerXXX message with your own method, since that was the only way to store those triggers.
    I would recommend you to use that list, it will give you more information about the trigger (or contact).

    Hi, I'm not sure what's happening there. Are you sure both AI characters have your character as the target? The follow behaviour just calculates the path based on that target. Also, you need to have both AI characters on a nav mesh (this AIBehaviour requires one).

    Oh, that makes sense.
    Disabling the CharacterActor component (in 1.1.2) will do the following (look for OnEnable in CharacterActor.cs):
    Code (CSharp):
    1.     protected virtual void OnEnable()
    2.     {      
    3.         // Add this actor to the scene controller list
    4.         SceneController.Instance.AddActor( this );    
    5.  
    6.         RigidbodyComponent.Constraints = initialRigidbodyConstraints;
    7.  
    8.     }
    9.  
    10.     protected virtual void OnDisable()
    11.     {
    12.         // Remove this actor from the scene controller list
    13.         SceneController.Instance.RemoveActor( this );
    14.        
    15.         RigidbodyComponent.Constraints = RigidbodyConstraints.FreezeAll;
    16.     }
    17.  
    In this case this is bad, since you want to change the position. This is something i fixed already for the next version, basically you enable/disable manually the component you want (RigidbodyComponent, ColliderComponent, etc) without me assuming you want to freeze or not your character.

    So, you can comment out those "RigidbodyComponent.Constraints = ..." and that should do the trick.

    Regarding the ragdolls, you can disable/enable the capcule collider by calling ColliderComponent from CharacterActor. In the next version, any collider inside the hierarchy will be ignored automatically by the capsule collider (also i added some ragdolls-related API).
     
    nobluff67 likes this.
  2. gentlegorilla

    gentlegorilla

    Joined:
    Jun 18, 2019
    Posts:
    19
    BTW: Loving CCP

    I was wondering how some1 would code a pushback in situations (like taking damage), so that the character jumps (but not teleports) to a position behind him (considering ground).

    Where to get started with it? Asking for a friend ;)
     
  3. gentlegorilla

    gentlegorilla

    Joined:
    Jun 18, 2019
    Posts:
    19
    Yes, both are placed on a navmesh. I set the follow target to my character on all prefab instances, as the prefab is ofc not saving scene GO references.

    It seems to not be caused by the AIFollowBehaviour not working. The Character is just doing nothing. Because, if I place it a bit above the navmesh surface, the initial prefab is dropping down on the nav mesh surface starting to follow, while the second one is staying in the air.

    Debugging into the AIFollowBehaviour and CharacterAIBehaviour:
    Both times follow target is set and navMeshPath is on pathComplete after CalculatePath(). SetMovementAction is also setting values to : characterActions.movement.value = inputXZ;

    However, the Velocity of the CharacterActor is only in the first case != Vector3.zero


    What is weird, but potentially hints to a spot. If I disable the initial GO, the second GO is starting to work properly. It seems like only one Instance of the prefab can work at the same time!
    If both are active, only the one that is above the other in the GO hierarchy is working.
    If I add create an additional prefab wit AISequenceBehaviour (compared to AIFollow), it is also not working, except it is the only or upmost instance in hierarchy.
     
    Last edited: Sep 25, 2020
  4. Ruchir

    Ruchir

    Joined:
    May 26, 2015
    Posts:
    934
    Is there a page in documentation or elsewhere where the order in which all the functions are called is listed, I am having a tough time following all the callbacks manually, It could really help having an reference to look at
     
  5. gentlegorilla

    gentlegorilla

    Joined:
    Jun 18, 2019
    Posts:
    19
    I probably found the cause:
    I add my prefabs to an empty gameObject to have a clean hierarchy view in unity. During debugging I noticed a Log output "Warning: GameObject prefab has the state NormalMovement repeated in hierarchy"
    This causes to not add the state to the states array. Why is this? Because the states array is filled by

    Code (CSharp):
    1. CharacterState[] statesArray = transform.root.GetComponentsInChildren<CharacterState>();
    note the .root
    This is going up till it finds my empty gameObject and then looks for the CharacterState components, guess what, it finds 2, as both prefab / AI instances are below the empty one.

    Working if instances are on root level. I found also other code parts where it is assumed, that the GameObject is on the root level (e.g. CharacterActor:935)
     
    Last edited: Sep 29, 2020
  6. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, that's what the API reference is for, you can find that inside the Documentation folder.

    Hi, it seems like you are right, the issue is caused by having multiples character actors inside a root object. This issue never happened to me before because normally you would have a character + camera prefab under a "root" object.
    Let me see what i can do.
     
  7. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi @noomieware , i think i fixed the problem :). Thanks for letting me know about that (and also for finding the cause).
    I'm gonna upload a fix today (there was too much code involved).
     
  8. gentlegorilla

    gentlegorilla

    Joined:
    Jun 18, 2019
    Posts:
    19
    Awesome, that was fast!
    For the playable character, I assume, that it is common to have it just below root. But in levels, which have a few dozen enemies, that will probably clutter the hierarchy a lot.
    Will be happy to test it.
     
  9. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Version 1.1.3 is out now, fix update!
    https://lightbug14.github.io/lightbug-web/character-controller-pro/releases.html

    Also the API reference is now online.

    ────────────────────────────────────────
    ( :eek: Extra info - Not important )

    To fix the issue mentioned by @noomieware, i made a simple GetComponentInBranch method that basically gets components in children (Unity's method) based on a "branch root" component.
    Problem: All CharacterActor components were choosing the first character in the hierarchy as "the" character.

    Of course you can fix this by manually choosing your character actor, and then get all the children involved. However, i like to do it in code.

    This is the method (in case you want to use it elsewhere):

    Code (CSharp):
    1. public static T2 GetComponentInBranch< T1 , T2 >( this Component callerComponent , bool includeInactive = true ) where T1 : Component where T2 : Component
    2. {
    3.     T1[] rootComponents = callerComponent.transform.root.GetComponentsInChildren<T1>( includeInactive );
    4.  
    5.     if( rootComponents.Length == 0 )
    6.     {
    7.         Debug.LogWarning( $"Root component: No objects found with { typeof(T1).Name } component" );
    8.         return null;
    9.     }
    10.  
    11.     for( int i = 0 ; i < rootComponents.Length ; i++ )
    12.     {
    13.         T1 rootComponent = rootComponents[i];
    14.  
    15.         if( !callerComponent.transform.IsChildOf( rootComponent.transform ) && !rootComponent.transform.IsChildOf( callerComponent.transform ))
    16.            continue;
    17.  
    18.         T2 targetComponent = rootComponent.GetComponentInChildren<T2>( includeInactive );
    19.  
    20.         if( targetComponent == null )
    21.             continue;
    22.  
    23.         return targetComponent;
    24.  
    25.     }
    26.  
    27.     return null;
    28.  
    29. }


    "Root" object has a Root component
    "Target" object has a Target component


    I don't know if there is a built-in method for this.
     
    Last edited: Oct 2, 2020
    Broudy001 likes this.
  10. trueh

    trueh

    Joined:
    Nov 14, 2013
    Posts:
    74
    Hi:

    Any chance to extend the Brain/CharacterActions framework so I can provide my own CharacterActions set without modifying the CharacterActions class? It is a little bit annoying to have to modify the CharacterActions class. If I remove any of the default actions the demo stops compiling. I do not want to remove the demo as I am learning the asset and I can use it as a reference.

    I was thinking on something like converting the CharacterActions struct into a class implementing an ICharacterActions interface, and make the CharacterActions property in CharacterBrain virtual. This way I would be able to extend CharacterBrain to provide my own ICharacterActions implementation. Obviously, this would also affect the Character Actions editor, which should be able to write a class implementing ICharacterActions on a chosen folder instead of overwriting the original class.
     
  11. filod

    filod

    Joined:
    Oct 3, 2015
    Posts:
    224
    about CCP

    i'd like to report a unexpected behavior when i dealt with unstable ground sliding velcoity:

    ```
    CharacterActor.Velocity += slidingDirection * verticalMovementParameters.GravityMagnitude * dt;
    ```

    from code side, CharacterActor.VerticalVelocity would always set to zero in every update when grounded(even unstable), and CharacterActor.PlanarVelocity is the real factor when character slides down, so my question is:

    1. bigger slope ,but slower drop velocity
    2. when i jump from a slope, UnstableJumpMode do nothing
    3. when i jump from a slope, all slope PlanarVelocity would keep it is (it means an unexpected horizontal boost in the air)

    this blurs my understanding about PlanarVelocity & VerticalVelocity, can you give some advices?

    -----------
    update: during experimenting with CCP 2d found some issues:

    1. cc seems causing penetration quite often.
    2. one way platform not working unless change code to this `CharacterActor.Position -= CharacterActor.Up * (CharacterActor.DefaultBodySize.y / 2 + 0.01f)`
     
    Last edited: Oct 20, 2020
  12. tvdmag

    tvdmag

    Joined:
    May 4, 2014
    Posts:
    2
    Sorry I know this is probably a dumb question, but how do you do a simple destroy on collision or trigger without the character controller freaking out.
     
  13. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    You need to work on your documentation, its incredibly weak. A setup video would help immensely. I hesitate to rate your product at this stage as it would be unfair as I cant use it if I cant find decent instructions.

    At this stage of me using the product, it doesn't even add the Collider and/or Rigidbody as per your instructions.
     
    Ruchir likes this.
  14. Ceraph

    Ceraph

    Joined:
    May 16, 2013
    Posts:
    19
    Hello,

    This asset has been a great starting point for me, it's a very robust system!

    I am running into an issue when running my game at low frame rates where the character moves extremely slowly or sometimes not at all. I am trying to optimize my game as much as possible but it's required to run on older Chromebooks so I'm never really going to achieve a smooth 60 fps across all devices.

    I've been doing a lot of research into this and I think I've narrowed down the cause, though I'm not really sure how to go about fixing it. All of your Character Actors update from FixedUpdate so they update in time with the physics step, which is definitely a good thing. The problem is that you're using Time.deltaTime to smooth out the movement vectors in NormalMovement.cs:

    Code (CSharp):
    1. planarVelocity = Vector3.MoveTowards( planarVelocity , targetGroundVelocity , influencedControl * dt );
    When using Time.deltaTime inside FixedUpdate, it will always return a constant value regardless of the frame rate of your game. In my case, it returns 0.02 every time regardless of if the game is running at 120fps or 30fps. As near as I can tell, multiplying the input values by Time.deltaTime inside FixedUpdate will not yield the intended result, where the character moves at a consistent units / second regardless of the frame rate. It essentially just ends up multiplying by a constant number, which doesn't really accomplish anything.

    I'm going to keep looking for a solution, but I thought I would share my findings here in case anyone else who is more familiar with this codebase has any ideas on how to solve this issue.

    For the sake of completeness, I tried the following already:

    I tried changing Simulate() in SceneController.cs to run in Update instead of FixedUpdate. As expected, this caused the entire system to go haywire and definitely didn't work

    I tried saving Time.deltaTime inside of a regular Update loop that then gets passed to Simulate() inside of FixedUpdate. This resulted in the gravity feeling a lot heavier and ultimately did not solve the issue of the character slowing to a crawl at low frame rate.

    Any help anyone could provide would be greatly appreciated!

    Thanks,
    Ceraph
     
  15. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, you have an entire section dedicated to this. This is the first "tutorial" (if you want):
    https://lightbug14.gitbook.io/ccp/how-to.../core/the-most-basic-character#creating-the-character

    First "info" tab:
    "There is no need to add a Collider and/or Rigidbody to the object. The CharacterBody and CharacterActor will do this for you."

    There was a "Quick Start" guide before, but for some reason that was causing even more confusion, people was doing everything exactly like the guide described (which is good), the problem came when they wanted to change something. Option A consisted in reading the fundamentals section (too heavy and boring), Option B consisted in doing the "Quick Start" guide (Too simple). So, instead of giving the recipe i ended up describing the ingredients a bit more.

    I agree, a video is far more appealing, also i really want to upload some tutorials, a simple but effective trailer, etc. I'll do this for 2.0.0.

    The same way you do it with any other object. To give you a proper answer i would need you to define the "freaking out" part, Error messages? Warnings? Erratic movements? CCP version? Your code? etc.

    The controller gives you the contacts directly, you don't need to do OnCollisionEnter (if your code is running from the character side).

    Very good argument, although you are missing one thing. Let's say update takes 0.1 second, you are saying that the next FU will take only 0.02 and that's not true, that would definitely not compensate the last update call.
    Luckily there is already a fix for this built-in inside Unity, and that's the "Maximum Allowed Timestep" (Time settings). In this case U = 0.1s, FU = 0.02s, so the physics engine will call FU 5 times in order to compensate that 0.1 sec Update. In summary, that MoveTowards will happen 5 times.

    Even though we all know FixedUpdate gives a constant delta time, it is always recommended to work with the right units. The engine should compensate those missing FixedUpdate calls, and we should always make code that works regardless of the update method (Update, LateUpdate, FixedUpdate, etc).
    If you bring an "Update delta time" into the mix it will definitely broke something. Coming back to the example, that will make that FixedUpdate to use 5 times that 0.1s deltaTime (instead of 1). Maybe you can get away with this by setting a Maximum Allowed Timestep = 0.02 (fixedTimeStep), but that would be too specific (which isn't good).

    Coming back to the main issue, maybe this is a Maximum Allowed Timestep problem. Try to increase this value,. Be very careful, a high value will "allow" more FU calls (low framerate), but this also will make the Update cycle longer (positive feedback).

    Yeah, that would definitely freak out the system.
    In general, it's always recommend to use FixedUpdate for every gameplay-related behaviour, and Update/LateUpdate for every Visual-related behaviour. Unity does recommend this as well (indirectly) since they disabled the autoSync functionality by default, so now it is you and the physics engine (and that requires to better understand how everything works, especially physics queries + interpolation). For previous versions (< 2017.3 i think) this autoSync thing was fixing some very important issues under the hood (costing you some performance).

    ──────────────────────────────────────────
    Some Updates:
    Version 1.2.0 is 99.5% ready. This version fix some of those issues @filod mentioned before:
    - Bye bye SceneController
    - Kinematic + Dynamic platforms support
    - Sliding works perfectly fine now. The controller now works based on the IsStable property (instead of the IsGrounded property).
    - One way platforms (not confirmed yet, but it seems to be working just fine).


    Just know that some of issues mentioned here (and by email as well) are already fixed. Unfortunately i can't release them now because that would break too much to be considered a minor/feature update.
     
    Last edited: Nov 23, 2020
    flashframe and filod like this.
  16. filod

    filod

    Joined:
    Oct 3, 2015
    Posts:
    224
    I have become more interested in what's new in 2.0.0 :D
     
  17. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    This looks like a really interesting controller. I tried taking a look at Kinematic Character Controller and as cool as it seemed, there was a ton of setting it up to get it to work in any visual scripting tool. I use Unity's Character Controller which is great as I can write the whole backend and just throw a vector into Move() (not SimpleMove) and it works well. I do think I'd like to have the ability to easily make my character walk on movable platforms and such, so I was wondering if this is similarly simple to set-up?

    Once again, I'll state that I have no issues with the built-in Character Controller as I do all my movement calculations myself and send it all into Move(), and I'm looking for something as simple to implement but better.

    Another question I have is about edge/ledge sliding, is it possible to have it so the player is walking against an edge whilst holding a 'walk' key, the character controller could slide along the edge/ledge (as long as it's a certain height) without falling? The original Tomb Raider games used to do this, but it's hard to do with the built-in charcatercontroller without firing lots of raycasts and using ProjectOnPlane. It would also be useful to have as a default for enemies like the original Doom games did, the monsters would just slide along edges as they followed you. Here's an example of legde/edge walking on Tomb Raider (sorry about the black at the start for a few seconds): https://i.imgur.com/I0s2eok.mp4 And here's an example of Doom's monsters, they look like they walk away from the edge a bit too, but I'm primarily looking to have monsters slide along the edge as they're tracking the player: https://i.imgur.com/NX3vhhv.mp4

    I've done a similar thing with Unity's CharacterController using a bunch of raycasts and ProjectOnPlane, but I've never gotten it really perfect and I'd love to have the functionality built-in to controller.
     
    Last edited: Nov 25, 2020
  18. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi @Zebbi, this controller works in a similar way to the Unity's CC. You have the CharacterActor which is the main component of the entire asset. By itself this component does nothing, basically it reads some internal values and do some processes inside (handle rotation, handle size, handle position, etc). All those internal values must be provided from the outside (the logic/gameplay of the character).

    Regarding the Move function, the CC has a Velocity field (same as rigidbody.velocity):
    So, this:
    Code (CSharp):
    1. // "Move" character to position "P"
    2. characterController.Move( P );
    3.  
    is equivalent to this:
    Code (CSharp):
    1. // "Move"character to position "P"
    2. characterActor.Velocity = (P - characterActor.Position) / dt
    You also have a "Move" function available in the 'RigidbodyComponent' component (CharacterActor) which does this exact same thing for you.

    Code (CSharp):
    1. public void Move( Vector3 position )
    2.     {
    3.         if( IsKinematic )
    4.             Interpolate( position );
    5.         else  
    6.             Velocity = ( position - Position ) / Time.deltaTime;
    7.     }
    Code (CSharp):
    1. // "Move"character to position "P"
    2. characterActor.RigidbodyComponent.Move( P );

    Sorry that's not implementated in the controller.
     
    Zebbi likes this.
  19. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    Thanks, that's really helpful!

    Actually, since the controller is nicely low-level, is there any ledge information I could grab from it to control the player? I'm not sure if the controller has any information about how steep the preceeding drop is that I could use to make the player edge-slide?

    Edit: wow, I just purchased and can not believe how much cool stuff this controller can do! I wasn’t expecting all of this functionality out of the box, and I usually see or feel some sort of wonkiness whenever I’ve tried a new controllers but this is so far flawless, really impressive!!
     
    Last edited: Nov 26, 2020
    lightbug14 likes this.
  20. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Thank you @Zebbi! I'm glad you like it :)

    Unfortunately in 1.1.X there is no such thing, but this is something i've added to version 2.0.0, basically if the "IsOnEdge" property is true then a ray is fired downwards (over the edge of course), giving you that info. This becomes useful if you combine it with the animator (e.g "close to the edge" animation).
     
    Zebbi likes this.
  21. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    That would definitely be cool! The method I used was to fire a ray down to get the normal beneath the player, then forwards in the direction of the player, then back towards the player (but down a bit) to get the normal of the edge, then i had to do this 3 other times to determine any intersecting normals either side. I then combined this with ProjectOnPlane to force the player's vector3 to only move against the edge normals which worked pretty well but I'd love to have a professional give it a proper attempt, haha!

    Thanks again!
     
  22. bluevariant_dev

    bluevariant_dev

    Joined:
    Feb 5, 2020
    Posts:
    3
    upload_2020-11-29_18-30-55.png
    How can I change my pivot of my character?
     
  23. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, How do you want to use that pivot? Because if it will be used for design purposes (moving the character inside the editor, or things like that) then you can put the character inside an empty object (obviously this is not the same as changing the pivot but it'll do). Changing the pivot is not posible atm, sorry, everything is calculated based on the "foot position" (feet position might be more appropiate, it's called foot because in 2D you see only one foot).
    https://lightbug14.gitbook.io/ccp/fundamentals/untitled/characterbody#foot-position

    For example:
    Code (CSharp):
    1. public Vector3 GetBottomCenter( Vector3 position , float bottomOffset = 0f )
    2. {
    3.     return position + Up * ( BodySize.x / 2f + bottomOffset );
    4. }
    Have you considered to use the available methods inside CharacterActor (GetCenter, GetTop, GetTopCenter, etc) instead of changing the pivot? Again, this depends on how do you want to use that pivot.


    Regards.
     
  24. squallfgang

    squallfgang

    Joined:
    Sep 13, 2016
    Posts:
    21
    notStayingOnTop.gif
    Hey great asset so far!

    I would like to achieve that the character can stay on top of a rotating dynamic rigidbody (see gif) But he doesn't stay on top. Is there a way to fix this?
    I used your Propeller (2) from demo scene just made the block wider and used different add torque value.
     
  25. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi @squallfgang, Thanks!
    Unfortunately in 1.1.5 that is not possible, only Kinematic platforms are supported. In 1.2.0 (almost there) this can be achieved with any type of rigidbody:
    Dprop.gif
     
    squallfgang and HellGate94 like this.
  26. HellGate94

    HellGate94

    Joined:
    Sep 21, 2017
    Posts:
    132
    thats great news! that means that i can finally switch to your character controller instead of my prototype controller. i assume it can also handle rotation of dynamic rigidbodys?
     
  27. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Yes, it supports rotation as well:
     
    squallfgang and HellGate94 like this.
  28. bluevariant_dev

    bluevariant_dev

    Joined:
    Feb 5, 2020
    Posts:
    3
    Thanks, but I want to rotate my character while diving.
    Can you help me, F for any ideas. I'll try it.
     
    Last edited: Dec 9, 2020
  29. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    I have a weirdly specific question...
    So what I want to do is I want to map character movement to the X and Y Axis. So any movement vector should be either on X or on Y, no angles in between.
    Now looking at the movement script, it feels like it will be impossible to edit, so I was wondering if I would just insert some code earlier, where the gamepad input is taken!
    Any tips on how you would go about doing this?

    Edit: Managed to dig through the code and get it to work!
     
    Last edited: Dec 10, 2020
  30. SilverStorm

    SilverStorm

    Joined:
    Aug 25, 2011
    Posts:
    712
    Hey lightbug I have just put the prefab for the camera and controller into my scene and things work good so far but the inputs are reversed and I'm not sure if this is intended behavior. In other words the character only takes inputs correctly when his Y rotation transform is 180 degrees and when I rotate him to 0 he just goes in the opposite input direction.

    I've tried putting a parent object onto him and doing some rotation hack but nope.
    To fix this I ticked the invert toggle in the input manager for the Movement X and Y
    and it's good to go now but I want to make sure this won't break anything with your system?
     
  31. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, ok that makes sense. I was doing that exact same thing, but in my case i was simulating this behaviour (swimming state) by using a sphere body and modifying the graphics object (i know, not the same thing).

    Unlocking rotation (removing the constraint):
    First of all, In order to rotate the character you need to change its vertical direction.
    Rotation = yaw + pitch + roll ... in CCP only yaw is allowed (pitch and roll are ignored). You can choose any rotation (quaternion) you want, however, only yaw will be valid. In summary, we need to "unlock rotation" first.

    In 1.1.X the vertical direction acts like a constraint. This constraint was necessary especially for root motion since some clips added some degree of pitch/roll (which is bad for stable movement).
    In 1.2.0 you can enable/disable this setting and rotate the character. Doing this in 1.1.5 is really simple, go to CharacterActor.cs, then HandleRotation method:
    Code (CSharp):
    1. public bool constraintRotation = true;
    2.  
    3. void HandleRotation( float dt )
    4. {  
    5.     if( !constraintRotation )
    6.         return;
    7.      
    8.     ...

    You can still use vertical direction to achieve the same effect, although rotation is much more intuitive.

    Rotating the character using some random pivot/axis:
    Also, changing the pivot in code is relatively simple as well, have in mind that my NormalMovement state handles yaw rotation based on the character velocity, this will definitely conflict with what you are trying to do. You can try something like this:
    1. Put the character in the air, and disable "useGravity".
    2. Disable "constraintRotation"
    3. Go to NormalMovement.cs --> HandleRotation, then modify the code:
    Code (CSharp):
    1. protected virtual void HandleRotation( float dt)
    2.     {  
    3.         // ignore yaw motion ... for now
    4.         // HandleLookingDirection( dt );    
    5.  
    6.         if( Input.GetKey( KeyCode.Y ) )
    7.         {
    8.             CharacterActor.Rotation = Quaternion.AngleAxis( 50f * dt , CharacterActor.Right ) * CharacterActor.Rotation;
    9.             CharacterActor.Position = CustomUtilities.RotatePointAround( CharacterActor.Position , CharacterActor.Center , 50f * dt , CharacterActor.Right );
    10.         }        
    11.     }
    This will make the character rotate 50 degrees/sec if you press the Y key (just an example). The center is the pivot, right is the axis (pitch rotation). Depending on what you want to achieve you will need to change the axis, the angular velocity, or whatever.


    i'll try to make this less tedious.

    Hi, interesting, One way you can detect if a X + Y are active is by doing:
    Code (CSharp):
    1. bool diagonal = false;
    2.  
    3. if( CharacterActions.movement.Detected )
    4.        diagonal = CharacterActions.movement.value.x * CharacterActions.movement.value.y != 0f ;
    5.                
    Once you have that you can decide what you want to do with the actual movement (velocity), for example you can keep the old velocity (not modifying the current one) or you can make it zero.


    Hi, I'm not sure what's happening there, i guess that by "Y rotation" you mean yaw rotation (for example moving the mouse horizontally in a first person shooter). What type of movement reference are you using? because what you describe sounds like a "world" movement reference type.
     
    bluevariant_dev likes this.
  32. cachetgames

    cachetgames

    Joined:
    Oct 18, 2019
    Posts:
    15
    Hi - I know I am doing something pretty stupid, but can't figure this out. I am trying to integrate CCP to use AStar Pathfinding Project for AI navigation/pathfinding. The thing is, AStar requires (I think) that the ground be in a specific layer (I am using "Ground"). My actual terrain is full of hills and troughs, and when I have the terrain layer set to Default, CCP works perfectly, and my AI's follow the terrain contours, but pathfinding does not work. However, when I set the layer to Ground to get pathfinding to work, the AI's stop working correctly. In fact, if the terrain is in any layer other than Default, the AI's don't work correctly. Is there a fix here?
     
  33. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, you probably need to add that "Ground" layer to the "tags and layers" static obstacles layermask. This is a separate asset inside CCP's Demo folder (Demo/Data/Tags and Layers). This asset defines what is ground, static obstacles, dynamic platforms, etc.
    (https://lightbug14.gitbook.io/ccp/how-to.../core/the-most-basic-character#3-add-the-characteractor)
     
  34. Ksanone

    Ksanone

    Joined:
    Feb 7, 2015
    Posts:
    41
    Hi, thanks for the product. I have two questions -
    1) How to assign which character action asset is being used by the character brain
    eg one for enemy actions that enemy AI use
    one for player
    or do we just make one big list that all character actors share?

    2) What is the best way to organise the hierarchy to work with Animation Events?
    eg to detect that an animation has finished or is at the point when a damage method should be called
    I have tried
    - animation event helper script that calls method on state - but needs a link to be made for each action
    - put the character state controller and states on the same game object with animator - issue with this is the character rotates with the camera if using camera as external movement reference

    Thanks for any info.
     
  35. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    Hey again!
    I've been making lots of adjustments with ease, but now I've hit a dead end.
    I'm trying to exchange the default Avatar with a different character mesh, but the animation system is really killing my head.
    Is there any comprehensive information on how to get a different character model integrated into your state system?
    Edit: I've literally tried for hours now, zero progress. This is a nightmare.
     
    Last edited: Dec 15, 2020
  36. joshuablazer

    joshuablazer

    Joined:
    Jul 25, 2018
    Posts:
    1
    Hi Carmofin,

    So I'm also working through this. I had success in adding another mesh using the same controller as the one in the demo scene. I just added it to the heirarchy and and attached the CCP character NormalMovement controller. This works. But it looks like in the package, all the animations in the demo CCP character are baked into the FBX, so I'm planning to restructure the character a bit to have them as individual animation files that can be easily replaced. Hope this is a helpful strategy. It will take some rebuilding of the animation controller though. Juan (lightbug) if you read this, I think it would be helpful to have the animations as separate files rather than in the fbx. It would make replacing them with custom animations much easier for some, particularly if you're wanting to grab them off Mixamo or similar.
     

    Attached Files:

  37. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, careful with the head!

    Avatars, humanoids, animators, rigs, etc. are not part of CCP, that's vanilla Unity stuff. So, you don't need to adapt anything (at least not in special way).
    The process is simple:
    1. the state tells the animator to update a parameter (look at the "Animation" header)
    2. The parameter is updated (if the current runtime animator controller has it)
    3 The node/transition is updated and plays some animation.

    Look if the problem is in 1,2 and/or 3. Take a look at each state, most of them expose some animation parameters. If you decide to use one of the demo states (e.g NormalMovement) please make sure those names match with your parameters (runtime animator controller). Finally, if you want to mix some of my clips with some of your clips make sure your character is a Humanoid.

    CCP does one big thing for you regarding animation, if the next state (in between a transition, or at the start) has an runtime animation controller assigned (see the image) then the state machine (CharacterStateController in this case) will override the current animator controller (the one from the Animator) with the one from the state. You can choose to ignore this approach and everything should still work without problems.

    For the next version i added this just to make things a little more clear:
    Override.gif


    Hi there, you're welcome!

    Actions are represented by this CharacterActions struct, this data acts almost exactly like the actions from the new input system (in this case they use a class). The goal was to make one unified list of actions, since the difference between a playable character and a non playable character has nothing to do with the logic itself (ideally).

    I guess you want the equivalent to different "action maps" (?).
    This does not mean you must use these actions inside your own logic, for instance, you can use the new input system for the players (taking advantage of every feature of the system) and use the CharacterActions actions for the AI (AIBehaviours). Obviously, if you want to use this approach with the current states (demo) you'll need to modify them in some way.

    Actions are a big topic, i'm always open to suggestions in this regard. Version 2.0.0 is being developed with this as the main thing (the character controller part was also improved a lot, but that is already in 1.2.0)


    Where exactly is the Animator? In the camera? In any case, i never liked moving things from object A to object B (Animator). If the state is outside the character hierarchy (CharacterActor as the root) then you'll find all sort of issues.
    For the movement reference problem you can use a dummy object that follows perfectly the camera transform, and use that as the movement reference instead of the camera itself.


    Exactly, this is what you need to do. I did this with the AnimatorLink component:

    OnAnimatorMove is a Unity message called everytime root motion does something. So, i created an C# event called OnAnimatorMoveEvent.
    Code (CSharp):
    1. void OnAnimatorMove()
    2. {
    3.      
    4.         if( OnAnimatorMoveEvent != null )
    5.             OnAnimatorMoveEvent( animator.deltaPosition , animator.deltaRotation );
    6.      
    7. }
    The CharacterStateController component listens to this event (OnAnimatorIK as well):
    Code (CSharp):
    1. animatorLink.OnAnimatorMoveEvent += OnAnimatorMoveEvent;
    2. animatorLink.OnAnimatorIKEvent += OnAnimatorIK;
    From now on i take care of OnAnimatorMove wherever i want.
    (BTW this is what some developers call "extracted motion")

    You mentioned that the helper (or Link) "needs a link to be made for each action", i guess you are talking about states, not actions. To fix this you need to reference the "link" component.


    I agree 100% in fact i'm doing that right now...one ability at a time
    upload_2020-12-16_0-18-53.png

    I didn't know how to remove animations clip from Blender :oops:, sorry!

    Regarding replacing animations specifically, that shouldn't be a problem since animations will appear in the list, it doesn't matter if they come from separate FBX or one big FBX. The most obvious problem is setting up those animations with all their corresponding source takes... this is a nightmare.
     
  38. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    That was the missing piece for me... Thanks.
    My character is not humanoid, which is why I need to use my own controller. But seems like all I wrote was correct and simply not working because this setting was overriding my own.
     
  39. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    Hi!
    So I have a new question!
    Is there any way to trigger the ladder action automatically with ease?
    I really don't want to press a button!
     
  40. cachetgames

    cachetgames

    Joined:
    Oct 18, 2019
    Posts:
    15
    Thanks lightbug14 - that worked like a champ. I was confused because the scriptable object was in Demo, and of course, I am not using Demo. Now I have figured it all out (until the next problem!).
     
  41. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Well you are correct. I forgot to mention (probably you already know this): it is recommended to create your own profile asset (right clicking or duplicating the asset) outside CCP's folder, and then assigning that profile to the CharacterActor component. Keeping your data inside CCP's folder is like putting it inside the recycle bin. Even if the import process doesn't erase your files (Unity adds or modifies the files) the asset directories/hierarchy might change (this might cause all sort of problems). A very common way to update any asset is by deleting the entire forlder and re-import the whole thing.
    This applies to any modified content from CCP (tags and layer profile, character actions, materials, etc). Always make your own version just in case.

    However, In 1.2.0 this layers profile is not required anymore, the layers considered by the actor are the ones considered by the physics system (collision matrix), if you need to push rigidbodies there is a "canPushRigidbodies" option with a layerMask associated. Dynamic platforms are those who have a vanilla Rigidbody/Rigidbody2D or "RigidbodyComponent". So, everything should be much more easy to set up (you don't need to add any external asset).

    Possible? yes.
    NormalMovement will allow a transition to LadderClimbing if the interact action is started + there is at least one trigger present. Go to NormalMovement.cs, CheckEnterTransition:
    Code (CSharp):
    1. ...else if( CharacterActor.Triggers.Count != 0 )
    2. {                            
    3.  
    4.      if( CharacterActions.interact.Started )
    5.      {
    6.            CharacterStateController.EnqueueTransition<LadderClimbing>();
    7.      }
    8.          
    9. }...
    So, change it to:
    Code (CSharp):
    1. ...else if( CharacterActor.Triggers.Count != 0 )
    2. {                            
    3.  
    4.      CharacterStateController.EnqueueTransition<LadderClimbing>();
    5.    
    6.          
    7. }...
    This will do what you want, but the character will not be able to get out that state (if the trigger is still touching the character after the animation). So, go to LadderClimbing.cs and add this condition in CheckEnterTransition:
    Code (CSharp):
    1. for( int i = 0 ; i < CharacterActor.Triggers.Count ; i++ )
    2. {
    3.       Trigger trigger = CharacterActor.Triggers[i];
    4.  
    5.       Ladder ladder = ladders.GetOrRegisterValue< Transform , Ladder >( trigger.transform );
    6.  
    7.       if( ladder != null )
    8.       {
    9.            // "firstContact" similar to "OnTriggerEnter"
    10.            if( !trigger.firstContact )   //<-------------------------
    11.                return false;
    12.  
    13.        ...
    14.  
    The same i said before, this is now a modified version of a state, from now on it is yours (remember It will be replaced by my version in the next update). I'll probably add this to the LadderClimbing state, so don't worry.
     
  42. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    Thanks a lot for the tip.
    This will do fine for prototyping, but ladderclimbing needs a lot of work...
    Some feedback:
    I want to be able to jump on the full ladder, not just enter at the bottom.
    When on the ladder I want to jump off at any moment.
    I want to control the climbing speed.
     
  43. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    Have you considered a discord server for CCP? It would be a great way for users to help each other out and discuss features and implementations between ourselves.
     
    Broudy001 likes this.
  44. antonsingov

    antonsingov

    Joined:
    May 11, 2014
    Posts:
    15
    obnoxious thread title
     
  45. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    Obnoxious response.
     
    Ksanone and lightbug14 like this.
  46. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    Also I dont see any way to increase the size of the ladder!
     
  47. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Thanks for the feedback. Let me be clear, creating specifics gameplay mechanics is not my job, all those states are just demo content using the main part of the asset. My job is to improve the character controller and everything around it to allow you to create those mechanics. One day a user ask me: "How can i add a delay in order to prevent my character to jump after landing?" And that's how GroundedTime was born. Recently another user thought it would be cool to implement a timer for all the bool actions, i thought that was very cool indeed, so i added some extra timers to the BoolAction struct:
    Code (CSharp):
    1. if( CharacterActions.Jump.StartedElapsedTime > 0.1f )
    2.      //Do something if the jump was started 0.1seconds ago or more
    After implementing this i was able to improve the coyote time, i even added pre-grounded jumps (those that can be activated if you press the jump button before touching the ground). These features are fairly easy to implement by yourself, the trick is doing that without creating timers everywhere in the script. Things like that improve the whole package, not specific gameplay mechanics.

    Also, these demo states serve as examples for those who want to read the code and learn how to implement something, for example: adding acceleration, changing the body size, handling actions in code, etc. Implementing a main locomotion state (Normal Movement in this case) is a must, because without it you can't showcase your own asset. Of course implementing those mechanics is really fun and useful for others, but this is not a priority at all.

    The reason why i have included LadderClimbing and LedgeHanging states is because they are based on root motion (1.1.0). If you want to modify the climb speed you need to modify the animation clip directly, this can be achieved by 1) modifying the animated model inside Maya,3d max , blender, etc, or by 2) changing the speed inside mecanim (much more easy of course).



    That would be very interesting, let me see what i can do (i never used discord before). Thanks for the suggestion!

    I agree, maybe something like this would be better :D:
    ░┼╝║╣╞├╗Üä┼─╞╘▐▀|░▒» Character Controller Pro (1.1.5) «░┼╝║╣«╞╗Ü╞┼─╞╘▐▀|▓

     
    Last edited: Dec 20, 2020
    Broudy001 and Zebbi like this.
  48. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    116
    Hi!
    Again I've been trying to do this for hours...
    I can't find anything in the documentation either!
    How do I change the character AI on the fly from one type to another?
    I see there is a function to do it but i cant find what parameters to use anywhere!
    Also I'm trying to understand how to trigger actions. The dcumentations ays "use character actions" and then only explains how to read them... I want to trigger them!
     
    Last edited: Dec 21, 2020
  49. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hi, Do you mean this function?
    Code (CSharp):
    1. public void SetAIBehaviour( CharacterAIBehaviour aiBehaviour ) ...
    The AIBehaviour is responsible for modifying the action values in code. Sequence does this following a sequence of actions, follow does the same by determining a path, and so on. If you need to change the AI behaviour on the fly you need to call this method and pass the behaviour you want (sequence, follow, etc).

    I will add a "How to" section explaining this.
     
  50. filod

    filod

    Joined:
    Oct 3, 2015
    Posts:
    224
    do u have any suggestions about integrating CCP with behaviour designer/tree ?