Unity 九宫格AOI视野算法

九宫格AOI视野算法介绍

AOI(Area Of Interest 感兴趣的领域 )
我们通常把玩家周围的可视区域,叫做玩家感兴趣的领域即AOI。它的大小其实就是玩家的视野大小。它的作用就是根据AOI来优化数据的操作,比如不在视野范围的其他活跃对象的行为就不需要让玩家知道(反正玩家也看不到),这样减少了数据的传输。再一个就是通过AOI来判断我们释放一些互动动作的有效范围内都有些什么活跃对象,然后再和这些对象发生交互。
AOI算法不仅仅局限于九宫格,根据游戏需求还可能会有四宫格,十六宫格等等,九宫格只是本篇文章的一个例子而已。
在这里插入图片描述
想这张图片我们把地图分为若干个小格子,当我们站到5号位置的时候我们就只需要加载我们周围的8个格子和自己所在格子范围内的(敌人,玩家,怪物),相对的当我们站到6号位置的时候我们就加载以6号格子为中心周边的格子啦。相对的之前1,4,7号格子里面的(敌人,玩家,怪物),我们就不加载了,因为我们完全看不到。这样就减少了我们的数据交互。
在这里呢我做了一个简单的小栗子,里面仅仅实现了地图显示的功能(对于敌人等,其他对象的显示和互动大同小异,大家可以自行拓展),大家可以参考下。(代码可能没有那么完美,大家多多指教)
先康康效果
请添加图片描述

地图管理

using System.Collections.Generic;
using UnityEngine;

public class MapManager : MonoBehaviour
{
    [Range(1, 10)]
    public int oneMapScale;
    Dictionary<int, Dictionary<int, GameObject>> allMaps = new Dictionary<int, Dictionary<int, GameObject>>();
    List<GameObject> mapPools = new List<GameObject>();
    public GameObject map;
    public void CreatMap(int x, int y)
    {
        List<GameObject> viewMap = new List<GameObject>();
        for (int i = -1; i < 2; i++)
        {
            for (int j = -1; j < 2; j++)
            {
                viewMap.Add(CreatOMap(x + i, y + j));
            }
        }
        for(int i=0;i<mapPools.Count; i++)
        {
            if (!viewMap.Contains(mapPools[i]))
            {
                mapPools[i].SetActive(false);
            }
        }
        mapPools.Clear();
        mapPools=viewMap;
        for(int i=0;i<mapPools.Count;i++)
        {
            mapPools[i].SetActive(true);
        }
    }

    private GameObject CreatOMap(int v1, int v2)
    {
        if (allMaps.ContainsKey(v1))
        {
            if (!allMaps[v1].ContainsKey(v2))
            {
                GameObject go = Instantiate(map, transform);
                go.transform.position = new Vector3(v1 * 10 * oneMapScale, 0, v2 * 10 * oneMapScale);
                go.transform.GetChild(0).GetComponent<TextMesh>().text="("+v1+","+v2+")";
                go.GetComponent<Renderer>().material.color= UnityEngine.Random.ColorHSV();
                allMaps[v1].Add(v2, go);
            }
        }
        else
        {
            GameObject go = Instantiate(map, transform);
            go.transform.position = new Vector3(v1 * 10 * oneMapScale, 0, v2 * 10 * oneMapScale);
            go.transform.GetChild(0).GetComponent<TextMesh>().text = "(" + v1 + "," + v2 + ")";
            go.GetComponent<Renderer>().material.color = UnityEngine.Random.ColorHSV();
            Dictionary<int, GameObject> v2map = new Dictionary<int, GameObject>();
            v2map.Add(v2, go);
            allMaps.Add(v1,v2map);
        }
        return allMaps[v1][v2];
    }
}

玩家控制器

using UnityEngine;

public class PlayerControl : MonoBehaviour
{
    public MapManager mapManager;
    Camera cam;
    int mapScale;
    int pyl;
    int x = 0;
    int y = 0;
    float v;
    float h;
    float speed = 10;
    Vector3 gs = new Vector3(0, 2, -2);
    private void Awake()
    {
        cam = Camera.main;
        mapScale = mapManager.oneMapScale * 10;
        pyl = mapScale/2;
        mapManager.CreatMap(x, y);
        cam.transform.position = transform.position + gs;
        cam.transform.LookAt(transform);
    }
    void Update()
    {
        v = Input.GetAxis("Vertical");
        h = Input.GetAxis("Horizontal");
        if(v!=0||h!=0)
        {
            transform.position += Vector3.forward * v * Time.deltaTime*speed;
            transform.position += Vector3.right * h * Time.deltaTime*speed;
            cam.transform.position=transform.position+gs;
            cam.transform.LookAt(transform);
            if(Mathf.Floor((transform.position.x+pyl)/mapScale)!=x|| Mathf.Floor((transform.position.z+pyl) / mapScale)!=y)
            {
                x = (int)Mathf.Floor((transform.position.x + pyl) / mapScale);
                y = (int)Mathf.Floor((transform.position.z + pyl) / mapScale);
                mapManager.CreatMap(x, y);
            }
        }
    }
}

以上就是我写的小栗子。没有注释因为方法名已经写的很明显了。
看不懂的小伙伴可以私信也可以评论区留言,我一定会积极回答的哦。
另外附上项目源码仅供参考!!!谢谢大家😘😘😘请添加图片描述

Unity中实现AOI(Area of Interest,兴趣区域)九宫格算法的方法如下: 首先,创建一个AOIManager类,用于管理和维护AOI区域和对象。该类需要包含以下几个关键组成部分: 1. AOI格子的定义:定义一个格子的大小,并将整个场景划分为多个格子。可以使用二维数组来表示格子,每个元素存储在该格子中的对象列表。 2. 对象的定义:定义一个对象的结构,包括对象的唯一标识ID和对象的位置信息。 3. 对象的管理:AOIManager类需要负责管理所有对象的位置和状态。当一个对象进入或离开一个格子时,需要更新该对象在AOIManager中的位置信息。 4. AOI九宫格算法的实现:在AOIManager中实现九宫格算法,根据一个对象的位置信息,计算出该对象所在的格子以及该对象周围的格子。 5. 状态更新:当一个对象的位置发生变化时,需要通过九宫格算法计算该对象应该进入或离开的格子,并更新该对象的位置信息。 6. 感知范围:根据九宫格算法计算出的周围格子,可以获取到该对象周围的其他对象。可以根据需要定义对象的感知范围,只获取特定范围内的对象。 总结一下,Unity实现AOI九宫格算法需要创建AOIManager类,实现格子划分和对象管理,以及实现九宫格算法来计算对象所在的格子和对象的感知范围。这种方法可以提高游戏中大量对象的更新效率,减少不必要的计算和通信开销,提升游戏性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不敲注释的呆呆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值