添加插件

This commit is contained in:
2025-11-10 00:08:26 +08:00
parent 4059c207c0
commit 76f80db694
2814 changed files with 436400 additions and 178 deletions

View File

@@ -0,0 +1,29 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_bool.asset", menuName = "Soap/ScriptableVariables/bool")]
[System.Serializable]
public class BoolVariable : ScriptableVariable<bool>
{
public override void Save()
{
PlayerPrefs.SetInt(Guid, Value ? 1 : 0);
base.Save();
}
public override void Load()
{
Value = PlayerPrefs.GetInt(Guid, DefaultValue ? 1 : 0) > 0;
base.Load();
}
/// <summary>
/// Use this to toggle the value of the variable.
/// </summary>
public void Toggle()
{
Value = !Value;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a11231538da9894d8dce88b47df6a36
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_color.asset", menuName = "Soap/ScriptableVariables/color")]
public class ColorVariable : ScriptableVariable<Color>
{
public override void Save()
{
PlayerPrefs.SetFloat(Guid + "_r", Value.r);
PlayerPrefs.SetFloat(Guid + "_g", Value.g);
PlayerPrefs.SetFloat(Guid + "_b", Value.b);
PlayerPrefs.SetFloat(Guid + "_a", Value.a);
base.Save();
}
public override void Load()
{
var r = PlayerPrefs.GetFloat(Guid + "_r", DefaultValue.r);
var g = PlayerPrefs.GetFloat(Guid + "_g", DefaultValue.g);
var b = PlayerPrefs.GetFloat(Guid + "_b", DefaultValue.b);
var a = PlayerPrefs.GetFloat(Guid + "_a", DefaultValue.a);
Value = new Color(r, g, b, a);
base.Load();
}
/// <summary>
/// Sets a random color.
/// </summary>
public void SetRandom()
{
var beautifulColor = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
Value = beautifulColor;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b7046b79ca6dcd147b7412e32a7dbb69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_component.asset", menuName = "Soap/ScriptableVariables/Component")]
public class ComponentVariable : ScriptableVariable<Component>
{
public override string ToString()
{
if (Value == null)
return $"{name} : null";
return $"{name} : {Value.GetType().Name} (GameObject: {Value.gameObject.name})";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6658d50afb1d4574ea142fa9bf4758ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,99 @@
using UnityEngine;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#else
using Obvious.Soap.Attributes;
#endif
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_float.asset", menuName = "Soap/ScriptableVariables/float")]
public class FloatVariable : ScriptableVariable<float>
{
[Tooltip("Clamps the value of this variable to a minimum and maximum.")]
#if ODIN_INSPECTOR
[PropertyOrder(5)]
#endif
[SerializeField] private bool _isClamped = false;
public bool IsClamped
{
get => _isClamped;
set => _isClamped = value;
}
[Tooltip("If clamped, sets the minimum and maximum")]
[SerializeField]
#if ODIN_INSPECTOR
[ShowIf("_isClamped")]
[PropertyOrder(6)][Indent]
#else
[ShowIf("_isClamped")]
#endif
private FloatReference _min = new FloatReference(0,true);
public FloatReference MinReference
{
get => _min;
set => _min = value;
}
public float Min => _min.Value;
[Tooltip("If clamped, sets the minimum and maximum")]
[SerializeField]
#if ODIN_INSPECTOR
[ShowIf("_isClamped")]
[PropertyOrder(7)][Indent]
#else
[ShowIf("_isClamped")]
#endif
private FloatReference _max = new FloatReference(float.MaxValue,true);
public FloatReference MaxReference
{
get => _max;
set => _max = value;
}
public float Max => _max.Value;
/// <summary>
/// Returns the percentage of the value between the minimum and maximum.
/// </summary>
public float Ratio => Mathf.InverseLerp( _min.Value, _max.Value, Value);
public override void Save()
{
PlayerPrefs.SetFloat(Guid, Value);
base.Save();
}
public override void Load()
{
Value = PlayerPrefs.GetFloat(Guid, DefaultValue);
base.Load();
}
public void Add(float value)
{
Value += value;
}
public override float Value
{
get => base.Value;
set
{
var clampedValue = _isClamped ? Mathf.Clamp(value, _min.Value, _max.Value) : value;
base.Value = clampedValue;
}
}
#if UNITY_EDITOR
protected override void OnValidate()
{
if (_isClamped)
{
var clampedValue = Mathf.Clamp(Value, _min.Value, _max.Value);
if (Value < clampedValue || Value > clampedValue)
Value = clampedValue;
}
base.OnValidate();
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a9978ce9c8bdc724896114c9952c52ea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_gameObject.asset", menuName = "Soap/ScriptableVariables/GameObject")]
public class GameObjectVariable : ScriptableVariable<GameObject>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5798d9261dd3eae4d920ab34987f7ade
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,103 @@
using UnityEngine;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#else
using Obvious.Soap.Attributes;
#endif
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_int.asset", menuName = "Soap/ScriptableVariables/int")]
public class IntVariable : ScriptableVariable<int>
{
[Tooltip("Clamps the value of this variable to a minimum and maximum.")]
#if ODIN_INSPECTOR
[PropertyOrder(5)]
#endif
[SerializeField]
private bool _isClamped = false;
public bool IsClamped
{
get => _isClamped;
set => _isClamped = value;
}
[Tooltip("If clamped, sets the minimum and maximum")]
[SerializeField]
#if ODIN_INSPECTOR
[ShowIf("_isClamped")]
[PropertyOrder(6)][Indent]
#else
[ShowIf("_isClamped")]
#endif
private IntReference _min = new IntReference(0,true);
public IntReference MinReference
{
get => _min;
set => _min = value;
}
public int Min => _min.Value;
[Tooltip("If clamped, sets the minimum and maximum")]
[SerializeField]
#if ODIN_INSPECTOR
[ShowIf("_isClamped")]
[PropertyOrder(7)][Indent]
#else
[ShowIf("_isClamped")]
#endif
private IntReference _max = new IntReference(int.MaxValue,true);
public IntReference MaxReference
{
get => _max;
set => _max = value;
}
public int Max => _max.Value;
/// <summary>
/// Returns the percentage of the value between the minimum and maximum.
/// </summary>
public float Ratio => Mathf.InverseLerp( _min.Value, _max.Value, Value);
public override void Save()
{
PlayerPrefs.SetInt(Guid, Value);
base.Save();
}
public override void Load()
{
Value = PlayerPrefs.GetInt(Guid, DefaultValue);
base.Load();
}
public void Add(int value)
{
Value += value;
}
public override int Value
{
get => base.Value;
set
{
var clampedValue = _isClamped ? Mathf.Clamp(value, _min.Value, _max.Value) : value;
base.Value = clampedValue;
}
}
#if UNITY_EDITOR
protected override void OnValidate()
{
if (IsClamped)
{
var clampedValue = Mathf.Clamp(Value, _min.Value, _max.Value);
if (Value < clampedValue || Value > clampedValue)
Value = clampedValue;
}
base.OnValidate();
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56cdb8ad39a5bdd4f8ed3d18fae14a63
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
using UnityEngine;
using Obvious.Soap;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_" + nameof(Quaternion), menuName = "Soap/ScriptableVariables/"+ nameof(Quaternion))]
public class QuaternionVariable : ScriptableVariable<Quaternion>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0d5e637945a57d243bfbf35cab0eba1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,342 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#else
using Obvious.Soap.Attributes;
#endif
namespace Obvious.Soap
{
public abstract class ScriptableVariable<T> : ScriptableVariableBase, IReset, IDrawObjectsInInspector
{
[Tooltip(
"The value of the variable. This will be reset on play mode exit to the value it had before entering play mode.")]
[SerializeField]
#if ODIN_INSPECTOR
[HideInPlayMode][PropertyOrder(-1)]
#endif
protected T _value;
[Tooltip("Log in the console whenever this variable is changed, loaded or saved.")] [SerializeField]
protected bool _debugLogEnabled;
#if ODIN_INSPECTOR
[PropertyOrder(1)]
#endif
[Tooltip("If true, saves the value to Player Prefs and loads it onEnable.")] [SerializeField]
protected bool _saved;
[Tooltip(
"The default value of this variable. When loading from PlayerPrefs the first time, it will be set to this value.")]
[SerializeField]
#if ODIN_INSPECTOR
[ShowIf("_saved")]
[PropertyOrder(2)]
[Indent]
[BoxGroup]
#else
[ShowIf("_saved", true)]
#endif
private T _defaultValue;
#if ODIN_INSPECTOR
[PropertyOrder(5)]
#endif
[Tooltip("Reset to initial value." +
" Scene Loaded : when the scene is loaded." +
" Application Start : Once, when the application starts." +
" None : Never.")]
[SerializeField]
private ResetType _resetOn = ResetType.SceneLoaded;
public override ResetType ResetType
{
get => _resetOn;
set => _resetOn = value;
}
protected T _initialValue;
[SerializeField]
#if ODIN_INSPECTOR
[HideInEditorMode][PropertyOrder(-1)]
#endif
protected T _runtimeValue;
private readonly List<Object> _listenersObjects = new List<Object>();
#if ODIN_INSPECTOR
[HideInEditorMode]
[ShowInInspector,EnableGUI]
[PropertyOrder(100)]
public IEnumerable<Object> ObjectsReactingToOnValueChangedEvent => _listenersObjects;
#endif
protected Action<T> _onValueChanged;
/// <summary> Event raised when the variable value changes. </summary>
public event Action<T> OnValueChanged
{
add
{
_onValueChanged += value;
#if UNITY_EDITOR
var listener = value.Target as Object;
AddListener(listener);
#endif
}
remove
{
_onValueChanged -= value;
#if UNITY_EDITOR
var listener = value.Target as Object;
RemoveListener(listener);
#endif
}
}
/// <summary>
/// The previous value just after the value changed.
/// </summary>
public T PreviousValue { get; private set; }
/// <summary>
/// The default value this variable is reset to.
/// </summary>
public T DefaultValue => _defaultValue;
#if UNITY_EDITOR
private T Read() => Application.isPlaying ? _runtimeValue : _value;
private void Write(T v)
{
if (Application.isPlaying)
_runtimeValue = v;
else
_value = v;
}
#else
private T Read() => _value;
private void Write(T v) { _value = v; }
#endif
/// <summary>
/// Modify this to change the value of the variable.
/// Triggers OnValueChanged event.
/// </summary>
public virtual T Value
{
get => Read();
set
{
var current = Read();
if (EqualityComparer<T>.Default.Equals(current, value))
return;
Write(value);
ValueChanged(true);
}
}
public virtual void SetValueWithoutNotify(T value)
{
var current = Read();
if (EqualityComparer<T>.Default.Equals(current, value))
return;
Write(value);
ValueChanged(false);
}
public virtual void ValueChanged(bool triggerEvent = true)
{
if (_saved)
Save();
if (_debugLogEnabled)
{
var suffix = _saved ? " <color=#f75369>[Saved]</color>" : "";
Debug.Log($"{GetColorizedString()}{suffix}", this);
}
if (triggerEvent)
_onValueChanged?.Invoke(Read());
PreviousValue = Read();
#if UNITY_EDITOR
if (this != null) //for runtime variables, the instance will be destroyed so do not repaint.
RepaintRequest?.Invoke();
#endif
}
public override Type GetGenericType => typeof(T);
protected virtual void Awake()
{
//Prevents from resetting if no reference in a scene
hideFlags = HideFlags.DontUnloadUnusedAsset;
}
protected virtual void OnEnable()
{
#if UNITY_EDITOR
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
#else
Init();
#endif
if (_resetOn == ResetType.SceneLoaded)
SceneManager.sceneLoaded += OnSceneLoaded;
}
protected virtual void OnDisable()
{
#if UNITY_EDITOR
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
#endif
SceneManager.sceneLoaded -= OnSceneLoaded;
}
protected virtual void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//the reset mode can change after the game has started, so we need to check it here.
if (_resetOn != ResetType.SceneLoaded)
return;
if (mode == LoadSceneMode.Single)
{
if (_saved)
Load();
else
ResetValue();
}
}
#if UNITY_EDITOR
public void OnPlayModeStateChanged(PlayModeStateChange playModeStateChange)
{
if (playModeStateChange == PlayModeStateChange.ExitingEditMode)
{
Init();
}
else if (playModeStateChange == PlayModeStateChange.EnteredEditMode)
{
if (!_saved)
{
ResetValue();
}
else
{
if (EqualityComparer<T>.Default.Equals(_value, _runtimeValue))
return;
// Set the value to the runtime value
_value = _runtimeValue;
_runtimeValue = _initialValue;
EditorUtility.SetDirty(this);
RepaintRequest?.Invoke();
}
}
}
protected virtual void OnValidate()
{
//In default play mode, this get called before OnEnable(). Therefore a saved variable can get saved before loading.
//This check prevents the latter.
if (EqualityComparer<T>.Default.Equals(Read(), PreviousValue))
return;
ValueChanged();
}
/// <summary> Reset the SO to default.</summary>
internal override void Reset()
{
base.Reset();
_listenersObjects.Clear();
Value = default;
_initialValue = default;
_runtimeValue = default;
PreviousValue = default;
_saved = false;
_resetOn = ResetType.SceneLoaded;
_debugLogEnabled = false;
}
public void AddListener(Object listener)
{
if (listener != null && !_listenersObjects.Contains(listener))
_listenersObjects.Add(listener);
}
public void RemoveListener(Object listener)
{
if (_listenersObjects.Contains(listener))
_listenersObjects.Remove(listener);
}
#endif
private void Init()
{
if (_saved)
Load();
_initialValue = _value;
_runtimeValue = _value;
PreviousValue = _value;
_listenersObjects.Clear();
}
/// <summary> Reset to initial value</summary>
public void ResetValue()
{
Value = _initialValue;
PreviousValue = _initialValue;
_runtimeValue = _initialValue;
}
public virtual void Save()
{
}
public virtual void Load()
{
PreviousValue = _value;
if (_debugLogEnabled)
Debug.Log($"{GetColorizedString()} <color=#f75369>[Loaded].</color>", this);
}
public override string ToString()
{
return $"{name} : {Value}";
}
protected virtual string GetColorizedString() => $"<color=#f75369>[Variable]</color> {ToString()}";
public IReadOnlyList<Object> EditorListeners => _listenersObjects.AsReadOnly();
public static implicit operator T(ScriptableVariable<T> variable) => variable.Value;
}
/// <summary>
/// Defines when the variable is reset.
/// </summary>
public enum ResetType
{
SceneLoaded,
ApplicationStarts,
None
}
public enum CustomVariableType
{
None,
Bool,
Int,
Float,
String
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9dcab23e1548c9344916733798631cec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
using UnityEngine;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
namespace Obvious.Soap
{
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-variable")]
public abstract class ScriptableVariableBase : ScriptableBase
{
#if ODIN_INSPECTOR
[PropertyOrder(4)]
[DisableIf("_saveGuid", SaveGuidType.Auto)]
[ShowIf("_saved")]
[Indent]
[BoxGroup]
#endif
[SerializeField]
private string _guid;
#if ODIN_INSPECTOR
[PropertyOrder(3)]
[ShowIf("_saved")]
[Indent]
[BoxGroup]
//[LabelWidth(80)]
#endif
[Tooltip("ID used as the Player Prefs Key.\n" +
"Auto: Guid is generated automatically base on the asset path.\n" +
"Manual: Guid can be overwritten manually.")]
[SerializeField]
private SaveGuidType _saveGuid;
public SaveGuidType SaveGuid => _saveGuid;
/// <summary>
/// Guid is needed to save/load the value to PlayerPrefs.
/// </summary>
public string Guid
{
get => _guid;
set => _guid = value;
}
public virtual ResetType ResetType { get; set; }
}
public enum SaveGuidType
{
Auto,
Manual,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dffd90b3e4094da298b30ac2f9553d0b
timeCreated: 1675031065

View File

@@ -0,0 +1,20 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_string.asset", menuName = "Soap/ScriptableVariables/string")]
public class StringVariable : ScriptableVariable<string>
{
public override void Save()
{
PlayerPrefs.SetString(Guid, Value);
base.Save();
}
public override void Load()
{
Value = PlayerPrefs.GetString(Guid, DefaultValue);
base.Load();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fbb51723e892a404a87b22018981eb5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d709c36840cc4b4986ebe2c5e3ed2b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Obvious.Soap
{
[System.Serializable]
public class BoolReference : VariableReference<BoolVariable, bool>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04cd28045cfa5ca40b0c1811c7de86af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Obvious.Soap
{
[System.Serializable]
public class ColorReference : VariableReference<ColorVariable, UnityEngine.Color>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c16be5b350d07740960221d2f880d4b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
namespace Obvious.Soap
{
[System.Serializable]
public class FloatReference : VariableReference<FloatVariable, float>
{
public FloatReference()
{
}
public FloatReference(float initialValue, bool useLocal = false)
{
LocalValue = initialValue;
UseLocal = useLocal;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d69d26f58cf51154cb43cf597b57d0dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
namespace Obvious.Soap
{
[System.Serializable]
public class IntReference : VariableReference<IntVariable, int>
{
public IntReference()
{
}
public IntReference(int initialValue, bool useLocal = false)
{
LocalValue = initialValue;
UseLocal = useLocal;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a9c0318cbda96274daa33a0b0a4a65a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Obvious.Soap
{
[System.Serializable]
public class StringReference : VariableReference<StringVariable, string>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5be4248575855e344ad1a3d62c03d779
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Obvious.Soap
{
//Unity cannot serialize generic types, so we need to create a non-generic base class
public abstract class VariableReferenceBase { }
[Serializable]
public abstract class VariableReference<V, T> : VariableReferenceBase, ISerializationCallbackReceiver where V : ScriptableVariable<T>
{
public bool UseLocal;
public T LocalValue;
public V Variable;
private Action<T> _onValueChanged;
[NonSerialized] private T _lastSerializedLocalValue;
public T Value
{
get
{
if (UseLocal)
return LocalValue;
if (Variable == null)
return default;
return Variable.Value;
}
set
{
if (UseLocal)
{
if (Equals(LocalValue, value))
return;
LocalValue = value;
_onValueChanged?.Invoke(LocalValue);
}
else
{
Variable.Value = value;
}
}
}
/// <summary> Event raised when the variable reference value changes.
/// Is triggered for both local and variable. </summary>
public event Action<T> OnValueChanged
{
add
{
_onValueChanged += value;
if (Variable != null)
Variable.OnValueChanged += value;
}
remove
{
_onValueChanged -= value;
if (Variable != null)
Variable.OnValueChanged -= value;
}
}
public static implicit operator T(VariableReference<V, T> reference)
{
return reference.Value;
}
public void OnBeforeSerialize()
{
_lastSerializedLocalValue = LocalValue;
}
public void OnAfterDeserialize()
{
if (UseLocal && !EqualityComparer<T>.Default.Equals(_lastSerializedLocalValue, LocalValue))
{
_onValueChanged?.Invoke(LocalValue);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8349e47b1834dc2409db52bf4844dabb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Obvious.Soap
{
[System.Serializable]
public class Vector2IntReference : VariableReference<Vector2IntVariable, UnityEngine.Vector2Int>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dbd9d492c80528946a0b29ed44c02f21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Obvious.Soap
{
[System.Serializable]
public class Vector2Reference : VariableReference<Vector2Variable, UnityEngine.Vector2>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d2475a2952069444791b28c347f20912
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Obvious.Soap
{
[System.Serializable]
public class Vector3Reference : VariableReference<Vector3Variable, UnityEngine.Vector3>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24c4af42bed07564ca5b965a62b3b6ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_vector2Int", menuName = "Soap/ScriptableVariables/Vector2Int")]
public class Vector2IntVariable : ScriptableVariable<Vector2Int>
{
public override void Save()
{
PlayerPrefs.SetInt(Guid + "_x", Value.x);
PlayerPrefs.SetInt(Guid + "_y", Value.y);
base.Save();
}
public override void Load()
{
var x = PlayerPrefs.GetInt(Guid + "_x", DefaultValue.x);
var y = PlayerPrefs.GetInt(Guid + "_y", DefaultValue.y);
Value = new Vector2Int(x,y);
base.Load();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1afa6fbeda4c35d45a09c5812a671a42
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_vector2.asset", menuName = "Soap/ScriptableVariables/Vector2")]
public class Vector2Variable : ScriptableVariable<Vector2>
{
public override void Save()
{
PlayerPrefs.SetFloat(Guid + "_x", Value.x);
PlayerPrefs.SetFloat(Guid + "_y", Value.y);
base.Save();
}
public override void Load()
{
var x = PlayerPrefs.GetFloat(Guid + "_x", DefaultValue.x);
var y = PlayerPrefs.GetFloat(Guid + "_y", DefaultValue.y);
Value = new Vector2(x,y);
base.Load();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33653d5fffc16644bb2d768701efbabf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using UnityEngine;
namespace Obvious.Soap
{
[CreateAssetMenu(fileName = "scriptable_variable_vector3.asset", menuName = "Soap/ScriptableVariables/Vector3")]
public class Vector3Variable : ScriptableVariable<Vector3>
{
public override void Save()
{
PlayerPrefs.SetFloat(Guid + "_x", Value.x);
PlayerPrefs.SetFloat(Guid + "_y", Value.y);
PlayerPrefs.SetFloat(Guid + "_z", Value.z);
base.Save();
}
public override void Load()
{
var x = PlayerPrefs.GetFloat(Guid + "_x", DefaultValue.x);
var y = PlayerPrefs.GetFloat(Guid + "_y", DefaultValue.y);
var z = PlayerPrefs.GetFloat(Guid + "_z", DefaultValue.z);
Value = new Vector3(x,y,z);
base.Load();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1300736a6c75069498acdad864241816
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8173878b5f4d7724784454801c58c9c4, type: 3}
userData:
assetBundleName:
assetBundleVariant: