90 lines
3.2 KiB
C#

using System.Collections;
using UnityEngine;
namespace NanoBrain.Unity.Braitenberg {
/// <summary>
/// A non-directional sensor
/// </summary>
/// The sensor has a field of view, but the signal returned does not include a direction
[HelpURL("https://passer.life/documentation/nanobrain/Documentation/html/class_nano_brain_1_1_unity_1_1_braitenberg_1_1_sensor.html")]
public class Sensor : MonoBehaviour {
/// <summary>
/// Maximum distance the sensor detects anything
/// </summary>
[Tooltip("Max distance sensor detects anything")]
public float sensorRange = 10f;
/// <summary>
/// Time between samples in seconds
/// </summary>
[Tooltip("Time between samples (sec.)")]
public float sampleInterval = 0.1f;
/// <summary>
/// Unity Layer for the light objects
/// </summary>
/// This is used to improve performance
[Tooltip("Unity Layer for the light objects")]
public LayerMask senseLayer;
/// <summary>
/// Output value of the sensor
/// </summary>
[Tooltip("Output value of the sensor")]
public float output { get; protected set; }
/// <summary>
/// The NanoBrain::Neuron which is stimulated by this sensor
/// </summary>
public Neuron sensoryNeuron;
/// <summary>
/// Unity calls Awake when loading an instance of a script component.
/// </summary>
protected virtual void Awake() {
Vehicle vehicle = GetComponentInParent<Vehicle>();
if (vehicle == null)
return;
Cluster brain = vehicle.brain;
if (brain == null)
return;
sensoryNeuron = brain.GetNeuron(this.name);
}
/// <summary>
/// Called when a component of an active GameObject is first enabled.
/// </summary>
void OnEnable() => StartCoroutine(SampleRoutine());
/// <summary>
/// Called when a component itself is disabled or its parent GameObject is deactivated.
/// </summary>
void OnDisable() => StopAllCoroutines();
/// <summary>
/// The sensor samping routine.
/// </summary>
/// <returns>IEnumerator such that it can run as a Unity Coroutine</returns>
/// The sample rate is defined by sampleInterval
/// This also stimulates the sensoryNeuron if is has been found.
private IEnumerator SampleRoutine() {
WaitForSeconds wait = new(sampleInterval);
while (true) {
output = SampleSensor();
sensoryNeuron?.ProcessStimulus(Vector3.one * (output + 0.00001f));
yield return wait;
}
}
/// <summary>
/// Performs a sampling function to retrieve a new sensor output value
/// </summary>
/// <returns>0.0</returns>
/// This is a dummy implementation which always returns 0.0
/// because this component is an abstract sensor
protected virtual float SampleSensor() {
return 0.0f;
}
}
}