A lot of time passed since the last news, many things happened on my side but today I can share some stuff with you.
During that time, we swapped back to our custom C++ engine, then again to Unity. The hardest for a programmer with Unity is to switch from a programming language where we can do anything we want anytime we need, to a scripting language where we do it faster but with constraints.
Well, at last, we’ll stay on Unity. After many tutorials, questions on Unity website and a bit of motivation, this tool gives me many more satisfaction I didn’t have before. And for some proof, here is one of the basic tool I could develop as an extension to the editor : the animated sprites.
In all the sprite editor I saw on the web and the Unity’s Asset Store, each have their own way to sort the base frames to create the final animated sprite. The great majority just put the frame one after another, using some strange Drag and Drop mechanism, or even less. It do the work, but it appears hard to work efficiently on complex animated sprites. That’s why I though it would be better to do our own animated sprite system.
In summary, I needed :
- A complete animated sprite system, covering all the need we have about animation.
- An time based system (instead of frame per frame), allowing to play the animation any speed we want, backward of forward.
- Including tools to rapidly implement basic tilesheets.
- Pre-generating the meshes used as sprite to avoid them generated on run-time, performance-wise.
- Accepting multiple animations for one animated sprite, allowing us to swap animation when needed.
- Allowing easy interaction with C# scripts.
And after a couple of days of research and intense scripting, here we go :
Pretty complicated stuff huh? Well, not that hard.
The Sprite Animation script inherit from ScriptableObject, allowing us to save them in the project window (4). I added a MenuItem to create them as a standard asset. The animation doesn’t have an inspector like other assets. Instead, I wanted it to be in an editor window to have the needed space. We can open the editor with the Open button (5) in the inspector of the current animation or open it with the Excellence menu in the menu bar.
Once the sprite is created, we assign it our sprite sheet, saved as a material in the material field in frame (1). Then we create and move the frames in the Timeline (7) and edit each with the Frame Edit (2). A preview of the sprite sheet and the current edited frame appear in the Frame View (6). Once the frames are created, we sort them with the Timeline’s curve (7). I need the system to be close to the timeline of 3D Studio MAX, working frame per frame on the Editor but being able to play the animation any speed we need later. For a classic sprite sheet like the one on the screen, it is not that useful as the curve will be a simple line going from top-left to bottom-right, but if I want to use this system later for, per example, a fighting game, it will allow me to place some pauses in the animation or repeat the same frame multiple time (like Chun-Li repeated kick. :D ), etc.
Once the animation is ready, we click the Compile button (1) to generate the meshes.
Then, we need to use the newly created animation, and for that we need the Animated Sprite.
In an empty GameObject, we add the Animated Sprite script. It automatically add the Mesh Renderer and Mesh Filter. Of course, we need those two components to render our sprite in the game, but also in the editor scene. Then you have to add at least one Animator. The animator tells how the animation will be “read”. We can add as much animator as we need, but only one is read at the time. Standard animator (1) simply read the animation from the first to last frame within a given duration, with a loop option. Linked animator (2) allow to link the animation to a variable. In the game, it is useful to rotate our enemies, like Pods and Buggies, giving the angles they are facing to. Targeted animator (3) gives a frame we want to display, and a cursor parse the animation back or forth until the desired frame is reached. It is the system used to display the player ship, as it will roll at its own speed with going left and right.
At last, to allow a good interaction with the scripts, the Animated Sprite object got some function to get and set the parameters at will. Those parameters are the same displayed in the inspector, marked as “not saved”.
public class MyObject : MonoBehaviour
public AnimatedSprite sprite;
// We retrieve the animated sprite attached to the game object
sprite = GetComponent (typeof(AnimatedSprite)) as AnimatedSprite;
// For a Standard animator, we can know if the animation is finished (in condition the animator don't loop)
bool isDone = sprite.GetBool("Done");
// For a Linked animator, we can give it the desired frame as an alpha value or an angle.
// The next 3 lines will set the frame to the middle of the animation.
sprite.SetFloat ("Radian", Mathf.PI);
// For the Targeted Animator, we can set the target frame and get the initial frame.
sprite.SetFloat ("Target", 0f); // Target the first frame of the animation
sprite.SetFloat ("Target", 1f); // Target the last frame of the animation
sprite.SetFloat ("Target", sprite.GetFloat ("InitialTarget")); // Target the initial frame.
// A call to setFloat with an unknown parameter name will simply be ignored. It avoid to have multiple if statement to known wich type of animator we are dealing with when passing a parameter.
// We can reset the sprite to retrieve the initial state. Each animator have its own way to be reset.
// And at last, we can select the desired animator by setting its index.
sprite.currentAnimatorIndex = 1;
Annnnd that’s it! We now have a powerful tool to create cool animated sprites rendered in the editor scene view! If you are curious about the system, feel free to post a comment. :]
Until next time!