【unity实战】如何更加规范的创建各种Rogue-Lite(肉鸽)风格的物品和BUFF效果(附项目源码)

文章目录

  • 前言
  • 定义基类
  • 实现不同的BUFF效果
    • 一、回血BUFF
      • 1. 简单的回血效果实现
      • 2. BUFF层数控制回血量
    • 二、攻击附带火焰伤害
    • 三、治疗领域
      • 1. 简单的治疗领域实现
      • 2. 添加技能冷却时间
  • 通过拾取物品获取对应的BUFF
  • 参考
  • 源码
  • 完结

前言

当创建各种Rogue-Lite(肉鸽)风格的游戏时,物品和BUFF效果是非常重要的元素之一。为了更加规范地创建这些物品和BUFF效果,可以使用抽象类来定义不同的BUFF。

那么什么是抽象类呢?他的用法?为什么用它?好处是什么呢?

在Unity中,抽象类是一种特殊的类,它不能被实例化,只能被用作其他类的基类。抽象类通常用于定义一些通用的行为和属性,但并不提供具体的实现细节。其目的是让子类来实现这些抽象方法和属性,以便根据具体的需求进行定制化。

使用抽象类的主要原因是为了实现代码的重用和统一性。抽象类可以定义一些通用的方法和属性,从而避免在多个类中重复编写相似的代码。同时,它也可以作为约定,强制子类实现特定的方法和属性,确保了程序的一致性和可扩展性。

抽象类的主要好处包括:

  1. 提供了一种模板化的设计方式,使得代码更易维护和扩展。
  2. 强制了子类必须实现抽象方法和属性,从而减少了程序出错的可能性。
  3. 通过抽象类可以实现多态性,使得代码更加灵活和可复用。

在Unity中,经常会用到抽象类来定义一些通用的行为或者规范,例如定义一个抽象的游戏角色类,其中定义了移动、攻击等方法,然后具体的角色类(如玩家角色、敌对角色等)继承并实现这些方法。这样可以保持代码的一致性和可维护性。

总之,抽象类在Unity中的使用可以帮助我们更好地组织和管理代码,提高代码的复用性和可维护性。

定义基类

物品就是物品BUFF,下面我都会用物品作为注释

新增Item,定义一个名为 Item 的物品BUFF抽象类

[System.Serializable]

public abstract class Item
{
    // 定义BUFF名称
    public abstract string GiveName();

    // 定义一个虚方法 Update,其中 player 表示玩家对象,stacks 表示物品的叠加数量(及BUFF层数)
    public virtual void Update(Player player, int stacks){ }
}

新增ItemList,定义物品BUFF列表参数

[System.Serializable]
public class ItemList
{
    // 表示物品
    public Item item;

    // 表示名称
    public string name;

    // 表示叠加数量(及BUFF层数)
    public int stacks;

    // 构造函数,用于初始化 ItemList 对象
    public ItemList(Item newItem, string newName, int newStacks)
    {
        item = newItem;
        name = newName;
        stacks = newStacks;
    }
}

实现不同的BUFF效果

一、回血BUFF

1. 简单的回血效果实现

定义一个名为 HealingItem 的类,继承自 Item,定义回血BUFF

public class HealingItem : Item
{
    public override string GiveName()
    {
        return "回血BUFF";
    }

    public override void Update(Player player, int stacks)
    {
        // 将玩家的生命值增加 5
        player.health += 5;
    }
}

新增玩家脚本,调用BUFF

public class Player : MonoBehaviour
{
    // 表示玩家的生命值
    public int health;

    // 表示玩家的物品BUFF列表
    public List<ItemList> items = new List<ItemList>();

    void Start()
    {
        HealingItem item = new HealingItem();
        // 将回血BUFF对象添加到物品列表中
        items.Add(new ItemList(item, item.GiveName(), 1));

        StartCoroutine(CallItemUpdate());
    }

    IEnumerator CallItemUpdate()
    {
        // 遍历物品列表中的每个物品
        foreach (ItemList i in items)
        {
            // 调用物品的 Update 方法
            i.item.Update(this, i.stacks);
        }
        
        //暂停1秒继续执行
        yield return new WaitForSeconds(1);
        
        // 重新启动协程 CallItemUpdate
        StartCoroutine(CallItemUpdate());
    }
}

运行效果,角色每秒回5点血
在这里插入图片描述

2. BUFF层数控制回血量

修改HealingItem

public override void Update(Player player, int stacks)
{
    // 将玩家的生命值增加
    player.health += 3 + (2 * stacks);
}

效果,两层每秒加7血
在这里插入图片描述
在这里插入图片描述

二、攻击附带火焰伤害

新增敌人脚本,定义敌人生命值

public class Enemy : MonoBehaviour {
    public int health;
}

修改Item,定义攻击事件

public virtual void OnHit(Player player, Enemy enemy, int stacks){ }

新增FireDamageItem,实现火焰攻击效果

public class FireDamageItem : Item
{
    public override string GiveName()
    {
        return "火焰攻击";
    }

    public override void OnHit(Player player, Enemy enemy, int stacks)
    {
        enemy.health -= 10 * stacks;
    }    
}

修改Player,默认加2层火焰攻击效果

// 表示玩家的攻击力 
public int attackDamage;

void Start()
{
    FireDamageItem item = new FireDamageItem();
    items.Add(new ItemList(item, item.GiveName(), 2));
}

public void CallItemOnHit(Enemy enemy)
{
    foreach (ItemList i in items)
    {
        i.item.OnHit(this, enemy, i.stacks);
    }
}

新增PlayerHitbox,定义攻击判定,攻击附加额外火焰攻击BUFF伤害

public class PlayerHitbox : MonoBehaviour
{
    public Player player;

    //触发器检测
    private void OnTriggerEnter(Collider other)
    {
        // 判断进入碰撞体的对象是否为敌人
        if (other.tag == "Enemy")
        {
            Enemy enemy = other.GetComponent<Enemy>();

            // 减少敌人的生命值,减少的值为玩家的攻击力
            enemy.health -= player.attackDamage;

            // 调用玩家的 CallItemOnHit 方法,附加额外伤害
            player.CallItemOnHit(enemy);
        }
    }
}

效果,攻击附带额外伤害
在这里插入图片描述

三、治疗领域

实现治疗领域效果一般需要加载一些特性,而我们定义的BUFF是没办法挂载特效物品的,这时候就需要使用Resources加载指定的特效了

在这里插入图片描述

1. 简单的治疗领域实现

绘制预制体
在这里插入图片描述

修改Item,定义跳跃方法

public virtual void OnJump(Player player, int stacks) { }

新增HealingArea,实现跳跃方法生成治疗领域

public class HealingArea : Item
{
	//特效
    GameObject effect;
    
    public override string GiveName()
    {
        return "治疗领域";
    }
    
    public override void OnJump(Player player, int stacks)
    {
        if (effect == null) effect= (GameObject)Resources.Load("Item Effects/Healing Area", typeof(GameObject));
        GameObject healingArea = GameObject.Instantiate(effect, player.transform.position, Quaternion.Euler(Vector3.zero));
    }
}

修改Player,实现每次按Space,执行治疗领域OnJump方法

private void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        CallItemOnJump();
    }
}
    
public void CallItemOnJump()
{
    foreach (ItemList i in items)
    {
        i.item.OnJump(this, i.stacks);
    }
}

效果,每次跳跃生成一个治疗光环
在这里插入图片描述

2. 添加技能冷却时间

修改HealingArea

public class HealingArea : Item
{
    GameObject effect;
    float internalCoolDown;//技能冷却时间
    
    public override string GiveName()
    {
        return "Healing Area";
    }

    public override void Update(Player player, int stacks)
    {
        internalCoolDown -= 1;
    }

    public override void OnJump(Player player, int stacks)
    {
        if (internalCoolDown <= 0)
        {
            if (effect == null) effect = (GameObject)Resources.Load("Item Effects/Healing Area", typeof(GameObject));
            GameObject healingArea = GameObject.Instantiate(effect, player.transform.position, Quaternion.Euler(Vector3.zero));
            internalCoolDown = 10;//技能冷却时间默认定义10秒
        }
    }
}

效果,每10秒才能释放一次治疗光环
在这里插入图片描述

通过拾取物品获取对应的BUFF

新增ItemPickup ,物品拾取类

public class ItemPickup : MonoBehaviour
{
    // 掉落的物品对象
    public Item item;
    // 物品类型
    public Items itemDrop;

    void Start()
    {
        // 调用 AssignItem 方法,传入掉落的物品类型,并将返回值赋值给 item
        item = AssignItem(itemDrop);
    }

    // 触发器检测
    private void OnTriggerEnter(Collider other)
    {
        // 判断进入碰撞体的对象是否为玩家
        if (other.tag == "Player")
        {
            // 获取玩家对象
            Player player = other.GetComponent<Player>();

            // 调用 AddItem 方法,传入玩家对象
            AddItem(player);

            // 销毁 Pickup 对象
            Destroy(this.gameObject);
        }
    }
    
