1.Animator
为了在游戏对象上有动画,需要添加一个组件Animator。
在工程窗口中,双击Robot 预制体。
如图所示,添加Animator组件。
2.Creating a New Controller
在工程窗口Animator文件夹中,右击新建Robot脚本,并应用到Animator上。
点右上角保存按钮。
3.动画Animations
为了在Unity Editor中建立动画,可以使用Animation window,在预制体中选择Robot ,点Window > Animation > Animation。
出现“To begin animating [Prefab/GameObject name], create an Animation Clip”, 点Create。
在Animations 文件夹中,建立RobotLeft.anim动画片段。
如上图,左边为动画属性,右边为动画 的关键帧。
4.修改精灵Changing a Sprite
在Art > Sprites > Characters中,可以找到MrClockworkSheet 。在单个图片中可以找到多个精灵。
按住shift键不放,选择MrClockworkWalkSides1,MrClockworkWalkSides2,MrClockworkWalkSides3,MrClockworkWalkSides4。将这些拖到动画窗口中。
点play看下效果。
设置Samples 为4,以使精灵运行正常。
5.建立一个动画 Creating an Animation
在上图左边点击Create New Clip,名为Right_Run,选择Animation 文件夹。
重新创建Left animation,并将四个精灵拖上去,并设置Samples 为4。点增加属性,从Sprite Renderer找到Flip X。
勾选上属性选项,
重复操作建立running up和running down。
6.建立一个脚本 Building the Controller
在工程窗口中,选中Robot预制体,点Windows > Animation > Animator。
上图左边中的层用于3D动画,参数用于向脚本传递信息。
动画状态机是动画的所有状态图,可以从一种状态转到另一个状态。
另一种方式是混合树,可以通过参数从一种状态转到另一种状态。可以通过方向参数来控制动画。
7.使用混合树 Using a Blend Tree
删除所有动画,右击Create State > From New Blend Tree,创建Blend Tree。
双击Blend Tree,点Blend Tree结点,打开如下图。
修改Blend Type类型为2D Simple Directional。
8.Parameters Move X and Move Y
在动画窗口中,点击参数。
点float类型Move X,和Move Y。点混合树视图,显示如下:
点右上角的加号,点Add Motion Field ,增加4个点,并调整它们的位置。
- Left : Pos X = -0.5 Pos Y = 0,Right: Pos X = 0.5 Pos Y = 0,Up: Pos X = 0 Pos Y = 0.5,Down: Pos X = 0 Pos Y = -0.5
调整后的图为
图像代表着混合,每个点代表一个片断,红点代表参数所给的位置前、后、左、右。
9.将参数发送给Animator脚本 Sending parameters to the Animator Controller
打开EnemyController 脚本,增加
Animator animator;
通过
animator.SetFloat("Move X", 0);
animator.SetFloat("Move Y", direction);
给Animator 传送方向。
10.设置主要脚色的动画 Setting Animation for the Main Character
在Ruby预制体中,增加Animator 组件,并指定Animation 文件夹中的动画Animator 组件的动画。现在Ruby的动画类似于下图。
在图上,精灵有三种状态:移动Moving、静止Idle、和其他物体有冲突时Hit。白色的代表了状态的转换。双击白线,可以看到如下的状态转换图。
上图中的Has Exit Time不有被选中。这意味着移动动画不会等到完成状态机变为空闲动画之前,它会立即更改。
最重要的最下面的Conditions 。如果没有它的话,转变将会在动画的最后发生。
11.修改代码如下Modifying the RubyController Script
1 增加Animator变量
2增加Vector2 变量 lookDirection 并初始化为 (1,0),里面有两个方向参数Look X 和a Look Y。
3 通过animator.SetTrigger("Hit");触发点击动画。
12.完整的脚本如下 Check Your Scripts
public class RubyController : MonoBehaviour
{
public float speed = 3.0f;
public int maxHealth = 5;
public float timeInvincible = 2.0f;
public int health { get { return currentHealth; }}
int currentHealth;
bool isInvincible;
float invincibleTimer;
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
Animator animator;
Vector2 lookDirection = new Vector2(1,0);
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
currentHealth = maxHealth;
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
Vector2 move = new Vector2(horizontal, vertical);
if(!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
{
lookDirection.Set(move.x, move.y);
lookDirection.Normalize();
}
animator.SetFloat("Look X", lookDirection.x);
animator.SetFloat("Look Y", lookDirection.y);
animator.SetFloat("Speed", move.magnitude);
if (isInvincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
isInvincible = false;
}
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
public void ChangeHealth(int amount)
{
if (amount < 0)
{
animator.SetTrigger("Hit");
if (isInvincible)
return;
isInvincible = true;
invincibleTimer = timeInvincible;
}
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
Debug.Log(currentHealth + "/" + maxHealth);
}
}
动画片段是进行动画的部分。通过状态机来表示动画之间的关联。通过Animator 来在控制器中进行动画的演示。下一章将进行发射炮弹的演示。