首先,创建一个空的工程,并导入标准资源库和机器人凯莉资源包。

unity 人物动画保持第一帧 unity3d人物动画_权重

unity 人物动画保持第一帧 unity3d人物动画_System_02

>>例行消除Unity标准资源包的报错

找到机器人模型

unity 人物动画保持第一帧 unity3d人物动画_System_03

这个是它的骨骼

unity 人物动画保持第一帧 unity3d人物动画_System_04

由于是新版unity,修改为人形

unity 人物动画保持第一帧 unity3d人物动画_Time_05

创建一个平面,导入机器人模型,然后创建一个球体

unity 人物动画保持第一帧 unity3d人物动画_System_06

把球体绑定到头上

unity 人物动画保持第一帧 unity3d人物动画_Time_07

创建动画状态集Curve

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_08

错误步骤:

unity 人物动画保持第一帧 unity3d人物动画_System_09

正确步骤:

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_10

错因:看错了,应该选HumannoidRun,而不是RobotBoyRun

单击选择HumanoidRun

unity 人物动画保持第一帧 unity3d人物动画_Time_11

在属性里找到曲线,添加曲线并通过曲线控制动画的播放

unity 人物动画保持第一帧 unity3d人物动画_Time_12

添加关键帧

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_13

unity 人物动画保持第一帧 unity3d人物动画_权重_14

一会儿跑慢,一会儿跑快

添加两个曲线,用这两个曲线获取参数,一个控制泡泡的大小,一个控制泡泡的颜色

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_15

若这两个曲线未添加,则不会有任何变化的效果

添加两个参数

unity 人物动画保持第一帧 unity3d人物动画_权重_16

将编辑好的动画状态集绑定到机器人上

unity 人物动画保持第一帧 unity3d人物动画_权重_17

这样机器人就跑起来了

如果想让机器人在原地运动,取消应用根运动即可

unity 人物动画保持第一帧 unity3d人物动画_权重_18

效果

unity 人物动画保持第一帧 unity3d人物动画_权重_19

附:

unity 人物动画保持第一帧 unity3d人物动画_权重_20

创建一个脚本

