With a toggle we can use a unityEvent to call function with dynamic parameters, like if toggle is ON then otherThing.gameObject.setActive() is also ON.
Very usefull to save script use, but can it be inversed?
I would like : if toggle is ON, then other gameObject is OFF.
1 Like
I think this is an elegant solution:
Attach this component to your Toggle gameobject and check out the Inspector:
using UnityEngine.EventSystems;
using UnityEngine;
using UnityEngine.UI;
public class InvertedToggleEvent : MonoBehaviour{
//wont show in inspector
//public UnityEngine.Events.UnityEvent<bool> toggleEvent;
//this will show in inspector
[System.Serializable]
public class UnityEventBool : UnityEngine.Events.UnityEvent<bool>{}
public UnityEventBool onValueChangedInverse;
private void Start()
{
GetComponent<Toggle>().onValueChanged.AddListener( (on)=>{ onValueChangedInverse.Invoke(!on); } );
}
}
3 Likes
How to do that without a script?
I believe nothing has changed since then, so you don’t.
Editor script for this issue. Generated with AI
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
[CustomEditor(typeof(Toggle), true)]
[CanEditMultipleObjects]
public class ToggleEditorExtended : ToggleEditor
{
public override void OnInspectorGUI()
{
// Display standard Toggle inspector
base.OnInspectorGUI();
// Check if ToggleExtended component exists
Toggle toggle = target as Toggle;
if (toggle == null) return;
// Ensure ToggleExtended component always exists
ToggleExtended toggleExtended = EnsureToggleExtended(toggle);
// Always display the inverted event section
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Extended Events", EditorStyles.boldLabel);
if (toggleExtended != null)
{
SerializedObject extendedObject = new SerializedObject(toggleExtended);
extendedObject.Update();
SerializedProperty invertedEventProp = extendedObject.FindProperty("m_OnValueChangedInverted");
if (invertedEventProp != null)
{
EditorGUILayout.PropertyField(invertedEventProp,
new GUIContent("On Value Changed (Inverted)",
"Event called with inverted Toggle value (true becomes false and vice versa)\n" +
"Supports EditorAndRuntime mode"));
}
if (extendedObject.ApplyModifiedProperties())
{
// If there were changes, mark object as dirty
EditorUtility.SetDirty(toggleExtended);
}
}
}
/// <summary>
/// Ensures ToggleExtended component exists on the Toggle
/// </summary>
/// <param name="toggle">Toggle to check</param>
/// <returns>ToggleExtended component</returns>
private ToggleExtended EnsureToggleExtended(Toggle toggle)
{
ToggleExtended toggleExtended = toggle.GetComponent<ToggleExtended>();
if (toggleExtended == null)
{
// Add component silently for all selected objects
foreach (var obj in targets)
{
Toggle t = obj as Toggle;
if (t != null && t.GetComponent<ToggleExtended>() == null)
{
toggleExtended = t.gameObject.AddComponent<ToggleExtended>();
// Hide component from inspector
toggleExtended.hideFlags = HideFlags.HideInInspector;
toggleExtended.Initialize();
EditorUtility.SetDirty(t);
}
}
// Get the component for the main target
toggleExtended = toggle.GetComponent<ToggleExtended>();
}
return toggleExtended;
}
}
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
#if UNITY_EDITOR
using UnityEditor;
#endif
[System.Serializable]
public class ToggleBoolEvent : UnityEvent<bool> { }
[RequireComponent(typeof(Toggle))]
[ExecuteAlways] // Allows execution in editor
public class ToggleExtended : MonoBehaviour
{
[SerializeField]
private ToggleBoolEvent m_OnValueChangedInverted = new ToggleBoolEvent();
private Toggle m_Toggle;
private bool m_IsInitialized = false;
#if UNITY_EDITOR
private bool m_PreviousToggleValue;
private bool m_EditorUpdateRegistered = false;
#endif
/// <summary>
/// Event that is called with inverted Toggle value
/// </summary>
public ToggleBoolEvent OnValueChangedInverted
{
get { return m_OnValueChangedInverted; }
set { m_OnValueChangedInverted = value; }
}
void Awake()
{
// Hide this component from inspector
hideFlags = HideFlags.HideInInspector;
Initialize();
}
void Start()
{
Initialize();
}
void OnEnable()
{
// Hide this component from inspector
hideFlags = HideFlags.HideInInspector;
Initialize();
#if UNITY_EDITOR
// In editor, subscribe to EditorApplication.update
if (!Application.isPlaying && !m_EditorUpdateRegistered)
{
EditorApplication.update += EditorUpdate;
m_EditorUpdateRegistered = true;
// Initialize starting value
if (m_Toggle != null)
{
m_PreviousToggleValue = m_Toggle.isOn;
}
}
#endif
}
void OnDisable()
{
#if UNITY_EDITOR
// Unsubscribe from EditorApplication.update
if (m_EditorUpdateRegistered)
{
EditorApplication.update -= EditorUpdate;
m_EditorUpdateRegistered = false;
}
#endif
}
#if UNITY_EDITOR
/// <summary>
/// Editor update for tracking Toggle changes
/// </summary>
private void EditorUpdate()
{
if (m_Toggle == null || Application.isPlaying) return;
// Check if value changed in editor
if (m_Toggle.isOn != m_PreviousToggleValue)
{
OnToggleValueChanged(m_Toggle.isOn);
m_PreviousToggleValue = m_Toggle.isOn;
}
}
#endif
/// <summary>
/// Initializes component with Toggle
/// </summary>
public void Initialize()
{
if (m_IsInitialized) return;
m_Toggle = GetComponent<Toggle>();
if (m_Toggle == null)
{
Debug.LogError("ToggleExtended: Toggle component not found!", this);
return;
}
// In runtime subscribe to event
if (Application.isPlaying)
{
m_Toggle.onValueChanged.AddListener(OnToggleValueChanged);
}
#if UNITY_EDITOR
// In editor save current value
if (!Application.isPlaying)
{
m_PreviousToggleValue = m_Toggle.isOn;
}
#endif
m_IsInitialized = true;
}
/// <summary>
/// Handler for Toggle value change
/// </summary>
/// <param name="value">New Toggle value</param>
private void OnToggleValueChanged(bool value)
{
// Invoke inverted event
try
{
m_OnValueChangedInverted.Invoke(!value);
}
catch (System.Exception e)
{
Debug.LogError($"Error invoking inverted event: {e.Message}", this);
}
}
void OnDestroy()
{
// Unsubscribe from event when component is destroyed
if (m_Toggle != null && Application.isPlaying)
{
m_Toggle.onValueChanged.RemoveListener(OnToggleValueChanged);
}
#if UNITY_EDITOR
if (m_EditorUpdateRegistered)
{
EditorApplication.update -= EditorUpdate;
m_EditorUpdateRegistered = false;
}
#endif
}
/// <summary>
/// Adds listener to inverted event
/// </summary>
/// <param name="call">Method to call</param>
public void AddInvertedListener(UnityAction<bool> call)
{
m_OnValueChangedInverted.AddListener(call);
}
/// <summary>
/// Removes listener from inverted event
/// </summary>
/// <param name="call">Method to remove</param>
public void RemoveInvertedListener(UnityAction<bool> call)
{
m_OnValueChangedInverted.RemoveListener(call);
}
/// <summary>
/// Removes all listeners from inverted event
/// </summary>
public void RemoveAllInvertedListeners()
{
m_OnValueChangedInverted.RemoveAllListeners();
}
}