    public Item AssignItem(Items itemToAssign)
    {
        // 根据不同的物品类型返回不同的物品对象
        switch (itemToAssign)
        {
            case Items.HealingItem:
                return new HealingItem();
            case Items.FireDamageItem:
                return new FireDamageItem();
            case Items.HealingAreaItem:
                return new HealingArea();
            default:
                return new HealingItem();
        }
    }

    public void AddItem(Player player)
    {
        // 遍历玩家物品列表中的每个物品
        foreach (ItemList i in player.items)
        {
            // 如果该物品已经存在于列表中,则将该物品的叠加数量加 1,并直接返回
            if (i.name == item.GiveName())
            {
                i.stacks += 1;
                return;
            }
        }

        // 将新的物品添加到玩家物品列表中
        player.items.Add(new ItemList(item, item.GiveName(), 1));
    }
}

// 定义一个公共枚举类型 Items,表示所有可用的物品类型
public enum Items
{
    HealingItem,
    FireDamageItem,
    HealingAreaItem
}

修改Player,删除前面旧的BUFF添加

// HealingItem item = new HealingItem();
// items.Add(new ItemList(item, item.GiveName(), 1));

// FireDamageItem item = new FireDamageItem();
// items.Add(new ItemList(item, item.GiveName(), 2));

新增各种BUFF物品,配置预制体
在这里插入图片描述效果,拾取物品即可获取对应的BUFF效果
在这里插入图片描述
ps:后续要加入其他BUFF,直接就可以修改ItemPickup很方便的进行添加定义即可

参考

【视频】https://www.youtube.com/watch?v=iU6mKyQjOYI

源码

源码整理好我会放上来,催更可以优先加急

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/179765.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

接口传参数list的时候,items里面放个​​​​​​​list

item里面放个list 先定义一个 list&#xff0c;循环add加入参数

xorm源码学习

文章目录 XORM源码浅析及实践ORMORM vs. SQLXORM软件架构 ORM 引擎 Engine——DBM*core.DB Golang&#xff1a;database/sql 源码基本结构连接复用&#xff0c;提高性能。增加数据库连接池数量连接管理 database/sql主要内容&#xff1a;sql.DB创建数据库连接sql.Open()DB.conn…

状态设计模式是什么?什么是 State 状态设计模式?Python 状态设计模式示例代码

什么是 State 状态设计模式&#xff1f; 状态设计模式是一种行为型设计模式&#xff0c;它允许一个对象在其内部状态发生改变时改变其行为&#xff0c;使其看起来好像改变了其类。状态模式主要解决的问题是&#xff1a;当一个对象的行为取决于它的状态&#xff0c;并且在运行时…

2023年亚太地区数学建模大赛

中国新能源电动汽车的发展趋势 新能源汽车是指采用先进的技术原理、新技术和新结构&#xff0c;以非常规车用燃料&#xff08;非常规车用燃料是指汽油和柴油以外的燃料&#xff09;为动力源&#xff0c;集成先进的汽车动力控制和驱动技术的汽车。新能源汽车包括四大类型&#…

人工智能带来的各方面影响

近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术在各个领域中的应用越来越广泛&#xff0c;已经开始对我们的生活方式、社会和经济结构产生深远的影响。 1.人工智能家庭化。人工智能技术使我们的生活变得更加便利和智能化。在家庭日常中&#xff0c;智能家居、智能…

WPF绘图使用介绍

文章目录 WPF绘图基本用法绘制直线在XAML中绘制直线在C#代码中绘制直线使用Path绘制直线注意 矩形绘制在XAML中绘制矩形在C#代码中绘制矩形设置矩形的位置使用圆角矩形 画刷1. SolidColorBrush2. LinearGradientBrush3. RadialGradientBrush4. ImageBrush5. DrawingBrush6. Vis…

FDG6306P PowerTrench® MOSFET P沟道 特点及其应用详解

关于PowerTrench MOSFET&#xff1f; 它是一种MOS场效应晶体管&#xff0c;可以提高系统效率和功率密度。该技术采用了屏蔽栅极技术&#xff0c;可以减少开关损耗和导通损耗&#xff0c;从而提高了系统效率。此外&#xff0c;PowerTrench MOSFET还具有低导通电阻和高开关速度的…

Python---函数的应用案例(多个)涉及函数、字符串翻转修改

案例&#xff1a;使用print方法打印一条横线 下面是最原始的方法&#xff1a; print(- * 40) 案例&#xff1a;对上个案例进行升级&#xff0c;可以根据输入的num数值&#xff0c;生成指定数量的横线 相关链接Python----range方法&#xff08;函数&#xff09;-CSDN博客 Pyt…

现代计算与光学的跨界机遇——

