基于Unity3d的多人合作游戏开发_第1页
基于Unity3d的多人合作游戏开发_第2页
基于Unity3d的多人合作游戏开发_第3页
基于Unity3d的多人合作游戏开发_第4页
基于Unity3d的多人合作游戏开发_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

摘要近几年来,随着科技的发展,计算机的配置越来越好,游戏行业也因为这一浪潮蓬勃发展。在社会的各种压力下,许多人都选择在下班时间与朋友一起玩游戏。在这一条件下促使了多人合作游戏的火热,这类游戏易上手,音乐节奏较为欢快。并且强调人们之间的沟通协作能力,在轻松慢节奏的游戏过程中增进彼此之间的友情。多人合作游戏经过长时间的发展变得多种多样,但总的来说均使玩家得到了轻松愉快的游戏体验。选择了Unity3D进行开发主要是开发易上手,开发界面交互较为友好,能够较为便捷的实现所需功能,并且支持为多个平台生成可执行文件,在Windows或者其他任何平台上启动它而无需任何额外的努力。并且开发者可以在Unity3D中的AssetsStore里购买到正版素材,无需为游戏素材担心。本文主要包括了此游戏的开发方式以及开发的原理,游戏场景关卡的设计和游戏的联网功能测试等步骤。希望能够为后续同类多人游戏制作者提供参考和借鉴。关键词:Unity3D多人游戏联网游戏

AbstractInrecentyears,withthedevelopmentofscienceandtechnology,theconfigurationofcomputersisgettingbetterandbetter,andthegameindustryisboomingbecauseofthiswave.Underallkindsofsocialpressures,manypeoplechoosetoplaygameswithfriendsduringoffhours.Underthiscondition,thepopularityofmultiplayercooperativegamesispromoted.Suchgamesareeasytoplay,andthemusicrhythmisrelativelyhappy.Andemphasizetheabilityofcommunicationandcooperationbetweenpeople,andenhancethefriendshipbetweenthemintheprocessofrelaxedandslow-pacedgame.Afteralongtimeofdevelopment,multiplayercooperativegameshavebecomediversified,butingeneral,theymaketheplayershavearelaxedandpleasantexperience. Unity3dischosenfordevelopment,whichiseasytostartwith,friendlytodevelopinterface,convenienttorealizerequiredfunctions,andsupportsgeneratingexecutablefilesformultipleplatforms,enablingitonwindowsoranyotherplatformwithoutanyextraeffort.Anddeveloperscanbuyauthenticmaterialsintheassetsstoreofunity3dwithoutworryingaboutgamematerials. Thisarticlemainlyincludesthedevelopmentmodeandprincipleofthegame,thedesignofgamescenelevelandthenetworkingfunctiontestofthegame.Hopetobeabletoprovidereferenceandreferenceforthefollowingsimilarmultiplayergamemakers.Keywords:Unity3DMultiplayergameNetworkinggames

目录第一章 绪论 绪论

选题的目的和意义近些年以来,随着计算机和通信领域的不断发展,网络带宽的配置也变得越来越好,因此网络游戏也随着更快的网络,更低的网络延迟而走进千家万户。网络游戏也因为硬件需求较为大众化,不需要特别好的电脑配置而广受电脑游戏玩家喜爱。其中多人合作网络游戏不仅配置的需求较低,玩法也更趋向于简单化,比一般的网络游戏更适合各个年龄段的玩家而广受追捧。此类游戏易上手,节拍也很欢快轻松。当然,玩家间的沟通和协作能力也是玩这类游戏不可缺少的,在轻松愉悦的游戏过程中,彼此之间的友情也得到了增进。选择了Unity3D进行开发主要是开发易上手,软件的交互做的比较友好,能够较为便捷的实现所需功能,并且支持为多个平台生成可执行文件,在Windows或者其他任何平台上启动它而无需任何额外的努力。并且用户可以在Unity3D中的AssetsStore里购买到正版素材,无需为游戏素材担心。通过设计和游玩多人合作游戏,让我切身体会到游戏的趣味性和游戏拉近了玩家之间的距离,增进了感情又可以让玩家得到身心上的放松,拉近朋友之间的距离,让人保持身心愉悦。本项目使用Unity3D开发和设计,探究如何设计开发一个多人游戏并实现多人联机功能是本次实验的主要目的。国内外研究现状近年来,随着Unity3D引擎的快速推广,越来越多的游戏厂商开始使用Unity引擎进行游戏开发,多人合作游戏在国外也发展迅速。其中由GhostTown工作室使用Unity3D引擎开发的多人合作游戏《Overcooked》在2016年获得了TGA最佳多人游戏提名,证明多人游戏在玩家间的受欢迎程度之高。随着网络技术的发展,网络游戏的玩家越来越多。网络游戏发展迅速,是当前游戏产业中规模最大的一类。国内首款自主研发的3D游戏始于2003年,到目前为止,国内在3D游戏方面已经有了很多的研究,不过考虑到3D游戏开发的复杂性和经济效益,国内拥有自主研发的3D游戏引擎的互联网公司屈指可数,中小型公司更多还是使用国外相较成熟的游戏工具。多人网络游戏的联机效果关乎到游戏过程的流畅性,游戏中的元素实时更新决定了游戏过程的流畅程度。是否使用更好的网络服务器以及优化较好的服务器引擎决定了玩家的游玩体验。国内的各大公司中,网易,腾讯等知名公司的联机游戏体验较好,但一般游戏开发商想要重新开发一个流畅的服务器引擎是不经济的,对于一般的开发者来说,熟悉并掌握Unity3D游戏引擎和第三方的服务器引擎可以降低游戏开发周期。论文组织架构论文从构思到实践查阅了大量的游戏开发手册以及专业的开发资料,进行了一个多人合作联网游戏的设计制作。其中具体介绍了游戏的设计思路以及制作步骤,包括游戏各部分的设计,部分代码的编写,以及将游戏部署在网络上并传输信息三个部分。论文分为六个章节,各章节的内容安排为:第一部分:绪论部分。主要内容是介绍了该项目设计和制作的背景,国内外关于游戏引擎和服务器引擎的研究现状和该项目的大致内容介绍;第二部分:主要阐述了本项目使用的开发工具,服务器引擎以及Unity3D等的大致介绍;第三部分:详细介绍游戏的设计思路以及实现的各个步骤;第四部分:游戏界面的UI设计;第五部分:运行游戏测试界面,打包封装;第六部分:总结项目的不足和缺陷以及改进的方向。

