- 自动生成地图系统
- AutoCreateMapSystem
- 神奇的六边形
- 六边形实体
- 创建者和创建六边形单元系统
- 更新计划
- 作者的话
- ECS系列目录
- ECS官方示例1:ForEach
- ECS官方案例2:IJobForEach
- ECS官方案例3:IJobChunk
- ECS官方案例4:SubScene
- ECS官方案例5:SpawnFromMonoBehaviour
- ECS官方案例6:SpawnFromEntity
- ECS官方案例7:SpawnAndRemove
- ECS进阶:FixedTimestepWorkaround
- ECS进阶:Boids
- ECS进阶:场景切换器
- ECS进阶:MegaCity0
- ECS进阶:MegaCity1
- UnityMMO资源整合&服务器部署
- UnityMMO选人流程
- UnityMMO主世界
- UnityMMO网络同步
- 用ECS做HexMap:自动生成地图系统
- 用ECS做HexMap:利用RenderMesh绘制六边形
- 用ECS做HexMap:利用RenderMesh为六边形涂色
- 用ECS做HexMap:六边形单元的颜色混合
- 用ECS做HexMap:重构地图系统
- 用ECS做HexMap:鼠标点击六边形单元涂色
ECS的世界由许许多多的系统来操控,在进入主世界的时候会创建这些系统,如下图所示:
上一篇中PlayerInputSystem负责处理玩家的操作,与之对应的组件有UserCommand(用户命令),TargetPosition(目标位置)和MoveSpeed(移动速度)。原本想一起看看源码,加一点注释进去,算是走马观花,画蛇添足。不过,这样做实在没有太多营养价值,如果大家有兴趣,自行看下源码吧。这一篇想写一点创造性的东西,例如生动生成地图系统。
AutoCreateMapSystem灵感来源于Unity Hex Map Tutorial,我觉得自动生成地图这件事情太适合ECS了,为什么?
- 自动生成的地图涉及到大量的实体;
- ECS的性能是为大世界而生,在其性能加持下,我们可以生成无限世界;
- 逻辑解耦,分工明确。
不管怎样,都值得尝试一下。 说下我的大概需求:
- 自动生成地图,利用各种System来制定地图的规则,使其尽量贴近自然;
- 无限地图,玩家离地图边缘一定距离后,预判玩家行走线路并在其方向上动态扩展;
- 将地图数据保存到服务器,与其他玩家进行同步;
- 动态加载和动态裁剪,以最小的资源做出最大的地图;
- 地图与玩家互动,可破坏,可创建,所有操作进行网络同步。
我觉得像MegaCity那样的大地图,太吃资源,如果把地图的所有一切都转换成数据。然后再通过数据来驱动无限地图,这样也许很有意思,但是也不是随机生成所有一切,要利用算法来尽量还原大自然的规则。 大概就是这样,我们先从最简单的开始,一步一步实现我们的需求。就先从六边形开始吧! 国外的大佬解释了六边形有多么神奇和好用,蜜蜂选择六边形来筑巢,足以说明这个东西道法自然,详情点上面的链接了解。
using UnityEngine;
///
/// 六边形常量
///
public static class HexMetrics {
///
/// 总的顶点数,一个六边形有18个顶点
///
public static int totalVertices = 18;
///
/// 六边形外半径=六边形边长
///
public const float outerRadius = 10f;
///
/// 六边形内半径=0.8*外半径
///
public const float innerRadius = outerRadius * 0.866025404f;
///
/// 六边形的六个角组成的数组
///
public readonly static Vector3[] corners = {
new Vector3(0f, 0f, outerRadius),//最顶上那个角作为起点,顺时针画线
new Vector3(innerRadius, 0f, 0.5f * outerRadius),//顺数第二个
new Vector3(innerRadius, 0f, -0.5f * outerRadius),//顺数第三个
new Vector3(0f, 0f, -outerRadius),//依次类推,坐标如下图所示
new Vector3(-innerRadius, 0f, -0.5f * outerRadius),
new Vector3(-innerRadius, 0f, 0.5f * outerRadius),
new Vector3(0f, 0f, outerRadius)
};
}
如图,红色虚线代表内半径,蓝色实线代表外半径,而其数值都是相对固定的常量,因此这里直接定义出来。 根据这些常量,设定圆心坐标为(0,0,0),我们以最上角最为起点,就可以得出六个角的顶点坐标了。
接下来创建六边形实体,如下图所示: 实际上就是个空对象,我本来要通过ConvertToEntity将其转化成实体的,但是出了一个红色警报,只好移除,保留E脚本:
///
/// E:六边形单元
///
[RequiresEntityConversion]
public class HexCellEntity : MonoBehaviour,IConvertGameObjectToEntity {
///
/// 三维坐标
///
public int X;
public int Y;
public int Z;
///
/// 颜色
///
public Color Color;
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
//数据交给C保存
dstManager.AddComponentData(entity, new HexCellData
{
X=this.X,
Y=this.Y,
Z=this.Z,
color=Color,
RadiansPerSecond= math.radians(DegreesPerSecond)
});
//添加父组件
dstManager.AddComponent(entity, typeof(Parent));
//添加相对父类的本地位置组件
dstManager.AddComponent(entity, typeof(LocalToParent));
}
}
对应的C组件:
///
/// C:保存六边形的坐标和颜色数据
///
[Serializable]
public struct HexCellData : IComponentData
{
public int X;
public int Y;
public int Z;
public Color color;
public float RadiansPerSecond;
}
暂时设定六边形的功能是旋转,后面再更改成变色:
///
/// S:这里暂时只做旋转,后面会变色等
///
public class HexCellSystem : JobComponentSystem {
EntityQuery m_Group;//查询到特定组件的实体,将其放入这个组中
///
/// 这里根据类型来查询到特定的实体
///
protected override void OnCreate()
{
///typeof(Rotation)=带有Rotation组件的;ComponentType=对应HexCellData组件类型的
/// ReadOnly=只读会加快获取实体的速度,ReadWrite=读写 则相对较慢
m_Group = GetEntityQuery(typeof(Rotation), ComponentType.ReadOnly());
}
[BurstCompile]//同样使用Burst编译器来加速,区别是使用了块接口:IJobChunk
struct RotationSpeedJob : IJobChunk {
///
/// 时间
///
public float DeltaTime;
///
/// 原型块组件类型=Rotation
///
public ArchetypeChunkComponentType RotationType;
///
/// 只读 原型块组件类型=HexCellData
///
[ReadOnly]
public ArchetypeChunkComponentType RotationSpeedType;
///
/// 找出满足条件的实体来执行
///
///
/// 块索引
/// 第一个实体索引
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
var chunkRotations = chunk.GetNativeArray(RotationType);
var chunkRotationSpeeds = chunk.GetNativeArray(RotationSpeedType);
for (var i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?