首先,创建一个空的工程,并导入标准资源库和机器人凯莉资源包。
找到机器人模型
这个是它的骨骼
由于是新版unity,修改为人形
创建一个平面,导入机器人模型,然后创建一个球体
把球体绑定到头上
创建动画状态集Curve
错误步骤:
正确步骤:
错因:看错了,应该选HumannoidRun,而不是RobotBoyRun
单击选择HumanoidRun
在属性里找到曲线,添加曲线并通过曲线控制动画的播放
添加关键帧
一会儿跑慢,一会儿跑快
添加两个曲线,用这两个曲线获取参数,一个控制泡泡的大小,一个控制泡泡的颜色
若这两个曲线未添加,则不会有任何变化的效果
添加两个参数
将编辑好的动画状态集绑定到机器人上
这样机器人就跑起来了
如果想让机器人在原地运动,取消应用根运动即可
效果
附:
创建一个脚本
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
效果
机器人边跑边吹泡泡,泡泡的大小和颜色随着跑步的节奏改变
附:
一定要记得随时保存场景
场景另存为场景1,再另存为场景2,在场景2中操作
取消泡泡
然后移除Curve脚本
创建一个动画状态集Layer
效果
机器人走了起来
创建一个图层
调整权重,同时执行两个动画
边走路边胳膊举起
上下半身动作分离
创建一个遮罩
下半身遮罩
下半身
上半身
效果
上半身挥手(起跳),下半身跑步
存在问题
不能循环播放动画
设置动画循环播放的方法
添加自循环,条件参数为loop,ture时循环
创建脚本
实现点击鼠标左键,让机器人循环抬手,点击右键则始终不抬手
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 反向运动学(注视动画)
知道末端节点(手)的位置,怎么通过反向的演算,知道其他节点(身体)的位置
比如眼睛看一个地方,手要动,头要动,还要弯腰
创建一个动画状态集
效果
人晃了起来
勾选IK处理,图层就支持IK反向动力学计算
创建一个脚本
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一直播放
创建脚本
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);
}
}
绑定到机器人上并如下图设置参数
动画状态集指定IK
效果
机器人用手够这个球
取消IsHand
机器人用脚够这个球
创建一个新场景和一个状态集
创建一个融合树节点
一维运动方向
调节此处可以修改运动方式
二维运动方向
添加参数
动画集参数设定(忘记了就不会动)
创建一个脚本
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);
}
}
效果
慢速行走,快速跑步,零速静止,左转右转动画显示正常
附:
若忘记设定参数,改成这个代码才能动
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);
}
}