游戏开发工具

Unity3D游戏引擎Unity3D软件介绍Unity3D是由UnityTechnologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。从通用性上考虑,Unity3D是目前使用范围最广的引擎。它可以在多个平台上进行开发,并可以较为方便地将项目配置在PC,手机等各个平台,其对于个人版免费的策略也非常适合游戏初学者上手。并且Unity3D支持C#,javascript等多种语言编程,操作界面也较为简单,易上手,包括project,hierarchy,inspector,scene,game等视图,分别用来存放游戏素材和资源,编辑游戏场景并放置游戏对象,描述并配置游戏脚本和素材信息,存放模型资源以及观察游戏实际运行效果。在游戏素材方面,Unity拥有AssestStore素材商店,支持.fbx,.dae,.3ds,.dxf,.obj等通用模型格式,不必担心游戏素材的问题。Unity3D引擎常用函数使用Unity3D引擎制作游戏时,需要经常用到几个生命周期函数:Awake():初始化函数,在游戏开始的时候自动进行调用,只会调用一次。Start():初始化函数,在Awake函数和Update函数之间调用。只调用一次。用于赋予变量初始值。Update():每一帧都会调用一次,受游戏的帧率影响。一般用于游戏内的数值监测。FixedUpdate():每隔一定的时间调用并且不受帧率影响。常用于物理引擎的调用,以及需要固定时间更新的函数。OnTriggerEnter():当配置了碰撞体的物体进入拥有此函数的物体之后,执行函数里的内容一次,用于判定角色是否触碰目标物体的判定。OnTriggerStay():当函数识别的碰撞体进入挂有该函数的物体后,不断执行函数内的内容,用于拾取物品等用途。Invoke():延时执行函数,在UI设置的界面的开启或者关闭或者是自身脚本的执行上使用。SendMessage():向该脚本所在的物体呼叫函数,一般用于传送消息。GUI(图形用户界面)GUI即GraphicalUserInterface(图形用户界面)的简称,泛指用户的操作界面。本文主要使用了UGUI对游戏的界面进行开发,UGUI就是Unity的GUI系统,在此前广泛使用的UI系统为NGUI,是UGUI出现之前非官方制作的GUI插件。作为一个非官方插件虽然让UI开发工作变得简单,但相比UGUI系统的Image可以使用material,不需要绑定Colliders便可以自动拦截事件,在Navigation在Scene中可视化等功能,其易用性是没法比的。UGUI是Unity3D原生支持的UI方案,使用上比NGUI插件更加的人性化。。3DsMax软件3DStudioMax常常简称为3DMax或3DsMax,由Discreet公司开发制作。前身为DOS系统上的3DStudio系列软件。因为可以安装更多插件,使用者多便于交流,上手容易,并且拥有强大的角色动画制作能力而广泛应用于三维动画,工业设计,建筑设计,游戏等领域的建模。 在本项目中3DsMax软件因为建模需要花费很多的时间与精力,所以并不会将软件用于建模功能,而是用于防止模型出错而下载备用。本项目所采用的建筑与人物模型将从Unity的官方商店AssetStore下载,以降低开发所需的时间成本。C#开发语言C#语言是由Microsoft公司发布的面向对象的,基于.NETFramework和.NETCore上的高级程序设计语言。C#几乎集中了所有关于软件开发和软件工程研究的最新成果:面向对象、类型安全、组件技术、自动内存管理、跨平台异常处理、版本控制、代码安全管理等等。根据以上特点,我们在Unity3D引擎上优先考虑使用C#语言进行开发。Photon引擎Photon引擎介绍在以前,制作一个合格的多人网络游戏需要大量的金钱及人力开发游戏引擎及服务器,。随着技术的进步,开始有了成型的游戏引擎,像Unity3D引擎、虚幻引擎等,也因为开发周期的需要出现了成型的服务器引擎。如SmartFoxServer、ElectroServer、PhotonServer等。这些成型的游戏服务器为游戏公司省下大量的开发费用,也让一些小型公司或独立制作团队有了开发网络游戏的能力,尤其在社群游戏盛行的这个年代成型的服务器越来越受欢迎。

Photon是一个泛用性的ScoketServer套装软件,可用于多人在线游戏、聊天室、大厅游戏,同时支持Windows、Unity3D、iOS、Android等平台。服务端底层由C++语言编写,客户端使用C#语言编写,跨多平台,拥有免费的体验服务器,并且Photon也是比较早且成熟的与Unity携手工作的引擎之一。Photon在多人在线共享游戏场景保持平台和多玩家(多客户端)的性能优越。

PUN(PhotonUnityNetworking)介绍PhotonUnityNetworking(首字母缩写PUN)是一个Unity多人游戏插件包。它提供了身份验证选项、匹配,以及快速、可靠的通过我们的Photon后端实现的游戏内通信。使用PUN不需要搭建服务器,与Unity3D引擎完美整合,项目可以导出至所有Unity支援的平台。根据以上与Unity完美兼容的特性以及易上手,无需自己维护服务器等特点,在本项目中采用PUN插件进行网络部分的配置。

游戏设计