unity 人物动画保持第一帧 unity3d人物动画_Time_21

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Curve : MonoBehaviour { public GameObject bubble; Vector3 originalScale;//设定初始泡泡大小 private Color originalColor;//设定初始颜色 Animator anim;//先定义一个动画器对象 // Start is called before the first frame update void Start() { anim = GetComponent<Animator>();//获取动画组件 originalScale = bubble.transform.localScale; originalColor = bubble.GetComponent<Renderer>().material.color; } // Update is called once per frame void Update() { float curve1 = anim.GetFloat("Curve1")*5;//通过调用动画对象的GetFloat函数来获取值,来修改泡泡的大小 float curve2 = anim.GetFloat("Curve2");///通过调用动画对象的GetFloat函数来获取值,来修改泡泡的颜色 bubble.transform.localScale = new Vector3(originalScale.x + curve1, originalScale.y + curve1, originalScale.z + curve1);//根据走路节奏调整泡泡大小,让其或大或小 bubble.GetComponent<Renderer>().material.color = new Color(originalColor.r* 100 * curve2, 0f, 0f, 0.2f);//调用对象的组件直接修改颜色 } }

绑定到机器人上,并指定bubble为Sphere

效果

机器人边跑边吹泡泡,泡泡的大小和颜色随着跑步的节奏改变

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_22

unity 人物动画保持第一帧 unity3d人物动画_System_23

附:

一定要记得随时保存场景

场景另存为场景1,再另存为场景2,在场景2中操作

取消泡泡

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_24

然后移除Curve脚本

创建一个动画状态集Layer

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_25

unity 人物动画保持第一帧 unity3d人物动画_System_26

unity 人物动画保持第一帧 unity3d人物动画_权重_27

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_28

效果

机器人走了起来

unity 人物动画保持第一帧 unity3d人物动画_Time_29

创建一个图层

unity 人物动画保持第一帧 unity3d人物动画_Time_30

unity 人物动画保持第一帧 unity3d人物动画_System_31

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_32

调整权重,同时执行两个动画

边走路边胳膊举起

unity 人物动画保持第一帧 unity3d人物动画_System_33

上下半身动作分离

创建一个遮罩

unity 人物动画保持第一帧 unity3d人物动画_System_34

下半身遮罩

unity 人物动画保持第一帧 unity3d人物动画_权重_35

unity 人物动画保持第一帧 unity3d人物动画_权重_36

下半身

unity 人物动画保持第一帧 unity3d人物动画_System_37

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_38

上半身

unity 人物动画保持第一帧 unity3d人物动画_权重_39

unity 人物动画保持第一帧 unity3d人物动画_System_40

效果

上半身挥手(起跳),下半身跑步

unity 人物动画保持第一帧 unity3d人物动画_权重_41

存在问题

不能循环播放动画

设置动画循环播放的方法

添加自循环,条件参数为loop,ture时循环

unity 人物动画保持第一帧 unity3d人物动画_权重_42

创建脚本

实现点击鼠标左键,让机器人循环抬手,点击右键则始终不抬手

unity 人物动画保持第一帧 unity3d人物动画_System_43

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Layer : MonoBehaviour { public float speed = 1f; private Animator anim; // Start is called before the first frame update void Start() { anim = GetComponent<Animator>(); } // Update is called once per frame void Update() { if(Input.GetMouseButton(0)) { float w=anim.GetLayerWeight(1) > 1 ? 1: anim.GetLayerWeight(1) + speed * Time.deltaTime; anim.SetLayerWeight(1, w); } if (Input.GetMouseButton(1)) { float w = anim.GetLayerWeight(1) > 0 ? 0 : anim.GetLayerWeight(1) + speed * Time.deltaTime; anim.SetLayerWeight(1, w); } } }

IK 反向运动学(注视动画)

知道末端节点(手)的位置,怎么通过反向的演算,知道其他节点(身体)的位置

比如眼睛看一个地方,手要动,头要动,还要弯腰

创建一个动画状态集

unity 人物动画保持第一帧 unity3d人物动画_System_44

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_45

unity 人物动画保持第一帧 unity3d人物动画_Time_46

效果

人晃了起来

unity 人物动画保持第一帧 unity3d人物动画_System_47

勾选IK处理,图层就支持IK反向动力学计算

unity 人物动画保持第一帧 unity3d人物动画_Time_48

创建一个脚本

unity 人物动画保持第一帧 unity3d人物动画_权重_49

using System.Collections; using System.Collections.Generic; using UnityEngine; public class IKLook : MonoBehaviour { Animator anim;//要用动画组件 Ray ray;//定义射线 RaycastHit raycastHit;//射线和地面有交叉,要定义一个射线相交的变量,就是一个注视点 // Start is called before the first frame update void Start() { anim = GetComponent<Animator>();//获取组件 } // Update is called once per frame void Update() { } private void OnAnimatorIK(int layerIndex)//反向动力学计算代码不在update,而是专门有一个函数 { //生成一个物理射线,把它与地面相交的点作为注视点 ray = Camera.main.ScreenPointToRay(Input.mousePosition);//发射向鼠标指向的位置 if(Physics.Raycast(ray,out raycastHit))//调用物理引擎的Raycast函数判断射线有没有相交 { Vector3 target = raycastHit.point;//如果有相交,把相交点作为一个目标 anim.SetLookAtPosition(target);//注视目标的函数,把地面相交的点作为注视点 anim.SetLookAtWeight(1f, 0.5f, 0.8f, 0.9f);//设定不同节点的权重 } } }

tips

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_50

效果

鼠标指向哪个地方,机器人就看哪个地方,并且手、头、背均有牵引运动

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_51

创建一个新场景

创建一个球体,放手边

给球体创建一个动画,让球上下运动

unity 人物动画保持第一帧 unity3d人物动画_System_52

创建一个空对象作为参照物

unity 人物动画保持第一帧 unity3d人物动画_权重_53

把参照物放在球心

unity 人物动画保持第一帧 unity3d人物动画_权重_54

然后把参照物作为机器人子物体

unity 人物动画保持第一帧 unity3d人物动画_权重_55

创建动画状态集

unity 人物动画保持第一帧 unity3d人物动画_权重_56

unity 人物动画保持第一帧 unity3d人物动画_Time_57

unity 人物动画保持第一帧 unity3d人物动画_System_58

unity 人物动画保持第一帧 unity3d人物动画_Time_59

效果

unity 人物动画保持第一帧 unity3d人物动画_Time_60

千万不要让Unity一直播放

unity 人物动画保持第一帧 unity3d人物动画_权重_61

创建脚本

unity 人物动画保持第一帧 unity3d人物动画_Time_62

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Animator))]//强制添加安妮梅特组件

public class IKMove : MonoBehaviour
{
    public GameObject target;//创建够的目标的变量
    public GameObject hint;//参照物

    Animator anim;
    public bool isHand = true;

    // Start is called before the first frame update
    void Start()
    {
        anim = GetComponent<Animator>();//获取组件
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void OnAnimatorIK(int layerIndex)
    {
        AvatarIKGoal g = isHand ? AvatarIKGoal.RightHand : AvatarIKGoal.RightFoot;
        AvatarIKHint h = isHand ? AvatarIKHint.RightElbow : AvatarIKHint.RightKnee;

        anim.SetIKPositionWeight(g, 1f);//设置位置的权重
        anim.SetIKPosition(g, target.transform.position);//设置位置
        anim.SetIKRotationWeight(g, 1f);//设置旋转及其权重
        anim.SetIKRotation(g, target.transform.rotation);

        anim.SetIKHintPositionWeight(h, 1f);
        anim.SetIKHintPosition(h, hint.transform.position);
    }

}

绑定到机器人上并如下图设置参数

unity 人物动画保持第一帧 unity3d人物动画_System_63

动画状态集指定IK

unity 人物动画保持第一帧 unity3d人物动画_权重_64

效果

机器人用手够这个球

unity 人物动画保持第一帧 unity3d人物动画_Time_65

取消IsHand

unity 人物动画保持第一帧 unity3d人物动画_System_66

机器人用脚够这个球

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_67

创建一个新场景和一个状态集

unity 人物动画保持第一帧 unity3d人物动画_Time_68

创建一个融合树节点

一维运动方向

unity 人物动画保持第一帧 unity3d人物动画_Time_69

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_70

调节此处可以修改运动方式

unity 人物动画保持第一帧 unity3d人物动画_权重_71

二维运动方向

unity 人物动画保持第一帧 unity3d人物动画_Time_72

添加参数

unity 人物动画保持第一帧 unity3d人物动画_权重_73

动画集参数设定(忘记了就不会动)

unity 人物动画保持第一帧 unity3d人物动画_System_74

unity 人物动画保持第一帧 unity3d人物动画_Time_75

unity 人物动画保持第一帧 unity3d人物动画_System_76

unity 人物动画保持第一帧 unity3d人物动画_System_77

创建一个脚本

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_78

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;//跨平台输入
[RequireComponent(typeof(Animator))]//强制绑定安妮梅特组件,如果这个对象没有,那么就自动添加上
public class BlendTree : MonoBehaviour
{
    Animator anim;

    // Start is called before the first frame update
    void Start()
    {
        anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        float h = CrossPlatformInputManager.GetAxis("Horizontal");
        float v = CrossPlatformInputManager.GetAxis("Vertical");

        Vector3 moveDirection = h * Vector3.right + v * Vector3.forward;//获取运动方向矢量

        if(Input.GetKey(KeyCode.LeftShift))
        {
            moveDirection.z *= 0.5f;
        }

        float turn = moveDirection.x;
        float forward = moveDirection.z;

        anim.SetFloat("speed", forward, 0.1f, Time.deltaTime);
        anim.SetFloat("turn", turn, 0.1f, Time.deltaTime);
    }
}

效果

慢速行走,快速跑步,零速静止,左转右转动画显示正常

unity 人物动画保持第一帧 unity3d人物动画_权重_79

附: 

unity 人物动画保持第一帧 unity3d人物动画_unity 人物动画保持第一帧_80

若忘记设定参数,改成这个代码才能动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;//跨平台输入
[RequireComponent(typeof(Animator))]//强制绑定安妮梅特组件,如果这个对象没有,那么就自动添加上
public class BlendTree : MonoBehaviour
{
    Animator anim;

    public Rigidbody rbody;//公开到显示面板
    public float speed = 30f;//速度预先定义在外部

    // Start is called before the first frame update
    void Start()
    {
        anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        float h = CrossPlatformInputManager.GetAxis("Horizontal");
        float v = CrossPlatformInputManager.GetAxis("Vertical");

        rbody.MovePosition(rbody.position + transform.right * h * Time.deltaTime * speed);//刚体左右移动
        rbody.MovePosition(rbody.position + transform.forward * v * Time.deltaTime * speed);//刚体上下移动

        Vector3 moveDirection = h * Vector3.right + v * Vector3.forward;//获取运动方向矢量

        if(Input.GetKey(KeyCode.LeftShift))
        {
            moveDirection.z *= 0.5f;
        }

        float turn = moveDirection.x;
        float forward = moveDirection.z;

        anim.SetFloat("speed", forward, 0.1f, Time.deltaTime);
        anim.SetFloat("turn", turn, 0.1f, Time.deltaTime);
    }
}