Unit 高效开发系列 - 第一章 代码自动化创建动画预制体

6 篇文章 0 订阅
1 篇文章 0 订阅

Unit 高效开发系列 - 第一章 代码自动化创建动画预制体

前言

Uinty高效开发系列主要包含一系列的Unity开发实例,主要来源于笔者的一个3D游戏项目和一个手机APP项目,适合利用Unity开发游戏或手机APP场景。

一、代码自动创建动画预制体实现

1.加载场景和角色模型,设置模型比例

static Dictionary<string, Dictionary<string, float>> g_RoleModeScal = new Dictionary<string, Dictionary<string, float>>()
{
    {
        "Role",new Dictionary<string, float>()
        {
            { "R_LT_F_01",120f }, 
            { "R_FT_M_01",125f },                
            { "R_JT_M_01",116f }, 
            { "R_YT_F_01",63f },                 
            { "R_HT_M_01",3.7f },
       }
    },
};
ModifyModelInfo(typeName, AssetsPath, g_RoleModeScal[typeName][objName] * g_Scale);

g_RoleModeScal用于定义模型个性化的比例,g_Scale用于全局调整模型大小比例。

2.切分模型动画

读取帧数分布.txt文件,切分模型动画
帧数分布.txt文件示例:

静止帧数    0
run:     5 - 33
standby:  35 - 125
attack: 135 -180
danti: 185 -240
qunti: 240 -315
fuzhu: 320 -375
hit:   380 -402
die:   402 -430
injury sart:435-455
injury stand:455-605
injury end:  605-625
sit start :625 -700
sit stand:  700 -820
meditation start:820-860
meditation stand:860-980
meditation end:  980-1020
sit end  :  1020 -1095  (动作结束,法杖消失)
collect   :1100 -1175
mining    :1185 -1235 (动作开始,锄头出现)
idle1: 1240-1415 (动作开始锄头消失,法杖出现)
idle2: 1415-1590
idle3: 1590-1760
defense:1760-1800
public static void ModifyModelInfo(string typeName,string AssetsPath, float ModeScale)
{
    ModelImporter importer = AssetImporter.GetAtPath(AssetsPath) as ModelImporter;
    if (importer != null)
    {
        importer.globalScale = ModeScale;
        importer.materialLocation = ModelImporterMaterialLocation.External;

        importer.clipAnimations = (ModelImporterClipAnimation[])SplitAnimationClip(typeName, AssetsPath).ToArray(typeof(ModelImporterClipAnimation));                     
        AssetDatabase.ImportAsset(AssetsPath);  //这句不加,面板上数字会变,但是实际大小不会变      
    }
}

public static ArrayList SplitAnimationClip(string typeName,string AssetsPath)
{
    ArrayList retList = new ArrayList();

    string ClipText = GetZhenFenBu(AssetsPath);
    if (ClipText == "")
    {
        return retList;
    }
    //Debug.Log("ClipText:" + ClipText);
    StreamReader file = new StreamReader(ClipText, Encoding.GetEncoding("gb2312"));
    string sAnimList = file.ReadToEnd();
    file.Close();

    
    string Name = AssetsPath.Substring(0, AssetsPath.LastIndexOf("/"));
    Name = Name.Substring(Name.LastIndexOf("/") + 1);
    ParseAnimFile(sAnimList, Name, ref retList);     

    return retList;
}

3.设置模型Shader

 List<CreatePrefabBase.ShaderPrep> lstShaderPrep = new List<CreatePrefabBase.ShaderPrep>();
 lstShaderPrep.Add(new CreatePrefabBase.ShaderPrep("_Brightness", 1.1f, CreatePrefabBase.ShaderPropertyType.SPT_Float));
 lstShaderPrep.Add(new CreatePrefabBase.ShaderPrep("_Saturation", 1.3f, CreatePrefabBase.ShaderPropertyType.SPT_Float));
 lstShaderPrep.Add(new CreatePrefabBase.ShaderPrep("_Contrast", 1.3f, CreatePrefabBase.ShaderPropertyType.SPT_Float));
 CreatePrefabBase.ModifyShader(cloneObj, AssetsPath, Shader, lstShaderPrep);

示例程序中附带一个非常好的带透明贴图的Shader,可以通过_Brightness、_Saturation、_Contrast三个参数分别设置明亮度、饱和度、对比度。两张图展示一下该Shader的效果:

在这里插入图片描述

4.添加动画对象属性

static Dictionary<string, List<SimperProperty>> AnimaPropertyDic = new Dictionary<string, List<SimperProperty>>()
{
    {"Role",new List<SimperProperty>(){
       new SimperProperty(typeof(Rigidbody).AssemblyQualifiedName,new Dictionary<string, string>{{"mass","200"},{ "useGravity", "true" } }),
       new SimperProperty(typeof(BaseCharacterController).AssemblyQualifiedName,null),
       new SimperProperty(typeof(CharacterMovement).AssemblyQualifiedName,null),
       new SimperProperty(typeof(GroundDetection).AssemblyQualifiedName,null),
       new SimperProperty(typeof(MeshCollider).AssemblyQualifiedName,null),
       new SimperProperty(typeof(NavMeshAgent).AssemblyQualifiedName,new Dictionary<string, string>(){ {"radius","0.01"}, { "enabled", "false"}}),
       new SimperProperty(typeof(AnimationEventPro).AssemblyQualifiedName,null),          

    } },
};
foreach (Si
mperProperty sp in AnimaPropertyDic[typeName])
{
    Component c = rooyObj.AddComponent(Type.GetType(sp.ScriptName));
    if (sp.PropertyValue != null)
    {
        foreach (string key in sp.PropertyValue.Keys)
        {
            switch (key)
            {
                case "enabled":
                    {
                        PropertyInfo propertyInfo;
                        propertyInfo = c.GetType().GetProperty("enabled");
                        if (sp.PropertyValue[key] == "false")
                        {
                            propertyInfo.SetValue(c, false, null);
                        }
                        else
                        {
                            propertyInfo.SetValue(c, true, null);
                        }
                    }
                    break;
                default:
                    {
                        PropertyInfo propertyInfo;
                        propertyInfo = c.GetType().GetProperty(key);
                        propertyInfo.SetValue(c, CreatePrefabBase.Parse(sp.PropertyValue[key], key), null);
                    }
                    break;
            }
        }
    }
}

5.添加动画状态机

Animator An = cloneObj.GetComponent<Animator>();
AnimatorController _animatorController = AddStateTransitionForRole(strName, AssetsPath);
An.runtimeAnimatorController = _animatorController;

动画状态机通过如下结构定义:

public struct AnimaInfoStrc
{
    public int def;
    public List<StateTransitionStrc> lstSt;
    public Dictionary<int,AnimaStateStuc> lstAs;      
    
    public AnimaInfoStrc(int _def,List<StateTransitionStrc> _lstSt, Dictionary<int, AnimaStateStuc> _lstAs)
    {
        lstSt = _lstSt;
        def = _def;
        lstAs = _lstAs;
    }
}

 public struct AnimaStateStuc
 {      
     public float pre;
     public float dur;
     public float skill;
     //public float post; //默认带后处理函数
     public AnimaStateStuc( float _pre = -1, float _dur = -1, float _skill = -1)
     {           
         pre = _pre;
         dur = _dur;
         skill = _skill;
         //post = _post;
     }
 }

