【Unity】入门学习笔记180602——人工智能(9)——视觉感知

感知=触发器+感知器+事件管理器


1、视觉感知:

视锥体是模拟视觉地基本方法,以眼睛为中心,一定锥角范围内为检测区域

除了判断物体是否在视锥体范围内外,还要进行视线测试(LOS),才能确定最终结果


原则上以玩家为中心,限定AI角色的智能。

对于AI角色看到需要做出响应的物体,添加Trigger派生类SightTrigger作为触发器

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SightTrigger : Trigger {

    public override void Try(Sensor sensor)
    {
        //如果感知器能感觉到这个触发器,那么向感知器发出通知,感知体做出相应的决策或行动
        if (isTouchingTrigger(sensor))
        {
            sensor.Notify(this);
        }
        
    }

    //判断感知器是否能感知到这个触发器
    protected override bool isTouchingTrigger(Sensor sensor)
    {
        GameObject g = sensor.gameObject;
        //如果这个感知器能够感知视觉信息
        if (sensor.sensorType == Sensor.SensorType.sight)
        {
            RaycastHit hit;
            Vector3 rayDirection = transform.position - g.transform.position;
            rayDirection.y = 0;

            //判断感知体的向前方向与物体所在方向的夹角,是否在视域范围内
            if((Vector3.Angle(rayDirection,g.transform.forward))<(sensor as SightSensor).fieldOfView)
            {
                //在视线距离内是否存在其他障碍物遮挡,如果没有障碍物,则返回true;
                if (Physics.Raycast(g.transform.position+new Vector3(0,1,0),rayDirection,out hit,
                    (sensor as SightSensor).viewDistance))
                {
                    if (hit.collider.gameObject == this.gameObject)
                    {
                    return true;
                    }
                }               
            }
        }

        return false;
    }

    //更新触发器的内部信息,由于带有视觉触发器的AI角色可能是运动的,因此要不停的更新这个触发器的位置
    public override void Updateme()
    {
        position = transform.position;
    }


    // Use this for initialization
    void Start () {

        //调用基类的Start()函数
        base.Start();
        //像管理器注册这个触发器,管理器会把它加入到当前触发器列表中
        manager.RegisterTrigger(this);
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class SightSensor : Sensor {

    //定义这个AI角色的视域范围
    public float fieldOfView = 45;
    //定义这个AI角色最远能看到的距离
    public float viewDistance = 100.0f;

    

    // Use this for initialization
    void Start () {

        sensorType = SensorType.sight;
        manager.RegisterSensor(this);
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public override void Notify(Trigger t)
    {
        //当感知器能够真正感觉到某个触发器的信息时被调用,产生相应的行为或做出某些决策
        //此处行为:打印相关信息,感知体和触发器之间画一条红色连线
        print("I see a " + t.gameObject.name + "!");
        Debug.DrawLine(transform.position, t.transform.position, Color.red);
    }

    private void OnDrawGizmos()
    {
        Vector3 frontRaypoint = transform.position + (transform.forward * viewDistance);
        float fieldOfViewinRadians = fieldOfView * 3.14f / 180.0f;
        Vector3 leftRaypoint = transform.TransformPoint(new Vector3(viewDistance * Mathf.Sin(fieldOfViewinRadians), 0,
            viewDistance * Mathf.Cos(fieldOfViewinRadians)));
        Vector3 rightRayPoint = transform.TransformPoint(new Vector3(-viewDistance * Mathf.Sin(fieldOfViewinRadians), 0,
            viewDistance * Mathf.Cos(fieldOfViewinRadians)));
        //
        
    }
}


猜你喜欢

转载自blog.csdn.net/Dylan_Day/article/details/80543233