个人Unity自用面经(未完)

目录标题

      • 1.在 2D 平台跳跃游戏项目中,你使用了对象池来生成和回收怪物包含阵亡的动画预制件。在对象池回收对象时,如何确保动画状态被正确重置,避免下次使用时出现异常?
      • 2.在僵尸吃脑子模拟项目中,你创建了继承于IAspect的aspect,并通过RefRW和RefRO定义访问的属性。能详细说说在实际使用中,RefRW和RefRO有什么区别吗?在什么场景下分别使用它们?
      • 3.在 2D 平台跳跃游戏项目中,你使用对象池来生成和回收怪物预制件。在对象池的设计与实现过程中,如何确定对象池的初始容量和最大容量呢?
      • 4.在 3D 回合制策略游戏中,你使用了状态机实现敌人的 AI,并且 AI 的行为带权。在不同情况下,不同动作的权值是如何确定的呢?
      • 5.在僵尸吃脑子模拟项目里运用了 ECS 架构,你也清楚 ECS 架构适合并行计算。那在实际开发中,是怎样去利用 ECS 架构实现并行计算,进而提升游戏性能的呢?
      • 6.在 2D 平台跳跃游戏项目中,你使用了 TileMap 瓦砾地图系统构建地图。在使用过程中,如何实现地图的动态加载与卸载,以优化游戏内存占用?
      • 7.在 3D 回合制策略游戏中,你使用了状态机来管理角色的行为状态。当角色的状态比较复杂,存在多种状态之间的相互转换,并且有一些状态还存在子状态时,你是如何设计状态机以确保逻辑清晰,易于维护和扩展的呢?
      • 8.在僵尸吃脑子模拟项目里,你运用了 ECS 架构。当游戏场景中僵尸数量极多,比如上万只时,可能会面临性能瓶颈。你打算采取哪些策略来优化 ECS 架构下大规模僵尸的性能表现呢?
      • 9.在你参与的 “3D 回合制策略游戏” 项目里,你使用了状态机实现敌人的 AI 且行为带权。在游戏运行过程中,如果玩家做出了一个游戏设计师未曾预料到的操作,导致敌人 AI 的权值计算出现异常,你会如何排查和解决这个问题?
      • 10.在 “僵尸吃脑子模拟” 项目里,你使用了 ECS 架构并创建了多个继承于ISystem的系统。当多个系统之间存在数据依赖关系时,你是如何管理和协调这些依赖关系,以确保系统执行顺序正确且数据一致性的?

豆包 中等偏上—优秀 评价

1.在 2D 平台跳跃游戏项目中,你使用了对象池来生成和回收怪物包含阵亡的动画预制件。在对象池回收对象时,如何确保动画状态被正确重置,避免下次使用时出现异常?

答:我在泛型对象池定义之初就设置了一个私有的抽象Reset函数,对于后续继承它的对象池必须要实现它,然后在对外公开的回收预制体函数ReturnToPool中调用这个Reset函数,这样来保证他们状态复原,避免异常。比如我在Reset中重新设定这个预制体的动画机中所有的转换条件参数复原,Transform属性复原,并且在Reset函数里使用了Try和catch来捕获重置失败的预制体。

2.在僵尸吃脑子模拟项目中,你创建了继承于IAspect的aspect,并通过RefRW和RefRO定义访问的属性。能详细说说在实际使用中,RefRW和RefRO有什么区别吗?在什么场景下分别使用它们?

答:Ref RW对应的就是ref关键字, read and write,RO 对应的就是 read only,意思就是前者是一个可读写的属性,后者是一个只可读的属性,这要根据需求来用,比如我项目里写了僵尸的行走速度,我不希望他改变所以我把aspect里面对僵尸速度属性的引用设置为只读的意味着我不希望改变他,比如项目中墓碑的Transform属性,我希望每个墓碑生成的位置角度是不一样的所以我设置他为可读写的。

3.在 2D 平台跳跃游戏项目中,你使用对象池来生成和回收怪物预制件。在对象池的设计与实现过程中,如何确定对象池的初始容量和最大容量呢?

