unity native2D教程第六课:Hero的状态机设置与人物的
状态机创建与设置
首先,我们要在Unity的Assets文件夹里创建一个Animator Controller,将其命名为Character。这个Character控制器就是我们Hero角色的Animator组件需要添加的控制器。
基础层(Base Layer)状态设置
在Base Layer中,我们需要创建五个状态(State),分别为Idle(闲置)、Run(奔跑)、Jump(跳跃)、Death(死亡)和Falling(下落)。创建好这些状态后,把之前创建好的动画剪辑(animation Clip)赋予到对应的状态的Motion参数上。
接着,在Animator窗口的左下角添加4个参数:
speed:类型为float,用于控制角色的移动速度。Jump:类型为Trigger,用于触发跳跃动作。Shoot:类型为Trigger,用于触发射击动作。Die:类型为Trigger,用于触发死亡动作。
状态转换设置
- Idle与Run状态转换:通过
speed参数来连接Idle和Run状态。在Inspector视图的conditions选项中进行设置,从Idle到Run状态,条件选择greater(即speed大于某个值时触发);反之,从Run到Idle状态,条件选择less。 - Run与Jump状态转换:使用
Jump参数连接Run和Jump状态。从Run到Jump,在condition中选择Jump;从Jump到Run,condition选择speed且设置为greater大于0.1,同时设置exit time为0.58。 - Idle与Jump状态转换:同样通过
Jump参数连接Idle和Jump状态。 - Death和Falling状态转换:在
any State(任意状态)中连接Death和Falling状态。
具体设置详情可参考下图:
射击层(Shooting Layer)设置
为了实现Hero角色在移动的同时能够进行射击,我们在Animator窗口的右上角增加一个shooting层。如果将射击状态放在Base Layer层,Hero会先停止当前的状态动画才去进行射击动画,这不符合我们的需求。
在shooting层,我们将weight(权重)设置为1,Blending选项设置为Override。这样,Hero就可以在移动的同时进行射击,两者互不影响。从Any State到shoot状态的触发器设置condition为shoot。设置效果如下图所示:
如果大家对状态机这部分的设置看上面的图不清晰,可以查看原来的项目。
脚本控制部分
接下来,我们进入脚本控制部分,开始编写Hero的控制脚本。创建一个名为PlayerControl的脚本,并将其挂载到Hero角色上。以下是实现角色移动的代码:
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour
{
[HideInInspector]
public bool facingRight = true;
[HideInInspector]
public bool jump = false;
public float moveForce = 365f;
public float maxSpeed = 5f;
private Animator anim;
private Rigidbody2D rigidbody2D;
void Awake()
{
anim = GetComponent<Animator>();
rigidbody2D = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
// 缓存水平输入
float h = Input.GetAxis("Horizontal");
// 设置Animator的Speed参数为水平输入的绝对值
anim.SetFloat("Speed", Mathf.Abs(h));
// 如果玩家改变方向(h与velocity.x符号不同)或者还未达到最大速度
if (h * rigidbody2D.velocity.x < maxSpeed)
{
// 给玩家施加一个水平方向的力
rigidbody2D.AddForce(Vector2.right * h * moveForce);
}
// 如果玩家的水平速度大于最大速度
if (Mathf.Abs(rigidbody2D.velocity.x) > maxSpeed)
{
// 将玩家的水平速度设置为最大速度
rigidbody2D.velocity = new Vector2(Mathf.Sign(rigidbody2D.velocity.x) * maxSpeed, rigidbody2D.velocity.y);
}
// 如果输入使玩家向右移动且玩家当前面向左
if (h > 0 && !facingRight)
{
// 翻转玩家方向
Flip();
}
// 否则,如果输入使玩家向左移动且玩家当前面向右
else if (h < 0 && facingRight)
{
// 翻转玩家方向
Flip();
}
}
void Flip()
{
// 切换玩家的朝向标记
facingRight = !facingRight;
// 将玩家的x局部缩放乘以 -1
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
这段代码的逻辑比较简单,通过调用AddForce方法给Hero施加一个方向上的力,使其能够在场景中移动,同时根据speed参数播放相应的移动动画。