Unity引擎2D游戏开发,人物属性及伤害计算

发布时间 2023-12-18 17:43:24作者: 心霖の雨

一、创建敌人2D模型

裁切野猪素材,并放置在Scene窗口中

打开文件夹,找到野猪待机素材
image

将素材进行必要的设置
image

点击窗口中的Sprite Editor,打开裁切窗口。点击Slice,选择Type,进行按网格计数裁切(Grid By Cell Count)
image

接着,然后在Column & Row中,写入4、1。即,4列1行。将中心点Pivot选择Bottom
image

自动裁切成功。
image

将Sheet_0拖入到Hierarchy窗口中,并命名为Boar
image

将Boar的图层顺序设置为Middle,并将Order设置为1。这样就不会被地面的草地遮挡
image

给野猪创建刚体和碰撞盒

选中Boar,点击Add Component,选择RigitBody 2D
image

Collision Detection设置为持续不断的(Continuous),并冻结Z轴
image

点击Add Component创建Box Collider 2D
image

点击Edit Collider将Box Collider设置为此大小
image

image

现在的Box Collider会导致人物穿过野猪时,会发生体积碰撞问题。这时就需要进行图层排除(Exclude Layer)。

点击右上角的Layer,选择Add Layer
image

新增两个图层,一个Player,一个Enemy
image

在Boar中,右上角Layer选择Enemy。在Player中,右上角Layer选择Player
image

image

然后在Boar的Layer Overrides内Exclude Layer中,选择Player和Enemy。这样就可以在此碰撞体中排除这两个图层。
image

为了实现人物的碰撞伤害,再给野猪创建另一个碰撞盒

选中Boar,创建Capsule Collider 2D
image

接着将Direction选择为Horizontal,实现横向形状的碰撞
image

然后点击Edit Collider,将碰撞盒修改为此大小
image

因为此碰撞盒是进行碰撞伤害,所以将Enemy图层排除
image

勾选Is Trigger,此碰撞盒进行触发碰撞伤害功能
image

二、伤害计算

准备

在Scripts下创建General文件夹
image

General文件夹内新建Character(人物数值计算)、Attack(攻击数值计算) C#文件
image

将Character添加进Boar和Player组件列表中
image

image

将Attack添加进Enemy组件列表中
image

基本数值创建

Character内新建角色基本属性

[Header("基本属性")]
public float maxHealth;
public float currentHealth;

Start()方法内,初始化血量
每次开始时,当前生命值初始化为最大生命值

private void Start()
{
    currentHealth = maxHealth;
}

Attack内新建攻击的基本属性

public int damage;
// 攻击范围
public float attackRange;
// 攻击频率
public float attackRate;

可以选中Boar对象,将damage设置为5,即伤害为5
image

Player对象,最大血量为100
image

攻击计算过程

Character内创建空白的TakeDamage()方法,以备进行伤害计算

public void TakeDamage(Attack attacker)
{

}

Attack内创建OnTriggerStay2D()方法,将被攻击的对象Collider2D传入Character组件内的TakeDamage()方法进行伤害计算

private void OnTriggerStay2D(Collider2D collision)
{
    collision.GetComponent<Character>()?.TakeDamage(this);
}

OnTriggerStay2D()方法:https://docs.unity3d.com/cn/2022.3/ScriptReference/Collider2D.OnTriggerStay2D.html

?相当于!=null,对collision.GetComponent<Character>()进行判null,如果为null,则不进行TakeDamage()

目前人物去对野猪进行碰撞,会发现短时间内被野猪造成持续不断的伤害。那么这时候就要增加“受伤无敌”的机制

Character内新建受伤无敌的基本属性

[Header("受伤无敌")]
// 无敌时间
public float invulnerableDuration;
// 计时器
private float invulnerableCounter;
// 无敌状态
public bool invulnerable;

创建TriggerInvulnerable()方法,编写无敌的触发条件

private void TriggerInvulnerable()
{
    if (!invulnerable)
    {
        invulnerable = true;
        invulnerableCounter = invulnerableDuration;
    }
}

如果当前不是在无敌的状态则赋予无敌状态,并且无敌的计数器等于无敌的时间周期

紧接着,在TakeDamage()方法中,写入新的关于无敌条件的代码

public void TakeDamage(Attack attacker)
{
    if (invulnerable)
    {
        return;
    }
    // Debug.Log(attacker.damage);
    if (currentHealth - attacker.damage > 0)
    {
        currentHealth -= attacker.damage;
        TriggerInvulnerable();
    } else
    {
        currentHealth = 0;
        // 触发死亡
    }
}

如果当前已经是无敌状态,则不进行伤害计算,直接跳出当前方法。接着,如果当前血量受到了一定数值的伤害导致血量还在大于0,则扣除伤害值,触发无敌。否则血量赋值为0,触发死亡。

为了让无敌时间进行缩减,则在Update()方法中,进行时间的扣除

private void Update()
{
    if (invulnerable)
    {
        invulnerableCounter -= Time.deltaTime;
        if (invulnerableCounter <= 0 )
        {
            invulnerable = false;
        }
    }
}

如果正在无敌,则将计数器扣除完成上一帧所使用的时间(以秒为单位)。如果计数器小于等于0,则更改当前的无敌状态为false。

可以将Player对象的无敌周期设置为1s,即受伤后的1s内无敌不会被短时间持续不断的受到伤害
image