答:初步预估对象池容量
统计游戏数据:在设计阶段,仔细分析游戏场景和玩法,统计出游戏中不同类型对象(如怪物、子弹、道具等)同时出现的最大数量和常见数量。例如在一个射击游戏中,统计一场战斗里最多会同时存在多少颗子弹,一般情况下又会有多少颗子弹。
考虑扩展系数:为了应对游戏中可能出现的特殊情况,如玩家触发特殊技能、进入特殊关卡等导致对象数量突然增加,需要在最大数量的基础上乘以一个扩展系数(通常为 1.2 - 1.5),以此确定对象池的最大容量。初始容量可以设置为常见数量的均值。
游戏测试阶段的性能监测
选择合适的监测工具:在 Unity 中,可以使用内置的 Profiler 工具来监测对象池的使用情况,它能提供详细的内存使用信息、对象创建和销毁的频率等数据。
关注关键指标:重点关注对象池的扩容次数、闲置对象数量、对象创建和销毁的时间等指标。如果对象池频繁扩容,说明初始容量设置过小;如果大部分时间对象池都有大量闲置对象,说明最大容量设置过大。
根据监测数据进行动态调整
增大初始容量:如果发现对象池频繁扩容,导致游戏性能下降,可以适当增大初始容量。例如,将初始容量增加 20% - 30%,然后再次进行测试,观察性能是否有所改善。
减小最大容量:如果对象池大部分时间都有大量闲置对象,占用了过多的内存,可以考虑减小最大容量。每次减小的幅度不宜过大,建议在 10% - 20% 之间,然后重新测试,确保不会影响游戏的正常运行。

4.在 3D 回合制策略游戏中,你使用了状态机实现敌人的 AI,并且 AI 的行为带权。在不同情况下,不同动作的权值是如何确定的呢?

答:
我的项目中敌人和友军都是继承自player这个父类的,所以他们能使用的动作是一样的,对于敌人他有移动,射击,手雷。3个动作,我把移动的权值设置成10 - 可攻击范围内敌人的数量 * 3,这样如果范围内有敌人那么他们就不更容易去移动,对于射击权值就是 8,手雷权值是8 + (可攻击范围内敌人的数量 - 1) * 2,于是在有敌人且只有一个的情况下会使用射击,有敌人且有多个的情况下会使用手雷,没有敌人的情况下会使用移动,同时攻击还跟敌人剩余的血量有关,对于移动还要计算每个可到达的地点的权值不同于之前的权值系统,它会优先选择更多可接触敌人的地点到达,这些其实都只和设计者的需求来设定。

5.在僵尸吃脑子模拟项目里运用了 ECS 架构,你也清楚 ECS 架构适合并行计算。那在实际开发中,是怎样去利用 ECS 架构实现并行计算,进而提升游戏性能的呢?

答:
首先建立一个Job : IEntityJob,把这个job需要用到的所有东西比如EntityCommandBuffer.ParallelWriter如果不是并发的那么不用使用ParallelWriter(ecb用于更改实体组件,生成实体等)可以暂存某些指令等到某个时间点一起执行以免出现并发的线程争夺和数据错读问题,还有一些数据,或者实体。然后实现这个Job的Execute方法,如有需要还要提供sortKey这个参数,在调用这个作业的时候会自动检索含有Execute带有的组件的实体,并且在运行的时候给他发配一个sortKey。最后只需要在调用这个任务的system中new这个job,然后给他提供所需要的参数比如使用SystemAPI.Getsingleton,GetComponent等等,用来new这个job并且调用它,需要注意的是在EntityCommandBufferSystem创建EntityCommandBuffer的时候要AsParallelWriter否则会报错,这里state作用是在非托管世界申请一个命令缓冲区并且视为并发写者来缓存并执行并发的命令,因为要并发执行,最后在new的尾处.ScheduleParallel()进行并发执行任务。

避免在一个任务中修改另一个任务需要读取的数据

6.在 2D 平台跳跃游戏项目中,你使用了 TileMap 瓦砾地图系统构建地图。在使用过程中,如何实现地图的动态加载与卸载,以优化游戏内存占用?

