{"id":14960750,"url":"https://github.com/nosloofah/unity-buff-system","last_synced_at":"2025-06-20T20:40:54.488Z","repository":{"id":215423444,"uuid":"738903563","full_name":"NoSLoofah/Unity-Buff-System","owner":"NoSLoofah","description":"该项目是一个通用的Buff系统，旨在帮助Unity开发者轻松实现游戏中的Buff效果。该系统能够轻松集成到现有项目，你可以方便地添加、管理和应用自定义逻辑的Buff。","archived":false,"fork":false,"pushed_at":"2024-10-31T12:22:02.000Z","size":12796,"stargazers_count":186,"open_issues_count":1,"forks_count":23,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-17T15:03:00.206Z","etag":null,"topics":["buff","unity","unity-editor","unity-package"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NoSLoofah.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-04T10:10:29.000Z","updated_at":"2025-05-15T10:11:48.000Z","dependencies_parsed_at":"2024-12-21T22:11:45.777Z","dependency_job_id":"43bf4832-3ffc-4c54-b4c8-328804bd046c","html_url":"https://github.com/NoSLoofah/Unity-Buff-System","commit_stats":{"total_commits":13,"total_committers":2,"mean_commits":6.5,"dds":"0.23076923076923073","last_synced_commit":"61a47e1d70ea2d11b2907ef21857baa7bad8fa42"},"previous_names":["nosloofah/unity-buff-system"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/NoSLoofah/Unity-Buff-System","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoSLoofah%2FUnity-Buff-System","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoSLoofah%2FUnity-Buff-System/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoSLoofah%2FUnity-Buff-System/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoSLoofah%2FUnity-Buff-System/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NoSLoofah","download_url":"https://codeload.github.com/NoSLoofah/Unity-Buff-System/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NoSLoofah%2FUnity-Buff-System/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261014027,"owners_count":23097157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buff","unity","unity-editor","unity-package"],"created_at":"2024-09-24T13:22:53.502Z","updated_at":"2025-06-20T20:40:49.470Z","avatar_url":"https://github.com/NoSLoofah.png","language":"C#","readme":"# Unity 通用Buff系统\n该项目是一个通用的Buff系统，旨在帮助Unity开发者轻松实现游戏中的Buff效果。该系统能够轻松集成到现有项目，你可以方便地添加、管理和应用自定义逻辑的Buff。\n\n[教程视频](https://www.bilibili.com/video/BV16e411H7Vx/)\n\n## 特性\n- 优秀的可拓展性：你可以根据游戏需求编写自定义逻辑的Buff\n- 内置Buff编辑器：你可以在编辑器管理和配置你创建的Buff\n- 简洁的接口和使用方法：系统提供了简单易用的API，使得添加和应用Buff变得简单明了。\n\n## 支持与联系\n- 邮箱：nosloofah@qq.com\n- bilibili：NoSLoofah\n![](./doc/LOGO.png)\n\n## 注意\n1. NoSLoofah_BuffSystem/BuffSystem文件夹可以移动，但不要改变该文件夹内部的文件位置\n2. 请保证项目中始终只有一个BuffMgr.prefab\n3. 如果要重置所有数据，可以直接删除Assets/NoSLoofah_BuffSystem/BuffSystem/Data/BuffData文件夹。下次打开BuffEditor时该文件夹会重新生成\n\n## 快速上手\n### 安装\n将Assets/NoSLoofah_BuffSystem/BuffSystem文件夹拷贝到你的项目\n\n或导入Release中的unitypackage\n### 打开编辑器和初始化\n在Unity编辑器的工具栏打开Tools/BuffEditor\n![](./doc/tutorial01.png)\n点击后打开Buff编辑器窗口，同时生成文件夹BuffSystem/Data/BuffData。BuffData文件夹保存了你配置的Buff数据，请不要修改其中资产的文件名，也不要改动他们的路径。\n![](./doc/tutorial02.png)\n### 编写自定义Buff\n创建任意名称的新Buff脚本，引用命名空间NoSLoofah.BuffSystem，让该类继承Buff。实现抽象类后的格式如下：\n```csharp\nusing UnityEngine;\nusing NoSLoofah.BuffSystem;\npublic class Buff_XXX : Buff\n{\n    public override void OnBuffAwake()\n    {\n        base.OnBuffAwake();\n    }\n    public override void OnBuffDestroy(){}\n    public override void OnBuffModifyLayer(int change){}\n    public override void OnBuffRemove(){}\n    public override void OnBuffStart(){}\n    public override void Reset(){}\n    protected override void OnBuffTickEffect(){}\n}\n```\n请在对应的函数里实现需要的功能。\nBuff的生命周期如下：\n![](./doc/Buff生命周期.png)\n1. **如果一个Buff没有因为Tag或其他原因被打断，那么它的生命周期是**：\n    1. 在被添加的那一帧执行**OnBuffAwake**\n    2. 下一帧执行**OnBuffStart**\n    3. 在执行**OnBuffStart**的同一帧及此后的每一帧执行**OnBuffUpdate**。**OnBuffUpdate**内调用了两个生命周期函数，依次是**OnBuffModifyLayer**和**OnBuffTickEffect**；前者在多层Buff的层数发生变化时执行，后者则执行Buff的周期性效果（如Buff持续期间每1秒损失一点生命）\n    4. Buff持续时间结束时，执行**OnBuffRemove**\n    5. 下一帧执行**OnBuffDestroy**，完成Buff的移除\n\n\u003e 注意：Buff执行的第一个Update会通过OnBuffModifyLayer将自己的层数从0提升为1，而OnBuffDestroy会将层数重置为0并F最后执行一次OnBuffModifyLayer\n\n2. **编写自定义Buff的逻辑时，你可能会用到这些成员：**\n![](./doc/tutorial11.png)\n3. **开启周期性效果的函数是StartBuffTickEffect(float interval)，停止周期性效果的函数是StopBuffTickEffect()**。如果周期性效果在Buff刚被添加时就开始计时，你可以在**OnBuffStart**里调用它；当然你也可以其他生命周期函数中调用。\n4. **你可以给Buff添加新的成员字段。** 如果你希望在编辑器里配置这些字段，我建议用 **[SerializeField] private**来修饰他们。\n\n一个简单的中毒Buff可以这样实现：\n```csharp\nusing UnityEngine;\nusing NoSLoofah.BuffSystem;\npublic class Buff_Poison : Buff\n{\n    [SerializeField] private int poisonDamage;\n    [SerializeField] private float poisonTimeInterval;\n    [SerializeField] private GameObject effect;\n    private Entity1 targetEntity;\n    public override void OnBuffDestroy() { base.OnBuffDestroy(); }\n\n    public override void OnBuffModifyLayer(int change) { }\n\n    public override void OnBuffRemove() { }\n\n    public override void OnBuffStart()\n    {\n        targetEntity = Target.GetComponent\u003cEntity1\u003e();\n        StartBuffTickEffect(poisonTimeInterval);\n    }\n\n    public override void Reset() { }\n\n    protected override void OnBuffTickEffect()\n    {\n        targetEntity.ModifyHealth(-Layer * poisonDamage);\n        var g = Instantiate(effect);\n        g.transform.position = Target.transform.position;\n    }\n}\n```\nEntity1可以换成你自己的业务类\n\n### 配置Buff\n打开BuffEditor，可以看到编辑器分为两栏：\n![](./doc/tutorial03.png)\n左栏显示项目中你配置好的所有Buff。每一项的冒号左侧是这个Buff的序号，右侧是Buff的名称。**如果Buff没有命名，则会显示为NULL，且系统会将其视为空Buff。配置的Buff是可以重名的，但是名称不能为空**。\n\u003e 也许你会好奇如果给Buff起名为NULL会怎么样——\n\u003e 实际上不会出现任何Bug，只会让你自己看着犯迷糊\n\n左下角可以修改**最大Buff数量**。如果你将数字改小，那么**序号排最后的Buff数据都会被删除**\n\n现在选中一个空Buff，右栏显示如下：\n![](./doc/tutorial04.png)\n出现了一个名为类的下拉框，其内容是**Buff的所有子类**。我们在上一步添加的Buff_Poison也自动显示在了上面（图上另外的两个Buff来自项目的示例文件）\n**选中Buff_Poison**，我们配置一个新的中毒Buff\n![](./doc/tutorial05.png)\n图中白框框住的是Buff类的成员，红框框住的是我们为Buff_Poison添加的独有的成员。下面介绍可以在Buff子类中访问到的成员：\n- 图标(Icon)\n- 名称(BuffName)\n- 重复添加方式(MutilAddType)：![](./doc/tutorial06.png)\n- Tag(BuffTag)：Buff的Tag，处理互斥关系。后文详细解释。\n- 永久的(IsPermanent)：在主动去除Buff前永久生效\n- Buff持续时间(Duration)：Buff的有效时间。如果Buff是永久的那么这一项无效。\n\n![](./doc/tutorial07.png)\n\n### 配置Tag\n**点击BuffSystem/Data/BuffData路径下的BuffTagData.asset**，观察Inspector\n![](./doc/tutorial08.png)\n目前Tag的数量是固定的，为**31**个。我们在上一节配置Buff时看到，每个Buff都可以配置**一个Tag**。我们在BuffTagData.asset配置Tag之间的互斥关系\n1. 当一个Buff（下文称之为newBuff）添加到一个对象身上时，它的**OnBuffAwake**会立即执行。\n2. 之后在同一帧，系统监测该实体身上已有Buff的Tag。以上图为例，如果newBuff的Tag为Tag3，而目标身上已经有Tag为Tag2（禁止该Tag添加的Buff）的其他Buff，那么我们会立即执行newBuff的**OnBuffDestroy**，并不将他添加到实体的Buff列表中。\n3. 如果没有其它Buff禁止添加newBuff，接下来会检查是否有可以被newBuff抵消的Buff。以上图为例，如果newBuff的Tag为Tag1，那么目标实体上所有tag为Tag1和Tag2的其他Buff都会被移除（按正常生命周期执行OnBuffRemove和OnBuffInterupt。具体可见“编写自定义Buff”中的生命周期图）\n\n如果你需要修改Tag的名称，请在**BuffSystem/Base/Tag/BuffTag.cs**修改\n### 让Buff发挥作用\n1. 在游戏场景添加**BuffSystem/Base**路径下的**BuffMgr**预制体![](./doc/tutorial09.png)\n2. 在接受Buff的游戏物体上添加**BuffHandler**组件\n3. 在添加Buff的脚本里调用上一步添加的**BuffHandler**。下面是它的接口\n```csharp\n public interface IBuffHandler\n {\n     /// \u003csummary\u003e\n     /// 添加Buff \n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"buffId\"\u003e施加Buff的ID\u003c/param\u003e\n     /// \u003cparam name=\"caster\"\u003e施加Buff者\u003c/param\u003e\n     public void AddBuff(int buffId, GameObject caster);\n     /// \u003csummary\u003e\n     /// 移除Buff\n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"buffId\"\u003e要移除的Buff id\u003c/param\u003e\n     /// \u003cparam name=\"removeAll\"\u003e如果对象同时存在多个同id的buff，是否将所有一并移除\u003c/param\u003e\n     public void RemoveBuff(int buffId, bool removeAll = true);\n     /// \u003csummary\u003e\n     /// 移除Buff（不执行OnBuffDestroy）\n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"buffId\"\u003e要移除的Buff id\u003c/param\u003e\n     /// \u003cparam name=\"removeAll\"\u003e如果对象同时存在多个同id的buff，是否将所有一并移除\u003c/param\u003e\n     public void InteruptBuff(int buffId, bool interuptAll = true);\n     /// \u003csummary\u003e\n     /// 注册事件：添加Buff时\n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"act\"\u003e\u003c/param\u003e\n     public void RegisterOnAddBuff(Action act);\n     /// \u003csummary\u003e\n     /// 删除事件：添加Buff时\n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"act\"\u003e\u003c/param\u003e\n     public void RemoveOnAddBuff(Action act);\n     /// \u003csummary\u003e\n     /// 注册事件：删除Buff时\n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"act\"\u003e\u003c/param\u003e\n     public void RegisterOnRemoveBuff(Action act);\n     /// \u003csummary\u003e\n     /// 删除事件：删除Buff时\n     /// \u003c/summary\u003e\n     /// \u003cparam name=\"act\"\u003e\u003c/param\u003e\n     public void RemoveOnRemoveBuff(Action act);\n }\n```\n例如，示例项目中通过按钮添加、移除、打断Buff是这样实现的：\n![](./doc/tutorial10.png)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnosloofah%2Funity-buff-system","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnosloofah%2Funity-buff-system","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnosloofah%2Funity-buff-system/lists"}