怪物AI之发现玩家(视觉范围发现系列)

来源:互联网 发布:数据建模数学 编辑:程序博客网 时间:2024/06/09 23:59

在网上找到一些资料参考,然后写写自己的想法。
这里感谢MOMO等大神。

我们用玩家检测怪物的方法来测,这样比较试用与弱联网游戏,每次在同步玩家的时候来判断玩家与怪物的位置。
这里给出两个处理方式:
1.碰撞器R范围检测。
2.地图分块范围检测。

这两种处理方式适用于不同的游戏。
再讲解这两种方式之前,我们先了解一下一个核心问题,怪物在玩家R半径内时怎么判断怪物是否在玩家视觉范围内。
如下图

在图中,
玩家的位置与怪物的位置会成一个向量。设为V1
怪物的朝向也是一个向量。设为V2
如果怪物能看到60°的角度的话。那么Vector(V1,V2)如果小于30°则证明玩家在怪物的视觉范围内。
代码为:

    private bool Find(GameObject _Monster)    {        Vector3 otherPos = _Monster.gameObject.transform.position;        v = transform.position - otherPos;        v.y = 0.5f; //处理一下y轴,因为判断建立在二维上        w = _Monster.gameObject.GetComponent<FindPlayerAI>().getFace() - otherPos;        w.y = 0.5f;        if (Vector3.Angle(v, w) < 30)        {            return true;        }        return false;    }

PS:如果想在三维上进行判断的话,同理在处理一下yz轴平面就ok了。

现在我们讲解一下第一种处理方式:
这种比较简单也很无脑。给Player加一个SphereCollider就好了,而且这样也可以判断三维状态。注:如果用Terrain做地面请屏蔽。
碰撞器代码:

    void OnTriggerEnter(Collider other)    {        if (!other.name.Equals("Terrain"))        {            if (Find(other.gameObject)) //接上一个Find代码            {                Debug.Log("发现");            }        }    }

然后就是第二种比较有想法的方式了。
将游戏地图分块。如下图
这里写图片描述

这里呢。大体思路为:
玩家在0号块,在这个状态的时候,只有a,b怪物可以与玩家进行角度判断,cdef都忽略掉。
代码如下:
Map.cs:

public class Map : MonoBehaviour{    private static Map _Instance;    public static Map Instance    {        get        {            if (_Instance == null)            {                _Instance = new GameObject("_Map").AddComponent<Map>();            }            return _Instance;        }    }    private int PlayerPos = -1;    private GameObject[][] Monster = new GameObject[100][];    private int[] MonsterNum = new int[100];    //public int n = 0;    void Awake()    {            for (int i = 0; i < 100; i++)        {            Monster[i] = new GameObject[10];            MonsterNum[i] = 0;        }    }    int getPos(GameObject go)    {        float x = go.transform.position.x;        float z = go.transform.position.z;        x /= 20;        z /= 20;        int pos = (int)(Mathf.Floor(x) + Mathf.Floor(z) * 10);        return pos;    }    public void setMonsterPos(GameObject _Monster)    {        int pos = getPos(_Monster);        Monster[pos][MonsterNum[pos]++] = _Monster;        Debug.Log(pos + _Monster.name);    }    public int getPlayerPos(GameObject _Player)    {        int pos = getPos(_Player);        if (PlayerPos == pos)        {            return -1;        }        else        {            PlayerPos = pos;        }        return pos;    }    public GameObject[] getMonster(int pos)    {        return Monster[pos];    }}

玩家AI.cs:

public class PlayerAI : MonoBehaviour {    Vector3 v;    Vector3 w;    Vector3 otherPos;    GameObject[] Monster = new GameObject[10];    private bool Find(GameObject _Monster)    {        otherPos = _Monster.gameObject.transform.position;        v = transform.position - otherPos;        v.y = 0.5f;        w = _Monster.gameObject.GetComponent<MonsterAI>().getFace() - otherPos;        w.y = 0.5f;        if (Vector3.Angle(v, w) < 30)        {            return true;        }        return false;    }    //void OnTriggerEnter(Collider other)    //{    //    if (!other.name.Equals("Terrain"))    //    {    //        if (Find(other.gameObject))    //        {    //            Debug.Log("发现");    //        }    //    }    //}    void Update()    {        int pos = Map.Instance.getPlayerPos(gameObject);        if (pos != -1)        {            Monster = Map.Instance.getMonster(pos);        }        for (int i = 0; i < Monster.Length; i++)        {            if (Monster[i] != null)            {                if (Find(Monster[i]))                {                    Debug.Log(i + "发现");                }            }        }    }}

怪物AI.cs:

public class MonsterAI : MonoBehaviour {    public GameObject Player;    private Vector3 Face;    void Start () {        Face = transform.position + transform.rotation * Vector3.forward * 10;        Map.Instance.setMonsterPos(gameObject);    }    public Vector3 getFace()    {        return Face;    }    void Update()    {        Face = transform.position + transform.rotation * Vector3.forward * 10;        //Debug.DrawLine(transform.position, Face, Color.red);    }}
0 0
原创粉丝点击