开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

首页   >   博客   >   ghjk

给游戏中的人物添加视野

个人分类: 游戏AI | 2018-2-8 11:41
    快过年了,今天闲着没啥事,写一写代码,大家共同学习,提前祝大家新年快乐
    这几天突然有个想法,打算研究研究游戏AI的东西,于是就翻阅了一些书看了看,基本上算是完成了一些基础的东西吧,写的代码不能保证是最优解,反正是功能实现了,如果有大神有更好的写法,非常感谢能提出建议,这次先写一个视觉的处理吧;(第一次写,写的不是很好,大家多多包含)

首先先写一个类ObjectProperties,这个类是包含AI角色的各种属性的类;

[code]phpcode:

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

public enum Properties //先写一个枚举,包含了英雄和敌人
{
Hero,
Enemy,
}
public class ObjectProperties : MonoBehaviour
{
    public Properties properties;

    void Start () {
    }
    void Update () {
       
    }
}


下面开始写人物视觉的处理 我给他起名叫VisualSensor

[code]phpcode:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//这个类主要就是处理游戏角色的视觉信息
public class VisualSensor : MonoBehaviour
{
    public float fieldOfView = 50;//这个变量定义了游戏角色的视觉范围
    public float viewDistance = 100;//这个变量定义了游戏角色可以看到的最远的距离
    public LayerMask layer;//这个变量主要是定义游戏角色可以看到哪些层
    public Properties properties;//这个变量就是刚才上面写的枚举变量
    private List<GameObject> Objs = new List<GameObject>();//定义一个列表,用于记录视觉范围内的物体
    void Start () {
    }
    void Update () {
        Debug.Log(FindGameObjectOfView());
    }
    /// <summary>
    /// 找到视野范围内最近的一个物体
    /// </summary>
    /// <returns></returns>
    private GameObject FindGameObjectOfView()//这个方法就是用来找到视野内所有的物体,并返回距离自己最近的一个
    {
        Objs.Clear();//清空列表,如不清会造成累加
        Collider[] collider = Physics.OverlapSphere(this.transform.position, viewDistance, layer);//调用Physics.OverrlapSphere方法获取以viewDistance为半径,layer层的所有物体
        if (collider == null) return null;//如果没有物体,那么就返回空
        float[] distance;//定义一个float数组
        GameObject[] Obj;//定义一个GameObject数组
        RaycastHit hit;
        for (int i = 0; i < collider.Length; i++)//循环遍历获取的所有物体
        {
            Vector3 rayDirection = collider[i].transform.position - this.transform.position; //得到两个物体之间的向量
            rayDirection.y = 0;
            if (Vector3.Angle(rayDirection, this.transform.forward) < fieldOfView)//用vector3.Angle()函数取得两个向量之间的角度然后判断是否小于视野角度,如果小于,那么物体就处于视野之内
            {
//随然处于视野之内了,但是如果两个物体之前有东西挡住了,还能看见,那么就是太不真实了,所以这里还要写个射线去判断
                if (Physics.Raycast(this.transform.position + new Vector3(0, 1, 0), rayDirection, out hit, viewDistance))
                {
                    Debug.DrawLine(transform.position + new Vector3(0, 1, 0), hit.collider.gameObject.transform.position, Color.red);
//这里判断是不是要找的物体,如果是就把他加入到列表中
                    if (hit.collider.gameObject.GetComponent<ObjectProperties>()!=null&&hit.collider.gameObject.GetComponent<ObjectProperties>().properties == properties)
                    {
                        Objs.Add(collider[i].gameObject);
                    }
                }
            }
        }
        if (Objs.Count == 0) return null;//如果列表是空的,那么就返回一个空
        Obj = new GameObject[Objs.Count];
        distance = new float[Obj.Length];
        for (int i = 0; i < Objs.Count; i++)//循环遍历进行数组的赋值
        {
            Obj[i] = Objs[i];
            distance[i] = ComputedRange(Obj[i], this.gameObject);
        }
        sort(distance, Obj, 0, Obj.Length - 1);//调用快速排序方法进行排序
        return Obj[0];//返回距离最近的一个物体
    }
#region 这里主要就是快速排序算法 
    private int sortUnit(float[] array, GameObject[] gameObjects, int low, int high)
    {
        float key = array[low];
        GameObject game = gameObjects[low];
        while (low < high)
        {
            while (array[high] >= key && high > low)
                --high;
            array[low] = array[high];
            gameObjects[low] = gameObjects[high];
            while (array[low] <= key && high > low)
                ++low;
            array[high] = array[low];
            gameObjects[high] = gameObjects[low];
        }
        array[low] = key;
        gameObjects[low] = game;
        return high;
    }
    public void sort(float[] array, GameObject[] gameObjectsa, int low, int high)
    {
        if (low >= high)
            return;
        int index = sortUnit(array, gameObjectsa, low, high);
        sort(array, gameObjectsa, low, index - 1);
        sort(array, gameObjectsa, index + 1, high);
    }
#endregion
//这个方法就是为了省事,用于计算两个物体距离的
    public float ComputedRange(GameObject obj1, GameObject obj2)
    {
        float distance = Vector3.Distance(obj1.transform.position, obj2.transform.position);
        return distance;
    }
}


好了,这里主要也就是两个类,把
VisualSensor类挂到需要赋予视野的物体上,然后调一下参数,在把 ObjectProperties 类挂到需要被发现的物体上,调一下参数,就OK了,可以看一下图片

0 0

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册帐号
返回顶部