static Dictionary<string,AnimaInfoStrc> g_AnimaInfo = new  Dictionary<string, AnimaInfoStrc>()
{
    {
        "Role",  new AnimaInfoStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2,new List<StateTransitionStrc>()
        {   new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_run_1 ,(int)RoleAnima.RoleAnimaEnum.AS_run_1, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_run_1),               
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_run_1 ,(int)RoleAnima.RoleAnimaEnum.AS_standby_2, AnimatorConditionMode.NotEqual,(int)RoleAnima.RoleAnimaEnum.AS_run_1,false),
                          

            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_attack_3, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_attack_3,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_danti_4, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_danti_4,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6,false),                
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_run_1, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_run_1,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_hit_7, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_hit_7,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_standby_2 ,(int)RoleAnima.RoleAnimaEnum.AS_collect_18, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_collect_18,false),

            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_attack_3, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_attack_3,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_danti_4, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_danti_4,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_run_1, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_run_1,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_hit_7, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_hit_7,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle1_20 ,(int)RoleAnima.RoleAnimaEnum.AS_collect_18, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_collect_18,false),

            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_attack_3, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_attack_3,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_danti_4, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_danti_4,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_run_1, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_run_1,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_hit_7, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_hit_7,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle2_21 ,(int)RoleAnima.RoleAnimaEnum.AS_collect_18, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_collect_18,false),

            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_attack_3, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_attack_3,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_danti_4, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_danti_4,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_qunti_5,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_fuzhu_6,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_run_1, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_run_1,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_hit_7, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_hit_7,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_start_12,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_idle3_22 ,(int)RoleAnima.RoleAnimaEnum.AS_collect_18, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_collect_18,false),


            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_sit_start_12 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_stand_13, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_stand_13,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_sit_stand_13 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_stand_13, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_stand_13,true),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_sit_stand_13 ,(int)RoleAnima.RoleAnimaEnum.AS_sit_end_17, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_sit_end_17,false),
            new StateTransitionStrc((int)RoleAnima.RoleAnimaEnum.AS_sit_end_17 ,(int)RoleAnima.RoleAnimaEnum.AS_standby_2, AnimatorConditionMode.Equals,(int)RoleAnima.RoleAnimaEnum.AS_standby_2,false),
        },
        new Dictionary<int,AnimaStateStuc> ()
        {
            { (int)RoleAnima.RoleAnimaEnum.AS_standby_2,new AnimaStateStuc(0,-1)},
            { (int)RoleAnima.RoleAnimaEnum.AS_run_1,new AnimaStateStuc(0,-1)}
        })           
    },
};

6.隐藏一些不需要显示的对象

  • DisableNoNeedObj(rooyObj);

7.设置对象旋转、中心点、添加碰撞体

  • 设置对象旋转
    public static Dictionary<string, Dictionary<string, Vector3>> g_ModeRoate = new Dictionary<string, Dictionary<string, Vector3>>()
    {
    {
    “Role”,new Dictionary<string, Vector3>()
    {
    { “R_LT_F_01”,new Vector3(0.0f,0.0f,0f)},
    { “R_FT_M_01”,new Vector3(0.0f,0.0f,0f) },
    { “R_JT_M_01”,new Vector3(0.0f,0.0f,0f) },
    { “R_YT_F_01”,new Vector3(0.0f,0.0f,0f) },
    { “R_HT_M_01”,new Vector3(0.0f,0.0f,0f) },
    }
    },
    };
 cloneObj.transform.rotation = Quaternion.Euler(CreateAnimaPrefab.g_ModeRoate[typeName][objName]);
  • 设置对象中心点
 public static Dictionary<string, Dictionary<string, Vector3>> g_ModePivotOffset = new Dictionary<string, Dictionary<string, Vector3>>()
 {
     {
         "Role",new Dictionary<string, Vector3>()
         {
             
             { "R_LT_F_01",new Vector3(0.0f,0.01f,0f)},               
             { "R_FT_M_01",new Vector3(0.02f,0.07f,0f) },
             { "R_JT_M_01",new Vector3(0.13f,0.03f,-0.185f) },
             { "R_YT_F_01",new Vector3(0f,0.04f,0f) },
             { "R_HT_M_01",new Vector3(0.148f,0.05f,-0.42f) },             
         }
     },        
 };
PivotPos = g_ModePivotOffset[typeName][objName] + new Vector3(0, Bs.center.y - Bs.extents.y, 0);
 API.SetPivot(rooyObj.transform, PivotPos, API.Space.Global);
  • 添加碰撞体
AddMeshCollider(rooyObj);

8.保存动画预制体

  GameObject _prefab = PrefabUtility.SaveAsPrefabAsset(rooyObj, PrefabPath + objName + ".prefab", out result);
  GameObject.DestroyImmediate(rooyObj);

二、示例工程编译及运行

  • 解压CreateAnimatPrefab.zip文件,可得到如下目录结构:

在这里插入图片描述

  • 使用unity 2019.2.2f1版本打开该文件夹:

在这里插入图片描述

  • 打开Login场景:

代码如下(示例):
在这里插入图片描述

  • 点击菜单栏“Tool”->"CreateChuChangPrefab"菜单,启动生成动画预制体,完成后可启动游戏。

三、资源下载

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值