2019-02-18 18:29:50 qq_43667944 阅读数 110
               

在手游中换装成了越来越不可缺的一个功能,毫无疑问各式各样的时装为游戏增添了不同的色彩。

对于2D手游,或许是更换对应的序列帧,也或许是如同3D手游一般,更换模型动画。


对于游戏中的人物,一般分为头、上身、下身、武器四大部分就可以了。所以在游戏中,我们把这四部分单独做四个模型动画,然后动态拼接为一个整体,达到换装的效果。


然后根据动画制作人员的喜好 又有两种方式来拼接:

1、每个身体部位自带动画数据

2、每个身体部位不带动画数据,动画数据单独提取出来


我们这里介绍第二种。

对于我们这种每一个动作的单独一个动作数据的方式,要怎么拼合到一个动画数据。Unity官方文档有介绍 - 分割动画

http://game.ceeger.com/Manual/Splittinganimations.html




来看我们实际项目中的Project视图:


把每一个动作的动画数据都单独提取出来,然后汇总到warrior这一个文件中。


让我们来看看如何加载这些动画数据和各个部位到游戏中。


把四个部位的模型拖到Scene中,可以看到拼成了一个完整的人物


但是没有动作效果,因为这些只是模型骨头,但是没有动作数据,从右边的红框就看出来。

所以我们需要把动作数据加入到模型中。


点击右边的小圆点,在弹出的动画列表中选择动画,比如我选择的 run ,为四个部位的模型都选择run。再运行,这是就有了动作。我们的主角在跑动。


下面让我们通过代码来把动作和模型数据加载进来。


首先加载进来模型

