Search Unity

Assets Detailed C# Third Person Controller Using Kubold Animations

Discussion in 'Works In Progress' started by PatysTy, Dec 6, 2018.

  1. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    Hello everyone,

    I am brand new to Unity so as an initial project I have decided to work on developing a third person controller using Kubold's animations with a focus on flexibility, realism, and responsiveness. I opted to build a controller off of Kubold's animation sets as they seem high quality, and his background in the industry. I have limited programming experience from my degree and some limited work experience, as a result much of this is for my own personal learning.

    I have created a basic pivot in place and walk system to figure out how the mecanim system is set up. Essentially Kubold built his mecanim system for locomotion taking in four parameters, input magnitude, direction, rotation and is right foot forward. Right now I am using the input from a gamepad, however, I am working to keep the logic of the input system and the movement system separate so that I can use the same controller for AI. Here is a showcase of what I have so far.



    I am thinking I will reprogram this system as there are some interesting results that have arisen with how I have set the system up. For example, I have two (small) issues with my system. The first is that the character will walk a small circle before walking backwards, and the second is when pivoting in place the character can overshoot his rotation making him pivot a second time to get back to zero.

    The mecanim system is set up such that the input direction is given in degrees from the input relative to the direction the character is facing. Zero degrees means the input is in the same direction as the character (forwards), ninety degrees means strafing left or right and 180 degrees means backwards. I use a lerp function to smooth out any changes in input to keep the animations from jumping around. The issue is the lerp function always smooths from zero degrees, so if the controller is pressed backwards then the lerp function smooths from zero degrees through to 180 degrees causing a little semi circle to be walked. This can be seen at 30 seconds in the video I embedded.

    Another issue I run into is the pivoting in place function checks if the difference between the camera's X-Z plane orientation and the character's is less than five degrees, if so then the rotation speed of the player is set to zero to stop rotation, however, at times the float will be changing quick enough that the difference float cycles past this range making the character rotate back and forth slightly before stopping rotation. You can see the character starting to do this as 7 seconds into the video I embedded. Again I think the solution is simply to increase the bounds, but I was wondering if the more experienced programmers had any other insights.

    Finally, I was wondering if anyone had any advice on how to effectively program smooth animation transitions and controllers. Pretty much all of the character controller tutorials I have found focus little or not at all on producing high quality animations, so I have been left to try to work much of this out on my own. Any insight and/or tutorials would be appreciate.

    Obviously I won't be able to release this character controller because of the licence of the animations, however, if I get it to a state that I feel is to a high enough quality I would look into making a set of tutorials on how to set up a smooth animation system.

    Cheers!
     
    florianalexandru05 and one_one like this.
  2. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    484
    Hey there, looks like a good start - and it's a good idea to have a test scene that covers all the scenarios your controller should be able to handle.

    Sounds like you only want your smoothing to run at smaller differences so that (your hopefully set up) transitional animations are used for those larger differences.

    This is called overshoot and one of the problems control theory tries to solve. With a simple proportional control as you use (the larger the angle difference, the larger the control signal) the issue essentially boils down to how large the tolerance is relative to the response speed (basically the opposite of the rise time, which is more commonly used in control theory.) Decrease the response speed (lerp more slowly) and you should get by with smaller tolerance bounds. But this of course makes the controller less responsive. If you increase the bounds and keep the response speed, your steady state error will increase, making your controller less granular. On a PC game with only keyboard controls this might be a tolerable scenario. In the end, it's mostly an act of balancing and trying out what works for your game.

    If you find that you need a smaller steady state error but also a high response speed you might want to look at PID controllers.

    Again - PID control is a good way to smooth signals. Other than that - it's simply a process that involves a lot of fiddling and which is not necessarily a hard science. There's often different stakeholders in that process as well - game designers will often want super-responsive controllers whereas animators would often prefer controllers with more 'weight' because these tend to look more natural.
    And quality animations are of course a key ingredient to having great looking and responsive locomotion. However, usually animations and writing the controller is tackled by two different people, which is probably why they're seldomly covered in the same tutorial. But if you're just prototyping and/or learning you could try your hand at procedural animation?
     
    PatysTy likes this.
  3. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    Thanks for the detailed reply! There's a lot in there that I will look into!

    I agree, right now I am focusing on just flat ground, eventually I would like to include uneven ground, steps, etc but will wait until I am happy with the flat ground results!

    That is true, this comment helps a lot since I initially took the naive approach of smoothing everything equally ignoring angular differences and states, I'll put some thought into how to take into account these differences without over-complicating the code. I am relatively new to programming, but I have found over-writing code can lead to many unintended side effects.

    I should've figured there would be a whole realm of study on this! My school background is in physics, and in computational physics we focused a great deal on numerical analysis but never much considered systems analysis, it is certainly one of my weak points. It didn't even occur to me to damp the signal, something I'll look in to.

    Thanks for the link to the video, I have looked at procedural animation and feel I may want to try and blend the two, I'll have to do some experimentation. I also found some video on motion matching which I am intrigued by and may look into. Seems an interesting system could be built by mixing motion matching with standard FSM animations.

    I was in the process of re-writing the walking system, but think I will start over again after doing some reading on PID systems and see if I think I want to try to implement one, or if I would prefer to work with tuning simpler systems.

    Cheers!
     
  4. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    484
    That's generally a good idea - make sure your system works well for your main use case and then move on to edge cases.

    That's perfectly fine - it's usually preferable to take an iterative approach with programming and add on further features as they are needed - rather than trying to engineer everything in from the start. However, as a general note for the future - at some point you will need to look into software architecture to make sure your code supports continuous editing or else it will look into spaghetti code. But that's a topic for after you're familiar with solving some smaller isolated problems and plan to take on bigger projects. So, also props to you for picking a relatively isolated project like a character controller, that's actually a pretty good thing to get started on.


    As is usually the case in programming, getting the right inspiration/ideas to work from can be the difference between getting it done or getting stuck. Note of course that there are other ways to solve the problem, like 'cheating' by directly setting the rotation to correct steady state errors etc. Basically, everything is possile in the world of programming ;)

    Motion matching is currently transitioning from research to commercial application. It's the cutting edge of character animation based on recent advances in machine learning - and will be pretty hard to pick up for a beginner, if only for lack of easily digestable information on the topic. Unity is cooking up something similar under the name of Kinematica, so if you're simply interested in dabbling with it, I'd highly suggest just waiting for that.
     
  5. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    Thanks for the detailed reply as always christopher_r. Many of the things you have said are very helpful.

    In terms of actual progress. I tried utilizing a PID controller, however it was very difficult to tune the controller in a useable manner especially since the character doesn't rotate at a constant rate necessarily. The result was far more over/undershoot problems than before. So I went back to my old control method, fixed some errors, and now I have almost no overshoot errors.

    I have also added running transitions to the controller. They ended up pretty good and I am happy with them so far.



    Unfortunately, Kubold left out some transitions from running to stationary and from stationary to running, so I will have to work around this.

    I've been continue to iterate on top of my code to make sure I can make stuff work out, but the code is starting the get very messy so my next goal is to rewrite the program in a far more organized manner. The next steps for me are to do some research on how to organize the code, what to break up into separate classes, and also some modifications to the code to make it more usable. Any suggestions on books or websites to read would be appreciated!
     
  6. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    484
    Great to hear! Yeah, true, PID controllers can be quite finnicky to tune - good to hear you've found an approach that better suits your needs. The video already looks pretty nice!

    Instead of a complete rewrite you may want to consider refactoring your code - which is something that should happen on a regular basis with WIP code. As a general starting point, you could look at the game programming patterns site, whose author kindly made his book available for free online. It's based on the classic https://en.wikipedia.org/wiki/Design_Patterns - do keep in mind that some of the concepts may be a little outdated by now and that design patterns are often a hotly debated topic. It should, however, serve as a good base to start off of, which game-relevant examples.
     
  7. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    Thanks Christopher_r as always for the response, they are useful. Had a day off work so I spent some time completely refactoring the code and separating the portions that relied on user input from the actual motor mechanics with hopes of being able to reuse the code for AI.

    One thing I haven't been able to figure out is how to properly set up the Avatar Motor script to properly interface with different Avatar Input scripts. The idea is to have the Avatar Input script take inputs either from a game controller or from an AI controller and break the inputs down into three variables; input magnitude, input direction and input rotation. These can then be fed into the Avatar Motor script to translate the variables into character movement.

    To interface between the two scripts I set up the AvatarInput as a script on the player object and set up my code as such

    Code (CSharp):
    1.     private AvatarInput avatarInput;
    2.  
    3.     void Start()
    4.     {
    5.  
    6.         avatarInput = GetComponent<AvatarInput>();
    7.  
    8.     }
    9.  
    10.     void myCustomFunction()
    11.     {
    12.         inputMagnitude = avatarInput.FetchInputMagnitude();
    13. }
    My confusion has come from how could I easily swap out the current Avatar Input script, which is driven by a controller, for another Avatar Input script that is controlled by an AI. I could just have two different Avatar Motor scripts that are almost identical except for referencing different script names for the Avatar Input, but this doesn't seem very elegant and appears to waste some resources. Any input would be appreciated.

    As always, here's another gif of my progress. The actual controls are vastly improved over the last file. I had changed up the testing area and found the older system too sloppy for doors and tighter areas. I reworked the old anim system that tested speeds for a system that directly modifies the mechanim system based off of direct user input and not from interpolated values. It is slightly less smooth but vastly more responsive.



    There's still some work to do with tweaking animation transitions (which I just discovered you could do) and tweaking interpolation values, but I feel I am nearing a point where I am happy with the results. Next steps will be to look into IK and maybe thinking of how to add realtime effects to the animations. Of course eventually I will add other aspects such as jumping and maybe combat.

    Cheers!
     
    one_one likes this.
  8. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    484
    Sounds reasonable.

    That's not a good way to handle it, I agree. What you're currently looking at is a dependency and coupling design issue. There are numerous ways to go about it:
    • In bigger/more complex object-oriented applications you would want to look at a concept called inversion of control. For dependency management, it means that dependencies are 'passed down' from higher level classes, instead of low level classes setting up all their dependencies by themselves, which gets messy really quickly. It's a bigger topic, though, and I would only recommend digging into it at such an early level if you already have done some previous reading on code/software architecture.
    • You could create an interface (as in C# interface, if you have not looked at those, you definitely should!) for the controller input, have both your AI and player input script derive from that. You can use GetComponent with interface types as well, so you'd only have to make sure to have either a player input or an AI component on your GO
    • You could have a 'data contaienr'/'blackboard' component for the input data, which the controller is reading from and your various input scripts would be writing to.
    • And then there's the 'Unity way', using the inspector. Because unity does not serialize interfaces out of the box, you would need your input scripts to all dervice from the same base class in order to utilise polymorphism. That, however, is usually not a very good idea, so I'm just leaving it as a 'honorable' mention at the end.
     
    PatysTy likes this.
  9. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    I've been interested in using interfaces, but didn't understand them enough to really set them up for anything. Now that you've suggested I look into them I have found a great overview on youtube by GameDevHQ. They seem like exactly what I need. I'm going to spend some time today trying to set up this code as an interface and see if I can get it working that way.

    Thanks again for your help, I would've been going down the wrong path without it!

    Edit: After some digging I also found references to abstract classes. In my situation would it be better to use abstract classes as I want some form of reused functionality? My understand is interfaces only give me a template meaning I would still have to duplicate functions, whereas an abstract class would allow me to have shared functionality across two different but similar classes (AI Character and Player Character).
     
    Last edited: Feb 13, 2019
  10. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    484
    Good to hear that it's been helpful!

    When choosing between abstract classes and interfaces, choose interfaces unless you have very good reasons to go with abstract classes. Code re-use isn't really the main goal of OOP (as it has been once touted a decade or so ago), so it doesn't make a lot of sense to design around that. Maintainability and readability are a lot more important. Keep the SOLID principles in mind and to favour composition over inheritance. Interfaces work much more nicely with composition because a single class can implement multiple interfaces - but only derive from a single base class (by design in C#). Additionally, interfaces encourage designing around contracts and functionality, rather than specific implementations.

    If you think that there is a lot of code that would be duplicated, consider 'outsourcing' it either into static methods or specific classes dedicated to the functionality that would need to be duplicated.
     
  11. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    Thanks Chris, I've been working on refactoring everything into interfaces. In the end it makes more sense as there will be some differences between how players and ai move.

    In terms of other progress, I managed to get the head to look at the camera target using Bio IK along with setting up a demo village scene with some assets from the asset store. The look at IK is subtle, but really adds believability to the head movements of the character. The textured scene and character also helped me with visualizing what the animations will look like on and around game assets.



    Next steps are finishing refactoring then foot IK. I have really enjoyed using Bio IK because of its modularity, I am excited to see what else I can do with the package. Hopefully more to come in a couple days.

    And apologies for the poor graphics quality and framerate. I've been working on my old macbook which has almost zero graphics processing juice. I do feel that it looks pretty good for a beginner's work when on higher graphics settings and rendered fullscreen!



    Assets used:

    Fast Fake Skin: https://assetstore.unity.com/packages/vfx/shaders/fast-fake-skin-42535
    Bio IK: https://assetstore.unity.com/packages/tools/animation/bio-ik-67819
    Rocky Hills Environment: https://assetstore.unity.com/packag...capes/rocky-hills-environment-pro-pack-111436
    Medieval Village: https://assetstore.unity.com/packages/3d/environments/fantasy/medieval-village-environment-121867
    Movement Animset Pro: https://assetstore.unity.com/packages/3d/animations/movement-animset-pro-14047
     
    florianalexandru05 likes this.
  12. Lesnikus5

    Lesnikus5

    Joined:
    May 20, 2016
    Posts:
    60
    The Asset Store does not have a sufficiently realistic locomotion controller for characters. The only good asset that I know exists for the Unreal Engine 4 and it is called Advanced Locomotion System. I advise you to look this for inspiration. In my opinion, it looks very cool. I would like to have something similar for Unity.



    Maybe you will be interested, but recently I participated in a discussion about the lack of a really beautiful character controller for Unity: https://forum.unity.com/threads/wha...-unity-asset-store.82355/page-18#post-4158676

    I see that your character moves its legs during rotation in place, there are transition animations. You are moving in the right direction. Do you plan to release an asset in the store?
     
  13. PatysTy

    PatysTy

    Joined:
    Jan 6, 2018
    Posts:
    21
    Hi Lesnikus! The UE4 Advanced Locomotion System was one of my first inspirations for this project actually. I did share your sentiment that I wasn't very content with the current systems available for unity for the price for what I wanted to do. Do understand however that many of the systems on the asset store are designed for a breadth of uses, so with generality other portions of the movement system go to the wayside.

    All that being said, most likely I won't be releasing this system for a couple reasons. First, my full time job has me going into the field for extended periods meaning I wouldn't be able to support the asset. Second, the system relies on other asset store assets. Finally, I have programming experience, but I am not a professional programmer. I wouldn't be able to guarantee that the programming was done in a stable way for all applications.

    All of that being said depending on where this goes I have thought of releasing this project in the future for free as open source. That way I can decouple systems so users could use their own animations, or purchase Kubold's. Bio IK could be an add on, but would require some manual work to get functioning.

    The last option, and this is the one I actually think would be the best, would be for me to develop a tutorial set on how to code a high quality animation controller. I think this would be the best solution as I could teach what I have learned on how to set up systems, and also how to get the controller to act in predictable but smooth ways. Of course this would be the most work for the user, but also the most valuable because they would have the ability to understand the logic of the controller and expand on it based on their needs.

    Again, if you want high quality, building it yourself is the way to go. Animation systems are a constant payoff between responsiveness and smoothness of animations. I feel a tutorial would let people set it up in a way that works best for them. Thanks for your interest in my project and make sure to keep checking back!
     
    Lesnikus5, Acissathar and mons00n like this.
  14. florianalexandru05

    florianalexandru05

    Joined:
    Mar 31, 2014
    Posts:
    915
    That looks pretty good, it has some flaws but still pretty decent, alright from what I see you're trying to get as close to better as possible. Just like I had to play with the wind settings for "CTI" to get what I wanted, I'm sure you'll pull this off eventually, maybe it's a matter of finding the right settings but I'm well aware of the recurring problems. Working with animation looks pretty difficult stuff to me but I'm sure you can do it!

    Thanks for using my nature assets, looks like you need more trees in there! ;)