场景设计游戏总共包括两个场景:场景1和场景2,场景1是游戏联机匹配的主页面,场景2是游戏的主场景。场景2中主要包括以下对象:地形:包括货柜,收银台等游戏场景。游戏对象:联机中的人物,由脚本在固定位置生成。其他物体:货篮等障碍物。场景的制作利用Unity3D的官方商店AssetStore寻找适合的场景,在AssetStore的页面中点击Import按钮将所需的场景导入到项目中。并在Scene面板中拖动至大致需要的位置,在Inspector面板设置各物体的具体位置参数。在Inspector面板中,设置物体的Transform选项比较重要,Position表示物体在世界坐标中的位置,Rotation表示物体模型沿着X,Y,Z轴旋转的角度,Scale表示物体在X,Y,Z轴的缩放。移动货篮,并拼凑相应的货架,修改并重新搭建原场景后,最终产生了适合游戏的场景,如图3-1所示。图3-1修改后的游戏场景人物的控制与动画导入人物模型首先要设计玩家在游戏中所使用并控制的人物,由于设计人物模型的时间成本较高,所以采用Unity官方商店AssetStore中的人物模型。Unity3D所支持的模型格式有许多种,在前期项目的关卡设计中我已经下载并导入项目中。将Project面板中的人物模型直接拖入Project中,调整原始的大小和旋转角度即可,如图3-2所示。图3-2导入后的人物模型人物模型运动的实现将人物模型导入后,给人物添加刚体Rigidbody以实现摩擦力,阻力等物理效果,给人物添加胶囊碰撞体CapsuleCollider,用于与其他碰撞体产生碰撞交互。 添加以上两个所需的组件后,需要设置其参数,Rigidbody的参数为默认即可,CapsuleCollider需要点击EditCollider更改其大小,以符合人物模型大小产生更合理的碰撞。如图3-3所示。图3-3人物模型及刚体的配置接下来给人物模型添加人物的移动脚本playerControl.cs,在此脚本中编写人物的移动和旋转函数。人物的移动使用的方法是Rigidbody.MovePosition()函数,人物旋转使用的方法是Rigidbody.MoveRotation()函数。移动和旋转脚本在FixedUpdate()函数中调用。 最后,给人物添加运动时播放的动画。在Inspector面板中添加Animator组件,并在Project面板中右键→Create→AnimationController新建一个动画控制器,将其拖入Animator组件中的Controller选项中。简单配置动画控制器,如图3-4所示。图3-4人物动画控制器配置

编辑脚本如下:

using

System;

using

System.Collections;

using

System.Collections.Generic;

using

UnityEngine;

public

class

playerControl

:

MonoBehaviourPun

{

public

float

speed

=

6f;

Vector3

movement;

Animator

anim;

Rigidbody

playerRigidbody;

int

floorMask;

float

camRayLength

=

100f;

private

void

Awake()

{

floorMask

=

LayerMask.GetMask("Floor");

anim

=

GetComponent<Animator>();

playerRigidbody

=

GetComponent<Rigidbody>();

}

private

void

FixedUpdate()

{

float

h

=

Input.GetAxisRaw("Vertical");

float

v

=

-Input.GetAxisRaw("Horizontal");

Move(h,

v);

Turning();

Animating(h,

v);

}

void

Move(float

h,

float

v)

{

movement.Set(h,

0f,

v);//存储键盘输入

movement

=

movement.normalized

*

speed

*

Time.deltaTime;

playerRigidbody.MovePosition(transform.position

+

movement);

}

void

Turning()

{

Ray

camRay

=

Camera.main.ScreenPointToRay(Input.mousePosition);

RaycastHit

floorHit;

if

(Physics.Raycast(camRay,

out

floorHit,

camRayLength,

floorMask))

{

Vector3

playerToMouse

=

floorHit.point

-

transform.position;

playerToMouse.y

=

0f;

Quaternion

newRotation

=

Quaternion.LookRotation(playerToMouse);

playerRigidbody.MoveRotation(newRotation);

}

}

void

Animating(float

h,

float

v)

{

bool

walking

=

h

!=

0f

||

v

!=

0f;

anim.SetBool("IsWalking",

walking);

}

游戏中的碰撞检测游戏需要检测人物碰到了什么,并处理碰撞体的信息。首先要在货架上添加BoxCollider碰撞体并调整大小用于物理碰撞,人物碰到货架时会停下来,然后添加货架的tag用于与非货架物体区分。 在playerController.cs编辑代码部分,用OnCollisionStay()函数检测人物模型所碰到的物体,用name储存物体碰撞体的名字,在人物碰到带有tag的货架时,玩家按键盘上的E键即可获取货架上的商品。脚本编辑完毕后,将player设置为预制体,在游戏开始时实例化。private

void

OnCollisionStay(Collision

collision)

{

string

name

=

;

if

(collision.gameObject.tag

==

"container")

{

if

(Input.GetKeyDown(KeyCode.E))

{

//按e拿取物品

Debug.Log("拿到了

"

+

name);

TaskEventArgs

e

=

new

TaskEventArgs();

e.id

=

name;

e.amount

=

1;

MesManager.Instance.Check(e);

}

}

3.4游戏中的任务系统 游戏中的任务内容通过XML文件储存。首先要新建Task.xml文件,编辑任务内容。部分任务内容如下:<Task1>

<taskName>购物清单</taskName>

<caption>苹果*2,冰棍*3</caption>

<conditionID>苹果</conditionID>

<conditionTargetAmount>2</conditionTargetAmount>

<conditionID>冰棍</conditionID>

<conditionTargetAmount>3</conditionTargetAmount>

<rewardID>报酬</rewardID>

<rewardAmount>5</rewardAmount>

</Task1>

<Task2>

<taskName>购物清单</taskName>

<caption>方便面*10,酱油*1</caption>

<conditionID>方便面</conditionID>

<conditionTargetAmount>10</conditionTargetAmount>

<conditionID>酱油</conditionID>

<conditionTargetAmount>1</conditionTargetAmount>

<rewardID>报酬</rewardID>

<rewardAmount>15</rewardAmount>

</Task2>

首先新建任务脚本Task.cs,用Task()函数将taskID所指向的任务初始化:利用taskID读取XML中的元素并装入XElement中,创建IEnumerable可枚举元素和Ienumerator枚举器迭代添加任务要求和任务报酬。public

class

Task

:MonoBehaviour

{

public

TaskItem

taskItem;//对应的UI面板

public

string

taskID;//任务ID

public

string

taskName;//任务名字

public

string

caption;//任务描述

public

List<TaskCondition>

taskConditions

=

new

List<TaskCondition>();

public

List<TaskReward>

taskRewards

=

new

List<TaskReward>();

//根据taskID读取xml,实现初始化

public

Task(string

taskID)

{

this.taskID

=

taskID;

XElement

xe

=

TaskManager.Instance.rootElement.Element(taskID);

taskName

=

xe.Element("taskName").Value;

caption

=

xe.Element("caption").Value;

IEnumerable<XElement>

a

=

xe.Elements("conditionID");

IEnumerator<XElement>

b

=

xe.Elements("conditionTargetAmount").GetEnumerator();

IEnumerable<XElement>

c

=

xe.Elements("rewardID");

IEnumerator<XElement>

d

=

xe.Elements("rewardAmount").GetEnumerator();

foreach

(var

s

in

a)

{

b.MoveNext();

TaskCondition

tc

=

new

TaskCondition(s.Value,

0,

int.Parse(b.Current.Value));

taskConditions.Add(tc);

}

foreach

(var

s

in

c)

{

d.MoveNext();

TaskReward

tr

=

new

TaskReward(s.Value,

int.Parse(d.Current.Value));

taskRewards.Add(tr);

}

}

接下来需要更新任务进度,并判断任务条件是否满足。编写Check()函数以实现:上文说到,玩家按E键即可获取商品,此时会调用check()函数。将玩家获取到的商品名称e.id传入函数中,用for循环检测目前的任务中是否有目标商品,若匹配,则将目标商品进度+1,并更新任务进度于UI面板中。当玩家完成了某一任务的目标进度,则调用FinishTask()提示TaskManger.cs玩家已经完成某任务。public

void

Check(TaskEventArgs

e)

{

TaskCondition

tc;

for

(int

i

=

0;

i

<

taskConditions.Count;

i++)

{

tc

=

taskConditions[i];

if

(tc.id

==

e.id)

{

tc.nowAmount

+=

e.amount;

if(tc.nowAmount

<

0)

tc.nowAmount

=

0;

if

(tc.nowAmount

>=

tc.targetAmount)

tc.isFinish

=

true;

else

tc.isFinish

=

false;

taskItem.Modify(e.id,tc.nowAmount);

}

}

for

(int

i

=

0;

i

<

taskConditions.Count;

i++)

{

if

(!taskConditions[i].isFinish)

{

taskItem.Finish(false);

return;

}

}

taskItem.Finish(true);

e.taskID

=

taskID;

TaskManager.Instance.FinishTask(e);

}

接下来新建TaskManager.cs脚本,用于接收Task.cs的消息并分发到各个函数中。TaskManager类继承了MonoSingletion类,MonoSingletion类是继承了MonoBehaviour的单例类。这样做保证了TaskManager类仅有一个实例,并在游戏场景中提供一个访问它的全局访问点。总结游戏中任务系统的设计思路:1.游戏开始时在初始化脚本GameManager.cs中调用TaskManager类中的GetTask()函数初始化所有任务。2.当玩家获得了目标商品,Task类更新任务进度并判断是否完成任务。3.若某个任务达成,Task类将信息传递到TaskManger类,再由TaskManager进行消息分发。public

class

TaskManager

:

MonoSingletion<TaskManager>

{

public

Dictionary<string,

Task>

dictionary

=

new

Dictionary<string,Task>();//id,task

public

XElement

rootElement;

public

event

EventHandler<TaskEventArgs>

getEvent;//接受任务时,更新任务到任务面板等操作

public

event

EventHandler<TaskEventArgs>

finishEvent;//完成任务时,提示完成任务等操作

public

event

EventHandler<TaskEventArgs>

rewardEvent;//得到奖励时,显示获取的物品等操作

public

event

EventHandler<TaskEventArgs>

cancelEvent;//取消任务时,显示提示信息等操作

void

Start()

{

MesManager.Instance.checkEvent

+=

CheckTask;

rootElement

=

XElement.Load(Application.dataPath

+

"/TestTask/Task.xml");//得到Task文件

}

public

void

GetTask(string

taskID)

{

if

(!dictionary.ContainsKey(taskID))

{

Task

t

=

new

Task(taskID);

dictionary.Add(taskID,

t);

TaskEventArgs

e

=

new

TaskEventArgs();

e.taskID

=

taskID;

getEvent(this,

e);

}

}

public

void

CheckTask(System.Object

sender,

TaskEventArgs

e)

{

foreach

(KeyValuePair<string,

Task>

kv

in

dictionary)

{

kv.Value.Check(e);

}

}

public

void

GetReward(TaskEventArgs

e)

{

if

(dictionary.ContainsKey(e.taskID))

{

Task

t

=

dictionary[e.taskID];

for

(int

i

=

0;

i

<

t.taskRewards.Count;

i++)

{

TaskEventArgs

a

=

new

TaskEventArgs();

a.id

=

t.taskRewards[i].id;

a.amount

=

t.taskRewards[i].amount;

a.taskID

=

e.taskID;

rewardEvent(this,a);

}

}

dictionary.Remove(e.taskID);

3.5添加游戏背景音乐 预先准备好游戏背景音乐的音频文件并导入项目中,在hierarchy面板右键→CreateEmpty新建空物体,命名为GameManager,用于添加游戏中的各种控制脚本。然后新建BgmController.cs脚本,通过UI中的Slider组件控制音量大小。public

AudioClip

music;

private

AudioSource

back;

public

Slider

slider;

void

Start

()

{

back

=

this.GetComponent<AudioSource>();

back.loop

=

true;

//设置循环播放

back.volume

=

0.5f;//设置音量最大,区间在0-1之间

back.clip

=

music;

back.Play();

//播放背景音乐

}

void

Update()

{

back.volume

=

slider.value;

}

游戏UI界面设计

菜单界面新建场景1菜单界面。菜单界面包括主菜单图片以及开始游戏,退出游戏按钮点击按钮,UI界面均使用Unity3D官方插件UGUI制作。

菜单界面功能开始游戏按钮:当鼠标点击该按钮,即跳转到场景2游戏主场景。 退出游戏按钮:点击按钮即可关闭游戏程序。 背景图片:装饰菜单界面。图4-1游戏开始菜单界面

菜单界面制作在project面板中点击右键→newScene新建场景,命名为StartGame。双击打开新建的场景,在hierarchy面板中右键→UI→Canvas新建画布,用于装载UI组件。在Canvas下新建两个Button组件,命名为ConnectButton和ExitButton,功能分别为开始游戏和结束游戏,再新建一个Image组件,用于显示背景图片。 将游戏菜单的背景图片导入项目中,在Project面板找到背景图,并在Inspector面板将其TextureType选项更改为游戏中支持的Sprite图,即可在UI中使用。 由于场景并不复杂,故载入场景时用Application.LoadLevel()函数载入场景。最终效果如图4-3所示。public

override

void

OnJoinedRoom()

{

Application.LoadLevel("_Demo");

}

public

void

ExitGame()

{

Application.Quit();

}

图4-3游戏主菜单界面游戏界面UI制作游戏模式采用了倒计时计分制度,即玩家在规定时间内达到一定分数即可通关。故在画面左上角设置计分和计时UI,并在画面右下角添加显示当前任务的UI。最后,考虑玩家在游玩过程中需要暂停或者退出游戏。在右上角添加暂停按钮,在画面中间设置暂停菜单,添加LeaveRoom和Resume两个按钮用于退出游戏和返回游戏。因暂停菜单平时无需显示在画面上,在Inspector面板中将选项框取消勾选,即可在场景中默认为隐藏状态。游戏界面UI总体设计如图4-4所示。

图4-4游戏场景的UI设计接下来制作UI的功能部分。在hierarchy面板中新建空物体,命名为GameManager,新建GameManager.cs脚本,用于管理游戏中的全局变量和菜单UI。编写GamePause()函数,并在暂停按钮的Inspector面板中添加OnClick()点击事件,当鼠标点击按钮时,暂停游戏,显示暂停菜单并取消显示暂停按钮。同理,编写GameResume()函数并绑定点击事件,重新开始游戏并隐藏暂停菜单栏,重新显示暂停按钮。左上角的计时器则用协程进行计时,每过一秒钟更新一次UI上的时间,若游戏时间归零,则游戏结束。

public

void

GamePause()

{

Time.timeScale

=

0;

pauseMenu.SetActive(true);

pauseButton.SetActive(false);

}

public

void

GameResume()

{

Time.timeScale

=

1f;

pauseMenu.SetActive(false);

pauseButton.SetActive(true);

}

public

IEnumerator

startCountDown()

//协程倒计时

{

while

(sumTime

>=

1)

{

sumTime--;

TimeLabel.text

=

"Time:"

+

sumTime;

if

(sumTime

==

0)

{

//当游戏时间用完则游戏结束

GameOver();

}

//每隔一秒调用一次

yield

return

new

WaitForSeconds(1);

}

}

此外,GameManager脚本还起到了初始化游戏的作用。Start()函数中,用Random.Range()函数在Z轴的-1.87到-12.87区间随机生成玩家,并开始游戏倒计时协程。GameStart()函数将所有的任务初始化。void

Start()

{

//随机位置生成玩家

PhotonNetwork.Instantiate(this.playerP,

new

Vector3(46f,0.2f,

Random.Range(-1.87f,

-12.87f)),

Quaternion.identity);

StartCoroutine(startCountDown());

}

void

FixedUpdate()

{

//初始化任务

GameStart();

}

public

void

GameStart()

{

if

(!condition)//只导入一次任务

{

for

(int

i

=

1;

i

<

11;

i++)

{

//导入所有任务

TaskManager.Instance.GetTask("Task"

+

i);

}

condition

=

true;

}

}

为了清楚的标识游戏中的货架名称,在每个货架上添加新的空物体作为子物体,并命名为nameItem。点击nameItem并在Inspector面板添加TextMesh组件,在TextMesh组件中的text中输入每个货架的名称。如图4-5所示。图4-5用TextMesh组件标示货架名称

将游戏更改为多人联网游戏

设置Photon引擎注册并配置Photo服务器首先访问Photon引擎的官网注册账号,Photon支持申请免费且最大连接数为20人的免费服务器,注册账号后登录并新建一个Application。PhotonType选择与Unity3D相匹配的PhotonPUN,然后填写项目名称并提交即可。刷新等待系统分配到服务器后,Photon服务器注册完成。5-1Photon服务器项目注册下一步是登陆Photon引擎国内代理商官网,进行中国区服务器注册。这一步有助于降低国内联机游玩的延迟。注册国内Photon服务器需要上一步所注册的国外服务器项目的appID和账号。填写相应的表单后,等待通过即可激活中国区Photon服务器。在Unity上配置PUN下一步是在Unity3D的AssetStore中下载并导入免费服务器所使用的PUN2-FREE插件。如图5-2所示。5-2下载并导入PUN-FREE插件导入插件后,根据官方教程,在Project面板→Photon→PhotonUnityNetWorking→Resources中找到PhotonServerSettings,并在Inspector面板中填入之前注册的服务器所分配的appID,并修改FixedRegion项内的值为cn,如图5-3所示。然后在Project面板搜索LoadBalancingClient.cs脚本,打开并找到NameServerHost一项,将它的原值更改为“”,更改完毕后项目就可以顺利连接上中国区的Photon服务器。5-3配置PhotonServerSettings游戏主菜单加入联网功能回到StartGame场景,新建空物体并命名为NetworkManager,然后新建同名脚本NetworkManager.cs用于管理主菜单界面的网络连接功能。首先导入Photon联网所需要的两个命名空间Photon.PUN和Photon.Realtime,然后将脚本所继承的类为MonoBehaviourPunCallBacks。编写Connect()函数,若玩家已连接到服务器,则将玩家分配到随机的房间。如果未连接PhotonCloud,则取消离线模式并尝试连接。接着编写连接回调函数OnConnectedToMaster()和OnDisconnected(),在玩家成功连接后加入游戏房间,连接失败时返回错误信息。然后重写进入房间失败和进入房间成功的函数。若进入房间成功,则在控制台输出相应信息并跳转到游戏场景;若进入房间失败,则新建一个最大人数为4人的新房间。//导入photon所需的命名空间

using

Photon.Pun;

using

Photon.Realtime;

public

class

NetworkManager

:

MonoBehaviourPunCallbacks

//改为PunCallbacks

{

//连接

public

void

Connect()

{

if

(PhotonNetwork.IsConnected)

{

PhotonNetwork.JoinRandomRoom();

}

else

{

PhotonNetwork.OfflineMode

=

false;

PhotonNetwork.ConnectUsingSettings();

}

}

//连接回调函数

public

override

void

OnConnectedToMaster()

{

base.OnConnectedToMaster();

Debug.Log("连接成功!");

//加入随机房间

PhotonNetwork.JoinRandomRoom();

}

public

override

void

OnDisconnected(DisconnectCause

cause)

{

base.OnDisconnected(cause);

Debug.Log("连接断开!");

}

//进入房间回调函数

public

override

void

OnJoinRandomFailed(short

returnCode,

string

message)

{

base.OnJoinRandomFailed(returnCode,

message);

Debug.Log("加入房间失败!");

Debug.Log("开始建立新房间");

PhotonNetwork.CreateRoom(null,

new

RoomOptions

{

MaxPlayers

=

4});

}

public

override

void

OnJoinedRoom()

{

base.OnJoinedRoom();

Debug.Log("加入房间成功!");

PhotonNetwork.LoadLevel("_Demo");

}

同步游戏玩家的数据同步人物的运动与旋转在Project面板找到玩家的预制体,然后在Inspector面板中新增PhotonView组件和PhotonTransformView组件。在PhotonView组件的ObservedComonents中点击“+”号新增同步列表,并将预制体的Transform组件拖动到列表中。然后勾选PhotonTransformView中的Position和Rotation选项。即可对人物的运动进行同步,如图5-4所示。图5-4新增相应组件使其同步同步游戏中的其他数据游戏中拥有任务系统,但每个玩家的人物都不应该是独立的。故我们应该将游戏中的任务进度也一并同步。在Photon服务器中同步数据有两种方式:使用PhotonPUNRPC和使用RaiseEvent发送事件和接受事件。前者较为方便快捷,故我们使用PhotonRPC来同步所需的函数,即可达到同步任务进度的效果。使用PUNRPC进行同步,首先需要在对象上添加PhotonView组件和需要同步的脚本。然后在需要同步的函数前面加上[PunRPC]标签。用玩家点击暂停按钮的函数GamePause()举个例子,GamePause()函数写在GameManager脚本中,而GameManager脚本挂载在GameManager对象上,并且对象添加了PhotonView脚本,在函数上添加[PunRPC]标签,即可使函数在同一房间的多个客户端中进行同步。[PunRPC]

public

void

GamePause()

{

Time.timeScale

=

0;

pauseMenu.SetActive(true);

pauseButton.SetActive(false);

}

游戏的打包与导出至此,游戏的制作与设计部分基本结束,最后的工作就是将游戏导出以及发布。在Unity3D上方的工具栏菜单选择File→BuildSetting选项,在ScenesInBuild选框内可以添加选择需要导出的场景。由于一开始并未添加游戏开始菜单场景,故将StartGame场景拖入选框中,场景切换功能就可以实现。其余的选项为默认,点击Build按钮,选择文件夹并等待游戏导出即可。图5-5在BuildSetting中进行导出游戏前的设置图5-6导出后的可执行游戏文件

游戏测试打开文件夹找到之前导出的游戏文件并点击.exe可执行文件即可打开游戏。在Graphics窗口中可以调整开始游戏时的分辨率大小,选择是否窗口运行,游戏的画面质量等参数。在Input窗口可以设置键位等。图6-1Graphics窗口设置游戏功能测试程序编译测试:Unity3D引擎控制台及编译无严重错误。(测试通过)界面UI:开始游戏界面/任务系统UI/暂停及开始游戏界面均可正常显示并且功能正常。(测试通过)玩家控制功能:玩家能够正常行走并拾取物品,能够在其他客户端正常更新。(测试通过)游戏通关等逻辑测试:玩家能够正常通关游戏并重新开始,游戏分数及计时器等运行正常。(测试通过)联网功能:玩家点击开始联网游戏之后,在Unity3D的控制台能够输出正常创建和进入房间的测试语句,并且其他玩家也能够正常进入及退出游戏房间。(测试通过)资源占用测试测试环境:处理器:AMDRyzen72700CPUEight-CoreProcessor内存:16GBDDR4显卡:AMDRadeonRX5802048SP系统:Windows10Pro1909测试情况如下:处理器占用率:最高21%,平均15%内存占用:101.0MB显存占用:120MB以上结果来自人工手动记录,在正常游玩情况下游戏的资源占用均处于正常范围。测试通过。小结经过测试和调整,游戏正常运行,没有出现卡顿,闪退等问题。屏幕和鼠标的交互正常,联机的人物没有出现卡顿,断连等网络问题。玩家能够正常获得游戏物品,并且能够实时在另一个客户端上更新。基本功能已经实现,游戏过程无异常。

总结基于Unity3D的多人合作游戏到此就圆满完成了,至此也表示毕业设计已经到了最终阶段。在整个毕业设计的过程中,通过对该游戏的开发与对多人联机类型游戏的研究,我收获了许多知识。但是在这过程中我也意识到自己还有很大的学习空间,在游戏制作的过程中深感自己知识储备的不足。通过在网上查阅资料,观看教学视频,咨询指导老师等方式最终将问题解决了。但是我认为这个项目中仍旧存在这许多不完美:1.关卡设计过于简单,可玩性不高;2.联机功能不够强大,在游戏的网络优化部分需要继续打磨;3.UI设计不够好看。Unity3D引擎因为功能强大,易上手等特点被越来越多厂商所使用,在未来可能会更加的热门,熟练掌握Unity3D引擎的使用有助于我们在游戏开发这一条道路上走得更远。在本次毕业设计所遇到的困难使我意识到自己经验与知识储备不足,将来的日子里,我会不断学习进步,争取在未来做出更好的作品。

参考文献[1][美]JosephHocking.Unity5实战[M].蔡俊鸿,译.北京:清华大学出版社,2016.[2]Unity3D游戏开发[M].人民邮电出版社,宣雨松,2012

[3][美]JesseSchell.游戏设计艺术:第二版[M]刘嘉俊等,译.北京:电子工业出版社.2016

[4]Unity.Unity3D参考手册.Unity,2010:94-121

[5]基于Unity3D的多通道下服务器客户端同步[J].汪瑞.现代计算机(专业版).2015(24)

[6]魏迎梅.虚拟环境中碰撞检测问题的研究.[D].长沙:中国人民解放军国防科学技术大学,2000:23-45

[7]宋传磊.Unity3D中物体间通信方式应用研究.[J].软件开发与应用,2015(12)

[8]吴晶晶,戴智超.基于Unity3D的多人在线网络游戏设计与开发.[J].计算机系统应用,2017,26(10):133−138

[9]肖俊.基于Unity3D的跨平台手机网络游戏的研究与实现.[J]科技与信息.2018(02)

[10]薛玉倩.基于Unity3D的网络游戏.[J]内蒙古科技与经济.2018.7(13)

[11]徐军,张子墨.基于Unity3d射击游戏的设计及其核心功能实现.[J]福建电脑.2018(7)

[12]李智鹏.基于Unity3D引擎的空中战机游戏设计与实现.[D].吉林.吉林大学.2016

[13]干建松.基于Unity局域网同步与多角色玩家的设计与实现.[J]盐城工学院学报(自然科学版).2018.9(3)

[14]吕圣卿,陈一民等.一种基于网络的并行渲染和跨平台同步展示系统.[J].计算机应用与软件.2017.10(10)

[15]梁成.基于Unity3D在基本游戏框架下客户端研究与实现.[J].现代计算机.2015.09(25)

致谢我的大学生涯随着毕业设计的完工也进入了尾声。在本次毕业设计开始之前,我大致了解了相关游戏的制作背景,我所模仿的游戏一开始仅仅由2人的团队研发,使我信心大增。但在游戏制作的过程中经常因为知识储备不足,对脚本开发的不够熟练,在各种问题上频频碰壁。例如在将单人游戏更改为网络联机游戏时,我就因为对计算机网络知识储备不足以及对Unity3D的网络开发了解不够,导致开发周期过长以及精力耗费过多。在此,我非常感谢对我有教育之恩的代课老师们,每一位老师的悉心教导都是我完成这篇论文的基础。感谢吴志达老师一直以来对我的鼓励和支持,为我的毕业论文格式进行指导,感谢指导老师王千秋老师在我陷入困境的时候给予我最中肯的指点,大学里有这两位恩师的存在让我少走了很多弯路。因为各位老师的无私奉献,我的毕业设计最终得以完工。我也非常感谢在网上提供各种资料和教程的许多无名人士,借着他们铺下的路,我的各种问题才得以解答。最后,感谢所有曾经帮助过我的人,在此真诚地向你们致谢!

PowerPoint课件制作实用技巧PowerPoint是微软公司生产的制作幻灯片和简报的软件(以下简称PPT)。在我们许多人看来,它只不过是一个简单地对文字、图形、图片进行演示的软件,教学中的课件制作软件当属Authorware、Flash。Authorware和Flash制作的动画效果的确很好,而且它们的功能也很强大。不过这些软件在制作课件的过程中往往非常耗时,用这些专业软件来制作课件用于平时的教学往往效率很低。PPT就是一个非常简单、实用的制作课件的软件,只要你用好它,同样能做非常棒的课件来。一、掌握基本,知道“插入”。(一)知道从“插入”菜单进入,会给PPT课件添加文字、图片、影片和声音等,也就会做一般的课件了。(二)图片插入与处理1.插入图片具体方法:a)插入剪贴画或文件中的图片;b)添加图片做背景;c)给自选图形做填充。2.处理图片具体方法:我们用PPT制作课件时,经常从网上下载图片来用,而网络中的图片往往含有超链接和网站名称痕迹,我们需要删除其中超链接,并对图片进行裁剪处理。在Powerpoint中,我们一般可以利用“图片”工具栏上的“裁剪”工具进行裁剪处理,但是,这里的工具只能对图片进行矩形裁剪,若想裁剪成圆形、多边形等其他形状,通常方法就无能为力了。其实这个问题在PPT中是可以解决的。我们用给自选图形做填充图片的方法就可以实现我们需要的效果。具体步骤:a)首先利用“绘图”工具栏画一个想要裁剪的图形,如椭圆。b)选中椭圆后单击“绘图”工具栏上“填充颜色”按钮右侧黑三角,从列表菜单中单击“填充效果”命令。c)打开选择“图片”选项卡,单击〔选择图片〕按钮,从“选择图片”对话框中找到合适的图片,单击〔插入〕按钮后返回到“填充效果”对话框最后单击〔确定〕按钮后退出。此图片当作椭圆图形的背景出现,改变了原来的矩形形状,获得了满意的裁剪图片效果。图片在插入PPT之前,我们可以用ACDSEE软件进行加工,如改变大小,裁剪等操作。二、学会下载,查找方法。在制作课件过程中,我们时常需要从网络上下载各种资源用以丰富课件内容,提升课堂效果。但有许多网站的flash动画都不提供下载;还有网站为我们提供了许多视频素材,这些视频素材都是FLV流媒体格式。FLV流媒体格式是一种新的视频格式,全称为FlashVideo。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现也有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等缺点。目前各在线视频网站均采用此视频格式。如新浪播客、56、优酷、土豆、酷6等,无一例外。FLV已经成为当前视频文件的主流格式。这些网站一般都不提供下载。我们想要这些素材,怎样办?1.寻找下载方法:a)在百度网站搜索栏中输入下载的内容,搜索下载方法。b)弄清格式,再搜索方法。2.具体方法推荐①flasah动画的下载方法一:IE缓存中寻找在网上看过一个flash后,一般情况下都会保存在IE缓存里。右击桌面上的IE图标,选“属性”命令,单击中间的“设置”按钮,弹出“Internet临时文件和历史记录设置”面板,单击“查看文件”,可以打开临时文件夹,按时间排序,找到刚才打开的flash动画文件。优点:不需要安装其它软件。缺点:操作相对烦琐。方法二:借助Flashsaver等软件下载,这些软件都可以快速、方便的下载你所需要的flash文件。优点:简单、方便、快速。缺点:需要安装使用。②FLV视频的获取方法一:IE缓存中寻找,方法同flasah。方法二:flv视频解析下载/三、学用控件,转化应用1.flash动画的插入方法一:安装flash插件,再插入flash。步骤:a)安装“ppt插flash软件”插件;b)单击“插入”→“flashmovie”→打开要播放的flash文件→确定。方法二:利用控件插入flash动画。步骤:a)插入“ShockwaveFlashObject”控件对象:右击“工具栏”→选“控件工具箱”(或点“视图→工具栏→控件工具箱”);点“其他控件”(控件工具箱中最后一个形似锤子斧头的按钮),拖动滚动条或在英文输入法状态下按键盘上“s”键,快速定位到以s开头的控件,选择“ShockwaveFlashObject”控件。将鼠标移到幻灯片工作区,鼠标指针变成“十”字型,拖动鼠标绘制出一个形似信封的矩形。b)打开控件对象“属性”对话框:右击矩形控件对象,在弹出的快捷菜单中选“属性”命令。c)正确设置控件对象属性:主要是在“Movie”空白文本域中正确输入演示文稿要播放的.swf动画的完整名称。d)将控件对象适当缩放:为了获得比较好的播放效果,拖动控件对象的缩放点使它几乎覆盖整个幻灯片工作区,但要在幻灯片工作区底部保留少许空白区域。这样既可以享受.swf动画大屏幕播放的好处,又能够保证幻灯片能够顺利地切换。e)一般情况下,幻灯片应显示出动画的第一帧图形。如果控件对象仍是空白的,可保存演示文稿,关闭后再打开它,按F5放映幻灯片,应该能够正确播放动画。2.FLV视频的插入FLV视频与FLASH不一样的。全称是flashvideo,所用的播放器也不一样。①利用控件插入PPT的方法也是有区别的。不同点:先要下载pptflv.swf文件,此文件是类似于网页中FLV视频播放器的一个Flash文件(可用百度搜索下载下来后记着要改文件名,保留扩展名);例如改成:pptflv1.swf“Movie”参数值填入方法不一样,参数值示例:pptflv.swf?file=视频.FLV“pptflv.swf”即为步骤一下载下来的Flash文件的完整文件,“视频.FLV”即为需要播放的FLV视频的文件名,大家只要将pptflv.swf换成自己下载后起的文件名,将“视频.FLV”换成自己的FLV视频文件名,则此FLV文件就可以在PowerPoint中播放了。如播放2.flv视频参数填法:示例:pptflv1.swf?file=2.FLV②方法二:将flv转换成swf再插入转换软件:UltraFlashVideoFLVConverter3.2.0软件说明:该软件又叫全格式FLV转换器,支持将几乎所有主流视频格式转换为FLV或者SWF且对用户较为关心的RealMedia(RM/RMVB...)和QuickTime(MOV/QT...)支持良好。三大特色功能:既可输出FLV格式,也可输出SWF格式,甚至同时输出FLV+SWF格式。此软件也支持创建调用播放的网页支持导入所有的主流字幕格式。srt,*.sub,*.idx,*.ssa,*.ass,*.psb,*.smi)有字幕合成功能,你现在无需再使用那些繁琐的专业软件来合成字幕到视频中去,字幕合成与格式转换一气呵成!支持视频分割,右键点击列表中的源文件,选择[编辑视频],自己设置下起点终点即可对视频进行去粗取精处理!③方法三:将flv转换成其他格式视频文件再插入工具:FLV转AVI(FreeFLVtoAVIConverter1.5)作用:一个免费的将FLV转换成AVI的软件,简单好用,自带解码器。四、学做交互,理解运用。1.利用母版进行交互母版≠模版母版和模版可以使课件统一整体风格,展现自己的个性和特点;模版是对同一类课件所做的整体风格统一设置,母版则是对某一部课件内部所做的个性化统一设置。母版设置得好,就可以存为模版,供别人在制作同类题材时使用。修改幻灯片母板的方法和技巧。如果我们希望为每一张幻灯片添加上一项固定的内容,并做超链接,可以通过修改“母板”来实现。a)执行“视图→母板→幻灯片母板”命令,进入“幻灯片母板”编辑状态。b)插入固定内容。例如:将图片插入到幻灯片中,调整好大小、定位到合适的位置上。c)给这张图片插入超链接,就可以进行交互了。d)单击“关闭母板视图”按钮退出“幻灯片母板”编辑状态。以后添加幻灯片时,该幻灯片上自动添加上该图片。如果说一个PPT有它的灵魂的话,那就是PPT的母板,它的作用犹如摩天大厦的根基一般。2.在PPT演示文稿中插入PowerPoint演示文稿对象实现交互具体效果:①导航目录内容展示效果②单击小图片就可看到该图片的放大图自动缩效果《画家乡》一课五个画面交互的具体操作方法:a)单击“插入→对象”,在出现的选择页中选择“MicrosoftPowerPoint演示文稿”,单击确定。此时就会在当前幻灯片中插入一个“PowerPoint演示文稿”的编辑区域。b)在此编辑区域中我们就可以对插入的演示文稿对象进行编辑了,编辑方法与PowerPoint演示文稿的编辑方法一样。c)在插入的演示文稿对象中创建所需的幻灯片。可将图片设置为幻灯片相同大小,退出编辑后,就可发现图片以缩小方式显示了(其实是整个插入的演示文稿对象被缩小显示了)。d)最后,我们只需对

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论