简述
参考教程:
敌人视野感知的实现
《U3d人工智能编程精粹》学习心得
Unity AI教程 之 简易的视觉感知系统.
Unity3D学习(五):实现一个简单的视觉感知.
例子结果:
player在一定范围,看到enemy后,enemy从原来的看不到变成看到。
操作过程
- 设置一个简单场景,包含障碍物(cube)、敌人(enemy)【球体表示】、玩家(player)【胶囊体表示】。
- 修改敌人和障碍物的标签,分别改为Enemy和Obstacles。
- 为玩家添加Player脚本,敌人添加enemy脚本。
public class Enemy : MonoBehaviour
{
public float HideCoolDown = 0.3f; //隐藏自己的冷却时间
public float AppearTime; //最后一次被发现的时刻
private MeshRenderer mr;
// Use this for initialization
void Awake()
{
mr = GetComponent<MeshRenderer>();
}
private void Start()
{
mr.enabled = false;
}
// Update is called once per frame
void Update()
{
if (Time.time - AppearTime < HideCoolDown)
return;
if (mr.enabled)
mr.enabled = false;
}
public void BeDiscovered() //被发现了
{
mr.enabled = true;
AppearTime = Time.time;
}
}
public class Player : MonoBehaviour
{
public float moveSpeed; //移动速度
public float EyeViewDistance; //视野距离
public float viewAngle = 120f; //视野角度
private Rigidbody rb;
private Collider[] SpottedEnemies; //附近的敌人
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
DetectEnemy();
}
// Update is called once per frame
void Update()
{
//AutoMove();
MoveAndTurn();
Debug.DrawLine(transform.position, transform.forward * 100, Color.red); //红色射线,面对的方向
}
void AutoMove() //向面对的方向自动移动
{
transform.position += transform.forward * moveSpeed * Time.deltaTime;
}
void MoveAndTurn() //玩家移动
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo = new RaycastHit();
//shoot a ray from cam to mouse position which is only detected by gameobject with "Plane" layer.
Physics.Raycast(ray, out hitInfo, 100, LayerMask.GetMask("Plane"));
if (hitInfo.collider != null)
{
transform.LookAt(new Vector3(hitInfo.point.x, transform.position.y, hitInfo.point.z));
}
rb.velocity = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized * moveSpeed;
}
void DetectEnemy() //探测敌人
{
//OverlapSphere内的敌人
SpottedEnemies = Physics.OverlapSphere(transform.position, EyeViewDistance, LayerMask.GetMask("Enemy"));
for (int i = 0; i < SpottedEnemies.Length; i++) //检测每一个敌人是否在视野区中
{
Vector3 EnemyPosition = SpottedEnemies[i].transform.position; //敌人的位置
//Debug.Log(transform.forward + " 面对的方向");
//Debug.Log("夹角为:" + Vector3.Angle(transform.forward, EnemyPosition - transform.position));
Debug.DrawRay(transform.position, EnemyPosition - transform.position, Color.yellow); //玩家位置到敌人位置的向量
if (Vector3.Angle(transform.forward, EnemyPosition - transform.position) <= viewAngle / 2) //这个敌人是否在视野内
{
//如果在视野内
RaycastHit info = new RaycastHit();
int layermask = LayerMask.GetMask("Enemy", "Obstacles"); //指定射线碰撞的对象
Physics.Raycast(transform.position, EnemyPosition - transform.position, out info, EyeViewDistance, layermask); //向敌人位置发射射线
Debug.Log(info.collider.gameObject.name);
if (info.collider == SpottedEnemies[i]) //如果途中无其他障碍物,那么射线就会碰撞到敌人
{
DiscoveredEnemy(SpottedEnemies[i]);
}
}
}
}
void DiscoveredEnemy(Collider Enemy) //发现敌人
{
//Do something
Debug.Log("发现敌军:" + Enemy.gameObject.name);
Enemy.GetComponent<Enemy>().BeDiscovered();
}
}
-
为player添加寻路系统。
(1)player添加NAV MESH AGENT组件,刚体组件。
(2)bake -
运行结果。