




免费预览已结束,剩余33页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
本科毕业论文本科毕业论文 (科研训练、毕业设计) 题题 目:脚本在游戏开发中的应用目:脚本在游戏开发中的应用 -基于基于 Lua 的分析的分析 姓 名: 学 院:软件学院 系:软件工程系 专 业:软件工程专业 年 级: 学 号: 指导教师(校内): 职称: 指导教师(校外): 职称: 年 月 I 脚本在游戏开发中的应用脚本在游戏开发中的应用 -基于基于 LuaLua 的分析的分析 【摘要】 在近几年来,进入到游戏中的脚本语言在很大程度上为那些制作游戏的人和玩 游戏的人提供了好处。例如程序员可以利用脚本语言来实现引擎特征,或者为游戏构建一个 版本 Debug,或者在一台并没有安装开发工具和源代码的计算机上对游戏进行 Debug。脚本 语言还可以帮助程序员很快地开发出一些功能,比如 AI 系统的有限状态机,或者任务管理 系统等。脚本语言的语句结构比 C+要简单的多,这种简单性允许游戏设计师不用等程序人 员花费时间编写 C+功能和重建游戏应用程序就可以自己实现一些游戏玩法特点。现在几乎 全世界每一个角落都有玩家在用脚本语言来编写他们最喜欢的游戏的 MOD。 今天,脚本语言和游戏引擎一样,已经很普及了。那种要想提供脚本支持只能从头专门 建立一个脚本语言系统的时代已经一去不复返了。现在的状况是,开发者可以根据他们在高 性能、高兼容性、多线程、网络化,简单化的需要,从多种高产品质量,现成的脚本系统中 挑选一种来使用。 对于众多的脚本系统,怎样才能选出最适合自己的脚本系统,怎样防止兼容性风险的同 时又能最大的发掘系统的特点?本论文从选择脚本开始,到与 C+对象的绑定,以及一些高 级的控制,最后结合一个应用实例,提供一些技巧来解决这些问题。 关键字:脚本 Lua 对象绑定 高级控制 角色属性 II Applying with script in game developing Analysing based on Lua 【Abstract】 Over the past several years, Scripts in games mostly benefit for people of making games and playing games. For example, programmer could implement the engine character by using Scripts, or build a Debug edition, also do Debugging of the game on a computer which dont install develop tools and has not source codes. Script languages could help programmer to rapidly develop some functionality part too, eg the finitude of states AI system, the task manage system and so on. Script languages programming structure is more simple than C+s, depending on the simple games designer can implement some special game playing style by themselves without programmer spending several time to edit C+ codes and rebuild the Game.exe. Recently, the players almost around the world Program their favorite MOD with scripts. Now, the script language is common as the same with the Game Engine. The time that people needing the support of scripts must build the script system from the bottom has gone forever. What is the case now, development team can choose the best one from the existing good script languages that fits the needs of the high performance, the good compatible, multi-thread environment, the Netting, and the simple. Facing the many script languages, How to find a Better one for self ? How to avoid either the risk for the problem of compatible or dig the advantages of the system out? This article begins with how to choose a script system, then talks about binding object to c+, and then some high controlling in programming, with an example provides some skills to solve these problems above at last. Key Word:Script Lua Object bindings Control in high level Actor Attribute III 目录 第 1 章 简介-2 1.1为什么要使用脚本语言-2 1.2如何选择脚本语言-2 1.2.1语言的编码-2 1.2.2与 C 和 C+的整合-2 1.2.3性能-2 1.2.4对开发的支持特点-3 第 2 章 对 C+对象的绑定-4 2.1轻量级用户数据-4 2.2轻量级用户数据类型-4 2.3完整用户数据-5 2.4可扩展用户数据-5 2.5表-6 2.6绑定策略衡量标准-6 第 3 章 协同程序实现高级控制-8 3.1协同程序相关概念-8 3.2生成过滤器-8 3.3实现更多功能-9 第 4 章 导出角色属性-11 4.1使用非插入型代理导出角色属性的方案-11 4.2角色、代理和属性-11 4.2.1角色-11 4.2.2角色代理-11 4.2.3角色属性-12 4.3构建角色属性-13 4.3.1函数-13 4.3.2Getter/Setter-13 4.3.3属性设计-14 4.4角色代理-15 第 5 章 UNREAL 脚本实例扩展-17 5.1UNREAL脚本开发-17 5.2建立一个 CAMERAACTOR类-17 5.3集成到 KISMET中-18 5.4演示结果-19 第 6 章 展望下一代游戏脚本-22 IV 第 7 章 结论-23 致谢语-24 参考文献-25 V Content Chapter1 Introduction-2 1.1Why do we choose scripts-2 1.2How to choose script language-2 1.2.1Code of language-2 1.2.2Combine with C/C+-2 1.2.3Performence-2 1.2.4The support for developing-3 Chapter2 Combine with C+ object-4 2.1Light user data -4 2.2Light user data type-4 2.3Full user data-5 2.4Extend user data-5 2.5Table-6 2.6The standard of combining-6 Chapter3 Coroutines for high controlling-8 3.1The concept of Coroutines-8 3.2Build filter-8 3.3Implement more-9 Chapter4 Export Actor Attribute-11 4.1The Solution using non-plug in-11 4.2Actor、Actor Proxy And ActorProperty-11 4.2.1Actor-11 4.2.2Actor Proxy-11 4.2.3ActorProperty-12 4.3Build Actor Attribute-13 4.3.1Function-13 4.3.2Getter/Setter-13 4.3.3Attribute Designing-14 4.4ActorProxy-15 Chapter5 Unreal the extend instance of scripts-17 5.1Unreal script coding-17 5.2Write a CameraActor class-17 5.3Integration in Kismet-18 5.4Result-19 Chapter6 Expect the next new script-22 VI Chapter7 Summary-23 Acknowledgement-24 References-25 引言 1 引言引言 当前游戏的资源越来越庞大,参与制作的人员也越来越多,这在很大程度上增加了游戏 内容的复杂性。而游戏脚本的出现,则在很大程度上为制作游戏的人和玩游戏的人提供了诸 多好处。针对不同的游戏特点,不同的开发团队,什么样的游戏脚本才是适合自己的?本论 文将对脚本邦定 C+及其扩展功能实现进行展开,阐明其实现机制,以便团队能针对自己开 发人员的特点和引擎的特点,更好地封装自己的脚本,快速构建游戏原型;本文侧重对机制 的剖析,开发团队可以针对自己引擎的特点选择合适的实现策略。 厦门大学学士学位论文 2 第第 1 1 章章 简介简介 1.11.1为什么要使用脚本语言为什么要使用脚本语言 脚本是对于美术师,设计师和玩家来说是一种方便的控制游戏的工具,例如用脚本来控 制动画的次序、敌人类 NPC 的行为,以及由 AI 控制的队友对玩家的指示反应,等等。另外, 脚本语言使得快速原型开发成为可能,而且这种模式也正在被越来越多的游戏开发团队所接 受。 1.21.2如何选择脚本语言如何选择脚本语言 当前比较受开发者欢迎的脚本语言有下面这些: Python,Lua,GameMonkey,AngelScript。它们都有很多共性,因此在如何选择或是改造适 合自己的脚本,我认为应该考虑如下四点。 1.2.11.2.1 语言的编码语言的编码 主要是考虑语言的特征和编码的易用性,如自动内存管理,流控制,迭代特征,类型安 全,参数传递等等。 1.2.21.2.2 与与 C C 和和 C+C+的整合的整合 脚本语言大多是对 C+核心语言的延伸。因此必须要确保在核心引擎和脚本之间的数据 转换不需要太多程序方面的努力,并且对于项目的需求来说要功能足够强大,并且足够有效。 1.2.3性能性能 尽管脚本并不用于游戏中与性能相关性很大的部分,但是,在进行游戏及游戏开发的时 候如果消耗过多的内存就是一个比较严重的问题了,另外一些任务的执行过缓还会影响到游 第一章 简介 3 戏的帧率。 1.2.4对开发的支持特点对开发的支持特点 一些能使脚本语言使用更为简单和简便的外加工具或功能可以大幅度提高开发人员的效 率。比较好的 Debug、说明图和记录工具可以帮助你更为迅速的解决问题。 厦门大学学士学位论文 4 第第 2 2 章章对对 C+C+对象的绑定对象的绑定 把一个脚本语言嵌入到游戏中最主要的问题是,如何为脚本语言提供宿主对象的访问。 因此嵌入相关问题和绑定相关问题就成为选择或修改脚本的两个关键特性。实现对宿主对象 的绑定有许多种策略,每种策略都自己的优点和缺点,游戏开发者必须在得到功能需求后才 能确定最合适的策略,下面将针对 5 个对实际绑定有用的策略进行分析。 2.12.1 轻量级用户数据轻量级用户数据 将 C+对象和 Lua 绑定的方法就是把它的内存地址映射成轻量级的用户数据。这种绑定 的策略就是用 Lua 中一个普通的值对应 C+对象的指针地址,对 C+对象的访问就是通过这 个地址值来实现1。 把对象映射成简单值至少有 3 个好处:简单、高效和小的内存覆盖。这种策略是非常直 截了当的,并且因为没有引入任何的间接访问和内存分配,Lua 和宿主语言之间的通信也是 最高的。然而,作为一个实现,这种简单的策略因为用户数据的值始终被当成有效的参数而 变得不安全;传入任何一个无效的对象都将会导致宿主程序的直接崩溃。 2.22.2 轻量级用户数据类型轻量级用户数据类型 加入类型检查机制来避免在 Lua 环境中导致宿主程序的崩溃,当然加入类型检查会降低 效率并且增加了内存的使用。如果脚本只是用在游戏的开发阶段,那么类型检查机制可以在 发布之前始终关闭。 创建一个把每个对象和 Lua 相对应类型名字映射的表,在这张表中,轻量级的用户数据 可以作为一个键,而字符串(类型的名称)作为值,该表可以被映射成函数调用。保持该表 的独立性是非常重要的,即保证从脚本环境中访问该表是不被允许的;但这仍然可能在脚本 中使宿主程序崩溃。保证独立性有几种方法:一种是使用注册表来存储,然而,注册表是惟 一且全局的,用它来存储我们的映射对象也阻止了其它的 C 程序库使用它来实现其它的控制 机制;另一种更好的方案是只给绑定函数提供访问类型检查表的接口;而在 Lua5.1 中的实 现方法是环境表的使用直接和 C 函数相关1。即把类型检查表设置成绑定函数的环境表,这 样,在函数里对表的访问就非常高效了。每个函数都需要注册到 Lua 中,从当前的函数中去 第二章 对 C+对象的绑定 5 继承它的环境表,因而只需改变初始函数的环境表关联就足够了。通过这些做法,绑定策略 仍然很高效,内存负载也非常低,所有的对象只有一个表实体。 2.32.3 完整用户数据完整用户数据 上面的绑定策略虽然高效,但它只是一个值,在 Lua 中你不能把它当成一个对象来对待, 所以就更无法使用面向对象的语法来引用它的方法,而且在脚本中无法管理对象的生命周期。 要完成对象到对象的映射,我们就得把 C+的对象对应成脚本中一个完整的用户数据。 在 Lua 中可以使用自己的 API 来创建一个内存数据块,然后作为一个不透明的对象映射 到 Lua 中,在 Lua 中是无法区分轻量级用户数据和完整用户数据的;但宿主能关联一张元数 据表。元数据表可以定义特定的行为,不同的对象拥有不同的元数据表,当然相同的对象类 型拥有一样的元数据表。然后要做的就是注册一个表项,即在一个全局表里把类型名和元数 据表映射起来,这样就可以通过类型名找到对应的元数据表,更通俗的说法是可以通过类对 象访问它的成员函数。要完成真正的面向对象特性对应,我们还要加上继承和多态。 实现面向对象特性实质就是要记录类的体系结构。我们分三步走:首先接收基类的类型 名;其次保存基类的元数据表;最后让保存表可以复制传递到下一代。完成后,脚本对象就 具有强大的功能了。 2.42.4 可扩展用户数据可扩展用户数据 添加可扩展性,就是能够为对象添加新的属性,重新定义已有的方法,或者扩展对象的 行为。 为了允许对象添加一个新的字段,我们使用对应的元事件关联,即属性对应属性元事件, 方法对应方法元事件。然后把元事件存储到到 Lua 的表中,只有当元事件第一被触发,我们 才把修改的环境表赋给用户。这个策略一个明显的缺点就是访问宿主方法的时候会出现性能 瓶颈,因为元事件无法直接映射到库表中,所以必须检查字段已经在环境表中,并且所以元 事件都通过这个环境表来访问库函数。 2.52.5 表表 这是个简单而且自然的策略,我们把宿主对象和 Lua 的表直接绑定2,为每一个对象创 建一个表,来取代为每个对象创建一个完整的用户数据。很明显这种策略与前面的策略比起 厦门大学学士学位论文 6 来分配了更多的内存。 2.62.6 绑定策略衡量标准绑定策略衡量标准 绑定策略一般都从灵活性、效率、和内存需求三方面来衡量,下面表 2-1,表 2-2,表 2-3 将针对这三方面做一些统计。 表 2-1 不同策略提供的特性 策略可访问性类型检查面向对象可扩展性 轻量用户数据 轻量用户数据类型 完整用户数据 可扩展用户数据 表 表 2-2 调用代码 100 万次平均耗时 时间策略 方法调用属性访问 轻量用户数据 0.49sN/A 轻量用户数据类型 0.73sN/A 完整用户数据 0.94sN/A 可扩展用户数据 1.38s0.59s 表 1.49s0.15s 表 2-3 内存消耗比较 内存消耗策略 每个对象额外属性 轻量用户数据 -N/A 轻量用户数据类型 EN/A 完整用户数据 U+EN/A 可扩展用户数据 U+E T+E/属性 表 T+E E/属性 表 3 中 U 表示一个完整的用户数据保存在指针中,T 表示一个最初的空白表,E 表示一 个表项。 第三章 协同程序实现高级控制 7 第第 3 3 章章协同程序实现高级控制协同程序实现高级控制 3.13.1 协同程序相关概念协同程序相关概念 协同程序在游戏编程中是一种非常有效的机制,它对于一个多线程系统中的线程来说会 更加的简单,它使用自己的本地执行栈,但是会和其它协同程序共享全局环境;而不像被操 作系统管理并在理论上并发执行的标准线程,只有系统程序能够在指定的时间内运行,就像 一个标准的函数。但和函数不同,协同程序能够在任意时候挂起并恢复3。因此,协同程序 提供一个并发执行的假象而没有任何的消耗和管理同步的负担,这能明显的简化程序结构。 Lua 协同程序有 3 种不同的状态:挂起、运行、死亡。并且协同程序从属于它的调用者 (比如唤醒它的函数) ,而且控制权总是会被传回给调用者。 3.23.2 生成过滤器生成过滤器 输入流 过滤器 输出流 图 3-1 简单过滤器 事件处理在游戏中是一个简单过滤器的例子:外部事情需要转换成游戏事件,如图 3-1 所示。 现在存在 3 种情况: (a)一个外部事件映射成一个游戏事件 (b)多个外部事件映射成一个游戏事件 (c)一个外部事件映射成多个游戏事件 在 C+中你需要控制多个函数指针,让他们在事件触发的时候配合使用,这需要同步管 理各个函数的调用。但在通过脚本协同程序,能很轻松实现这个事件过滤器,我们只需要 Swith (State) 厦门大学学士学位论文 8 Case A:调用对应协同程序处理事件 Case B:先合并两个事件,再调用协同程序 Case C:递归调用 Split 事件的函数,每个事件或是一组事件对应一个协同函数的调用 3.33.3 实现更多功能实现更多功能 协同程序类似于线程,因此我们能过很轻易的实现延迟函数,也能轻松的实现任务安排。 在游戏中我们可能需要协作式多线程一样的控制机制。 休眠等待 活动 死亡 发送消息 时间足够 休眠 进入等待状态 接收消息 返回 图 3-2 协作式控制机制 如图 3-2 所示,某一项任务可以拥有 4 种状态:活动、休眠、等待、死亡。由一个分发 器(Dispatcher)来控制该任务的执行。每一个注册过的任务都会被指派一个名字,这个名 字用于在数据转换机制中识别该任务。在每一次跌代中,分发器会访问所有注册过的任务, 并且在必要的时候执行。所有处于活动状态的任务都被执行,所有处于休眠状态的任务会被 检查,看其是否需要被激活执行。 利用 LUA 的协同程序能在更广阔的领域里解决其他问题,例如增量模拟、AI 以及文本处 理。在多线程环境下,开发和调试要比单线程环境下困难很多,只有几个少数团队成员可能 拥有多线程基于组件系统开发所需要的技巧和知识,所以通过协同程序来近似模拟多线程是 不错的选择。然而协同程序是一种“外来”流机制,广泛使用的语言几乎都不支持这种机制 (甚至连非 Stackless Python 都不支持它) 。 第四章 导出角色属性 9 第第 4 4 章章导出角色属性导出角色属性 4.14.1 使用非插入型代理导出角色属性的方案使用非插入型代理导出角色属性的方案 从某些观点来看,每一个游戏引擎都会在导出角色属性时遇到一些问题。哪怕是最简单 的引擎最终都需要拥有一个能给外部工具导出内部游戏角色属性的功能。关卡编辑器需要这 些属性帮助设计人员在不依靠开发人员的情况下制作地图。消息传递框架需要这些属性有效 地建立通用消息和发送网络更新。加载/保存模块需要它们来实现状态的持久化。尽管这些 功能需求非常清楚,但不幸的是,这个方案并不总是显而易见的,特别是对于 C+来说。 下面这个技巧描述了一个用于导出游戏角色属性的灵活且松散的结构。它也将展示如何 为您的游戏角色类解决这个问题而不需要做任何改动,当然有些时候需要通过重构来完成。 然而,在 C+中,这几乎肯定需要在你的角色上做一些改动,在您构建关卡编辑器、游戏管 理器甚至是消息框架时,这个方案都是比较理想的。 4.24.2 角色、代理和属性角色、代理和属性 4.2.1 角色角色 角色(Actor)在游戏中都是独一无二的。它们构成了游戏的内容,并且包含了许多游 戏世界交互的逻辑。车辆、天气系统、发射器、触发器和光这些都是角色。 4.2.24.2.2角色代理角色代理 角色代理(ActorProxy)是一个简单的面向数据的类,如图 3 所示,该类封装了每一个 角色的类。它们非常简单,但是他们通过实施两个系统中主要的工作,而在这个体系里扮演 了一个关键的角色5。首先,它们为关卡编辑器或者游戏管理器这样的外部工具提供了一个 通用而又统一的类,使它们有一个访问和维护属性的途径。其次,它们可以访问到他所封装 角色的所有东西,特别是属性。一旦定义之后,角色代理就可以用来代替角色,特别是对于 高端的工具来说。 厦门大学学士学位论文 10 +GetProperty() +GetProperties() +GetActor() +CreateActor() +GetActorType() +BuildPropertyMap() +IsPlaceable() +GetBillboardIcon() -propertyList -actor -actorType -className -billboardRenderMode -billboardIcon ActorProxy +AddedToScene() +GetName() +SetName() +GetUniqueID() +.() -UniqueID -Name Actor +GetDataType() +ToString() +FromString() +SetValue() +GetValue() -Name -Description -Label ActorProperty . +GetProperty() +CreatActor() +GetActorType() -Truck MyTruckProxy +SetSpeed() +GetSpeed() +SetWeapon() +GetWeapon() +.() -WeaponSlot -Speed -DamageState MyTruck . 图 4-1 角色代理类图 4.2.34.2.3角色属性角色属性 角色属性(ActorProperty)是一个单独的、关于角色信息的原子片。角色属性是你所 要导出的数据中含金量最高的部分。也是将要被编辑器显示并且有可能被网络发送的数据。 从图中能看到,角色属性被定义成一系列的 Set/Get 方法、To/From 字符窜方法和名字、描 述、标签这样的表识信息。 尽管为每一个属性维护这样一个信息会给你的系统增加一些处理损耗,但它能够极大的 提高系统弹性和游戏角色的有效性。当你的整个团队打算引入统一使用属性的概念时,这个 方法就会特别的有效。想象这种情况:你的一个团队成员创建了一个格子棋的角色作为游戏 夺旗模式的旗帜。它只是单一的为了达到这个目的。但是如果把贴图、周期、阶段和振幅这 样的数据都保存为属性,那么该成员就能创建一个通用的角色,并在布修改任何代码的情况 下将它作为人物 NPC、路径点、房间装饰甚至是背包对象! 第四章 导出角色属性 11 4.34.3 构建角色属性构建角色属性 4.3.1 函数函数 通常,我们会使用反射的技巧,C+语言并不自发的支持这样一个构造。我们需要使用 仿函数的概念,仿函数(Functors)是一个回调的函数指针。下面以一个简单的仿函数使用 来说明。 Class MyClass Public: Void SayHi() std :cout Class GenericActorProperty : public ActorProperty Public: GenericActorProperty(Functor1 GetPropFunctor = get; / 子类返回一个指定的数据类型 Virtual DataType / 通过调用 Set 方法来设置这个属性的值 Virtual void SetValue(SetType value) SetPropFunctor(value); / 通过调用 Get 方法来得到属性值 Virtual GetType GetValue() const Return GetPropFunctor(); 厦门大学学士学位论文 12 Private: Functor1SetProFunctor; Functor2GetProFunctor; ; 4.3.34.3.3属性设计属性设计 GenericActorProperty 只是一个基类,这个结构需要支持大量的数据类型,从简单的整 型、浮点型到复杂的贴图、网格和声音这样的属性。为此需要为每一个属性类型准备一个子 类,每个子类支持且只支持一类数据,图 4-2 展示了一个关于属性类的子设计。 +GetDataType() +ToString() +FromString() +GetValue() +SetValue() -Name -Description -label ActorProperty +SetValue() +GetValue() +ToString() +FromString() +GetDataType() -SetPropertyFunctor -GetPropertyFunctor
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 全程训练2025版高考政治一轮复习课练35唯物辩证法的联系观含解析
- 行政管理决策与执行试题及答案
- 行政管理中的团队灵活性与心理适应研究试题及答案
- 2025年行政管理自考思路清晰试题及答案
- 工业互联网平台中2025年异构数据库融合技术标准与规范解读报告
- 行政管理的社会需求分析试题及答案
- 行政管理本科试题及答案全面解析
- 工程经济投资回收试题及答案
- 2025市政工程基础知识试题及答案
- 2025年项目管理实践经验分享试题及答案
- 市政道路工程冬季施工方案及措施
- 2024年校园食品安全检测服务协议3篇
- 志愿者年度述职报告
- 2023年山东省济宁市中考历史真题(原卷版)
- 【MOOC】犯罪心理学-西南政法大学 中国大学慕课MOOC答案
- 中国融通集团笔试题库
- 乳酸性酸中毒护理
- 2024版保险合同法律适用与条款解释3篇
- 外科经典换药术
- 《尊师重道主题班会》课件
- 2024年支气管哮喘临床诊疗指南:课件精讲
评论
0/150
提交评论