IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity-动作系统-案例学习(4)人物受伤和死亡 -> 正文阅读

[游戏开发]Unity-动作系统-案例学习(4)人物受伤和死亡

系列文章目录

? ? ? ? 一 、 人物移动和转向

? ? ? ? 二、? 人物跳跃和落地

? ? ? ? 三、? 人物攻击和判定

? ? ? ? 四、? 人物受伤和死亡

? ? ? ? (更新中。。。)


目录

前言

一、人物受伤逻辑分析

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

三、人物受伤脚本实现

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

2.IMessageReceiver接口

2.IMessageReceiver接口实现(PlayerController上)

总结


前言

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

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

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

一、人物受伤逻辑分析

三个主要脚本:

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中的伤害的传递和接收,这只是其中的一种方法,今后还会继续完善,希望大家多多支持~~博主会继续更新~?

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 14:25:30  更:2021-08-14 14:26:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 18:06:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码