答:
地图分块处理
划分地图区域:把整个游戏地图按照一定规则划分成多个小的地图块,比如以正方形或矩形区域为单位。每个地图块都可以独立加载和卸载。例如,在一个大型的 2D 平台跳跃游戏世界中,可以将其划分为多个 10×10 个 Tile 的地图块。
确定加载范围:依据玩家当前所在的位置和视野范围,确定需要加载的地图块。一般来说,除了玩家当前所在的地图块,还需要加载其周围的一些地图块,以保证玩家移动时地图的连贯性。比如,玩家在一个地图块中,那么可以同时加载其上下左右以及四个对角方向相邻的地图块。
实现动态加载与卸载机制
加载逻辑:当玩家接近某个未加载的地图块时,触发加载操作。可以使用 Unity 的场景加载 API(如 SceneManager.LoadSceneAsync )来异步加载地图块。异步加载不会阻塞主线程,能保证游戏的流畅性。在加载时,还可以显示一个加载提示,提升用户体验。
卸载逻辑:当某个地图块远离玩家的视野范围,并且在一段时间内不会被玩家访问到时,触发卸载操作。使用 SceneManager.UnloadSceneAsync 来异步卸载地图块,释放内存。
缓存机制
临时缓存:为了避免频繁的加载和卸载操作,可以设置一个缓存区,将最近使用过的地图块暂时保留在内存中。当玩家再次需要访问这些地图块时,可以直接从缓存中获取,而不需要重新加载。
缓存淘汰策略:由于缓存区的容量是有限的,当缓存区达到最大容量时,就需要移除一些数据来为新的数据腾出空间。常见的淘汰策略有先进先出(FIFO)、最近最少使用(LRU)等。

7.在 3D 回合制策略游戏中,你使用了状态机来管理角色的行为状态。当角色的状态比较复杂,存在多种状态之间的相互转换,并且有一些状态还存在子状态时,你是如何设计状态机以确保逻辑清晰,易于维护和扩展的呢?

答:我使用状态机系统来维护我的状态,状态机内部只有 state currentstate,两个公开的方法public void changeState(State stateName)和public void Initial,然后每个state都继承自Istate必须实现Istate里的抽象方法,Enter,Exit,Update,然后在FSM类里创建一个枚举类State用于枚举每个状态的名字,和一个字典关联 State state 和 Istate theState,然后FSM里包含对状态机的声明,并且有AddState方法用于往字典里添加状态,在声明fsm变量的脚本中的Onupdate调用currenState.Update,这样就可以确保状态之间的模块化和解耦而且扩展方便,维护方便。子状态也同样可以这样使用和添加,确保同一个时间只有一个状态在执行。

8.在僵尸吃脑子模拟项目里,你运用了 ECS 架构。当游戏场景中僵尸数量极多,比如上万只时,可能会面临性能瓶颈。你打算采取哪些策略来优化 ECS 架构下大规模僵尸的性能表现呢?

答:
空间分区与裁剪:
将游戏场景划分为多个空间区域,比如使用**四叉树(2D 场景)或八叉树(3D 场景)**结构。为每个僵尸分配所属的区域,当进行渲染、碰撞检测或 AI 计算时,只处理玩家所在区域及相邻区域内的僵尸。例如,玩家在一个特定房间内,只计算该房间及其相邻房间内的僵尸,避免对整个场景中所有僵尸进行不必要的操作。
对于视野范围外的僵尸,不进行渲染和复杂的 AI 计算,只保留基本的位置追踪等轻量级信息,当僵尸进入玩家视野范围时再进行完整的处理。
批处理与合并:
在渲染方面,将多个僵尸的渲染数据合并成一个批次进行绘制。利用 GPU 的批处理功能,减少 Draw Call 的数量。比如,可以将相同类型、相同材质的僵尸的顶点数据、索引数据等合并,一次性提交给 GPU 进行渲染,提高渲染效率。
对于僵尸的物理碰撞检测,可以将多个僵尸分组,对组内的僵尸进行统一的碰撞检测处理,而不是逐个僵尸进行检测,减少碰撞检测的计算量。
优化组件与数据结构:
确保僵尸的组件设计简洁,只包含必要的数据和功能。避免在组件中存储过多冗余或不常用的数据。例如,如果僵尸的某个属性只在特定情况下使用,可以考虑在需要时动态获取,而不是一直存储在组件中。
选择合适的数据结构来存储僵尸相关的数据。例如,使用数组而不是链表来存储僵尸列表,因为数组在随机访问和遍历方面通常具有更好的性能。同时,可以对数据进行预排序,以便在进行某些计算(如距离排序)时提高效率。
并行计算与多线程优化:
充分利用 ECS 架构的并行计算优势,将僵尸的 AI 计算、物理模拟等任务拆分成多个并行任务,利用多核 CPU 进行加速。例如,为每个僵尸的 AI 行为计算创建一个 Job,通过 ScheduleParallel() 方法并行执行这些 Job。
注意避免多线程之间的资源竞争和数据冲突。合理使用锁机制或无锁数据结构来保护共享资源。例如,对于僵尸的生命值等共享数据的修改,使用线程安全的方式进行操作。
LOD(Level of Detail)技术:
为僵尸设置不同的细节层次模型。当僵尸距离玩家较远时,使用低细节模型,减少模型的顶点数量和纹理复杂度,降低渲染成本。当僵尸靠近玩家时,切换到高细节模型,提供更好的视觉效果。
同样,对于僵尸的 AI 行为也可以设置不同的细节层次。例如,远处的僵尸可以采用简单的巡逻行为,而近处的僵尸则执行更复杂的追逐和攻击行为。

