C#精要 - 线程篇
什么是线程、进程?线程是对物理CPU进行虚拟化,也是操作系统能调度的最小单位。
进程实际是应用程序的实例要使用的资源的集合,每个进程都被赋予了一个虚拟地址空间来避免被其它进程访问。
一个线程确定由某一进程拥有,一般不能跨进程。
线程结构线程有空间(内存耗用)和时间(上下文调度)上的开销。
内存耗用① 线程内核对象 (thread kernel object)
主要是有对线程的描述属性。x64使用约1240字节。
值得注意的是线程上下文(thread context):线程上下文是是线程上一次执行完毕后,CPU寄存器的状态(内存块)。
② 线程环境块 (thread environment block,TEB)
有GDI(图形设备接口)和OpenGL用的一些数据,以及异常处理链首:线程每进入一个try块,都会在链首(head)中插入一个节点(node),退出try块时删除该节点。x64中4KB。
③ 用户模式栈 (user- mode stack)
堆栈概念中的栈说的就是这个了,默认分配1MB内存(其实windows是保留1MB容量,等用了才调拨给你)。
④ 内核模式栈 (kernel- ...
C#精要 - GC篇
什么是GC?为什么需要GC?GC,即Garbage Collection,意为垃圾回收。
.Net不同于原生C++这种需要程序员手动管理内存的机制,存在自动释放内存的一套机制,这就叫GC。
GC可以让程序员不必关心资源的管理,也就是一个对象的生命流程中的4:
调用IL指令newobj,为代表资源的类型分配内存(C#中用new操作符完成)。
初始化内存,设置资源的初始状态并使资源可用。类型的实例构造器负责设置初始状态。
访问类型的成员来使用资源(有必要可以重复)。
摧毁资源的状态以进行清理。
释放内存。垃圾回收器独自负责这一步。
当然可以自己重写Finalize方法或手动调用GC.Collect。
简单列举GC的优势(对比手动管理)1.让程序员可以不必关心资源的管理。
2.避免手动管理时,顺序搞错,先销毁后调用导致空引用抛错。
3.避免手动管理时,由于标记引用未清空导致的内存泄露。
讲讲GC算法三个方向上讲:从总体流程上来说,它有标记 -> 压缩两个阶段;从确定是否销毁的方式上来说,它是从根遍历的;从销毁处理方式上来说,它是分代的。它解决了引用计数法循环引用的问题。
...
王者荣耀复刻项目 技能编辑器篇
从 技能配置可视化+纯业务 的角度,将原来的技能系统换个角度刨析一遍。
大体分类按照可配置的文件来分类,可分为以下五大类:
碰撞关系配置
buff配置
skill配置
单位配置
bullet配置
下面对这几类的核心配置数据进行列举。
碰撞关系配置
目标队伍
目标选择规则
目标单位
目标查找范围
buff配置
buff类型
buff附着目标
buff位置确定方式
碰撞关系配置
skill配置
图片、音效资源路径
技能动画名
技能目标确定方式、范围等
技能指示器类型
单位配置UnitInfoCfg,比较特殊,为了方便导表,逻辑碰撞体这块只提供一个Enum,在实际加载时使用它的派生类,根据Enum读取出不同的真实逻辑碰撞数据。
单位基础属性(基础血量、防御等)
单位资源位置
单位逻辑碰撞体类型(受击点高度 + 碰撞体大小、形状)
实现协作即想要结点编辑器、又想要表格式的批量填写。将他们协作起来需要多写一些代码,且他们的数据都必须来自同一套数据源——我采用Json数据源。
Luban由Luban提供2套类型:Editor专用的类型,用于和Json数据源 ...
工具篇:Odin 可视化编辑器
可视化方案什么是Unity的可视化方案很多,直接举例一些。
通用型github开源:
Node_Editor_Framework
xNode
特化型行为树
NodeCanvas
Behavior Designer
状态机
FlowCanvas
Bolt
PlayerMaker
行为树编辑器有什么作用
剧情(对话)编辑
AI编辑
技能编辑
碰撞关系编辑(纯数据,技能和单位是否可以碰撞)
装备合成路径编辑
其他
优劣
批量配置并不如Excel方便。
非常适合配合树状结构的数据。
思考实现Excel和可视化编辑器之间的相互转化,会方便很多。
下面只进行odin的使用,不再对行为树、状态机一类的可视化插件进行关注。
原生编辑器精灵、List、字典show.cs
123456789public class Show : MonoBehaviour{ public Sprite m_OriginSprite; public List<int> m_OriginList = new List<int>(); public Dicti ...
王者荣耀复刻项目 背包系统篇
设计基本实现数据库中只存储物品id、物品数量;客户端本地二进制式存储cfg,来显示物品详情;服务端本地二进制式存储cfg,来确定物品效果。
整体流程如下:
客户端登录时,获取到背包信息(物品id、物品数量)。
客户端打开背包时,根据内存中的背包信息 + 本地cfg,来展示物品。
客户端使用物品时,发送请求到服务端并让服务端在数据库验证数量。
如果数量不足,则失败;
如果数量足够,则根据服务端本地cfg来计算出账号收益,更新数据库后返回结果给客户端。
客户端获得返回结果,刷新内存数据。
优化
虚拟列表
对象池
异步加载
基础实现Scroller ViewViewport,遮罩,决定能看到的内容。(视野)
Content,真实内容。(履带)
设置格子锚点到左上角。
数据类型主要分为3块。
BagMgr,用来获取道具信息。
BagItem,背包格子类。
BagPanel,背包页面逻辑。
显式获取要计算出 起始显示的格子索引值、结束显示的格子索引值:
=========================================== ...
Enum转换List
EnumToList123456789101112131415161718192021222324252627282930313233343536373839public static List<T> EnumToList<T>(Type enumType) where T : ComboBoxSourceItem, new() { var result = new List<T>(); if (enumType.BaseType == typeof(System.Enum)) { foreach (var enumValue in System.Enum.GetValues(enumType)) { // 値の説明を取得する FieldInfo fi = enumType.GetField(System.E ...
工具篇:protobuf序列化
Protobuf 初识什么是Protobuf
Google Protocol Buffers(简单Protobuf或PB) 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关 、可扩展的序列化结构数据格式 。目前,几乎支持所有主流编程语言 。
他和xml、json一样,都属于数据标记语言。
Protobuf优势
序列化与反序列化速度极快。
与语言及平台无关,兼容性好,通过 proto文件生成多种语言文件 => 实现 服务端、客户端之间 跨语言平台的数据转换。
数据高度压缩 => 占用空间少,节省带宽。
Protobuf使用google官方全版本支持
.net专用版本 作者Marc Gravell(本篇使用)
Protobuf对比C#常规序列化标签不同,常规只需要对类打上[Serializable],而Protobuf需要对类打上[ProtoContract],再对属性打上[ProtoMember(1)],中间的数字是tag对应一个属性。 ...
工具篇:本地配置
非常感谢 luban 的作者,提供了如此好用的工具,并热心的教了我很多关于实际工作流的思路,对于我来说,这些都是很宝贵的。
初识luban简介就目前我的使用来说,luban可以用于excel导出配置数据、可以用于生成proto协议(并使用Bright.Net的序列化框架)、可以用于编辑器交互、可以用于编辑器数据源与运行时真实配置数据交互。是一个各方面都非常成熟的配置文件、通信协议的解决方案。
开源地址 : github
案例开源地址:github
luban高效地处理游戏开发中常见的excel、json、xml之类的数据,检查数据错误,生成c#等各种语言的代码,导出成bytes或json等多种格式。
强大的数据解析和转换能力 {excel(csv,xls,xlsx), json, bson, xml, yaml, lua, unity ScriptableObject} => {binary, json, bson, xml, lua, yaml, erlang}
增强的excel格式,可以简洁地配置出像简单列表、子结构、结构列表,以及任意复杂的深层次的嵌套结构。
完备的类型 ...
工具篇:帧同步网络库
我的解决方案CodingK_Session
聊聊网络基础起源起源于1969年美国国防部的军用项目,最初只是一个单个的分组交换网ARPANET(并不是一个互连的网络)。1983年TCP/IP协议成为ARPANET上的标准协议,使所有使用 TCP/IP协议 的计算机都能利用互连网相互通信。因此1983年被当作因特网(Internet)诞生的时间。之后经过不断发展,形成了如今的英特网(Internet)。
网络通信是指什么?计算设备之间通过网络交换数据,更通俗地说法就是:主机A上的某个程序(进程)与主机B上的某个程序(进程)进行数据交换。
网络通信如何实现?计算设备之间通过共同遵守的 网络协议(network protocol) ,以约定好的规则来交换数据。
计算机网络体系结构五层协议的体系结构
OSI七层协议:概念清楚,理论完整,但它复杂不实用。
TCP/IP四层协议:应用非常广泛。实质上,TCP/IP只有上面三层,最下层的网络接口层并没有什么具体内容。
综合前面两者,我们一般采用五层协议的体系结构来学习理解计算机网络原理。
五层协议功能划分应用层:直接为用户的应用进程提供服务。这一层的 ...
工具篇:定时系统
我的解决方案CodingKTimer
初识为什么需要定时系统Unity侧:
简化协程计时写法。
协程基于Monobehaviour来实现,而物体激活属性变化会导致中断调用。这可由定时器解决。
不需要依赖于unityAPI。
服务端侧:
简化代码 => 支持多线程、指定线程。
三种定时器TickTimer (高频高精度的毫秒级定时)
支持多线程;
不依赖 Unity引擎环境,可在客户端服务器使用;
可使用外部循环驱动计时,也可使用驱动线程(内部new的)来执行;
定时回调默认是线程池工作线程运行,也就是在驱动线程中运行,也可外部自己驱动Handle运行;
内部使用线程安全字典ConcurrentDictionary来存储Task,遍历过程中Remove无影响。
调用线程线程可以使用新工作线程:
123// 使用新线程:timerThread = new Thread(new ThreadStart(StartTick));timerThread.Start();
也可以在Unity的Update中调用计时器内部 UpdateTas ...


