根据序列帧生成Prefab,AnimationController,AnimationController和帧动画

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using U3d.Wj.Common;
using UnityEditor.Animations;

/// <summary>
/// Animation prefab creator.
/// Aurthor :   Wang
/// Date    :   20160608
/// Version :   Unity 5.2.2
/// PS      :   大部分代码都借鉴了雨松http://www.xuanyusong.com/archives/3243的文章
///             并根据需求以及API的更新修改了部分代码
///             实现功能为美工提供每个人物的所有动画序列帧 用此脚本直接生成预制体
/// </summary>

public class AnimPrefabCreator  {

#if UNITY_EDITOR
    class Generator
    {

        private static string ImagesPath = Application.dataPath + "/Resources/KingDomRush";
        private static string AnimationPath = "Assets/Animation";
        private static string AnimationControllerPath = "Assets/AnimationController";
        private static string PrefabPath = "Assets/Resources/Prefabs";

        [MenuItem("Edit/将所有序列帧生成预制体")]
        private static void CreateAnimation()
        {
            DirectoryInfo baseDictory = new DirectoryInfo(ImagesPath);

            // 获取所有人物分类文件夹
            foreach (DirectoryInfo dictorys in baseDictory.GetDirectories()) {
                List<AnimationClip> clips = new List<AnimationClip>();
                // 获取每个人物的所有动作分类文件夹 把每组帧动画生成一个动画文件
                foreach (DirectoryInfo dictoryAnimations in dictorys.GetDirectories()) {
                    AnimationClip clip = BuildAnimationClip(dictoryAnimations);
                    if(clip == null) continue;
                    clips.Add(clip);
                }
                // 将每个人物的所有动画文件生成在一个AnimationController里
                AnimatorController controller = BuildAnimationController(clips,dictorys.Name.StrToPinyin());

                // 最后生成程序用的prefab文件
                BuildPrefab(dictorys,controller);
            }
        }

        static void BuildPrefab(DirectoryInfo dictorys,AnimatorController animatorCountorller)
        {
            //生成Prefab 添加一张预览用的Sprite
            FileInfo images  = dictorys.GetDirectories()[0].GetFiles("*.png")[0];

            GameObject go = new GameObject();
            go.name = dictorys.Name.StrToPinyin();
            SpriteRenderer spriteRender =go.AddComponent<SpriteRenderer>();
            string imgPath = images.FullName.Replace("\\","/");
            imgPath = imgPath.Substring(imgPath.IndexOf("KingDomRush/"));
            // 移除".png"后缀名
            imgPath = imgPath.Remove(imgPath.Length - 4,4);
            spriteRender.sprite = Resources.Load<Sprite>(imgPath);
            Animator animator = go.AddComponent<Animator>();
            animator.runtimeAnimatorController = animatorCountorller;
            PrefabUtility.CreatePrefab(PrefabPath+"/"+go.name+".prefab",go);
            GameObject.DestroyImmediate(go);
        }


        private static AnimatorController BuildAnimationController(List<AnimationClip> clips,string controllerName)
        {
            AnimatorController animController = AnimatorController.CreateAnimatorControllerAtPath(AnimationControllerPath + "/" + controllerName + ".controller");
            AnimatorControllerLayer layer = animController.layers[0];
            AnimatorStateMachine sm = layer.stateMachine;
            foreach (AnimationClip newClip in clips) {
                // 将动画名字取出 放入state状态机里
                AnimatorState state = sm.AddState(newClip.name);
                state.motion = newClip;
                AnimatorStateTransition transition = sm.AddAnyStateTransition(state);

                // 移除默认时间条件
                //transition.RemoveCondition(transition.conditions[0]);
            }
            AssetDatabase.SaveAssets();
            return animController;
        }