9.在你参与的 “3D 回合制策略游戏” 项目里,你使用了状态机实现敌人的 AI 且行为带权。在游戏运行过程中,如果玩家做出了一个游戏设计师未曾预料到的操作,导致敌人 AI 的权值计算出现异常,你会如何排查和解决这个问题?

答:
我应该会在敌人AI采取行动的使用使用Try和Catch去捕捉错误,如果没有捕捉到说明没有语法上或者访问越界等的问题而是逻辑上的问题,那么如果是后者只能去跟随敌人状态机进行一步一步的调试,如果它引起了空间或者性能问题那么可以使用性能检测工具profile来检测哪个函数或者哪个部分出现了内存性能异常。

10.在 “僵尸吃脑子模拟” 项目里,你使用了 ECS 架构并创建了多个继承于ISystem的系统。当多个系统之间存在数据依赖关系时,你是如何管理和协调这些依赖关系,以确保系统执行顺序正确且数据一致性的?

答:
在ECS架构中不像Unity自带一个脚本执行顺序的调整功能。在ECS架构中你运行项目的时候如果先后顺序有问题那么大概率会报错并且无法运行,届时你可以到Windows->Entities->System中查看每个系统的执行时间,但是这里不像unity原生开发框架可以直接拖动,你必须到每个系统中使用UpdateInGroup(typeof(InitializationSystemGroup))此处可以替换为很多ECS内定好的系统组或者UpdateAfter,Before某个System来调整它们的执行顺序。通过这个动作来保证依赖的关系不会出现问题,比如我项目中僵尸生成系统就定义了[UpdateAftertypedef(TombStoneSpawnSystem)]因为我僵尸生成的位置依赖于墓碑生成的位置。
避免循环引用导致相互依赖,可以设置中间层来接收相互依赖之间的数据避免直接依赖来解耦,或者调整循环依赖之间的关系,让其中一个不再引用环中的数据。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计网】ICMP、IP、Ethernet PDU之间的封装关系

TCP/IP体系结构 应用层RIP、OSPF、FTP运输层TCP、UDP网际层IP、ARP、ICMP网络接口层底层协议(Ethernet) 数据链路层 Ethernet报文格式 6Byte6Byte2Byte46~1500Byte4Byte目的MAC地址源MAC地址类型/长度数据FCS 其中,类型 / 长度值小于 1536…

前端取经路——入门取经:初出师门的九个CSS修行

大家好,我是老十三,一名前端开发工程师。CSS就像前端修行路上的第一道关卡,看似简单,实则暗藏玄机。在今天的文章中,我将带你一起应对九大CSS难题,从Flexbox布局到响应式设计,从选择器优先级到B…

n8n工作流自动化平台的实操:Cannot find module ‘iconv-lite‘

解决问题: 1.在可视化界面,执行const iconv require(iconv-lite);,报Cannot find module iconv-lite [line 2]错误; 查看module的路径 进入docker容器 #docker exec -it n8n /bin/sh 构建一个test.js,并写入如何代码 vi tes…

如何在 PowerEdge 服务器上设置 NIC 分组

以下文章提供了有关 Windows、VMware 和 Linux 中的 NIC 分组的信息。 什么是网络适配器分组?设置 NIC 分组 Windows设置 NIC 分组 VMware设置 NIC 分组 Linux 什么是网络适配器分组(绑定)? 网络适配器分组是一个术语&#xff0…

【Java ee初阶】多线程(5)

一、wait 和 notify wait notify 是两个用来协调线程执行顺序的关键字,用来避免“线程饿死”的情况。 wait 和 notify 其实都是 Object 这个类的方法,而 Object这个类是所有类的“祖宗类”,也就是说明,任何一个类,都…

基于k8s的Jenkins CI/CD平台部署实践(二):流水线构建与自动部署全流程

基于k8s的Jenkins CI/CD平台部署实践(二):流水线构建与自动部署全流程 文章目录 基于k8s的Jenkins CI/CD平台部署实践(二):流水线构建与自动部署全流程一、Jenkins简介二、系统架构与环境说明1. 系统架构2.…

《Windows 环境下 Qt C++ 项目升级 GCC 版本的完整指南》

Windows 环境下 Qt C++ 项目升级 GCC 版本的完整指南 在 Windows 系统中升级 Qt C++ 项目的 GCC 版本需要同时考虑 Qt 工具链、MinGW 环境以及项目配置的调整。以下是详细的升级步骤和注意事项: 一、升级前的准备工作 1. 确认当前环境 检查 Qt 版本(建议使用 Qt 5.15+ 以获…

【coze】故事卡片(图片、音频、文字)

【coze】故事卡片(图片、音频、文字) 1、创建智能体2、添加人设与回复逻辑3、添加工作流(1)创建工作流(2)添加大模型节点(3)添加提示词优化节点(4)添加豆包图…

Maven 依赖发布与仓库治理

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

虚拟现实视频播放器 2.6.1 | 支持多种VR格式,提供沉浸式观看体验的媒体播放器

虚拟现实媒体播放器是一款专为在智能手机上播放VR(虚拟现实)照片和视频而设计的应用程序。它支持多种格式的影像内容,包括360和180等距矩形柱面、标准镜头和鱼眼镜头拍摄的照片和视频,并且兼容3D立体并排、上/下以及收缩媒体格式。…

ts axios中报 Property ‘code‘ does not exist on type ‘AxiosResponse<any, any>‘

ts语法有严格的格式,如果我们在处理响应数据时,出现了axios响应中非默认字段,就会出现标题那样的警告,我们可以通过创建axios.dt.ts解决这个问题 下面是我在开发中遇到的警告,code并不是axios默认返回的字段&#xff0…

tinyrenderer笔记(Shadow Mapping)

tinyrenderer个人代码仓库:tinyrenderer个人练习代码 前言 阴影是光线被阻挡的结果;当光源的光线由于其他物体的阻挡而无法到达物体表面时,该物体就会产生阴影。阴影能使场景看起来更真实,并让观察者获得物体之间的空间位置关系。…

debian中笔记本的省电选择auto-cpufreq

在reddit中,看评论区出现这个软件,于是打算尝试一下,应该能对不使用电源时笔记本的省电起到一定的作用。 https://github.com/AdnanHodzic/auto-cpufreq?tabreadme-ov-file#why-do-i-need-auto-cpufreq 作用 One of the problems with Linux…

Windows 查看电脑是否插拔过U盘

1、按 “WinR” 组合键打开 “运行” 对话框,输入 “regedit” 并回车,打开注册表编辑器。 2、依次展开HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR注册表项,这里记录了所有已连接过的 USB 设备信息,包括 U 盘&am…

426、N叉树的层序遍历

输入检查: if not root:return [] 如果根节点为空,直接返回空列表 初始化: result [] queue collections.deque([root]) result用于存储最终结果queue初始化包含根节点,使用双端队列实现 主循环: while queue:leve…

【ES】Elasticsearch字段映射冲突问题分析与解决

在使用Elasticsearch作为搜索引擎时,经常会遇到一些映射(Mapping)相关的问题。本文将深入分析字段映射冲突问题,并通过原生的Elasticsearch API请求来复现和解决这个问题。 问题描述 在实际项目中,我们遇到以下错误: Transport…

小红书怎么看自己ip地址?小红书更改ip地址教学

在社交媒体高度透明的今天,小红书等平台公开用户IP属地的功能引发了广泛讨论。无论是出于隐私保护的担忧,还是因需要切换属地,许多用户都迫切想知道:能否通过手动修改“伪装”所在地? 事实上,IP属地可能影…

深入理解 Java 观察者模式:原理、实现与应用

在软件开发领域,设计模式堪称开发者智慧的凝练结晶,它们为解决各类常见编程难题提供了行之有效的方案。观察者模式(Observer Pattern)作为行为型设计模式的重要一员,在处理对象间依赖关系与事件通知方面表现卓越。本文…

网络原理 TCP/IP

1.应用层 1.1自定义协议 客户端和服务器之间往往进行交互的是“结构化”数据,网络传输的数据是“字符串”“二进制bit流”,约定协议的过程就是把结构化”数据转成“字符串”或“二进制bit流”的过程. 序列化:把结构化”数据转成“字符串”…

2025年5月HCIP题库(带解析)

某个ACL规则如下:则下列哪些IP地址可以被permit规则匹配: rule 5 permit ip source 10.0.2.0 0.0.254.255 A、10.0.4.5 B、10.0.5.6 C、10.0.6.7 D、10.0.2.1 试题答案:A;C;D 试题解析: 10.0.2.000001010.00000000.00000010.0000000…