码迷,mamicode.com
首页 > 其他好文 > 详细

创建人物——03状态机

时间:2015-11-17 08:21:39      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:

学习笔记适合新手,如有错误请指正。?号处也请各位指点下,谢谢。

状态机(State Machine)主要用作状态管理和状态切换,如跑、跳、休息等都是一个单独的状态,各自有对应的动画

Idle:休息状态

Run:跑步状态

Jump:跳跃状态

Animator

技术分享

Controller增加Animator Controller,并重名为playerController

点击导航菜单栏》Window》Animator导航项,打开Animator视图

技术分享

左上角显示选中Base Layer,即当前编辑的是Base Layer动画层,我们还可以点击“+”按钮创建新的动画层,一个动画层对应一个状态机,一般来说,不同的动画层控制身体的不同部分

图中每一个长方形图案都是一个State状态,其中Entry是初始状态

创建跑步状态:在编辑区域内点击鼠标右键》Create State》Empty

选中State》第一行我们重命名为Run》将动画文件制定至Motion一栏,这样我们就建好了一个完整的带有动画的State

运行场景,在Scene视图中,看见人物在场景中会一直向前跑动,但是人物会穿出墙外,我们还需要做3件事:

1增加碰撞体

2添加摄像机

3添加控制功能

添加碰撞体

Character Controller是一个继承自Collier的类,

点击Inspector最下方的Add Component按钮,搜索栏输入“Character Controller”并添加,并将Character Controller所发呆的胶囊体与人类模型对齐

添加摄像机

创建摄像机并添加名为ThirdPersonCan的脚本

using UnityEngine;
using System.Collections;

public class ThirdPersonCam : MonoBehaviour
{
    //摄像机所跟随的对象
    public Transform follow;
    //摄像机在水平方向与对象的距离
    public float distanceAway;        
    //摄像机在垂直方向与对象的距离
    public float distanceUp;
    //过渡速度
    public float smooth;                
    //摄像机的目标速度
    private Vector3 targetPosition;        
    
    //在LateUpdate中执行摄像机操作,确保在对象的操作完成之后
    void LateUpdate ()
    {
        //计算目标位置
        targetPosition = follow.position + Vector3.up * distanceUp - follow.forward * distanceAway;
        //对当前位置进行插值计算
        transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smooth);
        //使摄像机观察对象
        transform.LookAt(follow);
    }
}

将参数设置如下:

Follow:设置为player游戏对象

Distance Away:设置为5

Distance Up:设置为2

Smooth:设置为3

动作混合与控制

动作混合是动画系统中比较重要的功能

例如:人物有向前跑的动作和向左侧跑的动作,将两者混合就是向左方跑的动作了

1动作混合

回到Animator视图

创建一个名为Direction的float参数(设置BlendTree混合树的时候会用到)

在Animator的左上角点击Parameters标签,进入Animator的参数表视图》点击“+”》“Float”按钮创建参数并起名“Direction”

用同样的方法创建float参数“Speed”,改参数在之后从Idle和Run的状态间切换时会用到

最后创建Bool参数Jump,该参数在之后从Run到Jump的状态间切换时会用到

技术分享

创建好Direction参数,创建Blend Tree,Blend Tree是不同动画的混合

选中Run状态,右键》“Create New BlendTree In State”按钮》双击Run状态进入BlendTree

技术分享

点击“+”》“Add Motion Field”按钮添加动作,并将动画文件指定至图Motion一栏,然后继续添加Run和Run Right动作

技术分享

Parameter参数一栏通过右侧的三角形下拉菜单选择之前创建的Direction参数,该参数决定着动作如何混合,在这里可理解为角色是向左跑还是向右跑

点击波形图下方的“0”。并输入-1.

波形图中左侧第一个三角形代表RunLeft,中间的陂型代表Run,右侧的波形代表RunRight,使用Rarameter Direction控制的

当为-1时,RunLeft向左跑动画

当为0时向前跑

当为1时是向右跑

当为之间的值时,比如0.5是向前跑和向右跑的混合,也就是向右前方跑

2动作控制

输入控制部分,我们主要用到Input.GetAxis()和Animator.SetFloat()这两个借口