时至今日&#xff0c;互补氧化金属半导体&#xff08;CMOS&#xff09;技术的飞速发展促进了集成电路的空前成功。 晶体管的创新与时俱进 正如戈登-E-摩尔&#xff08;Gordon E. Moors&#xff09;在1965年预测的那样&#xff0c;每隔18-24个月&#xff0c;计算芯片上的晶体管数…

手把手教你通过CODESYS V3进行PLC编程(二)

教程背景 在上一期教程中&#xff0c;我们已经完成了控制器设备的连接和配置。接下来的教程将继续以宏集MC-Prime为例&#xff0c;假设控制器已经配置并连接到开发者的PC上&#xff0c;为您演示如何为控制器安装合适的CODESYS V3版本并创建第一个程序。 一、安装CODESYS &…

TikTok青年领袖:短视频如何塑造新一代

在数字时代的潮流中&#xff0c;短视频平台TikTok崭露头角&#xff0c;成为年轻一代最喜爱的社交媒体之一。这个平台不仅改变了用户的娱乐方式&#xff0c;更在其中催生了一批富有创造力和影响力的青年领袖。 本文将深入探讨TikTok如何通过短视频内容塑造新一代的青年领袖&…

Modbus转Profinet改变局面,PLC与电力仪表秒级响应

Modbus转Profinet改变了传统的局面&#xff0c;实现了PLC与电力仪表之间的秒级响应。在过去&#xff0c;由于Modbus通信协议的限制&#xff0c;PLC与电力仪表之间的数据传输速度受到了很大的限制&#xff0c;无法满足工业自动化领域对实时性的要求。然而&#xff0c;随着Modbus…

加班做报表被嘲低效!快用大数据分析工具

做数据分析报表很耗时间&#xff0c;因为不仅要解决多业务系统数据质量标准不一问题&#xff0c;还需要进行大量的公式计算、报表设计与制作。但那是以前&#xff0c;在大数据分析工具强势崛起的当下&#xff0c;这些工作都能交给大数据分析工具来做了。以前是花90%的时间做报表…

快慢指针判断环形链表

我们在前面文章中写过用快慢指针判断链表是否带环&#xff1a; leetcode&#xff1a;环形链表-CSDN博客 我们用的是slow指针一次走一步&#xff0c;fast指针一次走两步&#xff0c;当slow入环后开始了追击&#xff0c;每走一次距离缩短1&#xff0c;最终就会相遇 思考问题 …

CURL踩坑记录

因为项目使用的windows server&#xff0c;且没有安装Postman&#xff0c;所以对于在本地的Postman上执行的请求&#xff0c;要拷贝到服务器执行&#xff0c;只能先转化成为curl命令&#xff0c;操作也很简单&#xff0c;如下&#xff1a; 注意&#xff0c;Postman默认对url包围…

Vocoder,声码器详解——语音信号处理学习(十)

参考文献&#xff1a; [1] Vocoder (由助教許博竣同學講授)哔哩哔哩bilibili [2] Oord A, Dieleman S, Zen H, et al. Wavenet: A generative model for raw audio[J]. arXiv preprint arXiv:1609.03499, 2016. [3] https://deepmind.com/blog/article/wavenet-generative-mode…

关于实时云渲染并发问题的分享,实时云渲染到底能不能省显卡?

近期遇到很多客户咨询实时云渲染技术中的并发问题&#xff0c;在这里点量小芹针对这个问题的几个常见疑惑进行集中的解答分享&#xff0c;希望对有迷惑的朋友有所启发和帮助。 第一个问题&#xff0c;实时云渲染能否扩展一张显卡支持的并发数&#xff1f; 实时云渲染是一个新兴…

没有淘礼金权限怎么办?

前面我写了一篇微信公众号创建淘礼金的博文&#xff0c;在实际开发中不少人遇到了&#xff0c;淘礼金没有权限的问题。 既然没权限&#xff0c;解决方法就是去申请权限&#xff0c; 只需要满足以下规则&#xff0c;就可以自主申请开通。 申请规则&#xff1a; &#xff11;&a…

uni-app 跨端开发注意事项

文章目录 前言H5正常但App异常的可能性标题二H5正常但小程序异常的可能性小程序正常但App异常的可能性小程序或App正常&#xff0c;但H5异常的可能性App正常&#xff0c;小程序、H5异常的可能性使用 Vue.js 的注意区别于传统 web 开发的注意H5 开发注意微信小程序开发注意支付宝…

SpringBoot 导入其他配置文件

默认情况下&#xff0c;springboot 初始的项目中都有一个 application.yml 或者 application.properties 文件&#xff0c;如果我们希望再定义一个独立的配置文件用来配置特定业务数据&#xff0c;而不希望把这些配置内容都堆积在 application 配置文件中&#xff0c;实现这个需…