diff --git a/Runtime/Event/Proxy/BooleanEventProxyEmitter.cs b/Runtime/Event/Proxy/BooleanEventProxyEmitter.cs
new file mode 100644
index 00000000..c855ddf0
--- /dev/null
+++ b/Runtime/Event/Proxy/BooleanEventProxyEmitter.cs
@@ -0,0 +1,23 @@
+namespace Zinnia.Event.Proxy
+{
+ using System;
+ using UnityEngine.Events;
+
+ ///
+ /// Emits a with a payload whenever the method is called.
+ ///
+ public class BooleanEventProxyEmitter : RestrictableSingleEventProxyEmitter
+ {
+ ///
+ /// Defines the event with the specified state.
+ ///
+ [Serializable]
+ public class UnityEvent : UnityEvent { }
+
+ ///
+ protected override object GetTargetToCheck()
+ {
+ return Payload;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Event/Proxy/BooleanEventProxyEmitter.cs.meta b/Runtime/Event/Proxy/BooleanEventProxyEmitter.cs.meta
new file mode 100644
index 00000000..df18744b
--- /dev/null
+++ b/Runtime/Event/Proxy/BooleanEventProxyEmitter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6e393984703cd914b9fdf5f9afa99672
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Tests/Editor/Event/Proxy/BooleanEventProxyEmitterTest.cs b/Tests/Editor/Event/Proxy/BooleanEventProxyEmitterTest.cs
new file mode 100644
index 00000000..c91c328b
--- /dev/null
+++ b/Tests/Editor/Event/Proxy/BooleanEventProxyEmitterTest.cs
@@ -0,0 +1,147 @@
+using Zinnia.Data.Type;
+using Zinnia.Event.Proxy;
+using Zinnia.Rule;
+
+namespace Test.Zinnia.Event.Proxy
+{
+ using NUnit.Framework;
+ using Test.Zinnia.Utility.Mock;
+ using UnityEngine;
+
+ public class BooleanEventProxyEmitterTest
+ {
+ private GameObject containingObject;
+ private BooleanEventProxyEmitter subject;
+
+ [SetUp]
+ public void SetUp()
+ {
+ containingObject = new GameObject("BooleanEventProxyEmitterTest");
+ subject = containingObject.AddComponent();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Object.DestroyImmediate(containingObject);
+ }
+
+ [Test]
+ public void Receive()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ bool payload = true;
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+
+ subject.Receive(payload);
+
+ Assert.IsTrue(subject.Payload);
+ Assert.IsTrue(emittedMock.Received);
+ }
+
+ [Test]
+ public void EmitPayload()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ bool payload = true;
+ subject.Payload = payload;
+
+ Assert.IsTrue(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+
+ subject.EmitPayload();
+
+ Assert.IsTrue(subject.Payload);
+ Assert.IsTrue(emittedMock.Received);
+ }
+
+ [Test]
+ public void ClearPayload()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ bool payload = true;
+ subject.Payload = payload;
+
+ Assert.IsTrue(subject.Payload);
+ subject.ClearPayload();
+ Assert.IsFalse(subject.Payload);
+ }
+
+ [Test]
+ public void ReceiveInactiveGameObject()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ subject.gameObject.SetActive(false);
+
+ bool payload = true;
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+
+ subject.Receive(payload);
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+ }
+
+ [Test]
+ public void ReceiveInactiveComponent()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ subject.enabled = false;
+
+ bool payload = true;
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+
+ subject.Receive(payload);
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+ }
+
+ [Test]
+ public void EmitPayloadInactiveGameObject()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ subject.gameObject.SetActive(false);
+ bool payload = false;
+ subject.Payload = payload;
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+
+ subject.EmitPayload();
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+ }
+
+ [Test]
+ public void EmitPayloadInactiveComponent()
+ {
+ UnityEventListenerMock emittedMock = new UnityEventListenerMock();
+ subject.Emitted.AddListener(emittedMock.Listen);
+ subject.enabled = false;
+ bool payload = false;
+ subject.Payload = payload;
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+
+ subject.EmitPayload();
+
+ Assert.IsFalse(subject.Payload);
+ Assert.IsFalse(emittedMock.Received);
+ }
+ }
+}
diff --git a/Tests/Editor/Event/Proxy/BooleanEventProxyEmitterTest.cs.meta b/Tests/Editor/Event/Proxy/BooleanEventProxyEmitterTest.cs.meta
new file mode 100644
index 00000000..acde7092
--- /dev/null
+++ b/Tests/Editor/Event/Proxy/BooleanEventProxyEmitterTest.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 32493973f3c780146b0814255b9c02c1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: