c++ 图形编辑器_从Box2D编辑器制作得到的感悟

e66ecbe6bc8f6e2d550f1a8492cbe0df.png

前言

我们需要把Box2D的碰撞体数据导入到服务端,然后让服务端读取这些数据,重建2D物理世界。那么,这些碰撞数据从哪来,怎么做的呢?

Box2D官方手册里有提到两个比较出名的编辑器。

`PhysicsEditor`和`RUBE`

这两个编辑器都很出色,但是他们都有一个共同的痛点——编辑的碰撞体对于Unity不是所见即所得的。

还有比较特殊的应用场景,比如做Moba这种伪3D游戏,物理世界完全是可以用Box2D做的,但是,游戏里许多模型都是3D的,而PhysicsEditor和RUBE都只支持导入图片,所以也不妥当。

在仔细研究了官方文档后对比Unity自带的2D物理系统有很多共同点,我就想能不能借助Unity自身物理系统的力量做一个Box2D编辑器呢,这样可以所见即所得。

其实硬要说技术含量的话,在Odin的帮助下,这个可视化编辑器还真没啥技术含量。所以我在这主要说一下思路和历程,希望能对大家以后解决类似问题有帮助。文中代码尽量采用伪代码的形式,方便大家理解。

正文

先放出一张UML图,方便大家理解下面的代码

0b65e4468847231f74568d341bb31c13.png

涉及到的相关知识点

  • 编辑器拓展插件:Odin
  • 序列化反序列化:Bson
  • 多边形分割:Antoan Angelov的Separator
  • 矩阵变换相关知识
  • Gizmos相关知识
  • Box2D的相关知识

要做这种需要导出数据的编辑器拓展,我一般都遵循数据逻辑分离的原则,这样开发时干净利落,序列化反序列化时没有冗余信息。

这里就以最为复杂的多边形碰撞体数据构建为例

本文代码中所有特性都是Odin插件提供的支持,如果没接触过Odin的,就把他理解为利用特性把这个字段可视化了。

数据结构的选定

首先是所有类型碰撞体都有的数据结构

public 

这里为什么不用Unity的Vector2或者System的Vector2呢,因为Bson不支持反序列化结构体。。。,所以只能自己写一个class了

而且,我们做这种导出数据给服务端读取的编辑器的时候,尽量不要引用到Unity的变量,不然你还得需要在服务端做一些操作匹配上这些数据类型才行。

然后是多边形的数据结构

    public class B2S_PolygonColliderDataStructure: B2S_ColliderDataStructureBase
    {
        [LabelText("碰撞体所包含的顶点信息(顺时针),可能由多个多边形组成")]
        public List<List<CostumVector2>> points = new List<List<CostumVector2>>();

        [LabelText("总顶点数")]
        public int pointCount;
    }

数据结构选好了,我们需要做一个数据载体,来承载所有的数据

    public class ColliderDataSupporter
    {
        [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
        public Dictionary<long, B2S_ColliderDataStructureBase> colliderDataDic = new Dictionary<long, B2S_ColliderDataStructureBase>();
    }

借助Unity设置碰撞体信息,并绘制出图形

数据层我们选好了,接下来要处理显示层,我选择了使用`Gizmos`来绘制线段

public class B2S_PolygonColliderVisualHelper
{
	[LabelText("Unity的多边形碰撞体")]
	public PolygonCollider2D mCollider2D;
	[LabelText("多边形碰撞体数据")]
    public B2S_PolygonColliderDataStructure MB2S_PolygonColliderDataStructure = new B2S_PolygonColliderDataStructure();
	
	//新建矩阵变换,确保绘制的线段与Unity碰撞体线段位置信息一致
	//从mCollider2D读取碰撞体信息,并赋值给一个临时List<Vector2>
	
	//由于Box2D默认支持的多边形最多只能有8个顶点,而且还得是凸多边形,
	//所以我们需要使用Separator来进行多边形的分割
	
	//使用Gizmos画线,注意使用矩阵的MultiplyPoint方法对顶点进行变换
}

由于我们使用了Gizmos,所以我们必须得需要一个挂载MonoBehaviour脚本的游戏物体进行驱动画线

        private void OnDrawGizmos()
        {
            foreach (var VARIABLE in this.MB2SColliderVisualHelpers)
            {
                if (VARIABLE.canDraw)
                    VARIABLE.OnDrawGizmos();
            }
        }

效果如图

e516761a42b4c634cfab07916148b4c3.png

序列化反序列化碰撞体信息与可视化

同样利用了Odin提供的特性,在EditorWindow做了数据的可视化,主要是方便开发调试时Debug

我们需要在打开EditorWindow的时候读取所有碰撞数据,并且根据所拖拽碰撞体来自动匹配已经保存好的数据(如果存在的话),避免重复写入数据造成人力的浪费。

253b2c4c1510b7636260d4aebcb2a7d8.png

如果大家对这个编辑器代码有兴趣的话,可以去

烟雨迷离半世殇/NKGMobaBasedOnET​gitee.com
d92ea1e1680a19f8252a3dd43a07725f.png

查看代码

献丑了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值