When things are static, it is sufficient to use the SkeletonRenderer
component instead of SkeletonAnimation
(it's a base class but not abstract), this saves the AnimationState overhead. This is also shown in the SpineGauge
example scene, on the health bar GameObject Spine GameObject (gauge)
. You can also disable the SkeletonRenderer
component to prevent any updates after Awake
, as you don't want the mesh to be updated later at all.
Ooh, thats nice. I'll give the SkeletonRenderer a try!
Please note that you can attach the SortingGroup
component directly at the SkeletonAnimation
or MeshRenderer
, it does not need to be a parent GameObject. Don't know if you have other reasons why you need the parent though.
My game is a top down SNES Legend of Zelda viewing angle -> the default y-axis sort-point for a spine mesh is its center, so I have to put the Spine gameobject as a child of another gameobject with a SortingGroup and then position them as-needed so that the sort-point (from the SortingGroup gameobject) is at the location where the spine animation is touching the ground. The configuration works great, but not being able to see the thumbnail image sucks when you have like 20+ plants/etc and are trying to find the correct one :confused:
I will have a look at how the thumbnail image is created for child GameObjects in other circumstances (normal meshes), however it might be out of our control.
Thanks! I'm going to keep looking too and see if I can figure it out - was hoping it would have been a quick thing (like drag and drop or something haha), but there seems to be very little info.
Worked perfectly. Thanks! :grinteeth:
Well I just spent an hour googling and couldn't find any way to set the Prefab's thumbnail. Maybe instead of setting the thumbnail, I could instead place the SkeletonAnimation on the parent gameObject of the prefab, and then on Awake() do some re-parenting? :think:
Whoops, just realized that I was incorrectly thinking that having the SkeletonAnimation in the parent of the prefab would set the thumbnail, but that doesn't seem to work. Looks like the Mesh doesn't get saved or something :think: I guess thats what you were talking about haha
Sorry for the reply-spam :p
I'm new to this area of Unity (editor/asset stuff) so bear with me if this stuff is already obvious. Seems like the goal with the thumbnail would be to get the same Preview as is shown for the SkeletonData asset, but to have it shown on a prefab that contains the SkeletonAnimation.
I was able to get/display the preview image in an Editor Window using this:
texture = AssetPreview.GetAssetPreview(my_skeletonData.asset);
or possibly more specifically for the thumbnail (EDIT: this returns the little grey/red Spine icon, not the Skeleton's preview, so use GetAssetPreview):
texture = AssetPreview.GetMiniThumbnail(my_skeletonData.asset);
This post seems to be asking a similar question, but I wasn't able to figure out too much from it: https://answers.unity.com/questions/1276359/how-can-i-create-a-custom-assetpreview-for-a-prefa.html
Going to keep looking around - even if its sort of hacky with an Editor Window or something.
Looking at this: https://docs.unity3d.com/ScriptReference/EditorApplication.ProjectWindowItemCallback.html
Here is a post using that callback where they are drawing on top of the default icon: https://forum.unity.com/threads/editor-changing-an-items-icon-in-the-project-window.272061/
Gonna try that out and see if I can get anywhere 🙂
Woohoo! Got a working configuration! :grinteeth:
These are all prefabs with SkeletonRenderers in them (can be anywhere within the prefab with this setup).
It's definitely sort of hacky the way I did it, I added this code to an Editor Window that I made. Basically it hooks into the EditorApplication.ProjectWindowItemCallback, checks if the name of the item ends in .prefab, then searches that prefab asset for a SkeletonRenderer. If it finds it, it gets the texture with Texture2D prefabIcon = AssetPreview.GetAssetPreview(skeletonRenderer.SkeletonDataAsset); and then it draws the icon texture on top of the "default prefab blue square" icon.
Here is the relevant code in case anyone else wants to give it a try. Note that this is calling Texture2D prefabIcon = AssetPreview.GetAssetPreview(skeletonRenderer.SkeletonDataAsset); every frame for each of the icons, which may not be the most efficient (I'm not sure if its making a copy of it or not). I didn't notice any lag/slowdown in the editor when enabling this. Also, the OnAfterAssemblyReload() doesn't seem to be getting called, so I have to press the "Enable" button again after a recompile. And just to clarify something I mentioned earlier - AssetPreview.GetMiniThumbnail() returns the tiny "spine" icon (little gray icon with red spine), and not the actual Skeleton preview.
//Prefab Icons
public bool prefabIconsEnabled = true;
private void Awake() {
AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;
EnablePrefabIcons();
}
private void OnGUI() {
//draw whatever other stuff you want in the editor window...
DrawPrefabIconOverride();
}
public void DrawPrefabIconOverride() {
if (GUILayout.Button("Enable")) { EnablePrefabIcons(); }
if (GUILayout.Button("Disable")) { DisableIcons(); }
}
public void OnAfterAssemblyReload() {
Debug.Log("assembly reloaded");
if (prefabIconsEnabled == true) { EnablePrefabIcons(); }
}
public void EnablePrefabIcons() {
prefabIconsEnabled = true;
EditorApplication.projectWindowItemOnGUI -= WindowItemOnGuiCallback();
EditorApplication.projectWindowItemOnGUI += WindowItemOnGuiCallback();
}
public void DisableIcons() {
prefabIconsEnabled = false;
EditorApplication.projectWindowItemOnGUI -= WindowItemOnGuiCallback();
}
public EditorApplication.ProjectWindowItemCallback WindowItemOnGuiCallback() {
EditorApplication.ProjectWindowItemCallback myCallback = new EditorApplication.ProjectWindowItemCallback(IconGUI);
return myCallback;
}
public void IconGUI(string s, Rect r) {
string fileName = AssetDatabase.GUIDToAssetPath(s);
if (fileName.Contains(".prefab")) {
if(r.height > 30) { //Prevents the icon from being drawn if the "icon size slider" (bottom right corner) is all the way to the left
GameObject prefabObject = AssetDatabase.LoadAssetAtPath<GameObject>(fileName);
SkeletonRenderer skeletonRenderer = prefabObject.GetComponentInChildren<SkeletonRenderer>(true);
if (skeletonRenderer) {
Texture2D prefabIcon = AssetPreview.GetMiniThumbnail(skeletonRenderer.SkeletonDataAsset);
Rect smallerRect = new Rect(r);
smallerRect.height = smallerRect.height * 0.85f;
GUI.DrawTexture(smallerRect, prefabIcon);
}
}
}
}