Skip to content

Demexis/Unity-Buffs

Repository files navigation

GitHub Release MIT license

Unity-Buffs

Readme Languages:
English Русский

A simple implementation of a buff-system for use in scripts. Its advantage is that you can use any C#-types as the buff value and value-processors.

In addition to the default processors for the buff values, you can create your own implementations.

Table of Contents


Setup

Requirements

  • Unity 2021.3 or later

Installation

Use ONE of two options:

a) Package Manager (Recommended)

  1. Open Package Manager from Window > Package Manager.
  2. Click the "+" button > Add package from git URL.
  3. Enter the following URL:
https://github.com/Demexis/Unity-Buffs.git

Alternatively, open Packages/manifest.json and add the following to the dependencies block:

{
    "dependencies": {
        "com.demegraunt.buffs": "https://github.com/Demexis/Unity-Buffs.git"
    }
}

b) Unity Package

Download a unity package from the latest release.

Usage

1) Create a buff with the desired type and bind an original value:

// This variable can change its value!
public float originalValue = 1f;
...
var buff = new Buff<float>(() => originalValue);

2) Add processor(-s) that will sequentially transform the original value:

private readonly Guid processorId = Guid.NewGuid();
...
buff.Add(processorId, new BuffProcessor<float>(value => value * 4f));

3) Calculate the buff value:

var resultValue = buff.Calculate();
Debug.Log(resultValue); // prints 4

4) Replace the processor:

buff.Replace(processorId, new BuffProcessor<float>(value => value + 20f));

resultValue = buff.Calculate();
Debug.Log(resultValue); // prints 21

5) Remove the processor:

buff.Remove(processorId);

resultValue = buff.Calculate();
Debug.Log(resultValue); // prints 1 - the original value

Examples

1: A sprint mechanic using a buff

using System;
using Demegraunt.Framework;
using UnityEngine;

public sealed class MovementWithBuff : MonoBehaviour {
    [field: SerializeField] public float Speed { get; set; } = 1f;
    [field: SerializeField] public float SprintMultiplier { get; set; } = 4f;
    
    private Buff<float> SpeedBuff { get; set; }
    private readonly Guid sprintProcessorId = Guid.NewGuid();

    private void Awake() {
        SpeedBuff = new Buff<float>(() => Speed);
    }

    private void Update() {
        if (Input.GetKeyDown(KeyCode.LeftShift)) {
            ActivateSprint();
        } else if (Input.GetKeyUp(KeyCode.LeftShift)) {
            DeactivateSprint();
        }

        transform.position += Vector3.right * (Time.deltaTime * SpeedBuff.Calculate());
    }

    public void ActivateSprint() {
        if (SpeedBuff.Contains(sprintProcessorId)) {
            return;
        }
        
        SpeedBuff.Add(sprintProcessorId, new BuffProcessor<float>(originalValue => originalValue * SprintMultiplier));
    }

    public void DeactivateSprint() {
        SpeedBuff.Remove(sprintProcessorId);
    }
}

2: One buff affects the other

public sealed class WalkRunBuffs : MonoBehaviour {
    [field: SerializeField] public float Speed { get; set; } = 1f;
    [field: SerializeField] public float SprintMultiplier { get; set; } = 4f;
    
    private Buff<float> WalkBuff { get; set; }
    private Buff<float> RunBuff { get; set; }
    private readonly Guid slowdownProcessorId = Guid.NewGuid();

    private void Awake() {
        WalkBuff = new Buff<float>(() => Speed);
        RunBuff = new Buff<float>(() => WalkBuff.Calculate() * SprintMultiplier);
    }

    private void Start() {
        Slowdown();
    }

    private void Update() {
        // always running
        transform.position += Vector3.right * (Time.deltaTime * RunBuff.Calculate());
    }

    public void Slowdown() {
        WalkBuff.Add(slowdownProcessorId, new FloatBuffMultiplier(0.1f));
    }
}

Hints

  • The package contains custom processors such as: FloatBuffAdder, FloatBuffMultiplier, IntBuffAdder, IntBuffMultiplier. You can define your own types of processors by inheriting from BuffProcessor<T>.

  • If you cache the created processor instance, you can access the ProcessCallback property to change the processing logic, instead of creating a completely new instance:

var buff = new Buff<float>(1f);
var processor = new BuffProcessor<float>(value => value + 5f);

buff.Add(Guid.NewGuid(), processor);
Debug.Log(buff.Calculate()); // prints 6

processor.ProcessCallback = value => value / 2f;
Debug.Log(buff.Calculate()); // prints 0.5
  • If you don't want to write separately a field with a parameter (float, int, ...) and a field with a buff, you can use the types: FloatBuffField, IntBuffField. You can also make an implementation for a new type by inheriting from BuffField<T> and adding the [Serializable] attribute.

About

A simple implementation of buffs for scripts in Unity.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages