BigMap
1.地图结点 MapNode
至今为止计算机的底层永远是 0 1 数据 层层封装到我们熟识的高级语言以及 “View” 视图是用来形象表达数据驱动形式的
没人能看到 ” 电子 “在导体中如何运动但是用过一些方式能让我们观察到 辟如 ”打雷“
地图的结点就是具体存储 数据流动性的一个点 视图中 是某个 固定的位置 逻辑中 是一个坐标点
10 X 10 的地图 在逻辑中我们由100个结点组成由 结点来保存地图每一块儿上的流动数据
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Ramdom = UnityEngine.Random;
/// <summary>
/// 大地图
/// </summary>
[System.Serializable]
public class BigMap : Singleton<BigMap>
{
const int mapCount = 10;
public List<MapNode> mapNodes;
public List<MapNode> obstacles;
int id;
public BigMap()
{
obstacles = new List<MapNode>();
mapNodes = new List<MapNode>();
}
/// <summary>
/// 初始化大地图
/// </summary>
public void Init()
{
GameObject p = Resources.Load<GameObject>("Plane");
for (int y = 0; y < mapCount; y++)
{
for (int x = 0; x < mapCount; x++)
{
MapNode node = new MapNode();
node.Id = id++;
Vector2 vector2 = new Vector2(x, y); //地图结点的中心点
node.SaveData(vector2, 1, 1); //设置地图 基于坐标系的 最大坐标 最小坐标
int b = Ramdom.Range(0, 10); //
if (b % 9 == 0)
{
node.CanGo = false; //设置障碍物 这里设置的障碍物 不是 基于 Unity3D 引擎 碰撞的障碍物
// 仍然是 普通地板 颜色不同而已
GameObject.Instantiate(p, new Vector3(node.Rect.center.x, 0.1f, node.Rect.center.y), Quaternion.identity);
}
else
{
node.CanGo = true;
}
mapNodes.Add(node);
}
}
}
//通过点的 检测下一个结点 是否可以通过
internal bool CheckNext(Transform cube)
{
Vector3 vector3 = cube.forward * 0.05f + cube.position;
Vector2 vector2 = new Vector2(vector3.x, vector3.z); // 下一步的 位置
for (int i = 0; i < mapNodes.Count; i++)
{
if (vector2.x >= mapNodes[i].Rect.min.x && vector2.x <= mapNodes[i].Rect.max.x &&
vector2.y >= mapNodes[i].Rect.min.y && vector2.y <= mapNodes[i].Rect.max.y )
{
if (mapNodes[i].CanGo)
{
return true;
}
}
}
return false;
}
}
2.基于地图的数据驱动
地图作为一个游戏绝对必要的模块 它是整个游戏的基层开始 ,没有地图架构的基础其他工作难以对接完成影响整体游戏开发进度。地图作为一个基体,他所承载的是所有游戏物体数据。
地图编辑器 地图配置文件Config 必要文件
当大地图通过 配置文件 数据驱动>>地图编辑器 “生成地图” 此时!! 还有其他的 配置文件 驱动程序
例如:主角 怪物 NPC 场景物体
此时创建好的物体实例索引 都会存储在所在的地图结点中方便取用
3.角色范围渲染
为了节省内存开销,减少不必要的DrawCall 范围渲染技术就应需而生。再许多游戏中我们只能看到基于角色为中心半径 固定的范围场景 或者是 游戏窗口 大小范围渲染。利用已经保存的地图结点索引我们可以通过算法求出我们周围半径多少的具体地图位置,来进行一个 渲染 减少内存开销 DrawCall的产生
4.基于地图的碰撞
每个地图 结点的周边都是可以通过存储好的数据来进行碰撞的一个检测 上部代码
// 地图结点
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 地图结点
/// </summary>
public class MapNode
{
Func<int> func;
bool canGo;
//string area;
int id;
Rect rect; //Rect 包含一堆 坐标什么的
Dictionary<string, Dictionary<string, object>> units; //人物 啥的 物体
//public OtherThing ; //放置其他的 需求数据
public Rect Rect { get => rect; set => rect = value; }
public Dictionary<string, Dictionary<string, object>> Units { get => units; set => units = value; }
public int Id { get => id; set => id = value; }
public bool CanGo { get => canGo; set => canGo = value; }
/// <summary>
/// 注册功能
/// </summary>
public void AddFunction(FunctionType type)
{
}
/// <summary>
/// 初始化结点
/// </summary>
public MapNode()
{
rect = new Rect();
}
/// <summary>
/// 保存地图数据
/// </summary>
public void SaveData(Vector2 center, float length, float width)
{
rect.center = center;
rect.height = length;
rect.width = width;
rect.max = new Vector2(rect.center.x + rect.height / 2, rect.center.y + rect.width / 2);
rect.min = new Vector2(rect.center.x - rect.height / 2, rect.center.y - rect.width / 2);
}
/// <summary>
/// 保存 MapNode 上存在的object 数据
/// </summary>
/// <param name="type"></param>
/// <param name="obj"></param>
public void SaveUnits(string type, string name, object obj)
{
if (units.ContainsKey(type))
{
foreach (var item in units.Values)
{
if (item.ContainsKey(name))
{
item[name] = obj;
}
else
{
item.Add(name, obj);
}
}
}
}
}