Skip to content

Instantly share code, notes, and snippets.

@herohiralal
Created February 15, 2022 04:03
Show Gist options
  • Save herohiralal/609efff99b4bb4369250f7fc92500ca0 to your computer and use it in GitHub Desktop.
Save herohiralal/609efff99b4bb4369250f7fc92500ca0 to your computer and use it in GitHub Desktop.
HiraBots sample 1
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class Archetype : MonoBehaviour,
IHiraBotArchetype<NavMeshAgent>,
IHiraBotArchetype<Animator>,
IHiraBotArchetype<ConsolidatedSensor>,
IHiraBotArchetype<HiraLGOAPRealtimeBot>,
IHiraBotArchetype<SightStimulus>,
IHiraBotArchetype<SoundStimulus>
{
[SerializeField] private Animator m_Animator = null;
[SerializeField] private NavMeshAgent m_NavMeshAgent = null;
[SerializeField] private ConsolidatedSensor m_Sensor = null;
[SerializeField] private HiraLGOAPRealtimeBot m_Brain = null;
[SerializeField] private SightStimulus m_SightStimulus = null;
[SerializeField] private SoundStimulus m_SoundStimulus = null;
Animator IHiraBotArchetype<Animator>.component => m_Animator;
NavMeshAgent IHiraBotArchetype<NavMeshAgent>.component => m_NavMeshAgent;
ConsolidatedSensor IHiraBotArchetype<ConsolidatedSensor>.component => m_Sensor;
HiraLGOAPRealtimeBot IHiraBotArchetype<HiraLGOAPRealtimeBot>.component => m_Brain;
SightStimulus IHiraBotArchetype<SightStimulus>.component => m_SightStimulus;
SoundStimulus IHiraBotArchetype<SoundStimulus>.component => m_SoundStimulus;
}
}
using System;
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class GetCreepedOutService : IHiraBotsService, IMessageListener<FanGreetingMessage>
{
public BlackboardComponent m_Blackboard;
public string m_ShyKey;
public string m_CreepedOutByKey;
public int m_Count;
public void Start()
{
}
public void Tick(float deltaTime)
{
}
public void Stop()
{
m_Blackboard = default;
}
public void OnMessageReceived(FanGreetingMessage message)
{
var isShy = m_Blackboard.GetBooleanValue(m_ShyKey);
if (!isShy)
{
return;
}
m_Count--;
if (m_Count == 0)
{
m_Blackboard.SetObjectValue(m_CreepedOutByKey, message.m_Fan);
}
}
}
public class GetCreepedOutServiceProvider : HiraBotsServiceProvider
{
public GetCreepedOutServiceProvider()
{
tickInterval = 1000f;
}
[SerializeField] private BlackboardTemplate.KeySelector m_CreepedOutBy;
[SerializeField] private BlackboardTemplate.KeySelector m_Shy;
[SerializeField] private int m_TimesGreetedBeforeCreepedOut = 3;
#region Validation Boilerplate
protected override void OnValidateCallback()
{
m_CreepedOutBy.keyTypesFilter = BlackboardKeyType.Object;
m_Shy.keyTypesFilter = BlackboardKeyType.Boolean;
}
protected override void Validate(Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_CreepedOutBy.Validate(keySet, BlackboardKeyType.Object))
{
reportError("no creeped out by key");
}
if (!m_Shy.Validate(keySet, BlackboardKeyType.Boolean))
{
reportError("no shy key");
}
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_CreepedOutBy.OnTargetBlackboardTemplateChanged(template, in keySet);
m_Shy.OnTargetBlackboardTemplateChanged(template, in keySet);
}
#endregion
protected override IHiraBotsService GetService(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
return new GetCreepedOutService
{
m_Blackboard = blackboard,
m_CreepedOutByKey = m_CreepedOutBy.selectedKey.name,
m_ShyKey = m_Shy.selectedKey.name,
m_Count = m_TimesGreetedBeforeCreepedOut
};
}
}
}
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public struct FanGreetingMessage
{
public GameObject m_Fan;
}
public class GreetCelebrityTask : IHiraBotsTask
{
public Animator m_Animator;
public float m_AnimationTime;
public GameObject m_SelfGameObject;
public BlackboardComponent m_Blackboard;
public string m_CelebrityGameObjectKey;
public void Begin()
{
m_Animator.SetTrigger(AnimatorHashes.s_Bowing);
}
public HiraBotsTaskResult Execute(float deltaTime)
{
var obj = m_Blackboard.GetObjectValue(m_CelebrityGameObjectKey) as GameObject;
if (obj == null)
{
return HiraBotsTaskResult.Failed;
}
m_AnimationTime -= deltaTime;
if (m_AnimationTime > 0f)
{
// turn towards celebrity
{
var transform = m_SelfGameObject.transform;
var eulerAngles = transform.eulerAngles;
transform.LookAt(obj.transform);
eulerAngles.y = transform.eulerAngles.y; // only need to change the yaw
transform.eulerAngles = eulerAngles;
}
return HiraBotsTaskResult.InProgress;
}
if (!obj.TryGetComponent<Archetype>(out var archetype)
|| archetype is not IHiraBotArchetype<HiraLGOAPRealtimeBot> bot)
{
return HiraBotsTaskResult.Failed;
}
bot.component.Message(new FanGreetingMessage { m_Fan = m_SelfGameObject });
return HiraBotsTaskResult.Succeeded;
}
public void Abort()
{
m_SelfGameObject = null;
m_Animator = null;
m_Blackboard = default;
}
public void End(bool success)
{
m_SelfGameObject = null;
m_Animator = null;
m_Blackboard = default;
}
}
public class GreetCelebrityTaskProvider : HiraBotsTaskProvider
{
[SerializeField] private float m_AnimationTime = 3f;
[SerializeField] private BlackboardTemplate.KeySelector m_CelebrityGameObject;
#region Validation Boilerplate
protected override void OnValidateCallback()
{
m_CelebrityGameObject.keyTypesFilter = BlackboardKeyType.Object;
}
protected override void Validate(System.Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_CelebrityGameObject.Validate(in keySet, BlackboardKeyType.Object))
{
reportError("no celebrity game object key");
}
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_CelebrityGameObject.OnTargetBlackboardTemplateChanged(template, in keySet);
}
#endregion
protected override IHiraBotsTask GetTask(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
if (archetype is IHiraBotArchetype<Animator> animator)
{
return new GreetCelebrityTask
{
m_Animator = animator.component,
m_AnimationTime = m_AnimationTime,
m_SelfGameObject = archetype.gameObject,
m_Blackboard = blackboard,
m_CelebrityGameObjectKey = m_CelebrityGameObject.selectedKey.name
};
}
return null;
}
}
}
using UnityEngine;
using UnityEngine.AI;
using Object = UnityEngine.Object;
namespace AIEngineTest
{
public class LookOutForCelebrityService : IHiraBotsService
{
private bool m_Bound = false;
public BlackboardComponent m_Blackboard;
public string m_ExcitementKey;
public string m_CelebrityGameObjectKey;
public string m_CelebrityTag;
public ConsolidatedSensor m_Sensor;
public void Start()
{
foreach (var o in m_Sensor.perceivedObjects)
{
if (o != null && o is GameObject go && go.CompareTag(m_CelebrityTag))
{
m_Blackboard.SetFloatValue(m_ExcitementKey, 100f);
m_Blackboard.SetObjectValue(m_CelebrityGameObjectKey, go);
return;
}
}
m_Sensor.newObjectPerceived.AddListener(OnObjectFound);
m_Bound = true;
}
public void Tick(float deltaTime)
{
}
public void Stop()
{
if (m_Bound)
{
m_Sensor.newObjectPerceived.RemoveListener(OnObjectFound);
}
m_Bound = false;
m_Blackboard = default;
m_Sensor = null;
}
private void OnObjectFound(Object o)
{
if (!m_Bound)
{
Debug.LogError("This shouldn't have happened.");
return;
}
if (o != null && o is GameObject go && go.CompareTag(m_CelebrityTag))
{
m_Blackboard.SetFloatValue(m_ExcitementKey, 100f);
m_Blackboard.SetObjectValue(m_CelebrityGameObjectKey, go);
}
}
}
public class LookOutForCelebrityServiceProvider : HiraBotsServiceProvider
{
public LookOutForCelebrityServiceProvider()
{
tickInterval = 1000f;
}
[SerializeField, TagProperty] private string m_CelebrityTag;
[SerializeField] private BlackboardTemplate.KeySelector m_ExcitementKey;
[SerializeField] private BlackboardTemplate.KeySelector m_CelebrityGameObject;
#region Validation Boilerplate
protected override void OnValidateCallback()
{
m_ExcitementKey.keyTypesFilter = BlackboardKeyType.Float;
m_CelebrityGameObject.keyTypesFilter = BlackboardKeyType.Object;
}
protected override void Validate(System.Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_ExcitementKey.Validate(in keySet, BlackboardKeyType.Float))
{
reportError("no excitement key");
}
if (!m_CelebrityGameObject.Validate(in keySet, BlackboardKeyType.Object))
{
reportError("no celebrity game object key");
}
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_ExcitementKey.OnTargetBlackboardTemplateChanged(template, in keySet);
m_CelebrityGameObject.OnTargetBlackboardTemplateChanged(template, in keySet);
}
#endregion
protected override IHiraBotsService GetService(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
if (archetype is IHiraBotArchetype<ConsolidatedSensor> sensor)
{
return new LookOutForCelebrityService
{
m_Blackboard = blackboard,
m_ExcitementKey = m_ExcitementKey.selectedKey.name,
m_CelebrityGameObjectKey = m_CelebrityGameObject.selectedKey.name,
m_CelebrityTag = m_CelebrityTag,
m_Sensor = sensor.component
};
}
return null;
}
}
}
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class SetTargetLocationAsPatrolPointTask : IHiraBotsTask
{
public BlackboardComponent m_Blackboard;
public PatrolPointCollection m_PatrolPointCollection;
public string m_Key;
public void Begin()
{
}
public HiraBotsTaskResult Execute(float deltaTime)
{
Vector3 destination;
Vector3 current = m_Blackboard.GetVectorValue(m_Key);
do
{
destination = m_PatrolPointCollection.GetRandom();
} while (destination == current);
m_Blackboard.SetVectorValue(m_Key, destination, true);
return HiraBotsTaskResult.Succeeded;
}
public void Abort()
{
}
public void End(bool success)
{
}
}
public class SetTargetLocationAsPatrolPointTaskProvider : HiraBotsTaskProvider
{
[SerializeField] private BlackboardTemplate.KeySelector m_Key;
[SerializeField] private PatrolPointCollection m_PatrolPointCollection;
protected override IHiraBotsTask GetTask(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
return new SetTargetLocationAsPatrolPointTask
{
m_Blackboard = blackboard,
m_PatrolPointCollection = m_PatrolPointCollection,
m_Key = m_Key.selectedKey.name
};
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_Key.OnTargetBlackboardTemplateChanged(template, in keySet);
}
protected override void OnValidateCallback()
{
m_Key.keyTypesFilter = BlackboardKeyType.Vector;
}
protected override void Validate(System.Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_Key.Validate(in keySet, BlackboardKeyType.Vector))
{
reportError("Unassigned key.");
}
if (m_PatrolPointCollection == null)
{
reportError("No patrol point collection present.");
}
}
}
}
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class StopSearchingAfterTimeService : IHiraBotsService
{
public float m_WaitTime;
public BlackboardComponent m_Blackboard;
public string m_ExcitementKey;
public void Start()
{
}
public void Tick(float deltaTime)
{
if (m_WaitTime < 0f)
{
return;
}
m_WaitTime -= deltaTime;
if (m_WaitTime < 0f)
{
m_Blackboard.SetFloatValue(m_ExcitementKey, 0f);
}
}
public void Stop()
{
m_Blackboard = default;
}
}
public class StopSearchingAfterTimeServiceProvider : HiraBotsServiceProvider
{
[SerializeField] private float m_WaitTime;
[SerializeField] private BlackboardTemplate.KeySelector m_Excitement;
#region Validation Boilerplate
protected override void OnValidateCallback()
{
m_Excitement.keyTypesFilter = BlackboardKeyType.Float;
}
protected override void Validate(System.Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_Excitement.Validate(in keySet, BlackboardKeyType.Float))
{
reportError("no celebrity status key");
}
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_Excitement.OnTargetBlackboardTemplateChanged(template, in keySet);
}
#endregion
protected override IHiraBotsService GetService(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
return new StopSearchingAfterTimeService
{
m_Blackboard = blackboard,
m_ExcitementKey = m_Excitement.selectedKey.name,
m_WaitTime = m_WaitTime
};
}
}
}
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class TrackCelebrityLocationService : IHiraBotsService
{
private bool m_Bound = false;
private bool m_DoNotTick;
public BlackboardComponent m_Blackboard;
public string m_CelebrityGameObjectKey;
public string m_CelebrityLocationKey;
public string m_CelebrityTag;
public ConsolidatedSensor m_Sensor;
public void Start()
{
var found = false;
foreach (var o in m_Sensor.perceivedObjects)
{
if (o != null && o is GameObject go && go.CompareTag(m_CelebrityTag))
{
found = true;
break;
}
}
if (!found)
{
Lost();
return;
}
m_Sensor.objectStoppedPerceiving.AddListener(OnObjectLost);
m_DoNotTick = false;
m_Bound = true;
}
public void Tick(float deltaTime)
{
if (m_DoNotTick)
{
return;
}
var go = m_Blackboard.GetObjectValue(m_CelebrityGameObjectKey) as GameObject;
if (go != null)
{
m_Blackboard.SetVectorValue(m_CelebrityLocationKey, go.transform.position);
}
else
{
Lost();
}
}
public void Stop()
{
if (m_Bound)
{
m_Sensor.objectStoppedPerceiving.RemoveListener(OnObjectLost);
}
m_Bound = false;
m_Blackboard = default;
m_Sensor = null;
}
private void OnObjectLost(Object o)
{
if (!m_Bound)
{
Debug.LogError("This shouldn't have happened.");
return;
}
if (o is GameObject go && go.CompareTag(m_CelebrityTag))
{
Lost();
}
}
private void Lost()
{
m_Blackboard.SetObjectValue(m_CelebrityGameObjectKey, null);
m_DoNotTick = true;
}
}
public class TrackCelebrityLocationServiceProvider : HiraBotsServiceProvider
{
[SerializeField, TagProperty] private string m_CelebrityTag;
[SerializeField] private BlackboardTemplate.KeySelector m_CelebrityGameObject;
[SerializeField] private BlackboardTemplate.KeySelector m_CelebrityLocation;
#region Validation Boilerplate
protected override void OnValidateCallback()
{
m_CelebrityGameObject.keyTypesFilter = BlackboardKeyType.Object;
m_CelebrityLocation.keyTypesFilter = BlackboardKeyType.Vector;
}
protected override void Validate(System.Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_CelebrityGameObject.Validate(in keySet, BlackboardKeyType.Object))
{
reportError("no celebrity game object key");
}
if (!m_CelebrityLocation.Validate(in keySet, BlackboardKeyType.Vector))
{
reportError("no celebrity location");
}
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_CelebrityGameObject.OnTargetBlackboardTemplateChanged(template, in keySet);
m_CelebrityLocation.OnTargetBlackboardTemplateChanged(template, in keySet);
}
#endregion
protected override IHiraBotsService GetService(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
if (archetype is IHiraBotArchetype<ConsolidatedSensor> sensor)
{
return new TrackCelebrityLocationService
{
m_Blackboard = blackboard,
m_CelebrityGameObjectKey = m_CelebrityGameObject.selectedKey.name,
m_CelebrityLocationKey = m_CelebrityLocation.selectedKey.name,
m_CelebrityTag = m_CelebrityTag,
m_Sensor = sensor.component
};
}
return null;
}
}
}
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class UpdateSpeedService : IHiraBotsService
{
public UpdateSpeedService(NavMeshAgent agent, Animator animator, float min, float max)
{
m_NavMeshAgent = agent;
m_Animator = animator;
m_Min = min;
m_Max = max;
}
private NavMeshAgent m_NavMeshAgent;
private Animator m_Animator;
private readonly float m_Min, m_Max;
public void Start()
{
}
public void Tick(float deltaTime)
{
var speed = m_NavMeshAgent.velocity.magnitude;
var normalizedSpeed = (speed - m_Min) / (m_Max - m_Min);
m_Animator.SetFloat(AnimatorHashes.s_Speed, normalizedSpeed);
}
public void Stop()
{
m_NavMeshAgent = null;
m_Animator = null;
}
}
public class UpdateSpeedServiceProvider : HiraBotsServiceProvider
{
public UpdateSpeedServiceProvider()
{
tickInterval = 1f;
}
[SerializeField] private float m_MinSpeed = 0f, m_MaxSpeed = 3f;
protected override IHiraBotsService GetService(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
if (archetype is not (IHiraBotArchetype<NavMeshAgent> navigatingSoldier and IHiraBotArchetype<Animator> animatedSoldier))
{
Debug.LogError("Attempted to get an update speed service for an invalid game object.");
return null;
}
return new UpdateSpeedService(navigatingSoldier.component, animatedSoldier.component, m_MinSpeed, m_MaxSpeed);
}
}
}
using UnityEngine;
using UnityEngine.AI;
namespace AIEngineTest
{
public class EscapeFanTask : IHiraBotsTask
{
public GameObject m_SelfGameObject;
public float m_DistanceSq;
public BlackboardComponent m_Blackboard;
public string m_CreepedOutByKey;
public float m_WaitTime;
public void Begin()
{
}
public HiraBotsTaskResult Execute(float deltaTime)
{
if (m_SelfGameObject == null)
{
return HiraBotsTaskResult.Failed;
}
var creepedOutBy = m_Blackboard.GetObjectValue(m_CreepedOutByKey) as GameObject;
if (creepedOutBy == null)
{
m_Blackboard.SetObjectValue(m_CreepedOutByKey, null);
return HiraBotsTaskResult.Succeeded;
}
var distSq = (m_SelfGameObject.transform.position - creepedOutBy.transform.position).sqrMagnitude;
if (distSq < m_DistanceSq)
{
return HiraBotsTaskResult.Failed;
}
m_WaitTime -= deltaTime;
if (m_WaitTime > 0f)
{
return HiraBotsTaskResult.InProgress;
}
return HiraBotsTaskResult.Succeeded;
}
public void Abort()
{
m_SelfGameObject = null;
m_Blackboard = default;
}
public void End(bool success)
{
m_SelfGameObject = null;
m_Blackboard = default;
}
}
public class WaitUntilEscapedFanTaskProvider : HiraBotsTaskProvider
{
[SerializeField] private BlackboardTemplate.KeySelector m_CreepedOutBy;
[SerializeField] private float m_Distance = 5f;
[SerializeField] private float m_WaitFor = 5f;
#region Validation Boilerplate
protected override void OnValidateCallback()
{
m_CreepedOutBy.keyTypesFilter = BlackboardKeyType.Object;
}
protected override void Validate(System.Action<string> reportError, in BlackboardTemplate.KeySet keySet)
{
if (!m_CreepedOutBy.Validate(keySet, BlackboardKeyType.Object))
{
reportError("no creeped out by key");
}
}
protected override void OnTargetBlackboardTemplateChanged(BlackboardTemplate template, in BlackboardTemplate.KeySet keySet)
{
m_CreepedOutBy.OnTargetBlackboardTemplateChanged(template, in keySet);
}
#endregion
protected override IHiraBotsTask GetTask(BlackboardComponent blackboard, IHiraBotArchetype archetype)
{
return new EscapeFanTask
{
m_Blackboard = blackboard,
m_CreepedOutByKey = m_CreepedOutBy.selectedKey.name,
m_DistanceSq = m_Distance * m_Distance,
m_SelfGameObject = archetype.gameObject,
m_WaitTime = m_WaitFor
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment