动画之人物移动旋转
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动画之⼈物移动旋转
⼀、动画状态机控制
1、导⼊⼈物动画,调整为⼈形动画,做好前期准备⼯作(修改动画是否循环,动画范围,动画旋转锁定,Y轴,XZ轴锁定等)
2、添加Animator组件,创建动画状态机
3、打开动画状态机,把⼈物待机、⾛路、跑步、向左跑、向右跑的动画添加到状态机中。
4、添加参数Speed、ISRun、TurnRun/移动速度、是否跑步、转向速度
⼆、混合树Blend Tree
1、1D混合树控制⼀个⽅向运动
在Animator⾯板下创建BlendTree,双击BlendTree进⼊编辑界⾯
2、2D混合树通过两个变量控制,⼀个使⽤速度控制PosY,另⼀个是⽤⾓度控制PosX
三、功能代码
1.相机跟随移动
1public Transform playerTran;//⽬标⼈物
2 Vector
3 offset;
3float smoothing=2;
4private void Start()
5 {
6 offset = transform.position - playerTran.position;//相机位置与⼈的位置差
7 }
8private void Update()
9 {
10 Vector3 targetPosition = playerTran.position + playerTran.TransformDirection(offset);
11 transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smoothing);
12 transform.LookAt(playerTran.position);
13 }
public class PlayerAnimationController : MonoBehaviour
{
public Animator playerAni;
int speedID = Animator.StringToHash("Speed");
int IsRunID = Animator.StringToHash("IsRun");
int turnRun = Animator.StringToHash("TurnRun");
void Update()
{
playerAni.SetFloat(speedID, Input.GetAxis("Vertical"));//控制移动
playerAni.SetFloat(turnRun, Input.GetAxis("Horizontal"));//控制转向
if (Input.GetKeyDown(KeyCode.LeftShift))//控制是否加速
{
playerAni.SetBool(IsRunID, true);
}
else if (Input.GetKeyUp(KeyCode.LeftShift))
{
playerAni.SetBool(IsRunID, false);
}
}
}
四、控制⼈物FQ
1、将修改完的FQ动画添加到状态机中,新添加变量SpeedX、SpeedY、IsOverTheWall
2、添加功能
int speedX = Animator.StringToHash("SpeedX");//转向的速度
int speedY = Animator.StringToHash("SpeedY");//前进的速度
int IsOverTheWall = Animator.StringToHash("IsOverTheWall");//FQ
bool isOverTheWall = false;//是否FQ
private Vector3 margetPosition=Vector3.zero;//FQ匹配的位置
//FQ
void PlayerVault()
{
isOverTheWall = false;
playerAni.SetFloat(speedX, Input.GetAxis("Horizontal") * 126);
playerAni.SetFloat(speedY, Input.GetAxis("Vertical") * 3.6f);
if (playerAni.GetFloat(speedY) > 2 && playerAni.GetCurrentAnimatorStateInfo(0).IsName("Locomotion"))
{
RaycastHit hit;
if (Physics.Raycast(transform.position + Vector3.up * 0.3f, transform.forward, out hit, 4))
{
if (hit.collider.tag == "Obstacle")
{
if (hit.distance > 3)
{
Vector3 point = hit.point;
point.y = hit.collider.transform.position.y + hit.collider.bounds.size.y + 0.1f;
margetPosition = point;//⽬标位置
isOverTheWall = true;
}
}
}
}
playerAni.SetBool(IsOverTheWall, isOverTheWall);
if (playerAni.GetCurrentAnimatorStateInfo(0).IsName("Vault") && playerAni.IsInTransition(0) == false)
{
//指定了匹配的位置、⾓度、⾝体的具体部位、权重、匹配开始时间和结束时间
playerAni.MatchTarget(margetPosition, Quaternion.identity, AvatarTarget.LeftHand, new MatchTargetWeightMask(Vector3.one, 0), 0.32f, 0.4f); }
}
3、给⼈物添加CharacterController,在动画状态机中新添加变量Collider来控制播放FQ动画是⾓⾊控制器与墙不发⽣碰撞
4、设置FQ动画下Curves,先确定两帧(开始FQ和结束FQ),编辑两个点⼤于0.5,并把设置的Collider变量放置在Curves上
5、效果展⽰
五、控制⼈物滑动
1、将修改完的滑动动画添加到状态机中,新添加变量Slider控制是否滑动
2、动画状态机连接情况如图
3、添加功能代码
int slider = Animator.StringToHash("Slider");//滑动
int playcollider = Animator.StringToHash("Collider");
void Update()
{
PlayerSlider();
PlayerVault();
playerCharacterController.enabled = playerAni.GetFloat(playcollider) < 0.45f;
}
//滑动
void PlayerSlider()
{
bool IsSlider = false;
if (playerAni.GetFloat(speedY) > 2 && playerAni.GetCurrentAnimatorStateInfo(0).IsName("Locomotion"))
{
RaycastHit hit;
if (Physics.Raycast(transform.position + Vector3.up * 1.5f, transform.forward, out hit, 3))
{
if (hit.collider.tag == "Obstacle")
{
if (hit.distance > 2)
{
Vector3 point = hit.point;
point.y = -10;
margetPosition = point + transform.forward * 2;
IsSlider = true;
}
}
}
}
playerAni.SetBool(slider, IsSlider);
if (playerAni.GetCurrentAnimatorStateInfo(0).IsName("Slide") && playerAni.IsInTransition(0) == false)
{
Debug.Log("滑动");
playerAni.MatchTarget(margetPosition, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(1, 0, 1), 0), 0.17f, 0.67f);
}
}
4、同样也给滑动动画下Curves添加Collider,在播放动画时关闭⾓⾊控制器
5、效果展⽰
六、动画状态机Layers层设置
Weight:1(对其他层的动画的影响权重值,1:完全影响(如果Blending为Additive的话,那么会将所有层的Additive的Weight的值进⾏同时计算),0:完全不影响)
Mask:HandWaveLMask(下⾯有图,我们只要保留左⼿绿⾊即可)
Blending:Override(该层的动画将会覆盖其他的)
1、举⽊头动画切换
2、由于举⽊头动画与移动动画有影响,创⾻骼遮罩在Projects——>Avatar Mask设置⾻骼遮罩
3、通过IK设置左右⼿位置,与⽊头更加吻合
勾选上图中IK Pass,添加两个点是左右⼿位置
代码如下:
1public Transform leftHandPos;//左⼿位置
2public Transform rightHandPos;//右⼿位置
3int holdLog = Animator.StringToHash("IsHoldLog");//是否举起
4private void OnTriggerEnter(Collider other)
5 {
6if (other.tag=="Wood")
7 {
8 Destroy(other.gameObject);
9 CreateWood();
10 }
11 }
12//显⽰⽊头
13void CreateWood()
14 {
15 newWood.SetActive(true);
16 playerAni.SetBool(holdLog, true);
17 }
18//通过IK动画设置举⽊头⼿的位置
19private void OnAnimatorIK(int layerIndex)
20 {
21float Weight = playerAni.GetBool(holdLog) ? 1 : 0;
22if (layerIndex == 1)
23 {
24//左⼿
25 playerAni.SetIKPosition(AvatarIKGoal.LeftHand, leftHandPos.position);//设置左⼿位置
26 playerAni.SetIKPositionWeight(AvatarIKGoal.LeftHand, Weight);//设置左⼿权重
27 playerAni.SetIKRotation(AvatarIKGoal.LeftHand, leftHandPos.rotation);//设置左⼿旋转
28 playerAni.SetIKRotationWeight(AvatarIKGoal.LeftHand, Weight);
29//右⼿
30 playerAni.SetIKPosition(AvatarIKGoal.RightHand, rightHandPos.position);
31 playerAni.SetIKPositionWeight(AvatarIKGoal.RightHand, Weight);
32 playerAni.SetIKRotation(AvatarIKGoal.RightHand, rightHandPos.rotation);
33 playerAni.SetIKRotationWeight(AvatarIKGoal.RightHand, Weight);
34
35 }
36 }
4、效果如图。