首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
SAAS
ToB门户
了解全球最新的ToB事件
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
微博
Follow
记录
Doing
博客
Blog
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
排行榜
Ranklist
相册
Album
应用中心
qidao123.com ToB IT社区-企服评测·应用市场
»
论坛
›
数据库
›
SQL-Server
›
游戏引擎学习第54天
返回列表
发新帖
游戏引擎学习第54天
[复制链接]
发表于 2025-12-3 19:09:00
|
显示全部楼层
|
阅读模式
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
×
堆栈
: https://gitee.com/mrxiao_com/2d_game
回顾
我们现在正专注于在游戏天下中放置小实体来代表全部的墙。这些实体围绕着天下的每个边沿。我们有活泼的实体,这些实体位于玩家的视野中,频仍更新,而那些离玩家较远的实体则以较低的频率运行,以镌汰盘算资源斲丧。我们必要开始优化我们的碰撞检测体系,以便处置惩罚这些实体更高效地。比方,纵然它们在屏幕外,其他实体也会与它们碰撞。我们正在渐渐实现这个体系,只管镌汰错误,确保游戏体验流畅。
移除休眠实体的来由
我们开始制作体系,以便当摄像机移动时,我们可以或许动态地调解实体residence的位置。我们移除了不再必要的高频实体。与此同时,低频实体不再包罗在我们模子中,由于它们没有须要的更新频率。我们现在只专注于高频实体,并删除全部休眠实体,简化了我们的实体管理体系。我们以为,这种调解可以或许镌汰复杂性,并使我们的体系更加高效。团体上,我们做出的改变使得游戏逻辑更加直观且不必要多余的管理。
关于解耦低实体和高实体数组的想法
我们现在有了一种添加实体的方法,这些实体可以从低状态开始,然后移动到高状态。这意味着大多数实体在天下天生时都是低状态的,而只有少数实体才会转移到高状态。这种分类方法资助管理实体的运动和模仿,从而进步服从和
性能
。
我们开始思量怎样更好地分别实体集。一个风趣的思绪是,高实体集只包罗离玩家迩来的有限数量的实体,而低实体则包罗更多的阔别玩家的实体。这种方式有助于将实体按必要移动到高集,从而优化
性能
。
别的,我们讨论了在高实体中是否包罗低实体的题目。一种方法是复制低实体数据到高实体中,但这大概会增长内存开销。因此,前向和后向指针的方式大概更为符合,即纪录低实体是否在高实体中,从而制止太过复制和不须要的内存访问。
总体而言,我们在思考怎样管理实体时,正在探求一种既能保持游戏
性能
,又能简化实体管理的方法。
默认情况下只在低实体列表中创建对象
我们现在只专注于在低频理想情况中创造一些东西,并开始处置惩罚列表中的项目。我们会有一个金融列表,包罗高频和低频账户。根本上,我们保持低状态,而且只把低频的数据提拔到高频时才使用。为了防止错误,我们必要确保全部索引都是正确的范例。我们应该确保
代码
路径总是有效,制止在运行时引入错误。如果高频表的空间不敷,我们可以降级全部数据至低频。终极,全部操纵的目的是将实体从低频提拔至高频,确保
代码
的稳固性和正确性。
关于高实体数组内存的备注
我们在
代码
中处置惩罚了将实体从低频状态转换为高频状态的题目。具体来说:
映射到相机空间
我们起首将实体的位置从天下坐标系中的瓷砖空间映射到相机空间。通过盘算瓷砖空间与相机位置的差值,我们可以将实体在天下坐标系的位置转换为相机坐标系中的位置。
性能限定
我们必要为高频实体设置一个固定的性能预算,不能无穷定地增长高频实体的数量。高频实体的数量受每帧CPU可处置惩罚的时间限定,意味着这个列表必须是有限的。我们将确保这个限定可以或许满意及时处置惩罚的需求。
高频实体的管理
转换为高频实体
:
如果实体没有高频索引,我们将其添加到高频实体列表中,并纪录其新位置、速率和其他属性。同时,在低频实体数据中生存其对应的高频索引。
处置惩罚高频实体列表
:
高频实体列表是有限的,而且用于管理当前运动、靠近玩家的实体。我们根据性能预算决定可以或许容纳多少个高频实体。
处置惩罚低频转换
如果必要将实体从高频状态规复为低频状态,我们会将其从高频列表中移除:
列表管理
:
如果高频实体位于列表的末端,我们只需将高频实体数量减一即可。
如果实体不在列表的末端,我们必要将列表中的末了一个实体移动到被移除的实体位置,以补充空缺,确保列表连续。
性能优化
:
为了包管常数时间的操纵,我们思量直接标志被移除的实体,而不留下空缺。我们也大概使用一个“空闲列表”(free list)来管理被接纳的位置。
处置惩罚逻辑
我们在编写逻辑时特殊关注以下几点:
确保实体状态转换操纵是高效的,制止在高频状态管理中出现性能瓶颈。
确保列表操纵不会留下空缺,从而导致处置惩罚时间增长。
将来的内存管理优化将重要围绕怎样更高效地维护高频实体列表以及内存接纳题目。
团体计谋
高频实体的管理:固定巨细的列表,用于生存当前必要高频处置惩罚的实体。
低频实体:重要用于
存储
不必要及时处置惩罚的实体,节省性能开销。
性能预算:根据CPU时间限定,动态调解高频实体数量,确保游戏性能稳固。
终极,我们必要通过及时测试确定高频实体的具体上限,以及最优的列表管理计谋。
思考使用空闲列表来代替压缩数组
我们在处置惩罚实体时,存在一个固定的预算限定,可以或许处置惩罚的实体数量是有限的。比方,如果我们最多只能处置惩罚256个实体,那么在迭代这些实体时,我们可以跳过那些被标志为“已处置惩罚”的实体。纵然跳过它们会造成肯定的性能丧失,但我们并不关心,由于只要全部实体都已填满,我们就必须在预算内完成处置惩罚。
一种公道的方案是维护一个
空闲列表
,用来追踪已经被移除或不再活泼的实体。当一个高频实体被移除时,我们将它的索引添加到空闲列表中。如许,当必要分配一个新的位置时,只需从空闲列表中取出一个索引即可。这种方法简朴明白,且符合现实需求。
别的一种方法是在移除某个实体时,将数组中的末了一个实体移动到当前被移除的位置,然后将实体计数减1。这种方法可以确保数组在内存中保持
紧凑
,制止留下“空洞”。但这种操纵必要实行一次实体数据的复制,而且必要更新指向被移动实体的引用,确保全部引用都正确指向新位置。
两种方法各有优缺点:
使用
空闲列表
:无需移动数据,操纵简朴,得就地景中不必要数组紧凑的情况,由于我们已经限定了数组巨细,确保了处置惩罚本领可以或许覆盖最大需求。
移动数组元素:保持数组的紧凑性,但必要举行数据复制和引用调解。
思量到我们已经有了固定的预算,数组的巨细也早已受限,因此保持数组的紧凑性并非须要。从性能和操纵的轻巧性出发,维护一个空闲列表好像是更符合的选择。
实现数组压缩
我们决定在当前情况下保持数组的
紧凑性
,以确保数据的完备性和可管理性。
当移除一个实体时,处置惩罚流程可以分为两种情况:
移除的是数组中的末了一个实体
:
这种情况下操纵非常简朴,直接将计数减1,即可完成移除。
移除的不是末了一个实体
:
这种情况下,我们必要举行
重新映射
,通过将数组中的末了一个实体移动到被移除的位置,确保数组不出现安定。
具体的处置惩罚步调如下:
起首,确定命组中被移除的目的实体。
如果被移除的实体不是末了一个实体,我们将数组中的
末了一个实体
移动到当前被移除的位置。
移动之后,必要更新对应的索引信息:
被移动实体的索引(高实体索引)必要指向新位置。
全部引用到该实体的低级实体也必要更新,确保它们指向移动后的新位置。
这一流程可以确保数组的团体紧凑性,同时保持全部索引和指向引用的正确性。
别的,当我们将高频实体转换为低频实体时,必要将高频索引打扫。这是由于该实体已经被标志为低频,失去了对应的高频索引。在全部情况下,操纵完成后,都会确保高实体数据和低实体索引的同等性。
团体来看,这种方法既能保持数组的紧凑性,又能确保全部实体的引用关系正确更新,制止了出现“悬空引用”或数据不同等的题目。
将 GetEntity 更改为 GetLowEntity 和 GetHighEntity
这段内容探究了实体管理的实现思绪以及操纵过程,特殊关注“低频实体”和“高频实体”之间的转换与调用逻辑。重要内容总结如下:
实体的获取与调用
实体管理的核心是通过方法获取“低频实体”,而不太关注“高频实体”的获取调用。团体计划假定大部门操纵是针对低频实体的,“获取高频实体”大概不必要单独实现。这简化了团体逻辑。
返回结果的处置惩罚
获取实体的方法必要有一个清楚的返回值逻辑:
如果实体存在,则返回对应实体;
如果不存在,则返回默认值,比方 0。
这种方式确保调用方可以根据返回结果判断实体是否有效。
索引与结果管理
在管理实体索引时,特殊是处置惩罚“第一个有效位置”和“末了一个位置”时,必要思量怎样返回正确结果。通过明白地返回索引大概 0,可以简化实体的映射管理。
方法的对称性
计划时确保获取低频实体和高频实体的方法是对称的,即两个方法在逻辑上可以相互增补。比方,低频实体的调用与高频实体的调用应该有同等的接口和返回方式,保持计划的简便性与可维护性。
实体状态转换
低频实体可以被提拔为高频实体。
在某些情况下,低频实体大概会更换或补充高频实体的位置。
这种状态转换是实体管理的紧张部门,确保资源得到有效使用,并制止无效的操纵或重复占用。
简化与重构
团体上夸大逻辑的简化,移除了不须要的情况和复杂处置惩罚。通过“低频到高频”的计划,制止太过关心无关部门,使得管理过程更加清楚明白。
机动性与可扩展性
保存计划的机动性,答应将来根据需求添加或扩展
功能
,比方同时提供“低频实体”和“高频实体”的获取方法。当前逻辑确保最根本的需求得到满意,同时具备肯定的可扩展性。
总之,这段内容围绕实体的获取、索引管理与状态转换睁开,夸大逻辑的简便性和对称性,同时包管返回结果的公道性,终极形成高效的实体管理方案。
将 AddEntity 更改为 AddLowEntity,并更新 AddWall
我们必要实现的是实体的添加操纵,现在我们决定始终添加一个低频实体。这意味着,全部的实体都会起首以低频情势存在。在举行实体的添加时,我们必要确保所添加的实体始终符合肯定的条件,比方索引范围必要在正当的低熵数组巨细以内。
在添加新实体的过程中,起首我们举行断言,验证当前的索引值小于低熵数组的巨细,以确保不会越界。接下来,我们对该实体举行初始化操纵,确保它处于正确的初始状态。
固然索引曾经是一个紧张的标识,但现在低频实体的索引渐渐显得不那么紧张了。在大多数情况下,实体索引对逻辑的作用变弱了,由于我们有了更加同一和抽象的管理方式。这使得外部调用者无需过多关心实体的具体索引,而只必要通过逻辑接口举行访问即可。
然而,仍旧有一些情况下,我们必要知道索引的范围,尤其是在处置惩罚指针前后引用等操纵时。这种情况下,索引信息仍旧不可或缺。总体上,这里的实体操纵都是基于低频实体举行的,这一层的抽象布局使得实体的管理更加流畅和有序。
我们也在思量实体访问的服从题目。固然现在实现的逻辑已经可以正常工作,但我们感觉在某些场景中,返回实体指针而不是索引大概会更加高效。然而,这种小的优化并不会对团体体系造成太大影响,以是暂时保持近况也是可以继承的。
综上所述,我们完成了低频实体的添加操纵,确保了索引的有效性和实体的初始化。同时,我们也渐渐淡化了索引在高层逻辑中的作用,进一步简化了实体管理的复杂性。
关于重构/重写代码的阐明
在开发和编写代码的过程中,我们常常会多次反复地重写代码。这是一种常见且须要的工作方式,就像塑造黏土一样,我们必要不停调解和修改,直到终极形成理想的形态。在最初的阶段,我们并不寻求美满的结果,而是通过多次实行来渐渐靠近终极目的。
我们风俗于先快速地将代码写出来,然后根据现实需求和结果举行修改和重构。这种反复的过程是代码质量提拔的关键。我们不会畏惧重新编写代码,由于快速的重写不会泯灭太多时间,也不会带来额外的资本。相反,如许的反复修改可以或许资助我们发现更好的办理方案,并终极产出更高质量的结果。
我们必要保持机动的态度,不停实行差别的实现方式,直到代码的表现和逻辑让我们感到满意。这种方法不但可以或许让代码更加美满,还能在实践中锻炼我们的头脑息争决题目的本领。通过快速地迭代和调解,我们可以或许制止僵化地对峙某个不成熟的计划,而是始终保持代码的机动性和可维护性。
在如许的过程中,代码重写并不是浪费时间的举动,而是寻求高质量结果的必经之路。只有通过反复地打磨和优化,我们才华终极形成真正符合需求的代码,实现稳固和高效的
功能
。
更新 AddPlayer 和 MovePlayer
在编写代码时,我们常常必要不停调解和优化代码的各个部门。在处置惩罚差别的实体和索引时,我们必须细致思量怎样优化和进步性能。对于添加的每个实体,我们起首不关心任何内部细节,只需确保这些实体可以或许正确地举行交互。
我们使用循环来遍历高和低的索引,确保每个实体都能正确地落入其预定位置。这个过程就是为了可以或许处置惩罚碰撞检测、任务实行等现实需求。我们必要对每个索引举行查抄,以确保它们是独立的,不会与本身发生碰撞。
别的,代码中的一些部门已经颠末了多次优化,比方将高索引与低索引组合在一起,以进步代码的实行服从。这些调解让代码更易于维护和扩展,从而产生更高质量的结果。只管过程大概反复且繁琐,但这种反复的工作可以或许终极提拔代码的性能和可读性。
终极,确保代码可以或许根据现实需求调解,并尽大概镌汰无效操纵,这是进步开发服从的关键。通过反复地优化和调解,我们可以在不增长性能开销的情况下,确保代码的质量和稳固性。
更新 SetCamera,将residence地从高频转移到低频实体
我们必要遍历高频实体。如许的做法是完全可以的。我们不必要担心,由于我们知道在高下的全部物体都是高的。我们所做的和之前的操纵一样,但是现在我们盼望可以或许在循环中改变人的residence。之以是这么做,是由于如许可以让迭代更加简朴,不会那么棘手。我们通过查抄这些高实体,如果它们不在特定的矩形地区内,就将它们从集会集移出。如许做的缘故因由是它使迭代非常顺遂,不必要使用其他方法来处置惩罚它们。团体来看,这个循环非常简朴,我们查抄矩形地区,找到不在此中的高频实体,并移出它们,同时我们也能从这些高实体中获取低索引。这种方法使得迭代非常简朴,而且不会频仍发生。这就是一个很有服从的循环。
一刻的顿悟;形貌在变更的数组上迭代时遇到的题目
我们必要处置惩罚一个特殊情况,即当某个人走出边界时。这种情况下,我们必要从集会集移除这些人。在实现中,我们盼望这两个子例程相互意识到,以保持迭代的简朴性。我们担心的是如果只是简朴的迭代,会导致数组被改变,因此无法正常工作。因此,我们盼望将这些家伙捆绑在一起,使得他们在代码中的意义更大。
起首,我们查抄这些高实体,如果它们不在特定的矩形地区内,则将它们从集会集移除。我们不盼望直接改变实体索引,而是通过一个有效的函数来完成这项操纵。然后,我们会处置惩罚低频的实体,在它们的地区内举行雷同的操纵。如许做的目的是保持高频和低频实体的操纵同等,同时制止直接修改数组。我们盼望在循环中每个人都能被正确的处置惩罚,而不因数组变异而出现题目。这种方法使得迭代变得更为简朴且高效。团体来看,这就是我们处置惩罚这个题目的方式。
处置惩罚控制实体
我们正在控制实体的方式。当我们添加一个玩家时,我们查抄控制器的低索引。如果低索引便是零,那么我们正在开始控制一个玩家。如果它不便是零,则正在处置惩罚已经控制的玩家实体。通过调用高亲和力函数,我们可以在高频段中获取和设置实体。为了确保不返回空指针,我们大概必要添加一个断言。如许做的目的是确保只有有效的低索引才会被处置惩罚。这种处置惩罚方式资助我们保持游戏状态的有效性和同等性。
调试瓦解题目
我们必要清算处置惩罚方式并查抄边界条件来确保正确创建高频实体。当前在快速移动操纵时存在题目,大概是由于未正确处置惩罚围绕题目或位置调解不妥。这些题目必要在后续的调试中办理,以确保高频实体的天生和位置的正确性。固然今晚大概无法完全办理这些题目,但来日诰日我们可以继承举行修复工作。
调试缺失墙壁和定位题目
我们必要审视代码中出现的题目,比方低频实体和高频实体的管理。发现低频实体计数禁绝确,大概是由于射线计数操纵被重复调用。我们修正了这个题目,并重新分配了实体索引和指针,以确保它们被正确地处置惩罚。如许,我们可以或许使渲染调用更加有服从,改善空间分区,优化整个体系。这些改进使代码布局更为公道,增强了整个引擎的运行服从,使其向更具体现力的状态迈进。只管还必要一些调解,但团体上的状态正在好转。
将低频实体和高频实体数组的巨细设为2的幂次方有什么上风?
关于实体的模仿,大概必要提前做好准备,确保可以顺遂举行交换。这种方法大概会带来肯定的上风,比方进步性能或活动性。我们倾向于使用2的幂次,这种方式通常能有效提拔性能。
现在尚不确定具体规模的巨细,由于这将完全基于性能需求。对于高频实体,我们会评估能支持的数量,预计大概会到达相当高的程度。然而,模仿这些实体的复杂度大概会限定规模,因此现实支持的数量大概会低于预期。相比之下,低频实体的数量预计会非常大,同时它们的属性和
存储
方式大概会占用游戏内存的大部门。这是我们的开端假设。
总结来看,低阶实体及其干系属性预计将在内存分配中占据重要比例,我们必要重点关注怎样优化
存储
和管理以提拔团体性能。
如果这是一个2D横向滚动平台游戏,你会怎样计划控制和移动的过程?
这是一个第三人称的游戏。如果这是一个二维横向卷轴平台游戏,控制和移动的创建过程与现在的游戏着实没有太大差别。现在控制部门还没有完成,因此可以比及正式处置惩罚这些内容时再讨论。
当前我们只是使用了一个暂时的控制机制,可以让脚色移动,但这并不是终极的手感。我们筹划先完成动画的制作,然后将动画和移动体系联合在一起,确保手感符合预期。
在碰撞检测方面,现在的设置中,重力只在脚色起跳时见效。而如果是平台游戏,重力通常会成为一个连续性的题目,必要更风雅的处置惩罚。除此之外,代码的大部门逻辑是相似的,没有太大的区别。团体流程中,核心逻辑保持同等,只是针对差别范例的游戏需求举行了恰当的调解。
你以为本日的代码会在优化过程中被重写吗?
在优化过程中,当前的内容大概会被重写。现在的重要目的是将全部的体系和逻辑安排好,以便明白规范和计划要求。当前的阶段重要是对代码布局举行整理,确保全部
功能
模块和接口清楚明白。通过这一阶段的工作,可以为接下来的开发奠定底子。
终极的办理方案和体系将基于当前的工作举行构建。在最初的几周内,重要任务是搭建框架并确认全部体系怎样协同工作。如果没有一个底子框架,单独开发体系大概会导致它们在集成时难以很好地共同,乃至会出现巨大题目。因此,起首创建一个可以或许公道融合的底子
版本
是关键。
接下来,在这个底子
版本
上对各个体系举行渐渐迭代和优化,终极将它们调解到理想状态。通过这种方式,可以确保全部模块在开发和优化过程中始终可以或许保持同等,并终极形成一个完备、调和的团体体系。
岂非不应该更轻易保持一个空实体插槽列表来在此中添加实体,而不是总是移动和更改此中一个指针吗?
关于怎样构建这些体系,有一种发起是使用一个包罗固定大的布局,通过一个空槽列表来管理空位,将新元素添加到空槽中,而不是总是移动条目和修改指针。这种方法大概会更轻易维护。
在选择具体方法时,对于两种方式的优劣尚未有明白的偏好。我们以为两者在本质上是相似的,并没有哪一种显着优于另一种。之以是选择当前的方法,是由于它的复杂性较低。具体来说,不必要为实体界说“空”的概念,因此在遍历实体时,不必要频仍查抄当前槽位是否现实包罗实体。
这种计划将复杂性会集在删除代码中,而不是将复杂性分散到整个体系的其他部门。这种方法可以或许更好地控制复杂性传播,因而被以为是一个更优的选择。不外,具体结果还必要在现实应用中举行验证和调解。
你是否相识游戏对象存储中的插槽映射(slot maps)?你是否会在这个项目中使用它们?我们在我们的引擎中使用它们。
关于slot maps的使用,现在对这个术语不太熟悉,必要进一步形貌才华明白。如果能具体形貌slot maps的界说和功能,就可以更确定地回复是否会在这个项目中使用它们。
slot maps的讨论涉及到游戏对象的存储管理,但由于对具体概念的明白尚不明白,以是暂时无法确认是否得当当前的项目。不外,如果slot maps可以或许提供更高效的对象管理方案,尤其是在复杂对象布局中大概产生上风的话,它确实值得思量。
现在,必要更多关于slot maps的细节阐明,以便更好地评估它们在体系中的埋伏应用代价和实用性。这种方法的选择终极照旧要看它是否能为项目的架构和性能带来现实的优化。
回复
使用道具
举报
返回列表
浏览过的版块
运维.售后
DevOps与敏捷开发
Mysql
前端开发
物联网
人工智能
Java
分布式数据库
linux
美丽的神话
+ 我要发帖
登录后关闭弹窗
登录参与点评抽奖 加入IT实名职场社区
去登录
微信订阅号
微信服务号
微信客服(加群)
H5
小程序
快速回复
返回顶部
返回列表