基础
TypeScrip的==和===的区别
① == 会进行类型转换在判断
② === 不会进行类型转换
JavaScript闭包和原理
闭包
①JavaScript闭包是指在函数内部创建的函数,它可以访问并持有创建它的父函数作用域中的变量,即使父函数已经执行完毕。闭包是JavaScript中强大而有用的概念,它可以用于创建私有变量、实现模块化和封装性,以及解决异步操作中的作用域问题。
原理
①JavaScript闭包的实现原理是利用了作用域链的特性
②在 JavaScript 中,每当创建一个函数时,都会为该函数创建一个作用域。作用域定义了变量和函数的可访问性和可见性。当函数在执行时,会创建一个执行上下文(execution context),其中包含了该函数的变量对象(variable object),该变量对象存储了函数的所有变量、函数参数和函数声明。
③作用域链是由多个执行上下文的变量对象组成的链条。在当前执行环境下访问变量时,JavaScript 引擎首先在当前执行上下文的变量对象中查找该变量。如果找不到,则沿着作用域链向上查找,逐级检查外部环境的变量对象,直到找到该变量或者到达最外层的全局作用域。
④当一个函数内部定义了另一个函数,并且内部函数引用了外部函数的变量,就形成了一个闭包。闭包就是由函数和其相关的引用环境(包括外部函数的作用域和全局作用域)组成的一个整体。
作用
①隐藏变量,避免全局污染:通过闭包,可以将变量限定在函数内部,避免其对全局作用域造成污染。外部无法直接访问闭包内部的变量,只有通过闭包提供的接口(函数)来访问和修改变量。这样可以有效地保护变量的安全性和私密性。
②读取函数内部的变量:闭包可以在函数外部访问函数内部的变量。当一个函数内部定义了另一个函数,并将内部函数作为返回值,外部代码可以通过调用返回的内部函数来访问内部函数中的变量。这种机制提供了一种方式来读取和操作函数内部的数据,使得函数可以保护和封装内部状态,同时提供一定的访问权限。
③变量不会被垃圾回收机制回收,使用不当会造成内存泄露:闭包使得内部函数持有对外部函数作用域的引用,导致外部函数的作用域及其相关变量不会被垃圾回收机制回收。如果闭包未正确处理,可能会导致一些不再需要的变量一直存在于内存中,造成内存泄露。因此,在使用闭包时需要注意及时释放不再使用的资源,避免潜在的内存泄露问题。
回收
①当不再需要使用闭包时,可以将对闭包的引用设置为 null,这样就打断了对外部作用域的引用链,使得垃圾回收机制可以回收相关资源
②如果闭包中包含了事件处理程序,确保在不需要时解绑它们。
③确保资源只在需要时存在,并在不再需要时及时销毁。这可以通过将资源定义在更小的作用域内,以便在作用域结束时自动释放。
mvc在项目中的使用
①UI管理:游戏的菜单、设置界面、商店等静态UI部分可以采用MVC模式。Model存储UI的状态和数据(如玩家的货币数量、装备信息),View负责渲染这些UI元素,Controller处理用户的点击事件,更新Model并触发View的相应变化。
②游戏状态控制:游戏的不同状态(如主菜单、游戏中、暂停、结束界面)可以通过MVC来管理。Model存储当前的游戏状态信息,View展示不同的游戏画面,Controller响应玩家操作(如开始新游戏、暂停、继续)来改变游戏状态。
③配置与设置管理:游戏中可调整的设置项(如音量、画质、控制方式)可以用MVC来设计,Model保存设置值,View展示设置界面,Controller处理用户更改设置的请求。
知识点
如何使用Cococs Creator制作一个地图编辑与寻路导航系统?
Cocos Creator 如何设计热更新系统,
Cocos Creator 如何设计自动化打包发布脚本?
如何做游戏框架,能让多人很好的协作,代码好维护?
怎么查找性能出现在哪里
节点池的基本原理是什么?什么时候释放?
基本原理
① 复用节点: 节点池预先创建一定数量的节点并存储起来。当需要一个新的节点时,不是直接创建新的实例,而是从池中取出一个已存在的闲置节点,重置其状态后重新使用。
② 减少开销: 通过复用,避免了频繁的内存分配和释放操作,降低了CPU和内存的使用峰值,减少了垃圾回收的频率和耗时,从而提升了游戏运行的流畅度。
③ 生命周期管理: 节点在不再需要时,不直接销毁,而是被送回节点池中,保持活跃状态,等待下一次复用。
释放
① 应用结束: 当整个应用程序或游戏即将关闭时,释放节点池可以帮助清理资源,防止内存泄漏。
② 长时间不使用: 如果某个功能模块长时间不会被再次触发使用,其对应的节点池可以被释放以回收资源。
③ 重大场景转换: 在进行大规模场景转换时,旧场景相关的节点池可以被释放,为新场景腾出资源空间。
spine、龙骨、序列帧动画的优缺点
Spine
优点
① 高效: 使用骨骼动画技术,通过控制骨骼来驱动角色动画,内存占用相对较小。
② 灵活: 支持复杂的动画混合、权重分配、 IK (反向动力学) 控制,便于创建流畅、自然的动作。
③ 物理系统: 内置物理引擎,可实现布料、绳索等自然运动效果。
④ Cocos Creator有成熟的Spine插件,方便导入和使用。
缺点
① 学习成本: 相比序列帧动画,Spine的编辑器和工作流程需要一定时间去熟悉。
② 授权费用: Spine是一款商业软件,虽然有免费试用版,但用于商业项目需要购买许可证。
DragonBones(龙骨)
优点
① 国产化: 针对中国开发者优化,中文界面友好,社区支持较好。
② 功能丰富: 支持骨骼动画、Mesh动画、序列帧动画等多种形式,灵活性高。
③ 兼容性: 跨平台能力强,与Cocos Creator整合良好。
④ 免费: 提供免费版本,适合预算有限的项目。
缺点
① 性能: 相比Spine,在复杂动画处理上可能稍逊一筹。
② 高级特性: 高级功能相比Spine可能不够强大,如物理模拟。
序列帧动画
优点
① 简单直观: 制作和理解都非常直接,适合快速原型开发或简单动画。
② 高质量: 每一帧都是独立图像,可以保证动画的高质量和细节。
缺点
① 资源消耗: 占用存储空间大,对于长动画或高分辨率资源尤为明显。
② 效率问题: 大量序列帧会增加内存使用,影响游戏性能,特别是在移动设备上。
③ 维护困难: 动画修改或调整较为繁琐,不如骨骼动画灵活。
昼夜系统怎么实现
① 自定义shader的全局变量,改变全局变量整体切换状态
② 遍历场景所有的物体,修改他们的颜色或贴图等信息
a星寻路优化
常规的a星星路算法,每次寻路后都需要重置使用过的格子数据,
① 格子加一个次数之类的字段,每次使用都递增,进行判断是否与本地的使用次数一致来判断是否使用过
a星寻路是最优路径吗
动态图集的好坏
优点
① 减少drawcall:它能在项目运行时动态地将贴图合并到一张大贴图中。
② 灵活性: 能够更好地适应游戏内容的变化,如角色换装、UI变化等,无需重新打包游戏即可更新资源。
缺点
① 性能开销:动态合图过程会引入额外的CPU和GPU负载,可能影响到游戏的运行效率。
② 增加内存:内存中多出了一份合并的图集内存
③ 释放有问题:动态合并后的图集在资源释放后不能有效的释放,可能因为别的地方在使用导致释放不成功甚至找不到释放的机会
④ 下载增加:单图变多了,导致客户端的下载资源次数大增
ai使用状态机还是行为树好
状态机(State Machine)
状态机通过定义一系列状态(States)、转换(Transitions)及触发条件来表示对象的行为模式。每个状态代表一种行为模式,当满足特定条件时,状态机从一个状态转移到另一个状态。
优点
① 简单直观:易于理解和实现,特别适合有限且明确的状态变化场景。
② 逻辑清晰:状态和转换关系明确,便于调试和维护。
③ 资源消耗较低:相比行为树,在简单场景下,状态机的运行开销较小。
缺点
① 状态爆炸:状态数量增多时,状态间转换复杂度急剧上升,管理困难。
② 难以表达复杂逻辑:对于需要同时处理多个并发行为或依赖上下文决策的情况,状态机表达能力受限。
行为树(Behavior Tree)
行为树是一种基于树状结构的编程模型,用于描述和控制复杂行为。它由叶子节点(执行具体动作)、分支节点(条件判断)和控制节点(循环、选择等)组成,自上而下评估节点直到找到可执行的动作。
叶子节点(Leaf Nodes)
① Action Nodes: 直接执行某种具体操作或行为的节点,如移动、攻击、播放音效等。它们是行为树的基本单元,没有子节点。
装饰器节点(Decorator Nodes)
① Inverter: 改变其子节点的成功/失败状态,即如果子节点成功,则装饰器使其失败;反之亦然。
② Repeat: 控制其子节点重复执行指定次数或无限循环。
③ Until Failure/SUCCESS: 其子节点执行,直到子节点失败/成功为止。
④ Timeout: 为子节点执行设定时间限制,超时则停止执行。
⑤ Probability: 以一定概率执行或忽略其子节点。
控制节点(Control Nodes)
① Sequence: 顺序执行子节点,直到遇到失败的节点。所有前置节点成功后,才会执行下一个节点。
② Selector: 选择性执行,从左至右尝试子节点,一旦有任意子节点成功,则整个Selector成功,后续节点不再执行。
③ Parallel: 并行执行子节点,根据设置的不同策略(如全部成功、一个成功、一个失败等)来决定整个Parallel节点的状态。
④ Random: 随机选择一个子节点执行。
优点
① 易于表达复杂逻辑:通过分支和控制节点,能高效处理并行、选择、循环等复杂行为逻辑。
② 可读性和可维护性强:树状结构清晰展现决策过程,便于理解和修改。
③ 灵活性高:易于添加新行为或修改现有行为,不影响整体结构。
缺点
① 实现复杂度较高:相较于状态机,构建和维护行为树需要更多前期设计工作。
② 资源消耗:在大规模或深度复杂的行为树中,评估开销可能较大。
选择
状态机适合于状态变化相对简单、明确的场景,易于快速开发和维护。
行为树则在处理复杂逻辑、多条件分支和行为灵活性方面表现更优,尤其适合于AI行为设计。
一个完整的游戏的框架有哪些部分
客户端与服务器怎么确认通信
客户端检测断线和进行重连
项目
建筑项目的建筑应该怎么摆放
优化
如何优化包体体积?
1. 资源优化
① 压缩纹理: 使用TexturePacker或Cocos内部的texture compression工具,对图片进行无损或有损压缩,选择合适的纹理格式(如ETC2, PVRTC等),针对不同平台优化。
② 音频处理: 转换音频文件为压缩格式(如.mp3或.ogg),并根据需要调整音质,减少音频文件大小。
③ 剔除无用资源: 审查项目,移除未使用的图片、音频、字体等资源。
④ Atlas合并: 将小图合并到大图集(Sprite Atlas)中,减少纹理切换,降低内存占用和加载时间。
2. 代码及脚本优化
① 精简代码: 删除无用的代码和注释,避免冗余逻辑。
② 使用模块化: 通过合理划分代码模块,按需加载,减少初始包的大小。
③ 利用Cocos Creator的Bundle系统: 分包加载,将不常用资源或大体积资源打包到扩展包中,首屏只加载必要的资源。
3. 引擎及第三方库
① 移除未使用的Cocos Creator模块: 在构建配置中关闭不需要的功能模块。
② 优化第三方库: 如果使用了第三方库,确保只引入需要的部分,考虑是否有轻量替代方案。
4. 构建设置优化
① 开启Release模式构建: Release模式会自动进行一系列优化,包括代码压缩、资源压缩等。
② 利用资源加密和压缩: 在构建时启用资源加密和LZMA压缩,进一步减少体积并保护资源。
如何做资源管理?
1. 组织目录结构
① 明确划分资源目录,例如,将图像资源放在assets/images,音频资源放在assets/audio等。
② 为每个场景或功能创建独立的子目录,存放相关的预制体、脚本和资源配置文件。
2. 使用Asset Management System(资源管理系统)
① 利用Cocos Creator的资源面板管理所有资源,支持导入、导出、重命名和删除操作。
② 确保资源引用路径正确无误,推荐使用相对路径以保持项目的可移植性。
3. Asset Bundle(资源包)的运用
① 通过Asset Bundle对资源进行分组,实现按需加载,减少首次启动加载时间。
② 在project.json中配置Asset Bundle的打包规则,或使用Cocos Creator的界面工具进行设置。
③ 构建时,Cocos Creator会根据配置自动将资源打包成指定的Bundle。
4. 资源的懒加载与预加载
① 利用cc.loader.load或cc.assetManager.loadAsset等API实现资源的懒加载,即在需要时才加载资源。
② 对关键资源或预期玩家即将需要的资源进行预加载,保证流畅体验。
Label的原理与如何节约Drawcall?
原理
1. 文本测量与排版
① Label首先会测量文本的宽度和高度,这依赖于字体大小、样式以及文本内容。
② 根据文本的对齐方式和行距等属性进行排版布局。
2. 创建纹理(Texture)
① 排版完成后,引擎会为文本生成纹理。如果是动态文本,可能会在每次文本变化时重新生成。
② 对于非动态文本或使用位图字体的情况,可能预先渲染好所有字符到一张大图上,然后根据需要截取显示。
3. 绘制到渲染队列
① 文本的纹理随后被添加到渲染队列中,等待GPU将其渲染到屏幕上。
② 每个独立的绘制指令通常对应一个Draw Call,过多的Draw Call会增加CPU和GPU的开销。
优化
1. 合批绘制(Batching)
① 尽量使具有相同材质和纹理属性的物体(包括Label)能够一起渲染,这样引擎可以将它们合并为一个Draw Call。
② 对于多个连续的Label,如果它们使用相同的字体和颜色,尝试使用一个大的Node容器包裹,以促进合批。
2. Atlas(纹理集)的使用
① 如果使用的是位图字体,确保所有字符位于同一个或少数几个Atlas中,减少切换纹理的次数。
② 对于多色或复杂样式的文本,尽管难以直接生成Atlas,但合理设计UI布局减少纹理切换也是有益的。
3. 减少动态标签的使用
① 动态更新的Label可能会频繁触发重绘和纹理更新,尽量减少这类变化或采用预渲染静态文本图片作为替代。
4. 字体与材质优化
① 减少字体样式和大小的种类使用,每种不同的字体或大小都会生成不同的纹理,进而增加Draw Call。
② 对于不常变化的文本,可以考虑将其渲染为图片作为背景或静态元素,避免作为动态Label处理。
背包系统可能会需要哪些优化?
① 使用虚拟列表来优化创建的格子数量
② 优化格子的图片资源和文本,尽量放到一个图集里面
固定宽度与固定高度的底层原理是什么?引擎是如何做适配的?
固定宽度与高度的底层原理
1. 布局约束(Layout Constraint)
① 当为节点设置固定宽度或高度时,实际上是为其施加了一个布局约束条件。Cocos Creator会根据这些约束条件,在布局过程中计算节点的实际尺寸。
② 对于UI元素,这些约束可以在编辑器的UI组件属性中直接设置;对于代码创建的节点,可以通过修改节点的width和height属性来实现。
2. 渲染适配
① 设置固定尺寸后,渲染系统会在光栅化阶段根据这些尺寸来决定纹理的采样区域,从而影响到实际渲染输出的大小。
② 对于文本(Label)而言,固定尺寸可能意味着文本需要换行、裁剪或调整字体大小以适应给定的空间。
适配策略
1. 分辨率适配策略
① 固定分辨率:项目以设计时的分辨率为准,不随设备改变,可能需要配合缩放模式使用。
② 屏幕自适应:通过设置设计分辨率和适配模式(如showAll, noBorder, fixedWidth, fixedHeight等),Cocos Creator会自动计算缩放因子,使得内容可以适应不同屏幕。
③ 自定义适配脚本:开发者可以根据需要编写脚本来实现更复杂的适配逻辑,比如根据屏幕宽高比动态调整节点的尺寸或布局。
2. 节点锚点(Anchor Point)与缩放
① 锚点决定了节点变换的中心点,结合节点的缩放属性,可以灵活地实现各种适配效果,比如让元素始终相对于屏幕边缘定位或按比例缩放。
3. Canvas组件的适配设置
① Canvas组件是UI根节点,其上的适配模式设置直接影响到整个UI界面的适配行为,如是否保持宽高比、是否填充屏幕等。
图集打包有什么意义,我们一般在项目里面怎么规划图集?
意义
① 减少draw call: 图集将多个小图合并成一张大图,游戏运行时引擎只需对这张大图进行一次draw call,大大减少了GPU切换纹理的次数,提高了渲染效率。
② 内存优化: 合理的图集打包可以减少纹理的冗余,因为单个大图的边角空白区域相比于多个小图独立存储所占用的额外内存要少。
③ 提升加载速度: 少量的大图比大量小图加载更快,因为减少了文件读取的次数。
规划建议
① 按类别划分: 根据资源类型(如UI元素、角色动画、背景等)创建不同的图集,便于管理和维护。
② 尺寸与分辨率匹配: 根据目标平台和屏幕分辨率准备对应尺寸的图集,避免不必要的放大或缩小导致的质量损失。
③ 纹理大小对齐: 保证图集的尺寸是2的幂次方,这能更好地利用GPU的纹理内存。
④ 避免溢出: 留意图集的容量限制,避免因单个图集过大导致加载问题,必要时拆分成多个图集。
⑤ 使用工具辅助: 利用Cocos Creator自带的图集打包工具或第三方工具自动化生成图集,减少人工错误并提高工作效率。
2D如何做Drawcall优化?
1. 纹理集(Texture Atlas)的使用
① 将多个小纹理整合到一个大纹理图集上。这样,当渲染使用这些纹理的精灵或标签时,可以减少纹理切换,从而减少Draw Call。
② 利用Cocos Creator的打包功能自动或手动创建纹理集。
2. 合批渲染(Batching)
① 确保使用相同材质和纹理的物件尽可能一起渲染。Cocos Creator自动对符合条件的节点进行合批,但开发者需注意避免使用不同的混合模式、深度测试等导致无法合批的属性设置
3. 减少材质使用
① 减少游戏中使用的材质数量。每个独特的材质配置都会导致一个新的Draw Call。通过复用材质或调整其属性,可以有效减少Draw Call。
4. 优化节点结构
① 简化节点树,避免不必要的嵌套,减少层级深度,因为每一层都可能引入额外的Draw Call。
② 使用Container节点来组合使用相同材质的子节点,有助于引擎进行合批处理。
5. 静态与动态Batching
① 静态Batching适用于不会改变位置、旋转或缩放的节点集合。
② 动态Batching则用于那些属性会变化的节点,但需注意,频繁变动的节点可能不适合动态Batching。
6. 避免在运行时修改纹理或材质属性
① 运行时的改动可能导致已经批处理的物件分离,增加Draw Call。
7. 使用预渲染技术
① 对于复杂的静态UI元素,可以考虑将其预渲染为图片,减少运行时的Draw Call。
场景的可交互对象太多怎么优化交互
① 将对象都按区域划分,只对角色周围的区域的对象进行检测
场景的对象太多怎么优化创建
① 将对象都按区域划分,只对屏幕的区域进行创建
场景的定时对象太多怎么优化检测
① 将对象都按区域划分,只对屏幕的对象进行定时操作
② 将对象进行队列操作,每一帧只对一定数量的对象进行定时操作