Repository URL to install this package:
Version:
1.1.0 ▾
|
using System.ComponentModel;
using Fluctio.FluctioSim.Common.Configuration;
using Fluctio.FluctioSim.Core.Components.MachineLearning.NumberProviders;
using UnityEngine;
#if UNITY_EDITOR
using Fluctio.FluctioSim.EditorUtils.Gui;
using UnityEditor;
#endif
namespace Fluctio.FluctioSim.Core.Components.MachineLearning.Triggers
{
[AddComponentMenu(Config.PrefixedName+"/Machine Learning/Triggers/Number Trigger", Config.ComponentMenuOrder + 70)]
public class NumberTrigger : AgentTrigger
{
#region Serialized fields
[field: SerializeField] public ConditionType ConditionType { get; private set; }
[field: SerializeField] public ComparisonType ComparisonType { get; private set; }
[field: SerializeField] public float ExactNumber { get; private set; }
[field: SerializeField] public float MinNumber { get; private set; }
[field: SerializeField] public float MaxNumber { get; private set; }
[field: SerializeField] public NumberProvider Number { get; private set; }
#endregion
#region State
private bool _wasConditionSatisfiedPreviously = false;
private float? _previousNumber = null;
private float? _number = null;
private bool _isConditionSatisfied = false;
#endregion
#region Episode initializing
private void OnEnable()
{
Agent.UnityAgent.EpisodeInitializing += OnEpisodeInitializing;
OnEpisodeInitializing();
}
private void Disable()
{
Agent.UnityAgent.EpisodeInitializing -= OnEpisodeInitializing;
}
private void OnEpisodeInitializing()
{
_wasConditionSatisfiedPreviously = false;
_previousNumber = null;
_isConditionSatisfied = false;
_number = null;
}
#endregion
#region Condition checking
private bool IsConditionSatisfied(float number)
{
return ComparisonType switch
{
ComparisonType.InRange => (number >= MinNumber) && (number <= MaxNumber),
ComparisonType.Max => number <= MaxNumber,
ComparisonType.Min => number >= MinNumber,
// ReSharper disable once CompareOfFloatsByEqualityOperator
ComparisonType.Exact => (number == ExactNumber),
ComparisonType.ApproximateFloat => Mathf.Approximately(number, ExactNumber),
ComparisonType.FallingEdge => number < _previousNumber,
ComparisonType.RisingEdge => number > _previousNumber,
_ => throw new InvalidEnumArgumentException(
nameof(ComparisonType),
(int)ComparisonType,
ComparisonType.GetType())
};
}
private void FixedUpdate()
{
_previousNumber = _number;
_wasConditionSatisfiedPreviously = _isConditionSatisfied;
}
public override bool IsSatisfied
{
get {
_number = Number.GetNumber();
_isConditionSatisfied = IsConditionSatisfied(_number.Value);
return ConditionType switch
{
ConditionType.EachStepWhileSatisfied => _isConditionSatisfied,
ConditionType.OnceWhenSatisfied => _isConditionSatisfied && !_wasConditionSatisfiedPreviously,
_ => throw new InvalidEnumArgumentException(
nameof(ConditionType),
(int)ConditionType,
ConditionType.GetType())
};
}
}
#endregion
}
#region Enums
public enum ConditionType
{
[Tooltip("Trigger each step while condition is true")]
EachStepWhileSatisfied,
[Tooltip("Trigger once when condition becomes true")]
OnceWhenSatisfied,
}
public enum ComparisonType
{
[InspectorName("Trigger when smaller than")]
Max,
[InspectorName("Trigger when bigger than")]
Min,
[InspectorName("Trigger when in range")]
InRange,
[InspectorName("Trigger when exactly")]
Exact,
[InspectorName("Trigger when almost exactly (use Mathf.Approximately)")]
[Tooltip("Uses Mathf.Approximately() to avoid floating point inaccuracies")]
ApproximateFloat,
[InspectorName("Trigger when smaller than previous value")]
FallingEdge,
[InspectorName("Trigger when bigger than previous value")]
RisingEdge,
}
#endregion
#if UNITY_EDITOR
[CustomEditor(typeof(NumberTrigger), true)]
public class DistanceTriggerEditor : Editor
{
// ReSharper disable once InconsistentNaming
private new NumberTrigger target => (NumberTrigger)base.target;
private void DrawDistanceProperties()
{
switch (target.ComparisonType)
{
case ComparisonType.Min:
serializedObject.DrawProperties(nameof(target.MinNumber));
break;
case ComparisonType.Max:
serializedObject.DrawProperties(nameof(target.MaxNumber));
break;
case ComparisonType.InRange:
serializedObject.DrawProperties(nameof(target.MinNumber), nameof(target.MaxNumber));
break;
case ComparisonType.ApproximateFloat:
case ComparisonType.Exact:
serializedObject.DrawProperties(nameof(target.ExactNumber));
break;
case ComparisonType.FallingEdge:
case ComparisonType.RisingEdge:
break;
default:
throw new InvalidEnumArgumentException(
nameof(target.ComparisonType),
(int)target.ComparisonType,
target.ComparisonType.GetType());
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
serializedObject.DrawProperties("ConditionType", "Number", "ComparisonType");
DrawDistanceProperties();
serializedObject.ApplyModifiedProperties();
}
}
#endif
}