文章目录
0.开发流程一
详见https://blog.csdn.net/xiji333/article/details/109621328。
1.Animation Events
首先来修改之前代码中的一个问题,你可能已经发现了,就是当人物从高处落下(不是跳跃后落下)时,动画并没有切换到 f a l l i n g falling falling,依然是 i d l e idle idle状态,而且此时落到敌人头上并不会消灭敌人,因为动画不是 f a l l i n g falling falling状态,现在来解决这个问题吧:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
void SwitchAnimation()
{
//animator.SetBool("idle", false);
if (rb2d.velocity.y < 0 && !boxCollider2D.IsTouchingLayers(ground)) //y轴速度<0且没有接触到地面时
{
animator.SetBool("falling", true);
}
}
}
记得也要修改 p l a y e r player player的状态机。
接下来制作敌人的动画:
设置状态机:
在修改代码之前,我们先来捋一下思路。我们要实现的是青蛙的移动,但是青蛙不能一直在跳跃呀,他需要适时的回到 i d l e idle idle状态,能不能找到一种方法,让青蛙在 i d l e idle idle动画播放完毕后自动跳跃一次呢?可以,通过 A n i m a t i o n E v e n t s Animation\ Events Animation Events我们可以在某个动画的某一帧设置一个事件,让他调用某个函数。那么我们可以在 i d l e idle idle结束的时候设置一个 e v e n t s events events,调用函数使青蛙进入跳跃状态,同时我们还需要在 u p d a t e update update内修改播放的动画,而且青蛙移动的逻辑也需要修改了,如果青蛙在跳跃过程中转向的话肯定会非常奇怪吧?所以我,我们需要提前判断落点位置是否在地面上,如果不在的话就需要提前进行转向啦。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Frog : MonoBehaviour
{
private Rigidbody2D rb2d;
private Animator animator;
private CircleCollider2D circleCollider2D;
public LayerMask ground;
//为了增加游戏的多样性 我们可以设置minSpeed和maxSpeed 随机选择中间的某个值作为青蛙的移动速度
public float minSpeed = 2.5f;
public float maxSpeed = 4f;
public float jumpForce = 4.5f;
[SerializeField]
private bool faceLeft = true;
//记录初始时的y坐标
private float initPositionY;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
circleCollider2D = GetComponent<CircleCollider2D>();
initPositionY = transform.position.y;
}
// Update is called once per frame
void Update()
{
SwitchAnimation();
}
//这个函数将通过animation event调用!
void Movement()
{
Vector2 frontPosition = transform.position;
frontPosition.y = initPositionY;
float speed = Random.Range(minSpeed, maxSpeed);
//预测落地 这里并没有精确计算 不过和你的jumpForce有关系
if (faceLeft)
frontPosition += Vector2.left * speed;
else
frontPosition += Vector2.right * speed;
if (!Physics2D.Linecast(frontPosition + Vector2.down, frontPosition, ground) || Physics2D.Linecast(frontPosition, frontPosition + Vector2.up * jumpForce, ground)) //没有检测到地面 或者头上有障碍物
{
faceLeft = !faceLeft;
transform.localScale = new Vector3(faceLeft ? 1 : -1, 1, 1); //角色反向
//注意此时应该结束这个函数 不然frog反向后依然会跳出去 然而你并不能确定这次跳跃的有效性
animator.Play("Frog_idle", 0, 0f);
return;
}
rb2d.velocity = new Vector2(faceLeft ? -speed : speed, jumpForce);
animator.SetBool("jumping", true);
}
void SwitchAnimation()
{
if (animator.GetBool("jumping")) //跳跃状态
{
if (rb2d.velocity.y < 0)
{
animator.SetBool("jumping", false);
animator.SetBool("falling", true);
}
}
else if (animator.GetBool("falling")) //下落状态
{
if (circleCollider2D.IsTouchingLayers(ground))
{
animator.SetBool("falling", false);
}
}
}
private void OnDrawGizmosSelected()
{
Vector2 frontPosition = new Vector2(transform.position.x, initPositionY) + Vector2.left * minSpeed * (faceLeft ? 1 : -1);
Gizmos.DrawLine(frontPosition + Vector2.down, frontPosition + Vector2.up * jumpForce);
frontPosition = new Vector2(transform.p