using UnityEngine;using System.Collections;using System.Collections.Generic;public class LoadTest : MonoBehaviour { // Use this for initialization void Start () {        GameObject head = Instantiate(Resources.Load("anim/character/warrior/fashion/head_1")) as GameObject;        GameObject jack = Instantiate(Resources.Load("anim/character/warrior/fashion/jacket_1")) as GameObject;        GameObject pant = Instantiate(Resources.Load("anim/character/warrior/fashion/pants_1")) as GameObject;        GameObject weapon = Instantiate(Resources.Load("anim/character/warrior/fashion/warrior_10l")) as GameObject; }  // Update is called once per frame void Update () {  }}

然后加载进来动画数据:

using UnityEngine;using System.Collections;using System.Collections.Generic;public class LoadTest : MonoBehaviour { // Use this for initialization void Start () {        //加载模型;        GameObject head = Instantiate(Resources.Load("anim/character/warrior/fashion/head_1")) as GameObject;        GameObject jack = Instantiate(Resources.Load("anim/character/warrior/fashion/jacket_1")) as GameObject;        GameObject pant = Instantiate(Resources.Load("anim/character/warrior/fashion/pants_1")) as GameObject;        GameObject weapon = Instantiate(Resources.Load("anim/character/warrior/fashion/warrior_10l")) as GameObject;        //加载动作数据;        Animation mation = Resources.Load("anim/character/warrior/warrior", typeof(Animation)) as Animation;        //获取所有的动作;        List<string> animList = new List<string>();        foreach (AnimationState state in mation)        {            Debug.Log(state.name);            animList.Add(state.name);            //添加到四个部位;            head.animation.AddClip(mation.GetClip(state.name),state.name);            jack.animation.AddClip(mation.GetClip(state.name), state.name);            pant.animation.AddClip(mation.GetClip(state.name), state.name);            weapon.animation.AddClip(mation.GetClip(state.name), state.name);        }        head.animation.Play("run");        jack.animation.Play("run");        pant.animation.Play("run");        weapon.animation.Play("run"); }  // Update is called once per frame void Update () {  }}

并且播放run 这个动作。

来看看效果


我们的主角就这样跑起来了。


           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

2018-10-09 16:02:51 qq_42850166 阅读数 2802

Unity3D中下载的模型动画自带位移,就是说没有写任何脚本,在动画控制器上添加动画,模型会自己移动,在模型Animator组件的属性上有一个Apply Root Motion的值,将勾选去掉的话就不会再自带位移了,勾上就是模型自带位移。
在这里插入图片描述

2019-12-04 18:15:00 u013628121 阅读数 23

为模型动画片段上设置动画事件

反正麻烦,u3d有两种动画播放系统Animation\Animator,

没有办法预览
有的模型和动画是分开的,这时点击动画就没有办法播放,因为它找不到对应的模型.

只读动画片段 改 可写
大多数模型动画片段是只读的,这时候就没办法编辑动画.从而设置动画事件. 
所以需要:在Project窗口上选中动画片段->按CTRL+D ,
这样就会复制一个新的动画片段就在当前目录,这个新的动画片段才是可编辑的.

设置动画事件方法1, 缺点:动画片段要可写的
在Project窗口上选中动画片段->
点击Inspector窗口上的Open按钮->
在Animation窗口时间栏上选择合适的时间(事件触发点)处右键->
点击Add Animation Event 按钮

设置动画事件方法2  通过代码

       AnimationClip gunMove = animation.GetClip("left");//动画名
        AnimationEvent aevent = new AnimationEvent();
        aevent.functionName = "setInfo"; //方法名
        aevent.time = 1.05f;
        aevent.objectReferenceParameter=GameObject; // object类型参数 
        // aevent.intParameter = 9;   // int类型参数  
        gunMove.AddEvent(aevent);


        
设置动画事件方法3 通过代码,监听这个播放进度值,用回调写事件
Animation["anim"].normalizedTime 的值始终都是从0f到0.97f的,不会到1f.

Animator 

    public float AnimPlayNormalizedTime(string animName)
    {
        var infos = Animator.GetCurrentAnimatorStateInfo(0);
        var str = "Base Layer." + animName;

        if (infos.IsName(str) )
        {
            return infos.normalizedTime;
        }
        else
        {
            Debug.LogError("找不到 正在播放的动画");
        }
        return 0;
    }

 

2020-01-05 21:49:14 liangyling3 阅读数 5

视频演示

优酷

智能巡逻兵

游戏设计要求:

  • 创建一个地图和若干巡逻兵(使用动画);
  • 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
  • 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
  • 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
  • 失去玩家目标后,继续巡逻;
  • 计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;

程序设计要求:

  • 必须使用订阅与发布模式传消息
    • subject:OnLostGoal
    • Publisher: ?
    • Subscriber: ?
  • 工厂模式生产巡逻兵

效果截图

在这里插入图片描述

在这里插入图片描述

具体实现

重要代码如下:

Patrol类

public class Patrol :MonoBehaviour
{
    public enum PatrolState { PATROL,FOLLOW};
    public int sign;        //the patrol in which area
    public bool isFollowPlayer = false;
    public GameObject player=null;       //the player
    public Vector3 startPos,nextPos;
    private float minPosX,minPosZ;  // the range of this patrol can move;
    private bool isMoving = false;
    private float distance;
    private float speed = 1.2f;
    PatrolState state = PatrolState.PATROL;
    private void Start()
    {
        minPosX = startPos.x - 2.5f;
        minPosZ = startPos.z - 2.5f;
        isMoving = false;
        AreaCollide.canFollow += changeStateToFollow;
    }

    public void FixedUpdate()
    {
        if((SSDirector.getInstance().currentScenceController as FirstController).gameState == GameState.END)
        {
            return;
        }
        if(state == PatrolState.PATROL)
        {
            GoPatrol();
        }
        else if(state == PatrolState.FOLLOW)
        {
            Follow();
        }
    }
    public void GoPatrol()
    {
        if (isMoving)
        {
            transform.position = Vector3.MoveTowards(this.transform.position, nextPos, speed * Time.deltaTime);
            distance = Vector3.Distance(this.transform.position, nextPos);
            if(distance < 0.5)
            {
                isMoving = false;
            }
            return;
        }
        float posX = Random.Range(0f, 5f);
        float posZ = Random.Range(0f, 5f);
        nextPos = new Vector3(minPosX+posX, 0, minPosZ+posZ);
        isMoving = true;    
    }

    public void Follow()
    {
        if(player != null)
        {
            nextPos = player.transform.position;
            transform.position = Vector3.MoveTowards(this.transform.position, nextPos, speed * Time.deltaTime);
        }
    }

    public void changeStateToFollow(int sign_,bool isEnter)
    {
        if(sign == sign_ )
        {
            if (isEnter)
            {
                state = PatrolState.FOLLOW;
                player = (SSDirector.getInstance().currentScenceController as FirstController).player;
                isFollowPlayer = true;
            }           
            else
            {
                isFollowPlayer = false;
                state = PatrolState.PATROL;
                player = null;
                isMoving = false;
            }
        }
        
    }
}

巡逻兵工厂

public class PatrolFactory:MonoBehaviour
{
    private List<GameObject> used = new List<GameObject>();    // the used patrol
    private Vector3[] PatrolPos = new Vector3[3];
    private bool isProduce = false;
    FirstController firstController;
    private void Start()
    {
        firstController = SSDirector.getInstance().currentScenceController as FirstController;
    }
    public List<GameObject> GetPatrols()
    {
        firstController = SSDirector.getInstance().currentScenceController as FirstController;
        if (!isProduce)
        {
            int index = 0;
            float[] posZ = { 3.75f, -3.75f };
            float[] posX = { 3.75f, -3.75f };
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    if(posX[j] > 0 && posZ[i] > 0)
                    {
                        continue;
                    }
                    PatrolPos[index++] = new Vector3(posX[j], 0, posZ[i]);
                }
            }
            for (int i = 0; i < 3; i++)
            {
                GameObject patrol = Instantiate(Resources.Load<GameObject>("Prefabs/Patrol"));
                patrol.transform.parent = firstController.plane.transform;
                patrol.transform.position = PatrolPos[i];
                patrol.GetComponent<Patrol>().sign = i + 1;
                patrol.GetComponent<Patrol>().startPos = PatrolPos[i];
                used.Add(patrol);
            }
            isProduce = true;
        }     
        return used;
    }

    public void destoryFactory()
    {
        foreach(var a in used)
        {
            DestroyImmediate(a);
        }
        used = new List<GameObject>();
        isProduce = false;
    }
}

