概念:感知系统:
在软件领域中:模拟人【或动物】的感觉的软件系统。
【代码 数据类型】
人的基本感觉:视觉、听觉、触觉、【嗅觉、味觉】
视觉、听觉:目前是对视觉听觉模拟!
智能感知系统架构:可以用于任何需要的系统中。
感应器:拥有XX能力
触发器:拥有被XX能力
例如:
视觉感应器:拥有视觉能力
视觉触发器:拥有被发现能力
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AI.Perception
{
///
/// 抽象感应器
///
public abstract class AbstractSensor:MonoBehaviour
{
///
/// 是否移除,是否禁用
///
public bool isRemove;
///
/// 没有感知事件:F1>F2【没有行为发生 触发什么事件】
///
public event Action OnNonPerception;
///
/// 感知事件事件:F1>F2【行为发生 触发什么事件】
///
public event Action<List<AbstractTrigger>> OnPerception;
///
/// 初始化
///
private void Start()
{
Init();
//把当前感应器放到 感应系统中
SensorTriggerSystem.Instance.AddSensor(this);
}
///
/// 预留初始化方法
///
abstract public void Init();
///
/// 销毁方法
///
private void OnDestroy()
{
isRemove = true;//把当前感应器从 感应系统中移除
}
///
/// 检测触发器:检查所有的触发器【触发 条件】
///
public void OnTestTrigger(List<AbstractTrigger> listTriggers)
{
//找到启用的所有触发器
listTriggers = listTriggers.FindAll(t => t.enabled
&& t.gameObject!=this.gameObject
&& TestTrigger(t));
//触发感知事件
if (listTriggers.Count > 0)
{
if (OnPerception != null)
OnPerception(listTriggers);
}
else
{
if (OnNonPerception != null)
OnNonPerception();
}
}
///
/// 检测触发器 是能够感知
///
abstract protected bool TestTrigger(AbstractTrigger trigger);
}
}
using UnityEngine;
namespace AI.Perception
{
///
/// 抽象触发器
///
public abstract class AbstractTrigger:MonoBehaviour
{
///
/// 是否删除,是否禁用
///
public bool isRemove;
///
/// 触发器类型
///
public TriggerType triggerType;
///
/// 初始化
///
private void Start()
{
Init();
//把当前触发器 加入到感应触发系统中(中介)
SensorTriggerSystem.Instance.AddTrigger(this);
}
///
/// 初始化方法
///
abstract public void Init();
///
/// 销毁方法:把当前触发器从 感应触发系统中移除
///
public void OnDestroy()
{
isRemove = true;
}
}
}
namespace AI.Perception
{
//触发器的类型
public enum TriggerType
{
Sight,//视觉
Sound,//听觉
}
}
using UnityEngine;
namespace AI.Perception
{
///
/// 视觉感应器
///
public class SightSensor : AbstractSensor
{
//字段
//视距
public float sightDistance;
//视角
public float sightAngle;
//启用角度检测
public bool enableAngle;
//启用遮挡检测
public bool enableRay;
//视线发射点
public Transform sendPos;
public override void Init()
{
//给视线发射位置 如果未赋值初始化
if (sendPos == null) sendPos = transform;
}
///
/// 检测触发器 是否应该触发
///
/// 被检测到的物体身上触发器
/// 距离 角度 遮挡 功能能否触发触发器
protected override bool TestTrigger(AbstractTrigger trigger)
{
//如果当前触发器类型不是视觉触发器 则触发器不能被触发
if (trigger.triggerType != TriggerType.Sight) return false;
var tempTrigger = trigger as SightTrigger;
//计算物体与视觉发射点距离 如果超过视距 则返回false
var dir = tempTrigger.recievePos.position - sendPos.position;
var result = dir.magnitude < sightDistance;
//启用角度检测
if (enableAngle)//视线发射点前方位置 是否在视角范围内
{
bool b1 = Vector3.Angle(sendPos.transform.forward, dir) < sightAngle / 2;
result = result && b1;
}
//遮挡 1 射中物体 2 射中的是触发器
RaycastHit hit;
//启用遮挡检测
if (enableRay)//视线发射点发射射线检测 到触发器之间有无其他物体遮挡
{
bool b1 = Physics.Raycast(sendPos.position, dir, out hit, sightDistance)
&& hit.collider.gameObject == trigger.gameObject;
result = result && b1;
}
return result;
}
}
}
using UnityEngine;
namespace AI.Perception
{
///
/// 视觉触发器
///
public class SightTrigger : AbstractTrigger
{
//记录当前物体触发器的位置
public Transform recievePos;
//初始化
public override void Init()
{
if(recievePos == null)
{
recievePos = transform;
triggerType = TriggerType.Sight;
}
}
}
}
using System.Collections.Generic;
namespace AI.Perception
{
///
/// 感知触发系统:感知系统 中介者
///
public class SensorTriggerSystem
:SingleCase<SensorTriggerSystem>//继承父类 单例模式
{
//单例模式 防止被外界随便new
private SensorTriggerSystem() {
}
///
/// 检测时间间隔
///
public float checkInterval = 0.2f;
///
/// 感应器列表
///
private List<AbstractSensor> listSensor = new List<AbstractSensor>();
///
/// 触发器列表
///
private List<AbstractTrigger> listTrigger = new List<AbstractTrigger>();
///
/// 添加感应器
///
public void AddSensor(AbstractSensor sensor)
{
listSensor.Add(sensor);
}
///
/// 添加触发器
///
public void AddTrigger(AbstractTrigger trigger)
{
listTrigger.Add(trigger);
}
///
/// 检测触发条件:每个感应器 检查 对应所有触发器
///
private void CheckTrigger()
{
for(int i = 0; i < listSensor.Count; i++) {
if (listSensor[i].enabled)
{
//当前在列表中的所有触发器进行检测能否被感应器感应到
listSensor[i].OnTestTrigger(listTrigger);
}
}
}
///
/// 更新系统
///
private void UpdateSystem()
{
listSensor.RemoveAll(s => s.isRemove);
listTrigger.RemoveAll(t => t.isRemove);
}
private void OnCheck()
{
UpdateSystem();
CheckTrigger();
}
private void OnEnable()//时刻刷新系统
{
InvokeRepeating("OnCheck", 0, checkInterval);
}
private void OnDisable()
{
CancelInvoke("OnCheck");
}
}
}
using System.Collections.Generic;
using UnityEngine;
using AI.Perception;
///
/// 测试代码
///
public class TestSight : MonoBehaviour
{
void Start()
{
//1 注册视觉感应器的事件
GetComponent<SightSensor>().OnPerception
+= TestSight_OnPerceptions;
GetComponent<SightSensor>().OnNonPerception
+= OnNonPerception;
}
//2 事件处理程序 F1事件》F2方法
void TestSight_OnPerceptions(List<AbstractTrigger> list)
{
list.ForEach(t => print("看见了:" + t.name));
}
void OnNonPerception()
{
print("看不到任何东西了");
}
}