2D Animation 7.0 released for Unity 2021.2

imagine if I build a game like vampire survivor, there will be so many enemies in the screen.

@PBKitty thank you for your feedback on both the Sprite Library flow and the Sprite Resolver. Regarding the Sprite Library flow, I would like to ask the same question to you as I did to PanthenEye;

All of this information helps us understand and prioritize improvements to our 2D toolsets. It also helps us create better internal repro cases, so we can walk similar pipelines to experience the issues first hand.

@Upp000 do let us know if you experience any issues with the current implementation, and we can take a closer look at it with more use case details at hand.

ā€œbut it is absolutely not a replacement for the removed functionality. It isnā€™t the same as just being able to have everything set up in the art file and set up with a single click.ā€

ā€œBingo. It is a lot like if you told 3d devs that theyā€™d now have to manually drag and drop skeleton bones into each imported mesh, or something equally absurd.ā€

Yes! Absolutely!
Thank you for the extremely accurate wording!
All that I canā€™t explain to the developers for several years.

-Do not force us, please, every time do everything manually from scratch!
The Idea of converting groups and layer names to Categories and Labels, in the functionality that was cut out new versions of the package
-was almost perfect!
And no ā€œdrags and a dropā€ do not replace this.

ā€¦that is brilliant.

1 Like

Ok, so, imagine that you have the fairly typical example of a character that uses sprite libraries for the eyes, mouth, and each hand- so four groups, each with a bunch of variants. In my art software(in my case Photoshop), I can create a group for each of these, and then in unity(with 5.x sprite editor) I select each group and convert it to a library.

It is very fast and easy; everything is named correctly. And, importantly, I can take art from someone else and as long as they followed the correct workflow I can one-click convert their layer groups to sprite libraries, too.

So not only does it save a lot of pointless manual work, but it also makes it much easier to collaborate.

1 Like

Hi! Iā€™m running into a bug with the replaced broken/constant tangent behavior in the animator for the Sprite Resolver component. Apologies if there is a better place to post this, but I didnā€™t see a pre-release thread for the version Iā€™m using (9.0.0-pre.3)

Before version 8.00, we would animate the Sprite Resolverā€™s Category/Label hash by keying it in the animator and then settings the keyā€™s tangents to Broken/Constant, to prevent interpolation between hash values. This should be done automatically for us now in 8.0.0+, but I am now running into an issue where certain spriteresolver hash values in my animation will swap on a frame even when there is no key set in the animation, indicating some kind of interpolation issue.

Attaching screenshots that highlights this. Note that the hash for ā€œHead.RGBA: Sprite Resolver.SpriteKeyā€ swaps from 1228760 to 103200 on frame 26 even though it shouldnā€™t key in the animation until frame 33.

I also filed a bug report! The case # is IN-11884

1 Like

Thanks for flagging this issue @alexlamar .
It is partially true that you do not need to set keyā€™s tangents to Broken/Constant in 2D Animation 8.x and newer versions. In 2D Animation 8.x we introduced a new property to fix the Broken/Constant issue prior 2D Animation versions had. This new property is called SpriteHash and will be automatically used when you key new Sprite Resolver frames in 2D Animation 8.x and newer. If you have Animation Clips made in past 2D Animation versions, you can use our new
2D Animation Asset Upgrader to upgrade these clips to use the new property. Before upgrading your clips, please make sure you have a backup of the clips, so that you can revert if anything goes wrong.

Let me know if this solves your issue!

Thank you, Ted! I must have missed the new tooling, but Iā€™m glad that you guys included it. The animation upgrader is going smoothly, Iā€™ll update you if I run into any additional problems :slight_smile:

2 Likes

Hello. I was messing with sources of animations packages for a while myself, but it became a huge hassle to try to keep it up to date due to all merge conflicts. I thought maybe I should just request that as features instead. It does not work with new batching system anymore as well.

Basically, it will be great to have extra settings in SpriteSkin components: offset (Vector2), scale (Vector2), flip (int). Itā€™s possible to do the same with extra child bones, but itā€™s such a hassle to do that every time and it looks really messy. Those transformations should happen in relation to either root bone, or some extra transform field you define.

  1. Flip feature is really important since I need that a lot when animating stuff. There are flip flags in SpriteRenderer, but they do not work correctly - they flip image in relation to objectā€™s root or something, but you usually want to flip in relation to root bone.
  2. There are surprisingly a lot of cases when you want to scale/offset/flip ONLY current sprite, while not affecting itā€™s children - itā€™s pretty hard to do when you have than as child transforms. Those settings help a lot here.
  3. Flip I suggested is int because animator blends bool values as ā€œTrue as long as transition lastsā€, while it should be ā€œChanges value in-wayā€. I reported this as a bug, like, 5 years ago, but nothing happened as usual.

It may not be something in the inspector either - may add some public method for SpriteSkin to load additional transformation matrix so I can make my own extra component to do so.

Edit:
How it looked with my changes:

I think it was made in one of the first versions of the package.

2 Likes

Hi @GamerXP

This thread is definitely a good place to share feedback and request features!

Thanks for sharing this. I think your points make perfect sense and Iā€™ll share them with the rest of 2D animation team

1 Like

@GamerXP a quick clarification on this point:

Sprite Renderer flips spriteā€™s mesh based on its pivot position. When using Sprite Skin, deformation is performed first, and then Sprite Renderer flips the X/Y axis before rendering hence the behaviour youā€™re experiencing.

Could you share some concrete examples of when you apply scale/offset/flip in your animation? For example: turn character head to look left-right. I can imagine that in this kind of situations you would also want to flip the bones that are influencing that sprite?

  1. Well, itā€™s just that you often donā€™t want this behaviour when using SpriteSkin. At least I canā€™t imagine me needing this instead of flipping along root boneā€™s axis. Anyhow, this one is a bit hard to use in animations because it has bool-type blending, which works incorrectly.

  2. Hmmā€¦ project where I tested it the most does not load for now, but from what I can rememberā€¦ For example, you want leg to rotate so feet faces inwards. And you want it to properly translate from outwards-facing to inwards-facing. If I flip the main leg bone - it will also flip child bones, forcing you to rotate those bones to match previous positions. Also, sometimes I want to scale arm or leg by X axis so they appear shorter. Scaling the bone will make child bones look distorted if they are also rotated.

1 Like

Howdy! Iā€™m working on some sprite keyframed animation heavy stuff right now, the SpriteLibrary and Resolver workflow is simplifying a lot of my process, however it certainly has its ā€¦ quirks. Iā€™m using Unity 2021.3.6f1 LTS with 2D Animation Package 7.0.7

The most glaring issue Iā€™ve ran it to has me questioning my own sanity, as I donā€™t seem to find any other people encountering this problem.

Setting up AnimationClips using the SpriteResolver completely breaks the curves view of the Animation window.

Sure, itā€™s keyframed animation, I donā€™t often need the curves view - but I donā€™t think that means causing the editor to explode in errors is an acceptable problem to have with one of Unityā€™s own packages, in a supposedly stable version, within an LTS editor?

As far as I can gather, this is happening because the float based hashes produced by the SpriteLibrary are absurdly small (e.g. -1.4877e-09)

The thing that further compounded by confusion was when I was poking around inside the SpriteResolver, I see that it looks like the float hashes are only used for the animation window, and the code primarily seems to be converting them to ints for lookups, which presumably wouldnā€™t have this problem to begin with?

So, uhhh, have I lost the plot, am I missing something, or is this just a big olā€™ weirdness I should justā€¦ live with?


While weā€™re here, are there any plans to make more of the 2D tools APIs public? Iā€™ve been wanting to extend various features to better support a keyframe workflow, such as extending the PSD importer, or adding additional editor windows, but my progress is being majorly hampered by every single method, class, struct being marked internal. Itā€™s not like internal truly blocks anything from being used anyway, Iā€™ve just resorted to some diabolical reflection to achieve what I wanted, without rewriting the entire PSD importer, but itā€™s far from ideal. Similar problems when trying to dynamically generate AnimationClips, the SpriteLibraryAsset.GetStringHash methods arenā€™t public, so itā€™s needlessly difficult to work with.

2 Likes

Hi 2D folks! :slight_smile: 2D Animation 8.0 was released with Unity 2022.1. Iā€™m unsticking this thread. Please join the discussion here.

1 Like

but what if weā€™re on LTS and canā€™t use 8.0 :frowning:

1 Like

Hello @SudoCat

No worries, keep posting in this thread if you like. We are just unsticking the thread to make room for the latest verified version of 2D Animation in the top of the 2D forum.

On to your questions!
Regarding the APIs, we tend to keep APIs internal by default. This makes it easier for us to make sure that the API surface areas are well tested. We can also make changes faster if the APIs are internal, as we only need to verify with our colleagues if we wish to make breaking changes to the APIs. However, we are always interested to know if there are any APIs you wish us to turn public. Do let us know which APIs and what you intend to use them for, so we can take them into consideration.

The second question is a bug. Sometimes those manage to sneak into LTS versions of the editor, unfortunately. Please file a bug report so that we can pass it along.

Thank you for the feedback!

1 Like

Thanks so much for the update!

This does make sense, although Iā€™m sure Iā€™ll still grumble every time I hit an internal I wanna play with. Iā€™ll run through some of the use cases Iā€™ve got, and how Iā€™m dealing with the situation.

Extending the PSD Importer
This was one of the big ones. I wanted to add some additional functionality to make the PSD Importer more useful for importing keyframed animations, providing a simpler way of managing our animations. Our animations are made of layered sprites. We want one PSB to equal one clip. This results in a whole lot less sprites hanging around in the project, and makes it much easier to update a single clip.

In order to achieve this, I created two additional classes, one to extend the PSDImporter, and one to extend the PSDImporterEditor. I needed to display additional settings on the object Inspector, to configuring Animation Clip and Sprite Library generation.

Ideally, I didnā€™t want to generate the character prefabs when importing PSBs. These files were never used in our project, so seemed a distraction. We also do not use the SpriteSkin system, so in theory I should have been able to simply disable the ā€œuse as characterā€ checkbox, add a new checkbox for clip generation, and then I could go about generating clips.

Unfortunately, it was very difficult to generate clips from the data available to me. I needed to know what sprites resided in which layer groups, and the position offsets used to match them to their positions in the PSB. Most of this data was stored on the internal classes, UnityEditor.U2D.PSD.PSDLayer class, and UnityEditor.U2D.PSD.SpriteMetaData. The properties for storing the PSDLayer classes are all internal. Most frustratingly, this method is exposed to data providers, but the raw output is not available anywhere. Even more frustratingly, the SpriteMetaData was even closer, but still out of reach. The PSDImporter implements ISpriteEditorDataProvider.GetSpriteRects, which when debugging I could see returned SpriteMetaData, but as the class is internal, I was unable to access any of its properties without reflection. The PSDImportData could have also proved helpful, but is also internal.

This made it incredibly difficult to access any information about the PSD itself, or the layers output from it. In the end, I resorted to a system where I leave the character generation enabled, and then I read those prefabs to access the transform offset positions. Not ideal, but functional.

The next roadblock was extending the editor. It was here I did decide my only viable option was to resort to some very dubious reflection. The last thing I wanted was to re-implement the entire Inspector pane, however all of the layout functionality is internal. However, the Editor implements a fairly straight forward tabbing system. Hereā€™s where the fun begins.

The tabs rely on a nested struct, UnityEditor.U2D.PSD.PSDImporterEditor.InspectorGUI, which is then used in an array. However, this only configures what callback to execute when the tab is active. The tabs themselves are managed by a readonly property inside the nested Styles class.This left me with no other alternative, I had to resort to lots of very hacky reflection, which is quite unreliable, and will almost definitely break with updates.

I donā€™t think making those Editor APIs public is the solution of course (maybe the struct). However, I feel it would be incredibly helpful to have a public API to allow adding additional tabs, so we could extend the PSD importer without losing the existing functionality.

So thatā€™s about it for Case Study 1: Extending the PSB importer. These other projects are pipe dreams which Iā€™m yet to thoroughly investigate, as I saw lots of immediate limitations. They consequently, wonā€™t have the same level of detail (so should save you some time reading them :sweat_smile:)

  • SkeletonTool and associated code is internal. I would have liked to make some extensions to this to aid in generating pivot data for keyframed sprites, without having to utilise SpriteSkinning (which seems a bit overkill when Iā€™m not using mesh deformation). I had hoped to also add my own SpriteEditorModule for previewing and editing clips, such as their timings, but this ultimately proved far too difficult to be worth the time investment at this stage.

  • Editor Styles. Thereā€™s so many little internal editor styles and UI utilties everywhere, which would be incredibly useful to have access when extending the editor. For my PSDImporterEditor extension, I ended up needing to copy and InspectorUtils.DrawHeaderFoldout into my project. However, In the end it proved preferable anyway, as I needed additional feattures, and the hasMoreOptions argument has not been implemented in this version.

  • Most properties of the PSDImporter are also set to private/internal. This means that derived importers canā€™t read the settings of the base importer. My custom importer requires some specific settings to be enabled in the base, but I canā€™t check for them from my OnImportAsset implementation.


Now Iā€™ll go report that bug, thanks again for your response, and I hope some of my long rambly feedback is useful.

1 Like

Thanks a lot for that write-down @SudoCat . We have many developers doing all sorts of custom implementations, serving their special needs, so understanding what you are doing and where you had difficulties helps us create better solutions in future versions of Unity.

It is interesting to hear that you are using psd files, where each layer is a frame in a flipbook animation. What makes this a preferred way of working compared with a ā€œflatā€ .png spritesheet? This is also something we can look at adding as a feature request to PSD Importer, as we would like to improve our flipbook animation offering in Unity.

I can also understand that you had a lot of issues extending both PSDImporter and its editor, as we havenā€™t looked into making it extensible for outside usage, at all. But good to know, so that we can consider updating it in future.

1 Like

Before I get into the Big Long Rambling Descriptionā„¢, Iā€™d say that to really improve flipbook animation within Unity, there are some small quality of life improvements that would make a big difference:

  • Project wide setting to change default AnimationClip behaviour to constants instead of smooth curves
  • Project wide setting to change Animatorā€™s to stop applying blends to transitions
  • Animation Blend Trees without the blending? Something to make it easier to sync run->walk frames, without interpolating between them

Easier said than done of course, but a lot of weird bugs appear when I forget to flatten a curve, or remove a transition offset, even more so when using SpriteResolvers.

The flipbooks are multi-layered, the traditional separate layers for arms to allow playing action animations over the top of movement animations. Our character animations are drawn in Clip Studio, and then exported out as the PSBs.

Using the PSD importer makes it slightly easier to compose the clips:

  • The PSD importer will automatically extract each layer, and crop it to the smallest possible size.

  • All sprites for each clip are automatically grouped into a single atlas, making it easier to optimise draw calls for each clip (all the parts for a single frame are guaranteed to be within the same texture), while also bypassing the difficulties of using sprite atlases with addressables. Thereā€™s a little more wasted texture space than using a single sprite atlas for the whole set, but Iā€™m hoping the difference is negligible.

  • The PSD importer also handles positioning the sprites relative to their original position in the PSB, based on the pivot. This data can be easily read for generating the AnimationClips, without having to reference all the original sprites.

  • Setting pivots for a new clip can be done in a single step, as you can edit all the pivots for frames in one clip very quickly.

  • Updating, replacing, or removing clips, frames or layers is a simple and intuitive process for our artist.

  • Lastly, it also makes it easier to navigate the project. We donā€™t need to have masses of folders filled with sprites, split out into clips and layers. Each character gets one folder, with about 30 PSBs in it. Itā€™s a minor difference, but it does make it easier to navigate the project!

Itā€™s probably worth noting that we arenā€™t actually creating any AnimationClip assets within the OnImportAsset step. During that process, Iā€™m simply storing all the relevant data in a ScriptableObject within the PSB, then adding a button to the Inspector to trigger the generation, outputting clips to the specified folder.

There are two main reasons for this:

  • Thanks to the SpriteLibrary/Resolver pattern, we no longer need a clip per character - only a new Sprite Library. Thus we only need to generate these clips once, for the ā€œbaseā€ character. We can manually control when we update them, and they arenā€™t directly associated with the PSB file.
  • If we added the AnimationClips as subassets of the PSB, theyā€™d be read only. We need to control the positions of other transforms to use as anchors for VFX. By keeping the clips separate, we can update these things. Iā€™ve configured the Clip Creation method to only overwrite specific AnimationCurve bindings, and the clip settings, so no data is lost via re-import.

We then have the other side of this, which is updating the SpriteLibraries. Itā€™s a similar process; store some data in a ScriptableObject during OnImportAsset, provide an reference to a SpriteLib in the inspector, update it via button.

This workflow likely is far from perfect, but itā€™s a big improvement over our previous import system. A nice benefit of this workflow was the minimal need for maintaining any custom UI, and a lot of the logic was provided for us by the existing tooling.

I find leveraging individual tools to build custom workflows are often more useful than predefined workflows, which might not fit the weird needs of chaotic users.

Ideally, weā€™d ditch the entire prefab generation, as we never use the prefabs, and just use the data from PSDLayer and
SpriteMetaData to produce the same results.

It would perhaps be better still to achieve this using custom SpriteEditorModules, rather than piggy-backing off the importer, however I found them slightly more difficult to work with, considering the restrictions on PSDLayer and SpriteMetaData access, combined with a lack of documentation. They also lacked the ability to automatically update data when the asset was imported, which is useful for keeping everything up to date.

I started down this route by an initial intent to leverage more of the 2D system, such as using the bones for managing pivots, and providing clip previews in SpriteEditorModules. Ultimately, as the work has gone on, thereā€™s been less and less of the provided features Iā€™ve found suitable for our needs.

Having written this out and taken a step back from the process, perhaps the implementation Iā€™ve arrived at is misuse of tools, or more bluntly, a bastardisation of them. Using asset importers without the expressed intent to create any asset more meaningful than data stores probably highlights that I could, and perhaps should be tackling this differently, which is certainly something Iā€™ll think more on. However, the current workflow Iā€™ve ended up with does feel good. Itā€™s easy for our non-technical team members to understand and use. It feels simple, and thereā€™s a low development maintenance cost.

Just found out about this, itā€™s great!
Would it be possible to make animations with this and import them in UI Toolkit instead of using spritesheets?