Guest User


a guest
Mar 30th, 2019
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  3. Feel free to contact me for help or questions.
  4. Email:
  5. Unity Connect:
  6. Unity Forums:
  10. The CSharpAnimator allows you to generate a Unity animator using C# code. In my experience, this is extremely useful
  11. for dealing with animators of moderate to large complexity. For one, the animator is now described in text form,
  12. meaning you can manipulate states and transitions much easier than in the Unity editor. I've found this alone extremely
  13. useful, since copying and pasting states and transitions in the animator window is not always possible. Secondly, as can
  14. be seen in an example provided, we can procedurally generate states and transitions. I've personally found organising my states
  15. in a heirarchy based on gameplay logic useful as well. For example, in "ClassAdvancedTest", we have a state machine called
  16. "OnGround", which contains all the states and sub state machines where the player can perform a jump animation from.
  17. When we're writing the transitions we can simply say, if the player is in any state included in the "OnGround" state machine,
  18. then they can jump, otherwise they can't. To support this, I've added the ability to specify whether a transitions source
  19. states should be a single state, a list of states, or recursively all states in a state machine.
  21. All these things together with the ability to run C# code to generate states and transitions makes this approach much
  22. more powerful in my opinion. In the end, when the animator is generated, you still get to visualise the graph(all node
  23. positions are saved when generating, so you don't have to keep moving them every time you regenerate.) and use it's
  24. debugging features. The only downside is that you can't edit the graph in the Unity editor anymore without your
  25. changes getting over written next time you generate.
  30. The first step in creating a CSharp animator is inheriting from one of two available classes. You can inherit from the
  31. "CSharpAnimator" class directly. This class itself inherits from scriptable object, so your derived class must go in it's
  32. own file, and the class name and file name must match:
  34. For example, in ScriptableObjectAnimator.cs:
  36. public class ScriptableObjectAnimator : CSharpAnimator
  37. {
  38. ...
  39. }
  41. Or you can inherit from "CSharpAnimator_ClassBase", which works the same, but eliminates the need to name the class the
  42. same as the file you place it in:
  44. public class ClassAnimator : CSharpAnimator_ClassBase
  45. {
  46. ...
  47. }
  48. Using "CSharpAnimator_ClassBase" means you can also have multiple CSharp animators in one file.
  50. Once these classes are created, no matter which method you choose, you must override the "Construct" method and return
  51. a valid "AnimatorData" instance:
  53. public class ClassAnimator : CSharpAnimator_ClassBase
  54. {
  55. public override AnimatorData Construct()
  56. {
  57. ...
  58. }
  59. }
  61. AnimatorData is a class that holds all the information required to generate an animator. Instead of manually setting
  62. up your AnimatorData instance, there are a bunch of methods provided that you should call in a structured way. The
  63. layout of these method calls are intended to be formatted in a readable way. Here's an example of a complete "Construct"
  64. method:
  66. ParameterData speed = FloatParam("Speed");
  67. ParameterData jumpTrigger = TriggerParam("JumpTrigger");
  68. Animator
  69. (
  70. Graph()
  71. [
  72. Layer("Base").DefaultState("Idle")
  73. [
  74. State("Idle", idleMotion),
  75. State("Run", runMotion),
  77. StateMachine("CrouchableStates").Tag("JUMP_TAG")
  78. [
  79. State("Jump0", jumpMotion0),
  80. State("Jump1", jumpMotion1),
  81. ]
  82. ]
  83. ],
  85. Transitions()
  86. [
  87. Transition().SourceMultiple("Idle", "Run").Destination("Jump")
  88. [
  89. Trigger(jumpTrigger)
  90. ],
  92. Transition().Source("Jump").Destination("Idle").ExitTime(0.9f),
  94. Transition().Source("Idle").Destination("Run")
  95. [
  96. Float(speed, speedForRun, ConditionMode.Greater)
  97. ],
  98. Transition().Source("Run").Destination("Idle")
  99. [
  100. Float(speed, speedForRun, ConditionMode.Less)
  101. ]
  102. ]
  103. );
  104. return currentData;
  106. In general, each element here is a method call to define a part of the animator, plus more method calls inside [] brackets.
  107. This allows us to specify the animator like a heirarchy. Most of these elements return an object that can have methods
  108. called on them to change certain properties of that element. For example:
  110. State("Jump0", jumpMotion0).Speed(2.0f).Mirror(true)
  112. Will specify that we want a state called "Jump0", which plays the motion jumpMotion0(from editor exposed variables),
  113. the speed is 2 times normal, and the motion is mirrored. Any parameter available to a particular element can be changed
  114. using this method and just chaining method calls:
  115. Transition().Source("Jump").Destination("Idle").ExitTime(0.9f).TransitionTime(1.0f)
  117. Inside certain element's [] brackets, you can list other elements one after the other as if it was a method call.
  119. The general structure of the Construct method typically goes like this:
  120. - Create parameters: Parameters are used through the ParameterData class. To create parameters call the *Param methods
  121. And pass in the required method parametes for name, default value etc. Here are the available Parameter methods:
  123. FloatParam(string name, float defaultValue = 0.0f)
  124. BoolParam(string name, bool defaultValue = false)
  125. IntParam(string name, int defaultValue = 0)
  126. TriggerParam(string name)
  127. These correspond to the parameters you can create in the Unity editor. Store these in local variables so we can pass
  128. them onto the transition methods later on.
  130. - Animator: This is the root method call. It expects you to pass in a graph and a group of transitions. It's mainly
  131. there because it needs to be syntactically, but you can think of it as "Create an entirely new animator, and it'll
  132. use this graph with these transitions."
  134. - Graph: This is the root of the animator graph data. This call will return an object which you can use the [] operator
  135. with. Inside the [] brackets, the Graph object takes a variable amount of layer objects. This is the same as the
  136. animator window allowing you to create many layers in the one animator graph.
  138. - Layer: This describes a layer in the animator graph. Any parameters of the layer can be set by calling methods on
  139. the object returned by the Layer() method call. Inside the [] brackets of the layer object, we can place a variable amount of
  140. state and statemachine objects. When you create a layer, it automatically also creates a base state machine.
  142. - StateMachine: The StateMachine call is used to define a state machine in the animator. Inside the [] brackets of
  143. the StateMachine object, you can provide a variable amount of other StateMachines and Stats. This allows you to nest
  144. StateMachines however you like.
  146. - State: States take a name and a motion parameter. This is a state in the animator graph and cannot have any children
  147. States or StateMachines, so it has no overloaded [] operator.
  149. - Transitions: This call is like the Graph() call. It just says that we are going to list all our transitions that
  150. exists in the animator. All transitions for your animator go in the [] brackets here.
  152. - Transition: Defines a single transition that will go into your animator. This requires a source state and a destination
  153. state. Source states can be either just "Source"(single), "SourceMultiple"(an explicit list of states), or
  154. "SourceRecursive"(recursively all states at or below the given state). Destination is always one single state.
  155. Inside the [] brackets of Transition, you can provide a variable amount of TransitionConditions.
  157. - TransitionConditions: These method calls return a TransitionCondition object that are used to create transition conditions.
  158. The different conditions available are:
  160. Bool(ParameterData parameter, bool value)
  161. Float(ParameterData parameter, float value, ConditionMode mode)
  162. Int(ParameterData parameter, int value, ConditionMode mode)
  163. Trigger(ParameterData parameter)
  164. This is the same as adding transition conditions in the animator window on a particular transition. Pass in the
  165. parameters you created earlier.
  168. NOTE: If you're inheriting from "CSharpAnimator", you'll have to create a way to access the scriptable object asset
  169. from the Unity editor. Here is the recommended way to do this with CSharpAnimator:
  171. [MenuItem("Assets/Create/CSharpAnimator/Default Asset Name")]
  172. public static void Create()
  173. {
  174. CreateWithType(typeof(<NameOfYourClassHere>));
  175. }
  176. This will create a menu in Assets/Create that will automatically create an asset of your animator type.
  178. Once you've written the method to generate the animator data, you can create an CSharpAnimator asset in Unity. If you
  179. inherited from "CSharpAnimator", use your custom menu item to create your animator. If you inherited from "CSharpAnimator_ClassBase",
  180. you can create the animator by selecting "Assets/Create/CSharpAnimator/CSharpAnimator Class", then selecting your custom
  181. type from the drop down menu in the inspector and hitting the "Apply new type" button.
  183. Note that both these methods will create a Unity animator asset, and not a scriptable object. The CSharpAnimator scriptable
  184. object is stored as a sub asset inside the animator itself. This is just so you don't have to manage both an animator
  185. and a scriptable object used to generate it.
  187. Also note that all state names MUST be unique. In order for the transition elements to know which state you're refering to,
  188. it needs to be given a unique way to identify that state. This is a tiny bit inconvenient, but in my experience hasn't been
  189. a problem.
  191. Code interacting with any part of CSharpAnimator should be editor only, since it's only purpose is to generate a
  192. Unity animator, which can only be done in the editor. Put all CSharpAnimator code in
  193. #if UNITY_EDITOR
  194. #endif
  195. Otherwise you will get compile errors when making builds.
  197. EXAMPLES:
  198. For more advanced examples, look at CSharpAnimatorExamples.cs. These examples show how to use more advanced features,
  199. with lots of comments.
  201. Inside "Assets/CSharpAnimator/Examples/TestAssets" there are some test assets to help visualise the result of CSharpAnimator.
  202. Open "Assets/CSharpAnimator/Examples/TestAssets/Scene/TestScene.unity" and press play to see a basic test scene where the
  203. example animators are played on the Unity Ethan model. Press left and right on the keyboard to change between example animators,
  204. and you can manipulate all the parameters in the animators using UI elements.
  206. "Assets/CSharpAnimator/Examples/Animator/" contains all the example animator assets. These can be regenerated using the inspectors
  207. for the assets.
RAW Paste Data