场景障碍物

public class AreaCollide : MonoBehaviour
{
    public int sign;
    public delegate void CanFollow(int state,bool isEnter);
    public static event CanFollow canFollow;

    public delegate void AddScore();
    public static event AddScore addScore;
    void OnTriggerEnter(Collider collider)
    {
        if (collider.gameObject.tag == "Player")
        {
            canFollow(sign,true);
        }
    }
    private void OnTriggerExit(Collider collider)
    {
        if (collider.gameObject.tag == "Player")
        {
            canFollow(sign,false);
            addScore();
        }
    }
}
2015-02-05 08:34:06 book_longssl 阅读数 5174

导入动画文件后,在工程(Porject)面板中选中,通过Inspector面板修改参数设置。

在项目视图中选中模型文件。如果想用旧版3.x的动画系统导入和编辑动画,请选择legacy选项。如果你有一个人性角色,比如,一个脑袋两条胳膊的两足动物,请选择Humanoid和‘Create from this model’,这样,一个完美匹配你角色骨骼关系的替身就可以被创建,或者你也可以选择其他预设好的替身。

如果你的角色不是人形物体,比如一个四足动物或者任何其它的你想编辑动画的物体-并且你希望新的动画系统Mecanim,请选择Generic选项,然后你必须在下拉菜单中为你的动画模型定义一个骨骼作为根节点。

Model选项卡

属性

Scale Factor 缩放系数。

Mesh Compression网格压缩.降低网格文件大小,但有可能导致变形。

Mesh Optimization 网格优化.优化三角形的排列顺序。

Generate Colliders产生碰撞体。生成网格碰撞体。

Swap UVs交换UV(通过改变纹理坐标,实现动态效果的纹理动画)当有光照贴图的物体的UV通道不正确时启用此选项。这将交换你的主UV通道与次UV通道。

Generate Lightmap产生光照贴图。

Normals 法线

Import 导入. 从文件导入法线。

Calculate 计算。根据平滑角度(Smoothing angle)计算法线。

None 不使用。如果网格既没有法线贴图,也不受实时光照影响,则可使用此选项。

Tangents 切线

Import 导入

Calculate计算切线和副法线。只有当法线为导入或计算时,此选项可用。

None禁用切线和副法线。如网格没有切线则不能使用法线贴图着色器。

Smoothing Angle 平滑角。设置边会被作为硬边处理的锋利程度。它还被用来切分法线贴图切线。

Split Tangents 分离切线。如果您的网格上的接缝破坏了法线贴图光照,启用此选项。这通常只适用于角色。

Import Materials 导入材质

Material Naming 材质命名。 此选项决定了Unity材质的命名方式.

Material Search 材质搜索。决定Unity如何根据材质命名选项中定义的名字查找已有的材质。

Rig选项卡

属性

Animation Type 动画类型

None 无

没有预制动画

Legacy 旧版

旧版系统动画

Generic 通用

通用Mecanim动画

Humanoid 人形

人形Mecanim动画系统

Avatar Definition 替身定义

在这里定义动画控制融合等。

Create from this model    从这个模型创建

替身物体将依据选择的模型创建

Copy from other Avatar    从其它替身拷贝

依据其它模型替身定义创建

Configure... 配置...

动画剪辑存储着所有可使用于角色动画或简单动画的动画数据。

unity3D 帧动画制作

博文 来自: zzlyym
没有更多推荐了,返回首页