学习资源:B站 M_Studio《Unity教程2D入门》14
Unity Assets:Sunnyland
预期效果:若在地面上碰到敌人,会触发受伤动画并反弹。
private void OnCollisionEnter2D(Collision2D collision)
{
//碰到敌人的时候
if(collision.gameObject.tag == "Enemy")
{
//如果是下落状态
if (anim.GetBool("isFalling"))
{
//敌人才会消失
Destroy(collision.gameObject);
//踩完后垫着敌人小跳一下
rb.velocity = new Vector2(rb.velocity.x, jumpforce * Time.deltaTime);
anim.SetBool("isJumping", true);
}
//否则,如果在左侧碰到敌人
else if(transform.position.x < collision.transform.position.x)
{
//向左反弹
rb.velocity = new Vector2(-speed * Time.deltaTime, rb.velocity.y);
}
//右侧同理
else if (transform.position.x < collision.transform.position.x)
{
//向右反弹
rb.velocity = new Vector2(speed * Time.deltaTime, rb.velocity.y);
}
}
}
但是这里存在一个问题:
Movement每帧都在调用,速度值就会一直被改写,而无法实现反弹一段距离的效果。
解决方法:在FixUpdate函数中加一个hurt判断条件。
if(!isHurt)
{
Movement();
}
//否则,如果在左侧碰到敌人
else if(transform.position.x < collision.transform.position.x)
{
isHurt = true;
//向左反弹
rb.velocity = new Vector2(-speed * Time.deltaTime, rb.velocity.y);
}
//右侧同理
else if (transform.position.x > collision.transform.position.x)
{
isHurt = true;
//向右反弹
rb.velocity = new Vector2(speed * Time.deltaTime, rb.velocity.y);
}
什么时候才可以让ishurt重归为false呢?
移动一段距离、经历一段时间、又或是velocity的速度减小为0
这里用的是最后一个方法,请注意,最后一个方法默认的是有摩擦力,也就是速度确实是在不断减小的,我们可以把Player–>Rigidbody–>linear Drag改大一些
在SwitchAnim中添加:
else if(isHurt)
{
if(Mathf.Abs(rb.velocity.x) <0.1f)
{
isHurt = false;
}
}
接下来,Player切换受伤效果动画
1.需要添加一个bool参数记录受伤状态
2.动画间的关系如下,idle、run、jump都可能切换到hurt状态,hurt结束后,切换至idle
(最后hurt应该能回到状态idle 条件为 hurt==false且idle==true)
3.切换时的参数调整记得注意
这里其实可以直接用动画效果里设置的hurt参数来替代原来设置的私有变量isHurt。用getbool来获取isHurt的布尔值,用setbool来改变它的布尔值。
现在的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
public float speed = 400;
public float jumpforce = 400;
[Space]
public LayerMask ground;//获取地面信息
public Collider2D coll;
[Space]
public int cherry;
public Text cherryNumber;
private Rigidbody2D rb;
private Animator anim;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
cherry = 0;//物品数量初始化为0
}
// Update is called once per frame
void FixedUpdate()
{
if(!anim.GetBool("isHurt"))
{
Movement();
}
SwitchAnim();
}
void Movement()
{
float horizontalmove = Input.GetAxis("Horizontal");
float direction = Input.GetAxisRaw("Horizontal");
//角色移动
if(horizontalmove!=0)
{
rb.velocity = new Vector2(speed * horizontalmove * Time.deltaTime, rb.velocity.y);
anim.SetBool("isRunning", true);
}
else
{
anim.SetBool("isRunning", false);
}
//角色朝向
if(direction!=0)
{
transform.localScale = new Vector3(direction, 1, 1);
}
//角色跳跃
if(Input.GetButtonDown("Jump") && coll.IsTouchingLayers(ground))
{
rb.velocity = new Vector2(rb.velocity.x, jumpforce * Time.deltaTime);
anim.SetBool("isJumping", true);
anim.SetBool("isIdle", false);
}
}
void SwitchAnim()
{
//最高点切换为下落动画
if(anim.GetBool("isJumping"))
{
if(rb.velocity.y < 0)
{
anim.SetBool("isJumping", false);
anim.SetBool("isFalling", true);
}
}
else if(anim.GetBool("isHurt"))
{
anim.SetBool("isRunning", false);
if(Mathf.Abs(rb.velocity.x) <0.1f)
{
anim.SetBool("isHurt", false);
anim.SetBool("isIdle", true);
}
}
//碰到地面切换为idle
else if(coll.IsTouchingLayers(ground))
{
anim.SetBool("isFalling", false);
anim.SetBool("isIdle", true);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
//如果碰撞体的tag是Collection,则销毁
if(collision.tag == "Collection")
{
Destroy(collision.gameObject);
cherry += 1;
cherryNumber.text = cherry.ToString();
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
//碰到敌人的时候
if(collision.gameObject.tag == "Enemy")
{
//如果是下落状态
if (anim.GetBool("isFalling"))
{
//敌人才会消失
Destroy(collision.gameObject);
//踩完后垫着敌人小跳一下
rb.velocity = new Vector2(rb.velocity.x, jumpforce * Time.deltaTime);
anim.SetBool("isJumping", true);
}
//否则,如果在左侧碰到敌人
else if(transform.position.x < collision.transform.position.x)
{
//向左反弹
rb.velocity = new Vector2(-6, rb.velocity.y);
anim.SetBool("isHurt", true);
}
//右侧同理
else if (transform.position.x > collision.transform.position.x)
{
anim.SetBool("isHurt", true);
//向右反弹
rb.velocity = new Vector2(6, rb.velocity.y);
}
}
}
}