        // 传值入一个目录文件夹 生成一个序列帧动画
        private static AnimationClip BuildAnimationClip(DirectoryInfo dictorys)
        {
            string animationName = dictorys.Name;
            // 查找所有png类型图片
            FileInfo[] images = dictorys.GetFiles("*.png");

            if(images.Length == 0) return null;

            AnimationClip clip = new AnimationClip();

            //AnimationClipSettings setting = new AnimationClipSettings();
            //AnimationUtility.SetAnimationClipSettings(clip,setting);
            EditorCurveBinding curveBinding = new EditorCurveBinding();
            curveBinding.type = typeof(SpriteRenderer);
            curveBinding.path = "";
            curveBinding.propertyName = "m_Sprite";
            ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[images.Length];

            // 动画播放速度 1/10表示1秒切10张图
            float frameTime = 1/10f;
            for (int i = 0; i < images.Length; i++) 
            {
                string imgPath = images[i].FullName.Substring(images[i].FullName.IndexOf("KingDomRush\\"));
                imgPath = imgPath.Replace("\\","/");
                NormalizeTextureType(DataPathToAssetsPath(imgPath));
                imgPath = imgPath.Remove(imgPath.Length - 4,4);
                Sprite sprite = Resources.Load<Sprite>(imgPath);
                keyFrames[i] = new ObjectReferenceKeyframe();
                keyFrames[i].time = frameTime * i;
                keyFrames[i].value = sprite;
            }
            // 动画帧率
            clip.frameRate = 30;

            // 需要设置循环的动画
            if (animationName.Equals("attack")  || animationName.Equals("run-right")) 
            {
                AnimationClipSettings setting = new AnimationClipSettings();
                setting.loopTime = true;
                AnimationUtility.SetAnimationClipSettings(clip,setting);
            }
            string parentName = Directory.GetParent(dictorys.FullName).Name;
            Directory.CreateDirectory(AnimationPath + "/" + parentName.StrToPinyin());
            AnimationUtility.SetObjectReferenceCurve(clip,curveBinding,keyFrames);
            AssetDatabase.CreateAsset(clip,AnimationPath + "/" + parentName.StrToPinyin() + "/" + animationName + ".anim");
            AssetDatabase.SaveAssets();

            return clip;
        }

        static void NormalizeTextureType(string path)
        {
            TextureImporter textureImporter = AssetImporter.GetAtPath(path)as TextureImporter;
            textureImporter.textureType = TextureImporterType.Sprite;
            TextureImporterSettings settings = new TextureImporterSettings();
            textureImporter.ReadTextureSettings(settings);
            textureImporter.SetTextureSettings(settings);
            AssetDatabase.ImportAsset(path);
        }

        // 例 abc.png
        // return "Assets/Resources/abc.png";
        static string DataPathToAssetsPath(string fullPath)
        {
            fullPath = "Assets/Resources/" + fullPath;
            return fullPath;
        }
    }

#endif
}

using U3d.Wj.Common;
是主程给我提供的命名空间。主要用到了里面的将中文文件夹名转换成拼音的API(.StrToPinyin());

一、问题的提出 做运动分析检测,需要有一定的素材视频,但是素材视频的编码OpenCV不能识别,无法对指定的视频做实验,怎么素材视频通用化使得OpenCV能正常识别? 二、解决的方法 (1)素材视频总是有配套的播放器来播放,那么使用这个播放器查看总数,和总播放时长,计算出率为25,表示一秒钟播放25图像。 (2)用这个配套的播放器对素材视频进行逐步进抓图,这个操作很辛苦,一秒钟25,那么抓25是一秒,素材视频30秒就要抓750,很辛苦。 (3)抓完后,发现一图1.4M,以位图格式保存,那么30秒就要达到1G的存储空间,怎么办?没办法,不知道怎么去获取解码器和安装解码器,就只能这么忍受。察看到逐步进抓图的存储是按序列编排文件名,那么要修改好使得每个文件名都是以规则“文件名”+“序列”的形式存在。 (4)编写根据序列图生成率25的视频的代码 三、问题的解决: (1)解决一个字符串合并的问题: 由于字符串参数有个赋值格式化设置函数叫做Format,要实现多类型参数的字符串化,可以参照如下示例: float f = 0.0; char sz[128]; int n = 1; CString str; str.Format("%f%s%d",f,sz,n); (2)采用MJPG的编码格式依次将这些图像序列写入到视频中保存起来,采用MJPG的编码格式是因为操作系统自带了Media player播放器,这种编码格式属于无压缩的,Media player可以识别播放。 (3)实现方式是使用MFC对话框窗体的按钮事件来进行视频的逐写图,由于数多,那么在写入器循环做写这个动作的时候,整个程序是假死在那里直到写入器的写入操作终结。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值