Skip to content

Instantly share code, notes, and snippets.

@SanielX
Created November 13, 2020 22:06
Show Gist options
  • Save SanielX/a49834bb7b8f7fdbfb19af8eb4ce0165 to your computer and use it in GitHub Desktop.
Save SanielX/a49834bb7b8f7fdbfb19af8eb4ce0165 to your computer and use it in GitHub Desktop.
Sometimes I want to change some value like "PlayerCanRun" without overriding it's actual value so I can return to it later. Also this helps dealing with situations when a lot systems could write to same value
using UnityEngine;
using System.Collections.Generic;
namespace HostGame.Utilities
{
[System.Serializable]
public abstract class BlendableValue<T>
{
protected List<BlenderOf<T>> Blenders = new List<BlenderOf<T>>();
[SerializeField] protected T defaultValue = default;
[Range(0.0f, 1.0f)]
[SerializeField] protected float weightOfDefault = 0.5f;
public void AddBlender(BlenderOf<T> blend)
{
if (!Blenders.Contains(blend))
Blenders.Add(blend);
}
public void RemoveBlender(BlenderOf<T> blend)
{
RemoveBlender(blend.ID);
}
public BlenderOf<T> GetBlender(int ID)
{
foreach(var blender in Blenders)
{
if (blender.ID == ID)
return blender;
}
return null;
}
public void SetDefaultValue(T val) => defaultValue = val;
public T DefaultValue { get => defaultValue; }
public void RemoveBlender(int id)
{
for (int i = 0; i < Blenders.Count; i++)
{
if (Blenders[i].ID == id)
{
Blenders.RemoveAt(i);
return;
}
}
}
public T Value
{
get => GetBlendedValue();
}
protected abstract T GetBlendedValue();
}
}
using System;
using UnityEngine;
namespace HostGame.Utilities
{
[Serializable]
public class BlendableFloat : BlendableValue<float>
{
public BlendableFloat(float defaultValue) => this.defaultValue = defaultValue;
protected override float GetBlendedValue()
{
float val = DefaultValue;
float multiplier = 1;
for (int i = 0; i < Blenders.Count; i++)
{
BlenderOf<float> blender = Blenders[i];
multiplier *= Mathf.Lerp(1, blender.Value, blender.Weight);
}
return val * multiplier;
}
}
[Serializable]
public class BlendableBool : BlendableValue<bool>
{
public BlendableBool(bool defVal) => defaultValue = defVal;
protected override bool GetBlendedValue()
{
float maxWeight = weightOfDefault;
bool maxWeightVal = defaultValue;
for (int i = 0; i < Blenders.Count; i++)
{
BlenderOf<bool> blender = Blenders[i];
if (blender.Weight > maxWeight)
{
maxWeight = blender.Weight;
maxWeightVal = blender.Value;
}
}
return maxWeightVal;
}
}
}
using UnityEngine;
using System.Collections.Generic;
namespace HostGame.Utilities
{
/// <summary>
/// Blenders are counted equal if their ID's are equal
/// </summary>
/// <typeparam name="T">Value they are supposed to blend (float for lerping between floats etc)</typeparam>
[System.Serializable]
public class BlenderOf<T>
{
public BlenderOf(PropertyName id, T value, float weight = 1)
{
ID = id.GetHashCode();
Value = value;
Weight = Mathf.Clamp01(weight);
}
public int ID;
public float Weight;
public T Value;
public static bool operator ==(BlenderOf<T> left, BlenderOf<T> right)
{
return left.ID == right.ID;
}
public static bool operator !=(BlenderOf<T> left, BlenderOf<T> right)
{
return left.ID != right.ID;
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is BlenderOf<T> blender)
return ID == blender.ID;
else
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment