Unity-动作系统-案例学习(4)人物受伤和死亡

系列文章目录

        一 、 人物移动和转向

        二、  人物跳跃和落地

        三、  人物攻击和判定

        四、  人物受伤和死亡



前言

上一章记录了人物的攻击实现和攻击有效判定,这里实现人物的受伤判定。

实现效果:(敌人的实现见下一章)

提示:以下是本篇文章正文内容,下面案例可供参考

一、人物受伤逻辑分析

三个主要脚本:

Damageable脚本,挂在受攻击对象上,负责接收从对方武器(meleeWeapon)传递的伤害信息,对伤害(Message)进行处理 --> 根据不同的受击效果调用不同委托事件  -->   最后将必要的信息传递给伤害接收者。(当然不一定要有接收者,看有没有需要复杂信息传递

IMessageReceiver接口: 自行定义的接口,在有需要接收伤害信息的对象上实现接口,实现在不同对象受伤或死亡的复杂伤害信息接收。

二、人物受伤和死亡动画逻辑

定义两个trigger参数,连接到在Anystate上;

三、人物受伤脚本实现

1.Damageable脚本(受击对象上)

这个脚本存储了玩家的血量,对伤害的接收处理,和不同伤害事件的响应。

编辑器中的设置:

代码如下(示例):

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
//My受伤反馈脚本
namespace MyPlayer
{
    public partial class MyDamageable : MonoBehaviour
    {
        [SerializeField]
        protected int curHitPoints;//当前血量
        protected Action schedule;//多播委托
        protected float myInvincibleTime = 3.5f;//无敌时间

        public int myMaxHipPoints;//最大血量
        public bool invincible = false;//无敌的
        public TextMesh m_HitPointsShow;//血量显示
        public UnityEvent OnDamage, OnDeath, OnResetDamage, OnBecmeVulnerable, OnHitWhileInvulunerable;//不同的受伤事件
        //[EnforceType(typeof(MyMessage.IMessageReceiver))]
        //public MonoBehaviour[] DemageReceiver;
        public List<MonoBehaviour> onDamageMessageReceivers;//伤害接收者,不一定有必要
        public int CurHitPoint { get { return curHitPoints; } }
        public void OnReSpawn()//复活
        {
            invincible = true;
            myInvincibleTime = 3.5f;
            OnResetDamage.Invoke();
            curHitPoints = myMaxHipPoints;
        }
        private void Awake()
        {
            curHitPoints = myMaxHipPoints;
            invincible = false;//开始有一段无敌时间
            if(m_HitPointsShow)
                m_HitPointsShow.text = curHitPoints.ToString();
        }

        //受到攻击时调用
        public bool OnGetDamage(MyDamageable.DamageMessage data)
        {
            MyMessage.MesssageType type;
            if (invincible || curHitPoints <=0)
            {
                return false;
            }
            curHitPoints -= data.amount;
            if (m_HitPointsShow)
                m_HitPointsShow.text = curHitPoints.ToString();
                if (curHitPoints <= 0)
            {
                schedule += OnDeath.Invoke;//死亡
                type = MyMessage.MesssageType.Death;
            }
            else
            {
                schedule += OnDamage.Invoke;//仅仅受伤
                type = MyMessage.MesssageType.Damage;
            }

            for (int i = 0;i< onDamageMessageReceivers.Count; i++)//向接收者传递信息
            {
                var receiver = onDamageMessageReceivers[i] as MyMessage.IMessageReceiver;
                receiver.OnMessageReceive(type,data.damager,data);
            }
            return true;
        }
        //直接死亡,特殊情况可以直接调用,比如跳进沼泽或者岩浆
        public bool Death()
        {
            if (invincible || curHitPoints <= 0)
            {
                return false;
            }
            curHitPoints = 0;
            schedule += OnDeath.Invoke;
            return true;
        }
        private void LateUpdate()
        {
            if(schedule!=null)
            {
                schedule.Invoke();//使用多播委托
                schedule = null;
            }
        }
        private void Update()
        {
            if(invincible)//处于无敌状态
            {
                myInvincibleTime -= Time.deltaTime;
                if(myInvincibleTime <= 0)//无敌时间到
                {
                    invincible = false;
                    myInvincibleTime = 3.5f;
                    OnBecmeVulnerable.Invoke();//恢复正常状态,直接调用,不委托
                }
            }
        }
    }
}

2.IMessageReceiver接口

定义了伤害信息的类型和伤害接收的接口。

代码如下(示例):

namespace MyPlayer
{
    namespace MyMessage
    {
        public enum MesssageType
        {
            Damage,Death,Respawn
        }
        public interface IMessageReceiver//接口
        {
            void OnMessageReceive(MesssageType type, object sender, object obj);
        }
    }
}

2.IMessageReceiver接口实现(PlayerController上)

代码如下(示例):

 public class PlayerController : MonoBehaviour, IMessageReceiver
    {
        //省略前面脚本内容
              public void OnMessageReceive(MesssageType type, object sender, object data)//实现消息接收的接口
        {
            switch (type)
            {
                case MesssageType.Damage:
                    {
                        MyDamageable.DamageMessage m_data = (MyDamageable.DamageMessage)data;
                        Damaged(sender,m_data);
                    }
                    break;
                case MesssageType.Death:
                    {
                        MyDamageable.DamageMessage m_data = (MyDamageable.DamageMessage)data;
                        Death(sender,m_data);
                    }
                    break;
                case MesssageType.Respawn://这个没什么必要
                    break;
            }
            return;
        }
        private void Damaged(object sender, MyDamageable.DamageMessage data)
        {
            if(isDeath || m_damage.CurHitPoint <= 0)//无敌状态或者死亡状态
            {
                return;
            }
            //伤害来源进行省略
            Vector3 direction = data.damageSource - transform.position;
            direction = transform.InverseTransformPoint(direction);
            direction.y = 0f;
            print("x :" + direction.x + "y:" + direction.z);
            m_animator.SetFloat(hashOfHitFromX,direction.normalized.x);
            m_animator.SetFloat(hashOfHitFromY,direction.normalized.z);
            m_animator.SetTrigger(hashOfHurt);//设置受伤trigger
            if (m_HurtAudioPlayer)
                m_HurtAudioPlayer.PlayAudioRandomly(null);
        }
        private void Death(object sender,MyDamageable.DamageMessage data)
        {
            isDeath = true; //死亡
            m_DeathAudioPlayer.PlayAudioRandomly(null);//死亡音效
            m_animator.SetTrigger(hashOfDeath);//设置死亡trigger
            m_animator.ResetTrigger(hashOfHurt);//重置受伤trigger,避免状态重叠
        }
    }


总结

以上就是今天要讲的内容,本文仅仅简单介绍了Unity中的伤害的传递和接收,这只是其中的一种方法,今后还会继续完善,希望大家多多支持~~博主会继续更新~ 

  • 4
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值