Input.GetAxis():返回axis,也就是控制轴的值,

  也可以通过点击导航菜单栏》Edit》Project Setting》Input菜单进入输入设置界面,在这个界面里,我们不仅可以定义水平轴和垂直轴的名称和参数,还可以定义其他按钮的名称和参数

  GetAxis返回的值域是-1到1

Animator.SetFloat():设置Animator的float参数

例如,Run这个BlendTree中的Direction就可以通过这个参数来设置

它的函数签名是public void SetFloat(string name,Float value,float dampTime,float deltaTime);

Name:参数的名称

Value:值

dampTime:参数到达该值所需要的时间

deltaTime:上一帧所消耗的时间

例如:

Animator.SetFloat("Direction",x);

animator.SetFloat("Direction",x,0.25f,Time.deltaTime);

接下来把Input.GetAxis()和animator.SetFloat()这两个接口结合了,创建一个名为“PlayerManager”的脚本,添加到player游戏对象上

using UnityEngine;
using System.Collections;

public class PlayerManager_1 : MonoBehaviour {
    private Animator animator;
    void Awake()
    {
        animator = GetComponent<Animator>();
    }
    void Update () 
    {
        //得到Joystick水平轴向输入的值
        float h = Input.GetAxis("Horizontal");    
        //将该值传递至animator的Direction参数
        animator.SetFloat("Direction", h, 0.25f, Time.deltaTime);    
    }
}

运行场景,可以用键盘的A/D键或者左箭头右箭头来控制角色,可以通过Animator视图观察状态变化

接下来我们在添加(Idle)休息状态,并将动画文件赋予Idle的栏

在代码中通过垂直轴对Speed赋值的功能

using UnityEngine;
using System.Collections;

public class PlayerManager_2 : MonoBehaviour {
    private Animator animator;
    void Awake()
    {
        animator = GetComponent<Animator>();
    }
    void Update () 
    {
        //得到Joystick水平轴向输入的值
        float v = Input.GetAxis("Vertical");
        //得到Joystick水平轴向输入的值
        float h = Input.GetAxis("Horizontal");
        //将该值传递至animator的Speed参数
        animator.SetFloat("Speed", h*h+v*v);
        //将该值传递至animator的Direction参数
        animator.SetFloat("Direction", h, 0.25f, Time.deltaTime);    
    }
}

运行游戏,开始时角色在休息状态,按W/D不在移动,因为需要从垂直轴向得到的Speed才能从休息状态切换到跑步状态

最后添加jump状态,本例设定需要移动的助跑才能跳,也就是不能从休息状态切换到跳跃状态,只能从跑动状态切换至跳跃状态

添加开火按钮,代码如下:

using UnityEngine;
using System.Collections;

public class PlayerManager_3: MonoBehaviour {
    private Animator animator;
    void Awake()
    {
        //得到Animator组件
        animator = GetComponent<Animator>();
    }
    void Update () 
    {
            //得到Joystick水平轴向输入的值
            float v = Input.GetAxis("Vertical");
            //得到Joystick水平轴向输入的值
            float h = Input.GetAxis("Horizontal");
            //将该值传递至animator的Speed参数
            animator.SetFloat("Speed", h*h+v*v);
            //将该值传递至animator的Direction参数
            animator.SetFloat("Direction", h, 0.25f, Time.deltaTime);    


            //得到Animator中序号为0的layer,也就是Base Layer的状态信息
            AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);        
            if (stateInfo.shortNameHash == Animator.StringToHash("Run"))
            {
                //Base Layer为Run状态,当检测到按下开火按钮,设置Jump为true
                if (Input.GetButton("Fire1")) animator.SetBool("Jump", true);                
            }
            else
            {
                //当Base Layer为其他状态时,设置Jump为false
                animator.SetBool("Jump", false);                
            }
    }
}

运行场景,角色已经可以跳了,但是依然存在两个问题

当角色跳跃时,我们观察Scene视图,发现在跳跃时角色身体会缩成一团,但是绿色的碰撞体却没有相应的变化

从平台上跳下,并没有落地却已回到跑步状态

待续。。。。。。。。。。。。2015-11-16

 

创建人物——03状态机

标签:

原文地址:http://www.cnblogs.com/kubll/p/4970606.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!