添加插件

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,38 @@
using System;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/9_scriptabledictionaries")]
[SelectionBase]
[RequireComponent(typeof(Element))]
public class AddRemoveElementToDictionary : MonoBehaviour
{
[SerializeField] private ScriptableDictionaryElementInt _scriptableDictionary = null;
private Element _element;
private void Start()
{
_element = GetComponent<Element>();
//Try to add the first element of this type
if (!_scriptableDictionary.TryAdd(_element.ElementType, 1))
{
//If its already in, just increment the count
_scriptableDictionary[_element.ElementType]++;
}
}
private void OnDestroy()
{
//Decrement the count of the element
_scriptableDictionary[_element.ElementType]--;
//If the count is 0, remove the element from the dictionary
if (_scriptableDictionary[_element.ElementType] == 0)
{
_scriptableDictionary.Remove(_element.ElementType);
}
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class AutoDisabler : MonoBehaviour
{
[SerializeField] private float _duration = 0.5f;
public void OnEnable()
{
Invoke(nameof(Disable),_duration);
}
private void Disable()
{
gameObject.SetActive(false);
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class AutoRotator : MonoBehaviour
{
[SerializeField] private float _speed = 350f;
public void Update()
{
transform.localEulerAngles += _speed * Vector3.up * Time.deltaTime;
}
public void SetRotationSpeed(float value)
{
_speed = value;
}
}
}

View File

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

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class AutoRotatorWithSingleton : MonoBehaviour
{
public void Update()
{
transform.localEulerAngles += SoapGameParams.Instance.CoinRotateSpeed * Vector3.up * Time.deltaTime;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a1d708df8b59405b8692b667623cd489
timeCreated: 1746103191

View File

@@ -0,0 +1,18 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class CoinCollector : MonoBehaviour
{
[SerializeField] private IntVariable _coinCollected;
private void OnTriggerEnter(Collider other)
{
if (other.transform.parent.name.Contains("Coin"))
{
_coinCollected.Add(1);
Destroy(other.gameObject);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 98f1921ce0b047ccbc1bd1994fb13c93
timeCreated: 1746103708

View File

@@ -0,0 +1,41 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class CoinSpawner : MonoBehaviour
{
[SerializeField] private GameObject _prefab = null;
[SerializeField] private float _radius = 10f;
private void Start()
{
Spawn(SoapGameParams.Instance.CoinSpawnedAmount);
}
private void Spawn(int amount)
{
for (int i = 0; i < amount; i++)
{
var spawnInfo = GetRandomPositionAndRotation();
var obj = Instantiate(_prefab, spawnInfo.position, spawnInfo.rotation, transform);
obj.AddComponent<AutoRotatorWithSingleton>();
obj.SetActive(true);
}
}
private (Vector3 position, Quaternion rotation) GetRandomPositionAndRotation()
{
var randomPosition = Random.insideUnitSphere * _radius;
randomPosition.y = 0f;
var spawnPos = transform.position + randomPosition;
var randomRotation = Quaternion.Euler(0, Random.Range(0, 360), 0);
return (spawnPos, randomRotation);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, _radius);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ef6e5b65ad7402f8024f23f702e0de7
timeCreated: 1746102664

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class DestroyObjectOnTrigger : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
Destroy(other.gameObject);
}
}
}

View File

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

View File

@@ -0,0 +1,28 @@
using TMPro;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/6_scriptableenums")]
[SelectionBase]
public class Element : MonoBehaviour
{
[SerializeField] private ScriptableEnumElement _elementType = null;
public ScriptableEnumElement ElementType => _elementType;
private void Start()
{
GetComponent<Renderer>().material.color = _elementType.Color;
GetComponentInChildren<TextMeshPro>().text = _elementType.Icon.name;
}
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.TryGetComponent<Element>(out var element))
{
if (_elementType.Defeats.Contains(element.ElementType))
Destroy(other.gameObject);
}
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap.Example
{
public class Enemy : MonoBehaviour
{
[SerializeField] private UnityEvent _onHitPlayerEvent = null;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
_onHitPlayerEvent?.Invoke();
}
}
}

View File

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

View File

@@ -0,0 +1,55 @@
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using Random = UnityEngine.Random;
namespace Obvious.Soap.Example
{
public class EnemyMovement : MonoBehaviour
{
[SerializeField] private FloatReference _speed = null;
[SerializeField] private UnityEvent _onStartMoving = null;
[SerializeField] private UnityEvent _onStopMoving = null;
private IEnumerator Start() //start can be a Coroutine :)
{
while (true)
{
_onStartMoving?.Invoke();
yield return Cr_MoveTo(FindRandomPositionInRadius(10f));
_onStopMoving?.Invoke();
yield return Cr_WaitRandom();
}
}
private IEnumerator Cr_WaitRandom()
{
var delay = Random.Range(0.5f, 2f);
yield return new WaitForSeconds(delay);
}
private Vector3 FindRandomPositionInRadius(float radius)
{
var randomPos = Random.insideUnitSphere * radius;
randomPos.y = 0;
return randomPos;
}
private IEnumerator Cr_MoveTo(Vector3 destination)
{
var direction = (destination - transform.position).normalized;
while (!IsAtDestination())
{
transform.position += direction * _speed * Time.deltaTime;
yield return null;
}
bool IsAtDestination()
{
var sqrDistance = (destination - transform.position).sqrMagnitude;
return sqrDistance <= 0.5f * 0.5f;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 51bcfe43449e44d5a38179065b42c189
timeCreated: 1652997661

View File

@@ -0,0 +1,62 @@
using System.Collections;
using Obvious.Soap.Attributes;
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap.Example
{
public class EnemyMovementInjected : MonoBehaviour
{
[RuntimeInjectable("speed")]
[SerializeField]
private FloatVariable _speed = null;
[SerializeField] private UnityEvent _onStartMoving = null;
[SerializeField] private UnityEvent _onStopMoving = null;
private void Awake()
{
_speed.Value = 10; //(or whatever dynamic value you want);
}
private IEnumerator Start()
{
while (true)
{
_onStartMoving?.Invoke();
yield return Cr_MoveTo(FindRandomPositionInRadius(10f));
_onStopMoving?.Invoke();
yield return Cr_WaitRandom();
}
}
private IEnumerator Cr_WaitRandom()
{
var delay = Random.Range(0.5f, 2f);
yield return new WaitForSeconds(delay);
}
private Vector3 FindRandomPositionInRadius(float radius)
{
var randomPos = Random.insideUnitSphere * radius;
randomPos.y = 0;
return randomPos;
}
private IEnumerator Cr_MoveTo(Vector3 destination)
{
var direction = (destination - transform.position).normalized;
while (!IsAtDestination())
{
transform.position += direction * _speed * Time.deltaTime;
yield return null;
}
bool IsAtDestination()
{
var sqrDistance = (destination - transform.position).sqrMagnitude;
return sqrDistance <= 0.5f * 0.5f;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ff3b678bcac6497fbbe09654154142f0
timeCreated: 1736517559

View File

@@ -0,0 +1,35 @@
using System.Collections;
using UnityEngine;
namespace Obvious.Soap.Example
{
[RequireComponent(typeof(CanvasGroup))]
public class FadeOut : CacheComponent<CanvasGroup>
{
[SerializeField] private float _duration = 0.5f;
private Coroutine _coroutine = null;
public void Activate()
{
if (_coroutine != null)
StopCoroutine(_coroutine);
_coroutine = StartCoroutine(Cr_FadeOut());
}
private IEnumerator Cr_FadeOut()
{
var timer = 0f;
_component.alpha = 1f;
while (timer <= _duration)
{
_component.alpha = Mathf.Lerp(1f, 0f, timer / _duration);
timer += Time.deltaTime;
yield return null;
}
_component.alpha = 0;
}
}
}

View File

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

View File

@@ -0,0 +1,28 @@
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Obvious.Soap.Example
{
public class GameManager : MonoBehaviour
{
[SerializeField] private KeyCode _reloadSceneKey = KeyCode.R;
[SerializeField] private KeyCode _deletePlayerPrefs = KeyCode.P;
void Update()
{
if (Input.GetKeyDown(_reloadSceneKey))
ReloadScene();
if (Input.GetKeyDown(_deletePlayerPrefs))
PlayerPrefs.DeleteAll();
if (Input.GetKeyDown(KeyCode.Escape))
Application.Quit();
}
public void ReloadScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
}

View File

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

View File

@@ -0,0 +1,26 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/4_scriptableevents/registering-to-events-from-code")]
public class HealVignette : MonoBehaviour
{
[SerializeField] private ScriptableEventInt _onPlayerHealedEvent = null;
[SerializeField] private FadeOut _fadeOut = null;
private void Awake()
{
_onPlayerHealedEvent.OnRaised += OnPlayerHealed;
}
private void OnDestroy()
{
_onPlayerHealedEvent.OnRaised -= OnPlayerHealed;
}
private void OnPlayerHealed(int amount)
{
_fadeOut.Activate();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bb7e17f9d514c644289c4e168d3e8da9
timeCreated: 1652997661

View File

@@ -0,0 +1,69 @@
using JetBrains.Annotations;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/1_scriptablevariables")]
public class Health : MonoBehaviour
{
[SerializeField] private FloatVariable _currentHealth = null;
[SerializeField] private FloatReference _maxHealth = null;
[Header("Scriptable Events")] [SerializeField] private ScriptableEventInt _onPlayerDamaged = null;
[SerializeField] private ScriptableEventInt _onPlayerHealed = null;
[SerializeField] private ScriptableEventNoParam _onPlayerDeath = null;
private bool _isDead = false;
private void Start()
{
_currentHealth.Value = _maxHealth.Value;
_currentHealth.OnValueChanged += OnHealthChanged;
}
private void OnDestroy()
{
_currentHealth.OnValueChanged -= OnHealthChanged;
}
private void OnHealthChanged(float newValue)
{
var diff = newValue - _currentHealth.PreviousValue;
if (diff < 0)
{
OnDamaged(Mathf.Abs(diff));
}
else
{
OnHealed(diff);
}
}
private void OnDamaged(float value)
{
if (_currentHealth <= 0f && !_isDead)
OnDeath();
else
_onPlayerDamaged.Raise(Mathf.RoundToInt(value));
}
private void OnHealed(float value)
{
_onPlayerHealed.Raise(Mathf.RoundToInt(value));
}
private void OnDeath()
{
_onPlayerDeath.Raise();
_isDead = true;
}
//if you don't want to modify directly the health, you can also do it like this
//Used in the Event example.
[UsedImplicitly]
public void TakeDamage(int amount)
{
_currentHealth.Add(-amount);
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
using Obvious.Soap.Attributes;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/8_runtimevariables")]
public class HealthBarSprite : MonoBehaviour
{
[BeginDisabledGroup]
[SerializeField] private FloatVariable _runtimeHpVariable;
[SerializeField] private Transform _fillTransform = null;
//The variable is manually injected by another script (RuntimeHealth in this case).
public void Init(FloatVariable runtimeVariable)
{
_runtimeHpVariable = runtimeVariable;
_runtimeHpVariable.OnValueChanged += OnHealthChanged;
}
private void OnDisable()
{
_runtimeHpVariable.OnValueChanged -= OnHealthChanged;
}
private void OnHealthChanged(float currentHpValue)
{
var hpRatio = Mathf.Clamp01(currentHpValue / _runtimeHpVariable.Max);
_fillTransform.localPosition = new Vector3((-1 + hpRatio) * 0.5f, 0,0);
_fillTransform.localScale = new Vector3(hpRatio,1,1);
}
}
}

View File

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

View File

@@ -0,0 +1,33 @@
using Obvious.Soap.Attributes;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/8_runtimevariables")]
public class HealthBarSpriteAutoInjection : MonoBehaviour
{
[Tooltip("This field will be injected at runtime")]
[SerializeField]
[RuntimeInjectable("hp")]
private FloatVariable _runtimeHpVariable;
[SerializeField] private Transform _fillTransform = null;
public void Awake()
{
_runtimeHpVariable.OnValueChanged += OnHealthChanged;
}
private void OnDisable()
{
_runtimeHpVariable.OnValueChanged -= OnHealthChanged;
}
private void OnHealthChanged(float currentHpValue)
{
var hpRatio = Mathf.Clamp01(currentHpValue / _runtimeHpVariable.Max);
_fillTransform.localPosition = new Vector3((-1 + hpRatio) * 0.5f, 0,0);
_fillTransform.localScale = new Vector3(hpRatio,1,1);
}
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using System;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-subassets")]
public class HealthPowerUp : MonoBehaviour
{
[SerializeField] private PlayerStats _playerStats;
private void OnTriggerEnter(Collider other)
{
_playerStats.Health.Add(30);
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
using UnityEngine;
using UnityEngine.UI;
namespace Obvious.Soap.Example
{
[RequireComponent(typeof(Button))]
public class HyperlinkButton : CacheComponent<Button>
{
[SerializeField] private string _url = string.Empty;
protected override void Awake()
{
base.Awake();
_component.onClick.AddListener(() => { Application.OpenURL(_url); });
}
}
}

View File

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

View File

@@ -0,0 +1,28 @@
using TMPro;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/3_scriptablelists")]
[RequireComponent(typeof(TMP_Text))]
public class ListCount : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _text = null;
[SerializeField] private ScriptableListPlayer scriptableListPlayer = null;
void Awake()
{
scriptableListPlayer.Modified += UpdateText;
}
private void OnDestroy()
{
scriptableListPlayer.Modified -= UpdateText;
}
private void UpdateText()
{
_text.text = $"Count : {scriptableListPlayer.Count}";
}
}
}

View File

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

View File

@@ -0,0 +1,42 @@
using JetBrains.Annotations;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Obvious.Soap.Example
{
public class ObjectSpawner : MonoBehaviour
{
[SerializeField] private GameObject _prefab = null;
[SerializeField] private int _amount = 10;
[SerializeField] private float _radius = 10f;
[UsedImplicitly]
public void Spawn()
{
for (int i = 0; i < _amount; i++)
{
var spawnInfo = GetRandomPositionAndRotation();
var obj = Instantiate(_prefab, spawnInfo.position, spawnInfo.rotation, transform);
obj.SetActive(true);
}
}
private (Vector3 position, Quaternion rotation) GetRandomPositionAndRotation()
{
var randomPosition = Random.insideUnitSphere * _radius;
randomPosition.y = 0f;
var spawnPos = transform.position + randomPosition;
var randomRotation = Quaternion.Euler(
Random.Range(0, 360),
Random.Range(0, 360),
Random.Range(0, 360));
return (spawnPos, randomRotation);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, _radius);
}
}
}

View File

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

View File

@@ -0,0 +1,18 @@
{
"name": "Obious.Soap.Example",
"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:6546d7765b4165b40850b3667f981c26",
"GUID:ee6baafdecd94804a8714654c4bd097f",
"GUID:d077ff18d774b9d479c2ce4c35deb3a1"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7bfe539b077dc974898ee3ed5a4be674
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using UnityEngine;
using UnityEngine.Events;
namespace Obvious.Soap.Example
{
public class Player : MonoBehaviour
{
[SerializeField] private ScriptableListPlayer scriptableListPlayer = null;
[SerializeField] private PlayerVariable _playerVariable = null;
[SerializeField] private UnityEvent _onNotified = null;
private void Awake()
{
_playerVariable.Value = this;
scriptableListPlayer.TryAdd(this);
}
private void OnDestroy()
{
scriptableListPlayer.Remove(this);
}
public void Notify()
{
_onNotified?.Invoke();
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
public class PlayerColorRandomizer : MonoBehaviour
{
[SerializeField] private ColorVariable _colorVariable;
private void Start()
{
if (SoapGameParams.Instance.RandomPlayerColorMode)
{
_colorVariable.SetRandom();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ade9e9448622420bb937d4c78eeaac7b
timeCreated: 1746104589

View File

@@ -0,0 +1,14 @@
using Obvious.Soap.Attributes;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/7_scriptablesubassets")]
[CreateAssetMenu(menuName = "Soap/Examples/SubAssets/PlayerEvents")]
public class PlayerEvents : ScriptableObject
{
[SerializeField] [SubAsset] private ScriptableEventInt _onDamaged;
[SerializeField] [SubAsset] private ScriptableEventInt _onHealed;
[SerializeField] [SubAsset] private ScriptableEventNoParam _onDeath;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 46c5bf15c65a44a2b0dd7e12cfccb0fc
timeCreated: 1716081578

View File

@@ -0,0 +1,24 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/1_scriptablevariables/solving-dependencies")]
public class PlayerInput : MonoBehaviour
{
[SerializeField] private BoolVariable _inputsEnabled = null;
[SerializeField] private Vector2Variable _inputs = null;
private Vector2 _currentInput = Vector2.zero;
void Update()
{
if (!_inputsEnabled.Value)
return;
_currentInput.x = Input.GetAxis("Horizontal");
_currentInput.y = Input.GetAxis("Vertical");
_inputs.Value = _currentInput;
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/1_scriptablevariables/solving-dependencies")]
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private Vector2Variable _inputs = null;
[SerializeField] private FloatReference _speed = null;
void Update()
{
var direction = new Vector3(_inputs.Value.x, 0, _inputs.Value.y);
transform.position += direction * _speed * Time.deltaTime;
}
}
}

View File

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

View File

@@ -0,0 +1,26 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/1_scriptablevariables/solving-dependencies")]
public class PlayerNotifier : MonoBehaviour
{
[SerializeField] private PlayerVariable _playerVariable = null;
private readonly float _delay = 1.5f;
private float _timer = 0f;
private void Update()
{
_timer += Time.deltaTime;
if (_timer >= _delay)
{
//perform any actions on the player!
//not need to find the player in the scene, or to access it via a singleton
_playerVariable.Value.Notify();
_timer = 0;
}
}
}
}

View File

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

View File

@@ -0,0 +1,31 @@
using JetBrains.Annotations;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/3_scriptablelists/adding-and-removing-elements")]
public class PlayerSpawner : MonoBehaviour
{
[SerializeField] private ScriptableListPlayer _scriptableListPlayer = null;
[SerializeField] private Player _prefab = null;
[UsedImplicitly]
public void Spawn()
{
var randomPosition = Random.insideUnitSphere * 10f;
randomPosition.y = 0f;
var player = Instantiate(_prefab, randomPosition, Quaternion.identity, transform);
player.name = $"prefab_player_{_scriptableListPlayer.Count}";
}
[UsedImplicitly]
public void DestroyOldest()
{
if (_scriptableListPlayer.IsEmpty)
return;
_scriptableListPlayer.DestroyFirst();
}
}
}

View File

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

View File

@@ -0,0 +1,14 @@
using Obvious.Soap.Attributes;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-subassets")]
[CreateAssetMenu(menuName = "Soap/Examples/SubAssets/PlayerStats")]
public class PlayerStats : ScriptableObject
{
[SerializeField] [SubAsset] private FloatVariable _speed;
[SubAsset] public FloatVariable Health;
[SubAsset] public FloatVariable MaxHealth;
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,50 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/3_scriptablelists/iteration")]
public class PlayersNotifier : MonoBehaviour
{
[SerializeField] private ScriptableListPlayer scriptableListPlayer = null;
[SerializeField] private IterationType _iterationType = IterationType.IEnumerable;
private float _delay = 1.5f;
private float _timer = 0f;
private enum IterationType
{
IEnumerable,
Foreach,
Index
}
private void Update()
{
_timer += Time.deltaTime;
if (_timer >= _delay)
{
NotifyPlayers();
_timer = 0;
}
}
private void NotifyPlayers()
{
switch (_iterationType)
{
case IterationType.IEnumerable:
foreach (var player in scriptableListPlayer)
player.Notify();
break;
case IterationType.Foreach:
scriptableListPlayer.ForEach(player => player.Notify());
break;
case IterationType.Index:
for (int i = scriptableListPlayer.Count - 1; i >= 0; i--)
scriptableListPlayer[i].Notify();
break;
}
}
}
}

View File

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

View File

@@ -0,0 +1,20 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/1_scriptablevariables/saving-variable-values")]
public class PositionSaver : MonoBehaviour
{
[SerializeField] private Vector3Variable _vector3Variable = null;
private void Start()
{
transform.position = _vector3Variable.Value;
}
private void Update()
{
_vector3Variable.Value = transform.position;
}
}
}

View File

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

View File

@@ -0,0 +1,60 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-variable/runtime-variables")]
public class RuntimeHealth : MonoBehaviour
{
[Tooltip("Leave this null if you wan it to be instantiated at runtime")]
[SerializeField]
private FloatVariable _runtimeHpVariable;
[SerializeField]
private FloatReference _maxHealth = null;
private void Awake()
{
CreateAndInjectRuntimeVariableManually();
}
private void CreateAndInjectRuntimeVariableManually()
{
//If the variable is not set in the inspector, create a runtime instance and set the reference.
if (_runtimeHpVariable == null)
_runtimeHpVariable = SoapRuntimeUtils.CreateRuntimeInstance<FloatVariable>($"{gameObject.name}_hp");
//Set the max and clamp the value (clamping is optional, but why not?).
_runtimeHpVariable.MaxReference = _maxHealth;
_runtimeHpVariable.IsClamped = true;
//Initialize the health bar only after the variable has been created.
//You can use events to decouple components if your health bar is in another scene (UI scene for example).
//In this example, it's a local Health bar so a direct reference is fine.
GetComponentInChildren<HealthBarSprite>().Init(_runtimeHpVariable);
}
private void Start()
{
//For the runtime variables, you can do this in Awake, after creating the runtime instance.
//However, because doing this in Start works for both cases (when creating a runtime variable and referencing an existing one), it's better to do it in Start.
//Indeed, for the Boss, its value is reset OnSceneLoaded and because of the execution order:
//Awake-> SceneLoaded -> Start , the value should be Set to the max health in Start.
//Note that you could also remove Awake entirely and have the logic before these lines.
_runtimeHpVariable.Value = _maxHealth.Value;
_runtimeHpVariable.OnValueChanged += OnHealthChanged;
}
private void OnDisable()
{
_runtimeHpVariable.OnValueChanged -= OnHealthChanged;
}
private void OnHealthChanged(float newValue)
{
if (newValue <= 0f)
gameObject.SetActive(false);
}
//In this example, this is called when the enemy collides with the Player.
public void TakeDamage(int amount) => _runtimeHpVariable.Add(-amount);
}
}

View File

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

View File

@@ -0,0 +1,36 @@
using Obvious.Soap.Attributes;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/soap-core-assets/scriptable-variable/runtime-variables")]
public class RuntimeInjectedHealth : MonoBehaviour
{
[Tooltip("This field will be injected at runtime")]
[SerializeField]
[RuntimeInjectable("hp")]
private FloatVariable _runtimeHpVariable;
[SerializeField] private FloatReference _maxHealth;
private void Start()
{
_runtimeHpVariable.Value = _maxHealth.Value;
_runtimeHpVariable.OnValueChanged += OnHealthChanged;
}
private void OnDisable()
{
_runtimeHpVariable.OnValueChanged -= OnHealthChanged;
}
private void OnHealthChanged(float newValue)
{
if (newValue <= 0f)
gameObject.SetActive(false);
}
//In this example, this is called when the enemy collides with the Player.
public void TakeDamage(int amount) => _runtimeHpVariable.Add(-amount);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 90c1d0975e41490e842db574d2fb29b9
timeCreated: 1736038800

View File

@@ -0,0 +1,37 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/5_scriptablesaves/save-manager")]
public class SaveManager : MonoBehaviour
{
[SerializeField] private ScriptableSaveExample _scriptableSaveExample;
[SerializeField] private IntVariable _levelVariable;
private void Awake()
{
_scriptableSaveExample.OnLoaded += SetLevelValue;
_scriptableSaveExample.OnSaved += SetLevelValue;
}
//Load on start as other classes might register to OnLoaded in their Awake
private void Start()
{
if (_scriptableSaveExample.LoadMode == ScriptableSaveBase.ELoadMode.Manual)
_scriptableSaveExample.Load();
else
SetLevelValue();
}
private void OnDestroy()
{
_scriptableSaveExample.OnLoaded -= SetLevelValue;
_scriptableSaveExample.OnSaved -= SetLevelValue;
}
private void SetLevelValue()
{
_levelVariable.Value = _scriptableSaveExample.Level;
}
}
}

View File

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

View File

@@ -0,0 +1,34 @@
using TMPro;
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/5_scriptablesaves/save-reader")]
public class SaveReader : MonoBehaviour
{
[SerializeField] private ScriptableSaveExample _scriptableSaveExample;
[SerializeField] private TextMeshProUGUI _nameText;
private void Awake()
{
_scriptableSaveExample.OnLoaded += RefreshText;
_scriptableSaveExample.OnSaved += RefreshText;
_scriptableSaveExample.OnDeleted += RefreshText;
if (_scriptableSaveExample.LoadMode == ScriptableSaveBase.ELoadMode.Automatic)
RefreshText();
}
private void OnDestroy()
{
_scriptableSaveExample.OnLoaded -= RefreshText;
_scriptableSaveExample.OnSaved -= RefreshText;
_scriptableSaveExample.OnDeleted -= RefreshText;
}
private void RefreshText()
{
_nameText.text = _scriptableSaveExample.LastSerializedJson;
}
}
}

View File

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

View File

@@ -0,0 +1,35 @@
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Obvious.Soap.Example
{
[RequireComponent(typeof(Button))]
public class SceneDocumentationButton : CacheComponent<Button>
{
private const string SceneDocURL = "https://obvious-game.gitbook.io/soap/scene-documentation/";
protected override void Awake()
{
base.Awake();
#if UNITY_EDITOR
var sceneName = SceneManager.GetActiveScene().name.Replace("_Example_Scene", string.Empty);
//var parentFolder = Path.GetDirectoryName(GetSoapUserGuidePath());
//var docPath = parentFolder + $@"\Example Scenes\{sceneName}.pdf";
var docPath = SceneDocURL + sceneName;
_component.onClick.AddListener(() => { Application.OpenURL(docPath); });
#endif
}
#if UNITY_EDITOR
private string GetSoapUserGuidePath()
{
var guid = AssetDatabase.FindAssets("Soap User Guide").FirstOrDefault();
return guid != null ? AssetDatabase.GUIDToAssetPath(guid) : null;
}
#endif
}
}

View File

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

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[CreateAssetMenu(fileName = "ScriptableDictionaryElementInt",
menuName = "Soap/Examples/ScriptableDictionary/ScriptableDictionaryElementInt")]
public class ScriptableDictionaryElementInt : ScriptableDictionary<ScriptableEnumElement, int>
{
}
}

View File

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

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using UnityEngine;
namespace Obvious.Soap.Example
{
[CreateAssetMenu(fileName = "scriptable_enum_Element", menuName = "Soap/Examples/ScriptableEnums/Element")]
public class ScriptableEnumElement : ScriptableEnumBase
{
//convenient to have additional data in the ScriptableEnum
public Sprite Icon = null;
public Color Color = Color.white;
public List<ScriptableEnumElement> Defeats = null;
}
}

View File

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

View File

@@ -0,0 +1,16 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[CreateAssetMenu(menuName = "Soap/Examples/ScriptableLists/Player")]
public class ScriptableListPlayer : ScriptableList<Player>
{
//you can add custom methods in your custom scriptable lists like these!
public void DestroyFirst()
{
var playerToDestroy = _list[0];
Destroy(playerToDestroy.gameObject);
}
}
}

View File

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

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Obvious.Soap.Example
{
// This class is a simple example of a Save Data class.
// This should be in its own file, but for readability, it is included here.
[Serializable]
public class SaveData
{
public int Version = 1;
public int Level = 0;
public List<Item> Items = new List<Item>();
}
[Serializable]
public class Item
{
public string Id;
public string Name;
public Item(string name)
{
Id = Guid.NewGuid().ToString();
Name = name;
}
}
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/5_scriptablesaves/save-data")]
[CreateAssetMenu(fileName = "scriptableSaveExample.asset", menuName = "Soap/Examples/ScriptableSaves/ScriptableSaveExample")]
public class ScriptableSaveExample : ScriptableSave<SaveData>
{
//Useful getters
public int Version => _data.Version;
public int Level => _data.Level;
public IReadOnlyList<Item> Items => _data.Items.AsReadOnly();
#region Useful Methods
public void AddRandomItem() => AddItem(new Item("RandomItem_" + Items.Count));
public void AddItem(Item item)
{
_data.Items.Add(item);
Save();
}
public Item GetItemById(string id)
{
return _data.Items.Find(item => item.Id == id);
}
public void ClearItems()
{
_data.Items.Clear();
Save();
}
public void IncrementLevel(int value)
{
_data.Level += value;
Save();
}
public void SetLevel(int value)
{
_data.Level = value;
Save();
}
#endregion
protected override void Upgrade(SaveData oldData)
{
if (_debugLogEnabled)
Debug.Log("Upgrading data from version " + oldData.Version + " to " + _data.Version);
// Implement additional upgrade logic here
oldData.Version = _data.Version;
}
protected override bool RequiresUpgrade(SaveData saveData)
{
return saveData.Version < _data.Version;
}
}
}

View File

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

View File

@@ -0,0 +1,33 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[CreateAssetMenu(fileName = "SoapGameParams", menuName = "Soap/Examples/ScriptableSingleton/SoapGameParams")]
public class SoapGameParams : ScriptableSingleton<SoapGameParams>
{
//You can add any Soap SO here to manipulate the game parameters
//They are also accessible from the Soap wizard, but sometimes it's convenient
//to have them in a single place for easy access
public FloatVariable PlayerHealth;
public ScriptableEventNoParam ReloadSceneEvent;
[Range(0, 100)] public int CoinSpawnedAmount = 10;
[Range(0, 1000)] public int CoinRotateSpeed = 200;
public bool RandomPlayerColorMode = false;
//You can add useful methods here to manipulate the game parameters
[ContextMenu("Heal Player")]
public void HealPlayer()
{
PlayerHealth.Value += 10;
Debug.Log("Player healed. Current health: " + PlayerHealth.Value);
}
[ContextMenu("Damage Player")]
public void DamagePlayer()
{
PlayerHealth.Value -= 10;
Debug.Log("Player took damage. Current health: " + PlayerHealth.Value);
}
}
}

View File

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

View File

@@ -0,0 +1,51 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/9_scriptabledictionaries")]
public class UIElementInfo : MonoBehaviour
{
[SerializeField] private ScriptableEnumElement _scriptableEnumElement = null;
[SerializeField] private ScriptableDictionaryElementInt _scriptableDictionary = null;
[SerializeField] private TextMeshProUGUI _text = null;
[SerializeField] private Image _image = null;
private void Awake()
{
_scriptableDictionary.OnItemAdded += OnItemAdded;
_scriptableDictionary.OnItemRemoved += OnItemRemoved;
_scriptableDictionary.Modified += OnModified;
_text.transform.parent.gameObject.SetActive(false);
_image.sprite = _scriptableEnumElement.Icon;
}
private void OnDestroy()
{
_scriptableDictionary.OnItemAdded -= OnItemAdded;
_scriptableDictionary.OnItemRemoved -= OnItemRemoved;
_scriptableDictionary.Modified -= OnModified;
}
private void OnItemAdded(ScriptableEnumElement element, int value)
{
if (element != _scriptableEnumElement)
return;
_text.transform.parent.gameObject.SetActive(true);
}
private void OnItemRemoved(ScriptableEnumElement element, int value)
{
if (element != _scriptableEnumElement)
return;
_text.transform.parent.gameObject.SetActive(false);
}
private void OnModified()
{
if (_scriptableDictionary.TryGetValue(_scriptableEnumElement, out var count))
_text.text = $"Count: {count}";
}
}
}

View File

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

View File

@@ -0,0 +1,37 @@
using UnityEngine;
namespace Obvious.Soap.Example
{
[HelpURL("https://obvious-game.gitbook.io/soap/scene-documentation/3_scriptablelists/callbacks")]
public class VfxSpawner : MonoBehaviour
{
[SerializeField] private ScriptableListPlayer scriptableListPlayer = null;
[SerializeField] private GameObject _spawnVFXPrefab = null;
[SerializeField] private GameObject _destroyVFXPrefab = null;
public void Awake()
{
scriptableListPlayer.OnItemRemoved += OnPlayerDestroyed;
scriptableListPlayer.OnItemAdded += OnPlayerSpawned;
}
public void OnDestroy()
{
scriptableListPlayer.OnItemRemoved -= OnPlayerDestroyed;
scriptableListPlayer.OnItemAdded -= OnPlayerSpawned;
}
private void OnPlayerSpawned(Player player)
{
Instantiate(_spawnVFXPrefab, player.transform.position, Quaternion.identity, transform);
}
private void OnPlayerDestroyed(Player player)
{
Instantiate(_destroyVFXPrefab, player.transform.position, Quaternion.identity, transform);
}
}
}

View File

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