c# - 使用 Unity EditorWindow 从 Spritesheet 创建动画?
问题描述
目前我正在 Unity 中开发一款 2D 游戏。我正在使用 EditorWindow 对导入的 spritesheet 进行切片并从这些 sprite 中创建动画。
目前,我有代码来分割电子表格的功能,下面为那些有兴趣参考的人详细介绍:
public void Slice()
{
var textures = Selection.GetFiltered<Texture2D>(SelectionMode.Assets);
foreach (var texture in textures)
{
ProcessTexture(texture, pixelPerUnit, spriteSize, pivot, alignment);
}
}
static void ProcessTexture(Texture2D texture, int pixelPerUnit,
Vector2Int spriteSize, Vector2 pivot, Alignment alignment)
{
string path = AssetDatabase.GetAssetPath(texture);
{
TextureImporter textureImporter =
TextureImporter.GetAtPath(path) as TextureImporter;
//Set characteristics for spritesheet
textureImporter.textureType = TextureImporterType.Sprite;
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
textureImporter.spritePixelsPerUnit = pixelPerUnit;
textureImporter.filterMode = FilterMode.Point;
textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
int colCount = texture.width / spriteSize.x;
int rowCount = texture.height / spriteSize.y;
//Create Spritesheet Metadata based on characteristics
List<SpriteMetaData> metas = new List<SpriteMetaData>();
for (int c = 0; c < colCount; c++)
{
for (int r = 0; r < rowCount; r++)
{
SpriteMetaData meta = new SpriteMetaData();
meta.rect = new Rect(c * spriteSize.x,
r * spriteSize.y,
spriteSize.x, spriteSize.y);
meta.name = (rowCount - r - 1) + "-" + c;
meta.alignment = (int)alignment;
meta.pivot = pivot;
metas.Add(meta);
}
}
//Apply the metadata to the spritesheet
textureImporter.spritesheet = metas.ToArray();
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
}
}
目前让我悲伤的部分是通过脚本将这个新切片的电子表格转换为动画。
目前我可以使用下面的代码片段在 spritesheet 的目录中创建一个空的动画剪辑:
string path = AssetDatabase.GetAssetPath(texture);
string newPath = Path.GetDirectoryName(path);
AnimationClip clip = new AnimationClip();
AssetDatabase.CreateAsset(clip, newPath + "\\" + spriteName ".anim");
我很难找出如何将精灵添加到这个新创建的动画中。我查看了AnimationCurves和AnimationEvents,但似乎找不到通过编辑器将精灵链接到动画的步骤。
如果有人对通过脚本创建统一动画剪辑有经验或知识,任何见解将不胜感激。如果我需要更多信息,请告诉我。这是我第一次使用这项服务。谢谢大家的帮助!
解决方案
如果其他人想参考它,我会在这里发布我的决议!我最终参考了文章Create Animation Clip from Sprite[] (Programmatically)和How to get child sprites from a 'Multiple Sprite' Texture。
通过编辑器窗口从选定的精灵表创建动画的结果代码粘贴在下面:
public void Animate()
{
var textures = Selection.GetFiltered<Texture2D>(SelectionMode.Assets);
foreach (var texture in textures)
{
GenerateAnimations(texture, spriteSize, spriteName);
}
}
static void GenerateAnimations(Texture2D texture, Vector2Int spriteSize, string spriteNameGlobal)
{
//Create an Array of all sprites in the selected texture
string path = AssetDatabase.GetAssetPath(texture);
Sprite[] allSprites = AssetDatabase.LoadAllAssetsAtPath(path).OfType<Sprite>().ToArray();
string newPath = Path.GetDirectoryName(path);
//Determine the number of rows & columns based on preset "spriteSize" Vector2
int colCount = texture.width / spriteSize.x;
int rowCount = texture.height / spriteSize.y;
//Loop through each row of the spritesheet to make an animation
for (int i = 0; i < rowCount; i++)
{
//Create a sprite subsection for a row of sprites
Sprite[] batchSprites = new Sprite[colCount];
for (int j = 0; j < batchSprites.Length; j++)
{
batchSprites[j] = allSprites[i * colCount + j];
}
//Create the base AnimationClip
AnimationClip clip = new AnimationClip();
clip.frameRate = 12f;
//Create the CurveBinding
EditorCurveBinding spriteBinding = new EditorCurveBinding();
spriteBinding.type = typeof(SpriteRenderer);
spriteBinding.path = "";
spriteBinding.propertyName = "m_Sprite";
//Create the KeyFrames
ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[colCount];
for (int j = 0; j < spriteKeyFrames.Length; j++)
{
spriteKeyFrames[j] = new ObjectReferenceKeyframe();
spriteKeyFrames[j].time = j/clip.frameRate;
spriteKeyFrames[j].value = batchSprites[j];
}
AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames);
//Set Loop Time to True
AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);
settings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, settings);
//Save the clip
AssetDatabase.CreateAsset(clip, newPath + "\\" + spriteNameGlobal + i + ".anim");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
在使用此代码时,如果不小心,会出现一些有趣的问题。一个主要的问题是没有将 spriteBinding.propertyname 设置为“m_Sprite”。如果您决定修改此代码,请注意这一点。
我希望这被证明是有用的!如果有任何不清楚的地方,或者有进一步的明确建议,请回复,我可以尝试改进此回复。
推荐阅读
- ruby-on-rails - 为什么 Fixture_file_upload 在 RSpec 中不可用(没有 ActiveRecord)?
- sql - 使用 SQL 格式化字符串中的日期信息
- python - Pandas 中的行满足一些条件,将 do 条件的值分配给一个单元格
- javascript - 我可以在用户编辑输入字段后操纵显示的字符吗
- c# - 如何使用 Mono.Cecil 0.10.2 获取指令的行号?
- c# - 如何反序列化 json 而不是在统一 3d 和 simplejson 中创建类的多个实例?
- curl - 来自贝宝的 Yii Curl 请求令牌不起作用
- javascript - 如何使锚点的整个父元素可点击?
- wordpress - 停止通过电子邮件在 Wordpress 中以纯文本形式发送新的用户注册密码
- rust - 如何使用 Cargo 运行项目示例?