Source file unity-csharp/systemic-design/ElementSource.cs from the GDnD code examples. Download raw file

// GDnD wiki example (3 of 3: ChemistryRules.cs, ChemistryBody.cs, ElementSource.cs)
// Demonstrates: the "element" side of a Breath of the Wild-style chemistry engine. A trigger
//   volume that applies its element to every ChemistryBody inside it: a campfire (Fire), a pond
//   (Water), an ice patch (Ice), a charged plate (Electricity) or a gust (Wind). Expose() applies
//   rule 2, so sources can change each other: water puts a campfire out, fire melts ice to water.
// Related pages: [[breath-of-the-wild]], [[emergent-design]], [[unity-collider2d-and-triggers]],
//   [[source-botw-breaking-conventions-gdc-2017]]
// Unity 6 (6000.x), 2D physics.
//
// Setup: add to a GameObject with a Collider2D set to Is Trigger. Trigger callbacks need a
//   Rigidbody2D on at least one of the two objects (the moving ChemistryBody usually has one;
//   otherwise give the source a Kinematic Rigidbody2D). Call Expose from anything that throws an
//   element at the source, e.g. a water-bucket projectile calling source.Expose(Element.Water).
 
using UnityEngine;
 
namespace GDnD.Systemic.Chemistry
{
    [RequireComponent(typeof(Collider2D))]
    public class ElementSource : MonoBehaviour
    {
        [SerializeField] private Element element = Element.Fire;
        [SerializeField] private Vector2 windDirection = Vector2.right;
 
        public Element Current => element;
 
        public void Expose(Element incoming) => element = ChemistryRules.Combine(element, incoming);
 
        private void OnTriggerStay2D(Collider2D other)
        {
            if (element != Element.None && other.TryGetComponent(out ChemistryBody target))
                target.ReceiveElement(element, windDirection);
        }
    }
}