版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
摘要随着互联网时代的进步,游戏行业的推动,影响着人们的生活方式。在学习工作之余,轻松愉快的游戏娱乐成为了人们休闲娱乐的生活方式之一。而游戏与虚拟仿真的结合也开始受到越来越多的人们关注。通过虚拟仿真类游戏,让游戏玩家体验到更加丰富多彩的生活,了解到更多不一样的知识,因此虚拟仿真类游戏越来越受欢迎。Unity3D是目前最流行的游戏开发引擎之一,以其低成本与高效率被多数游戏开发者所使用。本论文探究基于Unity3D的海关仿真游戏开发与实现的过程,首先确定游戏设计方向,其次列举了游戏的实现内容。其中包括了道具的使用、入境人员的信息、以及人工智能对话,开发过程中所应用到的框架方法,如使用管理UI的PureMVC框架、管理状态的有限状态机,以及仿真游戏所需的渲染方法,比如使用了LightWightRenderPipeline工具。让想要了解海关检查员工作的游戏玩家,能够更加真实地体验海关检查员的具体工作流程。最后,对游戏的功能进行打包运行。关键词:Unity3D;虚拟仿真类游戏;海关模拟AbstractWiththeprogressoftheInterneteraandthepromotionofthegameindustry,people'slifestyleisaffected.Afterstudyingandworking,relaxedandhappygameentertainmenthasbecomeoneofthelifestyleofpeople'sleisureandentertainment.Andthecombinationofgameandvirtualsimulationhasattractedmoreandmoreattention.Throughvirtualsimulationgames,thegameplayerscanexperiencemorecolorfullifeandlearnmoredifferentknowledge,sovirtualsimulationgamesaremoreandmorepopular.Unity3disoneofthemostpopulargamedevelopmentengines,whichisusedbymostgamedeveloperswithitslowcostandhighefficiency.ThispaperexploresthedevelopmentandimplementationprocessofCustomssimulationgamebasedonunity3d.Firstly,thedesigndirectionofthegameisdetermined,andthentheimplementationcontentofthegameislisted.Itincludestheuseofprops,informationofentrypersonnel,andartificialintelligencedialogue.Theframeworkmethodsappliedinthedevelopmentprocess,suchasthepureMVCframeworkusingthemanagementUI,thefinitestatemachinemanagingthestate,andtherenderingmethodsneededforthesimulationgame,suchastheuseofthelightwiderenderpipelinetool.Letthegameplayerswhowanttoknowabouttheworkofcustomsinspectorsexperiencethespecificworkprocessofcustomsinspectorsmoretruly.Finally,packandrunthefunctionsofthegame.Keywords:Unity3D;Virtualsimulationgames;Customssimulation广东东软学院本科生毕业设计(论文)目录第一章 绪论 11.1 选题的背景和意义 11.2 国内外研究现状 11.3 论文组织结构 2第二章 开发工具介绍 32.1 Unity3D引擎 32.1.1 Unity3D软件介绍 32.1.2 物理引擎 32.1.3 轻量级渲染管道 32.2 C#开发语言 32.3 VisualStudio2019 4第三章 游戏总体设计 53.1 游戏背景介绍 53.2 游戏玩法 53.2.1 操作机制 53.3 游戏主要过程 53.4 游戏得分机制 53.4.1 绩效得分 53.4.2 服务得分 53.4.3 安全得分 63.5 系统整体设计 63.6 游戏界面设计 7第四章 游戏实现 84.1 游戏场景 84.1.1 场景设计 84.1.2 场景制作 84.1.3 灯光 94.2 特殊道具 104.2.1 电脑 104.2.2 笔记本电脑 134.2.3 红色盖章和绿色盖章 154.2.4 金属探测仪 174.2.5 危险警报器 184.2.6 通行证和护照 194.3 入境人员 234.3.1 创建入境人员信息 234.3.2 入境人员携带物品 244.3.3 入境人员动作 254.3.4 入境人员交互 274.3.5 入境人员路径 304.3.6 入境人员状态 314.3.7 创建入境人员 334.4 玩家控制对象 354.4.1 创建对象 354.4.2 控制镜头 354.4.3 控制道具 374.4.4 控制对象状态 41第五章 游戏打包与测试 485.1 游戏打包 485.2 游戏运行 48第六章 总结 51参考文献 52致谢 53绪论选题的背景和意义随着社会进步的发展,地球村更加进一步的形成。现如今,人们之间的生活联系更加密集,国与国之间的联系也更加密集,通过人才运输,理想的各自不同,跨地区,跨国家之间的交流更加频繁密集。现阶段我国综合国力的上升,加入WTO带来了外汇资本的涌入,改革开放进程推进,“一带一路”战略吸引了大量的外来流动人口访华交流合作,为了有效阻断国家与国家之间人员频繁来往成为犯罪以及逃亡,加剧流行性传染疾病,2020年年初,一场“新型冠状病毒”席卷全球,在我国基本控制疫情的同时,国外疫情却不减反增的趋势,国内入境病例随着提高,从而导致了国家与人民群众陷入恐慌,因此需要监管进出境的人员是否符合相应安全条件,并因此建立了海关站。全国海关目前共有46个直属单位(广东分署,天津、上海特派办、41个直属海关,2所海关院校),600个隶属海关和办事处,通关监管点近4000个。中国海关现有关员(含海关缉私警察)约5万人。随着现在科技进步,互联网的普及,电子游戏形式总类越来越丰富,其中虚拟仿真类游戏也开始逐渐受到游戏玩家青睐,3D类型游戏已经在生活中各类电子多平台得到了普及,对比与传统2D类型游戏,3D类型游戏能够带给游戏玩家更加完善的体验,而结合3D虚拟仿真制作出的游戏能使游戏体验回馈更加真实。因此,将使用Unity3D制作一款海关虚拟仿真类游戏。现实生活中普通群众很难接触到海关检查工作人员每日工作流程,以及面临到的危险、应具备相应的专业知识。通过虚拟仿真效果制作一款海关模拟游戏基于游戏玩家体验,使普通群众了解可靠的仿真理论系统,从而达到科普宣传海关站的相应知识,更加完善地了解基础知识,可能面临到的危险。国内外研究现状随着互联网技术和终端硬件的发展与完善、人们生活水平的提高,游戏市场越来越受到重视,游戏产业高速发展。2019年全球数字游戏总营收高达1201亿美元,而国内游戏产业实际销售收入达2308.8亿元,同比增长7.7%(2018年同比增长5.3%);其中移动游戏实际销售收入达到1581.1亿元,同比增长率18.0%。因此可看出国内游戏行业增长趋势猛增,单机领域市场占比却仅为0.3%,虚拟仿真类单机游戏寥寥无几。因此,开发一款虚拟仿真类海关游戏即可抢占虚拟仿真游戏市场份额又可丰富游戏种类。论文组织结构论文从总体设计到最终的完成,结合应用了游戏开发相关的知识和技术,成功实现了一个基于Unity3D的海关仿真游戏开发与实现,其中具体介绍了游戏框架设计以及游戏制作的关键步骤,也包括游戏的系统功能设计和一系列代码的编写。论文分为六章,各章节安排如下:第一部分:绪论,主要介绍了选题的背景以及意义、相关课题国内外研究现状;第二部分:介绍了本文制作游戏使用的各类开发工具和Unity3D的大致介绍;第三部分:详细介绍游戏的各个模块的总体设计,游戏背景,清晰明确游戏内部关系,界面设计;第四部分:具体实现过程框架使用和方法;第五部分:对游戏进行打包并测试;第六部分:结论以及游戏的缺陷和今后的改进方法。开发工具介绍Unity3D引擎Unity3D软件介绍Unity3D是一款由UnityTechnologies公司所开发的跨平台游戏开发软件,作为一款专业的游戏开发引擎,它有资深技术团队的支持、友善的图形化界面、丰富的拓展插件和多平台的导出配置,是一款整合多功能于一身的游戏开发引擎。Unity3D适合新手学习,上手难度较小,因此降低了游戏开发门槛,给热爱游戏开发的开发者提供了一个平台。使用Unity开发游戏的无需底层复杂技术,就可以使用它开发设计出高质量的游戏,并且Unity3D开发的游戏可支持Windows、Mac、iPhone和Android等多种平台发布[12]。因此,是大多数游戏公司和游戏开发者最佳选择。物理引擎Unity内置了NVIDIA的PhysX物理引擎,PhysX是目前使用最为广泛的物理引擎,被很多游戏大作所采用,开发者可以通过物理引擎高效、逼真地模拟刚体碰撞、车辆驾驶、布料、重力等物理效果,使游戏画面更加真实而生动。并且还可以在Windows、Mac、Linux和Android等多种平台上运行轻量级渲染管道LightweightRenderPipeline(LWRP),轻量级渲染管线,是一个Unity预制的ScriptableRenderPipeline(SRP)。LWRP可以为移动平台提供图形渲染功能,但也可以在高端主机和PC上使用LWRP。LWRP使用简化的、基于物理的光照和材质。使用LWRP,可以在几个平台上得到优化了的实时渲染性能。C#开发语言C#是微软公司发布的一种运行于.NETFramework和.NetCore上的高级程序设计语言,不仅面向对象,类型安全。C#是一种面向对象的语言。不仅如此,C#还进一步支持面向组件的编程。当代软件设计越来越依赖采用自描述的独立功能形式的软件组件。此类组件的关键是它们提供包含属性、方法和事件的编程模型。它们包含提供组件相关声明性信息的属性。它们合并了自己的文档。C#提供了语言构造来直接支持这些概念,让C#成为一种非常自然的语言,可用于创建和使用软件组件,因此成为了Unity3D开发的主流语言。VisualStudio2019VisualStudio是美国微软公司的开发工具包系列产品。它是一个基本完整的开发工具集,包括了整个软件生命周期中所需要的大部分工具,提供强大的调试和性能分析工具,快捷地查找和修复错误的方式,强大的库调用和云集成,为Unity3D游戏开发提高了效率。游戏总体设计游戏背景介绍《海关检查员》是一款由玩家扮演海关检查员,主要的工作在于检查每一位海关入境者的证件、是否存在走私或者违禁物品,以及判断入境者的身份是否符合入境的条件。体验一个检查员日常工作一些相关的操作,体验这份工作背后的艰辛以及压力,以及是如何成为一名称职的检查员,以及背后遇到的世间辛酸、恐吓、要挟。当这些降临在玩家面前,玩家该如何选择。是一款玩家内心的问卷答题通关游戏。游戏玩法操作机制《海关检查员》是第一视角控制游戏,以键盘WSAD控制人物视角上下左右移动,鼠标左键点击为拾取、与NPC进行交互以及触发事件,鼠标右键点击为放下,ESC键调出/关闭菜单。游戏主要过程进入游戏,点击电脑熟记当前的日期,开始检察入境人员,询问入境人员具体情况,审阅证件是否准确,金属探测仪检验是否携带危险器具,判断是否给予入境,点击下一位,选择检验下一位入境人员,系统对游戏玩家进行评分。游戏得分机制绩效得分以游戏玩家判断的准确性为依据,若判断通行、拒绝准确率越高,绩效得分越高。服务得分初始入境者随机设定情绪,随着玩家与入境者互动,改变情绪,服务得分随情绪变化得分。安全得分错误通行危险入境者,城市安全指数降低。系统整体设计游戏的主要玩法是玩家与NPC的交互,NPC的AI十分重要,直接影响游戏体验。所以使用有限状态机来控制NPC的行为状态。使用有限状态机的方式,把NPC的AI行为划分为多个不同的状态,通过不同逻辑块的执行形成NPC的完整行为,NPC的AI逻辑更加的清晰,便于修改与完善,也可以为后期拓展提供途径。图3-1NPC的AI逻辑图游戏界面设计游戏界面是开始进入游戏主场景之后,主摄像机看到的内容,其中包括了海关站界面、检查入境人员界面、证件界面、金属探测仪界面,以及电脑操作界面。表3-1游戏界面海关站界面办工操作台左侧排队等候区右侧电脑信息检查入境人员界面入境人员通行盖章、拒绝盖章金属探测仪证件界面通行证(盖章区域、证件照、姓名、性别、日期、国籍、通行编号)护照(姓名、通行编号、入境理由、日期)金属探测仪界面手持金属探测仪显示入境人员携带金属物品电脑操作界面入境人员信息表(证件照、姓名、性别、年龄、国籍、职业、人家原因、)信箱(每日信息)游戏实现游戏场景场景设计系统场景包括(Scene1、StartScene),StartScene为开始游戏场景,Scene1为主场景。表4-1系统场景如下图StartScene开始游戏按钮可持续播放的背景动画Scene1接待以及检测入境人员的海关站办公桌,以及可操作电脑提供检查入境人员工具场景制作使用Unity自带的地形系统搭建自己想要的海关站,在Hierarchy面板中创建一个片面Plane,在Inspector面板中Transform修改平Plane的大小以及位置,原有的网格渲染器MeshRenderer将静态光照贴图LightmapStatic勾选,并加入碰撞体BoxCollider。搭建好一块平面地形。参数如图:图4-1平面地形参数接着在Hierarchy面板中创建三个平面Cube,将海关站搭建在平面地形上,在Inspector面板中Transform修改平Cube的大小以及位置,并在MeshFilter添加好相应的素材,搭建成一个海关站模型,并在网格渲染MeshRenderer中Element拖进相应的材料。图4-2游戏场景场景里添加一些物体丰富游戏场景,例如,桌椅、电脑、笔记本、电脑桌、书架、办公桌、盆栽、世界地图背景,以及地板,这便是大致的海关站内部场景。图4-3游戏内部场景灯光在Hierarchy面板中新创建的GameObject重命名为Lights,在Lights选项中创建一个DirectionalLight,在Inspector面板中调整位置以及角度,并在Light中Color将Hexadeciml改变为FFF4D6,Mode改为Mixed,Intensity改为2,选择ShadowType下拉列表SoftShadows,并改变相应想要的数值。在Hierarchy面板中Lights选项中创建一个Cube,重命名为CubeLight,在Inspector面板中更改位置以及大小,并网格编辑器MeshRenderer中元素Element拉进素材LightHardCookie,接着在CubeLight选项中创建PointLight,在Inspector面板中Light的范围Range设置为7,模式Mode选项选为Baked。将CubeLight拉进预制体_Prfabs中,并再重复使用拉进Lights选项中,并改变其相应位置,形成灯光环境。图4-4灯光显示图特殊道具想要保证游戏的可玩性,需要提供更多的游戏道具,丰富游戏玩法。因此在Hierarchy面板中创建一个Empty,将新创建的GameObject重命名为Interaction,并以此来存放特殊道具。特殊道具包括了:电脑、笔记本电脑、红色盖章和绿色盖章、危险警报器以及通行证和护照。因此,以下内容将是这些特殊道具的实现和说明。电脑办公桌右手边的电脑将显示入境人员的基本信息,以及游戏玩家进行匹对,以及提供点击下一位按钮。在Hierarchy面板中的Interaction右键,创建一个Empty,将新创建的GameObject重命名为Computer,并在Inspector面板中Transform修改位置,在Tag选项中点击AddTag添加Computer并选择,在Computer选项中创建一个Cube,将新建好的Cube重命名为computer,在在MeshFilter添加computer素材,接着在computer选项中创建一个Canvas,并在Inspector面板Canvas中渲染模式RenderMode选项中选择WorldSpace,随后在Canvas选项中创建两个Image,随着重命名为BasePanel、NPCInfoPanel,在BasePanel的Inspector面板中将已经在Photoshop做好的“桌面1”拖进ScourceImage,在NPCInfoPanel选项下创建一个Image,将其命名为dImage_Ce_C作为入境人员的信息照片,接着创建7个文本Text,并在Inspector面板Text相应的填上(入境人员详细信息、姓名、性别、年龄、国籍、职业、入境原因),又创建对应的6个空白文本Text,并重新命名,命名格式末尾带“_C”。以及创建一个Button并且点击下一位。图4-5电脑Hierarchy图图4-6电脑显示图设计好电脑后,在代码中使用一个单例类UIManager,类型为Dictionary<string,Dictionary<string,Transform>>的字典方法将父节点的名称以及带“_C”重命名子物体,存放进一个键值,并且对其字典的添加、移除和获取。其中包括了:AddUI(添加UI组件)、RmoveUI(移除UI组件)、GetUI(获取UI组件)。电脑上的UI将使用PureMVC框架实现功能,由经典的Model、View、Controller三层分离的方式。Model层由Data和Proxy组成,Data保存了View层的数据,而Proxy将Data封装起来,负责数据的获取和操作。View层由Mediator组成以及相应的UI组件,Mediator负责操作UI组件的命令。Controller层由Command组成,而Model和View通过了Command进行交互。表4-2PureMVC具体操作表View层编写了ComNPCInfoMediator继承了Mediator触发UI界面时、实例化其对应的Mediator、Proxy、Command,通过UIIManager获取UI组件。重写ListNotificationInterests和HandleNotification方法用于Notification的注册和接收。以及UpdateNPCInfo方法,将信息显示在UI文本。Model层编写ComNPCDataProxy继承Proxy初始化data数据,并监听触发UI监听。在UpdateNPCData方法中判断当前入境人员的信息是否为空,调用Mediator注册好的的Notification传送data数据作为参数进行View层的更新。获取新数据后,把数据更新到data中。Command层编写ComUpdateNPCInfoCommand继承SimpleCommand当实例化时便执行Execute方法。调用UpdateNPCData,更新Model层数据。Façade层脚本ComFacade继承Façade使用switch和case的方法判断不同的UI再分别的使用RegisterMediator、RegisterProxy、RegisterCommand的方法进行注册。编写OnDestroy方法,为委托添加对应的三层注销方法并存储到字典内,当该界面移除时,触发该委托执行,从而进行对应三层的注销。最后在主代码ComputerView中,每个UI的初始化时,遍历自身的所有节点,将所需要的子物体保存到字典内。使用这种方式后,我们只需要知道父物体的名称,该物体的名称,以及该物体的类型,就可以根据获得的transform得到对应的组件。UIManager.Instance.Init();
Transform[]
allChild
=
gameObject.transform.GetComponentsInChildren<Transform>();
foreach
(var
item
in
allChild)
{
if
(.EndsWith("_C"))
{
UIManager.Instance.AddUI(,,item);
foreach
(var
i
in
parents)
{
if
(item.parent.gameObject
==
i)
break;
}
parents.Add(item.parent.gameObject);
}
}
笔记本电脑笔记本电脑放置在主场景摄像机的左手方向,提供给游戏玩家当前的绩效、服务满意度、以及城市安全。当作玩家的得分状况。在Hierarchy面板中的Interaction右键,创建一个Empty,将新创建的GameObject重命名为portable,并在Inspector面板中Transform修改位置,在Tag选项中选择Computer,在网状过滤器MeshFilter以及网状渲器MeshRenderer中拖入相应的素材;添加组件碰撞MeshCollider,把portable添加进Mesh中;在portable中创建一个Panle,在Panle中拉入预先设计好的素材;接着在Plane中创建三个Text文本。图4-7笔记本电脑显示图在portable创建脚本SmallCom,创建一个UpdateText的方法,将相应的信息填写进三个text文本中。
void
Start()
{
text1
=
transform.Find("Canvas/Panel/Text1").GetComponent<Text>();
text2
=
transform.Find("Canvas/Panel/Text2").GetComponent<Text>();
text3
=
transform.Find("Canvas/Panel/Text3").GetComponent<Text>();
ScoreManager.Instance.UpdateTo();
}
public
void
UpdateText(string
str1,string
str2,string
str3)
{
text1.text
=
str1;
text2.text
=
str2;
text3.text
=
str3;
}
}
并在引用ScoreManager类里,初始分数设置为,工作绩点:15;服务满意:50;城市安全:100;并且通过if-else语句更新分数。表4-3得分机制表入境人员是否入境工作绩效服务满意城市安全安全是↑↑↑否↓↓↑危险是↓↑↓否↑↓↑当绩效低于5分,绩效不合格,游戏结束。if
(score
<=
5)
{
GameOver(OverType.score);
}
public
void
GameOver(OverType
type)
{
if
(type
==
OverType.score)
{
MenuManager.Instance.DisplayMenu(MenuType.gameover,
"绩效不达标!");
}
}
并且将使用ToString方法将intl类型转化为string类型,输入与笔记本电脑上的text文本。public
void
UpdateTo()
{
string
tmp
=
(score
/
10).ToString()
+
"."
+
(score
%
10).ToString();
evaluate
=
evaluate
<=
0
?
0
:
evaluate;
evaluate
=
evaluate
/
100f
>
1
?
1
:
evaluate;
string
tmp2
=
(evaluate
/
100f
).ToString();
smallCom.UpdateText(tmp,
tmp2,
secure.ToString());
}
红色盖章和绿色盖章通过游戏玩家判断入境人员是否符合入境资格,使用红色盖章拒绝通行,绿色盖章允许通行。在Hierarchy面板中Interaction的创建一个Empty,创建两个新的GameObject重命名为PassSeal、RejectSeal,并将Tag选为Interaction,在Inspector面板中改变两个物体的相应位置,添加碰撞BoxCollilder以及刚体Rigidboby,接着在PassSeal下使用Unity自带的ProBuilder工具搭建盖章模型,并创建Empty,重命名为HandTarget附着在盖章模型把手上当作抓取位置,添加OnTarch脚本;RejectSeal同理。图4-8盖章显示图在脚本里将盖章物体加入PlayCrt脚本中的<OnTarch>列表,创建一个的数组存放盖章上的MeshRenderer的组件,并遍历使用“标准着色器”在材质上设置值“_Value”,在PlayCrt脚本中使用实现交互效果。public
class
OnTarch
:
MonoBehaviour
{
MeshRenderer[]
renderers;
PlayerCtr
player;
private
void
Start()
{
renderers
=
new
MeshRenderer[transform.childCount];
renderers
=
transform.GetComponentsInChildren<MeshRenderer>();
player
=
GameObject.FindWithTag(Tag.Player).GetComponent<PlayerCtr>();
player.RegistInteraction(this);
}
public
void
Disable()
{
foreach
(var
renderer
in
renderers)
{
renderer.material.SetFloat("_Value",
0);
}
}
}
以及在PlayCrt脚本中使用射线RaycastHit实例UI形印章图片SetParent附着在想要的物体想以及保持之前的位置、旋转量、缩放值,而印章图片通过Resources加载预先放置的Pass(通过印章图片)、Reject(拒绝印章图片)。public
class
PlayerCtr
:
MonoBehaviour
{
public
List<OnTarch>
InteractionList;
public
void
InstanceSeal(RaycastHit
hit,
string
SealName)
{
GameObject
img
=
PoolManger.Instance.GetInstance(SealName);
img.transform.position
=
hit.point;
img.transform.forward
=
hit.normal;
if
(img.transform.rotation.y
!=
0)
img.transform.Rotate(0,
0,
90);
img.transform.SetParent(hit.transform,
true);
}
public
void
RegistInteraction(OnTarch
onTarch)
{
InteractionList.Add(onTarch);
}
}
金属探测仪金属探测仪是检测入境人员随身是否携带有危害金属物品,可以检测到如:手机、刀、枪械等等。在Hierarchy面板中Interaction的创建ProBuilderCube,重命名为Checker,并将Tag选为Interaction,创建出探测仪的模型,拉入MeshFilter素材;接着创建Empty,重命名为HandTarget附着在探测仪模型把手上当作抓取位置;接着创建Empty,重命名为CheckBox,加入碰撞体BoxCollider并点击EditCollider改变大小并勾上IsTrigger。图4-9金属探测仪显示图添加OnTarch脚本在Checker中,当游戏运行时,将探测仪添加进<OnTarch>列表中,在CheckBox添加CheckerBoxCollider脚本,使用Collider检测CheckBox与Tag标签里的CheckOB碰撞显示出物体,若使用LayerMask也检测CheckBox与layer层CheckOB发出警报声并且入境人员进行怀疑状态。public
class
CheckerBoxCollider
:
MonoBehaviour
{
private
void
OnTriggerEnter(Collider
collider)
{
if
(collider.tag.Equals(Tag.CheckOB))
{
foreach
(var
item
in
collider.gameObject.GetComponentsInChildren<MeshRenderer>())
{
item.enabled
=
true;
}
if
(LayerMask.LayerToName(
collider.gameObject.layer).Equals(Tag.CheckOB))
//被发现携带危险品
{
AudioManager.Instance.Play("check",
transform.position);
collider.transform.parent.parent.parent.GetComponent<NPC>().EvilBeFind();
}
}
}
}
危险警报器当检测到入境人员属于危险人员时,可按压安置在办公桌下方的红色按钮,保护自我的人生安全。在Hierarchy面板创建创建Cube,重命名为ArrestBtn,将素材拖进MeshFilter中,并添加胶囊碰撞体CapsuleCollider,点击EditCllider改变大小形状。图4-10危险警报器显示图创建ArrestBtn脚本放进ArrestBtn中,使用Tweener方法将危险警报器x轴方向前进0.008f,并保持该动画不变,不关闭改动画。public
class
ArrestBtn
:
MonoBehaviour
{
Tweener
tweener;
void
Start()
{
Vector3
target
=
transform.position;
target.x
+=
0.008f;
tweener
=
transform.DOMove(target,
1);
tweener.SetLoops(2,
LoopType.Yoyo);
tweener.Pause();
tweener.SetAutoKill(false);
}
}
接着在OnMouseDown方法里重新检验动画是否播放成功,并判断入境人员若是在怀疑状态则,发出警报声加载预制体的警察出现。或在检查状态则发出疑问。private
void
OnMouseDown()
{
if
(!tweener.IsPlaying())
{
tweener.Restart();
tweener.Play();
if(NPCManager.Instance.CurrentNPC!=null)
NPCManager.Instance.CurrentNPC.GetComponent<NPC>().BtnDown();
if(NPCManager.Instance.CurrentNPC.GetComponent<NPC>().fsmsys.CurrentIndex==((int)State.Doubt))
Instantiate(Resources.Load("NPC/swat"));
}
}
通行证和护照通行证以及护照是入境人员检查时提供的有效证件,检查证件也是游戏玩家查验入境人员身份的重要步骤。在Hierarchy面板中创建两个创建Cube,重命名为PassForm、SimplePassport,将通行证PassForm素材拖进Element里,添加BoxCollider,接着创建Panel,调整RectTransform中的位置以及大小,护照SimplePassport同理。在PassForm选项里的Panel中创建4个Text文本,并重命名为后缀带有“_C”调整到相应的位置RectTransform,将OnTarch脚本拖进PassForm将通行证也加入<OnTarch>链表中,以及创建脚本PassFormInfo并拖进PassForm,将入境人员的的信息赋值到通行证的Text文本中,如果入境人员状态为“evil”的并使用Random随机生成0-6个数字,随机改变通行证上的Text文本框信息。形成通行证信息与入境人员自身信息不同的情况。图4-11通行证和护照public
class
PassFormInfo
:
MonoBehaviour
{
...
public
void
UpdateInfo(BaseNPC
info)
{
nameText.text
=
info.Name;
passNOText.text
=
info.PassNO;
causeText.text
=
info.Cause;
dateText.text
=
info.Date;
if
(info.Evil)
{
switch(
Random.Range(0,
6))
{
case
0:nameText.text
=
NPCManager.Instance.Databuilder.GetRandonName();
break;
case
1:passNOText.text
=
NPCManager.Instance.Databuilder.GetRandomPassNO();
break;
case
2:causeText.text
=
NPCManager.Instance.Databuilder.GetRandomCause();
break;
case
3:dateText.text
=
NPCManager.Instance.Databuilder.GetRandomDate();
break;
}
}
}
}
在SimplePassport选项里的Panel中创建5个Text文本,1个Image并重命名为后缀带有“_C”调整到相应的位置RectTransform,将OnTarch脚本拖进SimplePassport将通行证也加入<OnTarch>链表中,创建脚本PassPortInfo并拖进SimplePassport,脚本逻辑与PassFormInfo同理。在预先写好的PlayerCtr脚本中,使用射线RaycastHit功能检测碰撞体是否为护照,并调整好位置并使用Material对应的盖章渲染出来。public
void
UpdatePassFormSealTextPos(RaycastHit
hit)
{
Vector3
offset
=
hit.collider.gameObject.transform.position
-
hit.point;
offset
*=
10f;
offset.x
=
offset.x
<
0
?
offset.x
*
-2f
:
offset.x
*
-1f;
offset
+=
new
Vector3(1,
0,
0.7f);
offset.x
/=
3;
offset.z
/=
1.5f;
offset
*=
-3f;
offset
+=
new
Vector3(0.5f,
0,
0.5f);
Material
tmpMater
=
hit.collider.gameObject.GetComponent<MeshRenderer>().material;
tmpMater.SetTexture("_SealText",
sealText);
tmpMater.SetVector("_Offset",
new
Vector4(offset.z,
offset.x,
0,
0));
tmpMater.SetFloat("_IsSeal",
1);
}
接着实现查看通行证和护照以及取消查看,在Hierarchy面板中创建Empty,重命名为PassportViewPos,并在下列创建四个Empty,分别重命名为From0、From1、To0、To1,调整好Transform,分别两两对应,并在PlayerCtr脚本中创建两个Transform数组存放,当作查看通行证和护照时显示位置;再创建Tweener数组存放两组From0到To0、以及From1到To1的动画显示。public
class
PlayerCtr
:
MonoBehaviour
{
tweener[0]
=
fromPos[0].transform.DOMove(toPos[0].position,
1);
tweener[0].Pause();
tweener[0].SetAutoKill(false);
tweener[1]
=
fromPos[1].transform.DOMove(toPos[1].position,
1);
tweener[1].Pause();
tweener[1].SetAutoKill(false);
...}
创建一个Transform数组resetPassportPos存放护照和通行证放置在办公桌的位置,当要查看证件时先判断fromPos[0]是否已存在物体,若无物体则将所查看的证件存放在fromPos[0],并且播放tweener[0]动画;若已有物体存在则将证件存放在fromPos[1],并播放tweener[1]动画。public
void
UpdateSeeAnim(int
index)
{
if
(index
==
0||index==2)
{tweener[0]
=
fromPos[0].transform.DOMove(toPos[0].position,
1);
tweener[0].Pause();
tweener[0].SetAutoKill(false);
}
if
(index
==
1||index==2)
{tweener[1]
=
fromPos[1].transform.DOMove(toPos[1].position,
1);
tweener[1].Pause();
tweener[1].SetAutoKill(false);
}
}
public
void
SeePassport(GameObject
ob)
{
int
index
=
fromPos[0].childCount
==
0
?
0
:
1;
UpdateSeeAnim(index);
tweener[index].OnStepComplete(()
=>
{
});
ob.transform.SetParent(fromPos[index]);
ob.transform.position
=
fromPos[index].position;
ob.transform.rotation
=
fromPos[index].rotation;
tweener[index].PlayForward();
}
当取消查看证件时,判断取消查看物体是否存在fromPos[0],若存在证件则使用PlayForward反向播放tweener[0]动画并且将物体存放在Transform数组resetPassportPos位置上;若不存在则反向播放tweener[1]动画并且将物体存放在Transform数组resetPassportPos位置上。public
void
QuitSee(GameObject
ob)
{
int
index
=
==
"From0"
?
0:1;
tweener[index].OnStepComplete(()=>
{
ob.transform.SetParent(null);
ob.transform.position
=
resetPassportPos[index].position;
ob.transform.rotation
=
resetPassportPos[index].rotation;}
);
tweener[index].PlayBackwards();
}
入境人员检查入境人员是这款游戏的主要玩法,因此丰富入境人员便丰富了游戏玩法,增加了游戏的可玩性。我将从入境人员的基本信息多种类、携带的物体、创建入境人员信息入境人员的信息是使用序列化Serializable,分别创建编号、姓名、性别、年龄、入境原因、国籍、以及通行证编号,将序列化好的信息实例好在BaseNPC中;并且将大量不重复的姓名、性别、年龄、入境原因、国籍分别填入txt文件中,作为入境人员的信息资料。因此,创建一个NPCDataBuilder类,使用UnityWebRequest方法读取txt文件,将txt文件上的信息赋值给入境人员,并且使用string系统里的Split方法将txt文件中的信息切割成一组一组数组成为入境人员的信息。例如:string
text
=
textNameMan._WWW.downloadHandler.text;
string[]
texts
=
text.Split(System.Environment.NewLine.ToCharArray(),System.StringSplitOptions.RemoveEmptyEntries);
nameMan
=
new
string[texts.Length];
for
(int
i
=
0;
i
<
texts.Length;
i++)
{
nameMan[i]
=
texts[i];
}
接着在GetNPCData中使用Random.Range方法随机生成字符串数组赋值给对应的入境人员数据中。public
BaseNPCDataTmp
GetNPCData()
{
BaseNPCDataTmp
npc
=
new
BaseNPCDataTmp();
npc.Sex
=
Random.Range(0,
5)
<
4
?
"男"
:
"女";
npc.Name
=
npc.Sex
==
"男"
?
nameMan[Random.Range(0,
nameMan.Length)]
:
nameWoman[Random.Range(0,
nameWoman.Length)];
npc.Age
=
(byte)Random.Range(18,
58);
npc.Nation
=
nation[Random.Range(0,
nation.Length)];
npc.Occu
=
occu[Random.Range(0,
occu.Length)];
npc.Cause
=
cause[Random.Range(0,
cause.Length)];
return
npc;
}
入境人员携带物品入境人员携带的物品,包括通行证和护照,以及可能包括危险金属物品(枪械,刀)和普通金属物品手机等等。因此在入境人员选项中创建六个空物体创建Empty,分别重命名为Passport、Passform、0、1、2、3,其中调整Passport和Passform的Transform位置为入境人员的手心,作为通行证和护照,接着0、1、2、3,分别调整Transform位置为入境人员的衣兜、以及口袋,并归于CheckOBPos选项下,当作金属物品存放位置。在NPCManager脚本中实例携带的物品,若入境人员为危险人员,则必须携带一件或者多个以上的危险物品,并随机放置在(0、1、2、3)上。
private
void
InstanCheckOB(bool
isEvil,
GameObject
npcModel)
{
int
count
=
Random.Range(0,
3);
if
(count
==
0
&&
isEvil)
{
count
=
1;
}
for
(int
i
=
0;
i
<
count;
i++)
{
GameObject
tmp;
if
(i
==
0
&&
isEvil)
{
tmp
=
Instantiate(Models.GetCheckOBRandom());
npcModel.GetComponent<NPC>().weapon
=
tmp;
}
else
{
tmp
=
Instantiate(Models.GetSaveOBRandom());
}
tmp.transform.SetParent(npcModel.transform.Find("CheckOBPos").transform.Find(Random.Range(0,
4).ToString()));
tmp.transform.localPosition
=
Vector3.zero;
tmp.transform.right
=
Camera.main.transform.forward;
MeshRenderer[]
meshs=
tmp.GetComponentsInChildren<MeshRenderer>();
foreach
(var
item
in
meshs)
{
item.enabled
=
false;
}
}
}
入境人员动作当入境人员运行其中一种触发的时候,会导致其他动作无法触发,造成动作之间不相协调失去仿真性,以下是我实现入境人员动作的方法。我入境人员的动作如下表,创建对应的Animator。表4-4Animator表动作名称Animator名称步行Walk谈话Talk坐下Sit拿起特殊道具(枪械、证件)Take举手投降HandUp图4-12动画状态图在游戏创建入境人员时就会添加AI脚本,使用Animator.StringToHash将对应的动作生成ID,并使用Animator系统中的AnimatorOverrideControllerr生成状态机动画存放在animationClips数组里,对基础的AnimatortControll进行覆盖,等待被激活使用。图4-13动画状态图为了使入境人员的动作更加仿真,给人物添加了程序化动画绑定(AnimationRigging),如<TwoBoneIKConstraint>、<MultiParentConstraint>、<MultiAimConstraint>,将这些组件添加在人物关键的骨骼上。在脚本里添加入境人员神态眼睛看的地方,以及改变Rig的权重。private
void
Update()
{
//如果使用左手,权重设置在1到随速度2线性插值
if
(lfHandEnable)
{
lfHandWeight
=
Mathf.Lerp(lfHandWeight,
1,
Time.deltaTime
*
weightSpeed);
}
else
{//若小于0.1f设置为0
if
(lfHandWeight
!=
0)
{
if
(lfHandWeight
<
0.1f)
{
lfHandWeight
=
0;
}
else//若大于0.1f,则设置在0到随速度2线性插值
lfHandWeight
=
Mathf.Lerp(lfHandWeight,
0,
Time.deltaTime
*
weightSpeed);
}
}
if
(rtHandEnable)
//如果使用右手,权重设置在1到随速度2线性插值
{
rtHandWeight
=
Mathf.Lerp(rtHandWeight,
1,
Time.deltaTime
*
weightSpeed);
}
else
{//若小于0.1f设置为0
if
(rtHandWeight
!=
0)
{
if
(rtHandWeight
<
0.1f)
{
rtHandWeight
=
0;
}
else//若大于0.1f,则设置在0到随速度2线性插值
rtHandWeight
=
Mathf.Lerp(rtHandWeight,
0,
Time.deltaTime
*
weightSpeed);
}
}
}
入境人员交互与入境人员进行简单对话推动了游戏的剧情进程。在入境人员选项下创建两个文本框,并且制作一份入境人员对话的Excel表格,并且创建一个NPCTalkMag基类,获取了读取对话Excel表格转化为Json文件数据、以及使用JsonMapper.ToObject储存在一个BaseTalkTmp数组中。并遍历使用字典Dictionary添加,如:string
str
=
txt._WWW.downloadHandler.text;
BaseTalkTmp[]
tmp
=
JsonMapper.ToObject<BaseTalkTmp[]>(str);
foreach
(var
item
in
tmp)
{
BaseTalkTmpForRead
tmptalk
=
new
BaseTalkTmpForRead(item);
dict.Add(tmptalk.Mood,
tmptalk);
}
枚举了入境人员谈话过程中可能出现的状态greet、jumpQueue、beJumpQueue、accept、reject、pass、nopass、doubt、evil、panic、thank、disappoint。编写BaseTalk方法,使用while将第一轮对话进行到底,跳出循环进行第二轮对话。
while
(tmpbase
!=
null)
{
tmpbase.index
+=
index;
tmpbase.question
=
_talk.strs[tmpbase.index];
tmpindex
=
tmpbase.index;
tmpbase
=
tmpbase.answer1;
}
answer2
=
ans2;
tmpbase
=
answer2;
tmpindex
=
index;
while
(tmpbase
!=
null)
{
tmpbase.index
+=
index;
tmpbase.question
=
_talk.strs[tmpbase.index];
tmpindex
=
tmpbase.index;
tmpbase
=
tmpbase.answer2;
}
question
=
_talk.strs[index];
}
接着在入境人员选项下创建两个Button,与入境人员进行交互,基础脚本TalkBoxCtr继承于NPCTalkMag,添加了按钮触发事件。private
void
BtnEvent(int
index)
{
HideSelect();
bool
isPositive
=
answer1Index
==
index
?
true
:
false;
BaseTalk
tmp
=
isPositive
?
baseTalk.answer1.answer1
:
baseTalk.answer2.answer1;
TalkOrMood(tmp.question);
SendEvent(isPositive);
baseTalk
=
null;
}
不同状态触发不同事件,通过判断NPCTalkMag类里入境人员枚举的状态,例如偏激状态下不同入境人员(危险人员、插队人员、被插队人员)的回应。示例如:偏激状态下危险人员回答的问题。
if
(talkState
==
TalkState.greet)
{
if
(IsPositive)
{
if
(npc.baseNPC.Evil)
TalkOrMood(NPCManager.Instance.Databuilder.GetRandomCause());
else
TalkOrMood(npc.baseNPC.Cause);
}
}
使用SetPositionAndRotation和Vector3系统中Lerp方法实现对话框分段上升动画效果。private
void
UpdatePanel(int
Listindex,bool
isMoverToUp=false)
{
if
(Listindex>=panels.Count)
return;
RectTransform
tmp
=
panels[Listindex];
int
index;
if
(tmp.Equals(panel[0]))
index
=
0;
else
index
=
1;
time[index]
-=
Time.deltaTime;
if
(time[index]
<=
0)
{
time[index]
=
0;
HideTalk(index);
return;
}
if
(isMoverToUp)
{
Vector3
target
=
new
Vector3(panel[index].position.x,
secondPosY,
panel[index].position.z);
Vector3
lerp
=
Vector3.Lerp(panel[index].position,
target,
Time.deltaTime
*
moveSpeed);
panel[index].SetPositionAndRotation(lerp,
panel[index].rotation);
}
}
主要对话交流进程。当点击左右两个按钮提出简单问题询问入境人员相关情况,入境人员并随着回答。。public
void
TalkByBaseTalk(BaseTalk
_baseTalk,TalkState
state)
{
talkState
=
state;
baseTalk
=
_baseTalk;
TalkOrMood(baseTalk.question);
button[0].GetComponentInChildren<Text>().text
=
null;
button[1].GetComponentInChildren<Text>().text
=
null;
if
(baseTalk.answer1
==
null)
return;
int
index
=
Random.Range(0,
1);
answer1Index
=
index;
button[index].GetComponentInChildren<Text>().text
=
baseTalk.answer1.question;
if
(baseTalk.answer2
==
null)
return;
button[++index
%
2].GetComponentInChildren<Text>().text
=
baseTalk.answer2.question;
}
当游戏过程中,添加了入境人员出现插队的状况,因此添加了NPCThinkMag类。等待过程中,入境人员通过判断检查人员以及被插队人员都不为空并且自身的情绪数值小于3便进行插队;public
void
ThinkForChangeState(NPC
npc)
{
if
(npcMag.npcQueue.Count
!=
0
&&
npcMag.JumpQueueNPC
==
null&&
!npcMag.SomeoneReadToJump
&&
npcMag.BeJumpNPC==null
&&npc.baseNPC.mood<3)
npc.fsmsys.ChangeState((int)State.JumpQueue);
else
if
(npcMag.CurrentNPC
!=
null
||
npcMag.JumpQueueNPC
!=
null
||
npcMag.BeJumpNPC
!=null)
npc.fsmsys.ChangeState((int)State.Sit);
else
npc.fsmsys.ChangeState((int)State.Check);
}
当游戏玩家面对插队情况下,选择被插队人员或者插队人员时,被插队人员和插队人员通过自身的情绪数值表现出的不同状态回应。public
bool
ThinkForBeRejectJumpQueue(NPC
npc)
{
npc.baseNPC.mood--;
if
(npc.baseNPC.mood.Equals(0))
return
true;
else
return
false;
}
public
bool
ThinkForBeJumped(NPC
npc)
{
if
(npc.baseNPC.mood-1<1)
return
true;
else
return
false;
}
入境人员路径当游戏运行时,入境人员由游戏场景外进入摄像头场景,游戏进程的不同则入境人员相应的位置也不相同。因此,需要规范好相应的路径点,规范好游戏进程的顺序。在Hierarchy面板中创建8个空物体(出生起点、进门点、检查点、入境消失点、拒绝入境消失点、排队一、排队二、排队三),以及两个空物体,重命名为JumpQueuePos、BeJumpQueuePos,分别为插队
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 考研《美术学(050403)》名校考试真题试题库(含答案)
- 2025年陕西职教高考《职业适应性测试》考前冲刺模拟试题库(附答案)
- 2025年河南工业和信息化职业学院高职单招语文2018-2024历年参考题库频考点含答案解析
- 专题07 浮力(讲练)
- 幼儿园自理能力活动策划方案五篇
- 镍铁购销合同
- 幼儿园制作蛋糕活动策划方案四篇
- 家具安装合同范文
- 人工智能产业基金投资合同
- 农场果品购销合同模板范本
- 2024年公安机关理论考试题库附答案【考试直接用】
- 课题申报参考:共同富裕进程中基本生活保障的内涵及标准研究
- 2025中国联通北京市分公司春季校园招聘高频重点提升(共500题)附带答案详解
- 康复医学科患者隐私保护制度
- 环保工程信息化施工方案
- 红色中国风2025蛇年介绍
- 《内脏疾病康复》课件
- 家具厂各岗位责任制汇编
- 提高检验标本合格率品管圈PDCA成果汇报
- 世界古代史-对接选择性必修(真题再现) 高考历史一轮复习
- 植物的类群及演化
评论
0/150
提交评论