Unity 3D官方教程——Adventure Game学习记录

1.Interactable System:

1.Picture Interactable:Player走到SecurityRoom墙前的那张画

Unity 3D官方教程——Adventure Game学习记录_第1张图片

 

2.Fish Interactable鱼档前的交互

Unity 3D官方教程——Adventure Game学习记录_第2张图片

 

3.Guard Interactable守卫

Unity 3D官方教程——Adventure Game学习记录_第3张图片

 

2.Player

这一Phase要实现在SecurityRoom里点击地板Player在上面随着鼠标点击走动的效果。

----------------

首先设置SecurityRoom的环境。

点击Hierarchy下的SecurityRoomEnvironment里的指定选项,勾选Static,因为NavMash必须在静态的环境上Bake然后生效。

Unity 3D官方教程——Adventure Game学习记录_第4张图片

 

Window→Navigation→Bake按如下选项

Unity 3D官方教程——Adventure Game学习记录_第5张图片

各选项意义见下:

Unity 3D官方教程——Adventure Game学习记录_第6张图片

 

Hierarchy下新建UI→EventSystem,并给EventSystem加上Audio Listener组件。注意,完整的游戏里EventSystem都是建在Presistent Scene里的,这里只是为了检测该单元而建立,之后会删掉。

Unity 3D官方教程——Adventure Game学习记录_第7张图片

 

接着在Hierarchy下的Camera添加组件Physics Raycaster,该组件将对Scene里的物体进行光线投射,并把消息发送到(send)到EventSystem

Unity 3D官方教程——Adventure Game学习记录_第8张图片

 

接着在SecurityRoom上添加添加Mesh Collider组件,Mesh选存好的方案。接着添加Event Trigger组件,点+添加新事件,内容暂时为空(截图用的是完整游戏)

Unity 3D官方教程——Adventure Game学习记录_第9张图片

Unity 3D官方教程——Adventure Game学习记录_第10张图片

 

这里介绍一下EventSystem,它分为三步骤:发送(Send events),接收(Receive events)和执行(Manage events)。关系如下:

Unity 3D官方教程——Adventure Game学习记录_第11张图片

 

上面Camera上挂Physics Raycaster组件是为了Send,刚才的SecurityRoom上挂Ecent Trigger组件是为了Receive。

----------------------

然后设置Player

在Project View下选择Animators文件夹→Player文件夹下新建Animator Controller命名为ClickToMove。Unity里Animator和Animation都是动画插件,Animator主要为了动画直接的切换,和什么情况下播什么动画;Animation主要控制一个动画的播放内容,比如先哪一帧后一帧。

Unity 3D官方教程——Adventure Game学习记录_第12张图片

 

双击ClickToMove点+新建float型参数命名为Speed,再建4个trigger分别命名为HighTake,MedTake,LowTake,AttemptTake。

Unity 3D官方教程——Adventure Game学习记录_第13张图片

 

在中间的操作区Base Layer上点击右键→Create State→From New Blend Tree创建一个新的混合树(Blend Tree)并命名为Walking。

Unity 3D官方教程——Adventure Game学习记录_第14张图片

 

双击Walking混合树,在Inspector里改名为WalkingBlendTree,点击+选择Add Motion Field。共添加3个三个Motion Fields,然后按名字添加3个对应的状态动画。不要勾选Automate Thresholds(自动化阈值),然后点击Compute Thresholds选择Speed,可以看到3个Motion后的阈值比不再是1:0.5:1而是0:1.5:5.6了。

Unity 3D官方教程——Adventure Game学习记录_第15张图片

 

点击Base Layer回到操作界面,在Animations文件夹→Player下多选Idle,TakeObjectAttempt和TakeObjects动画放入操作界面,并放置成这样

Unity 3D官方教程——Adventure Game学习记录_第16张图片

 

再在这些动画间Make Transition如下图

Unity 3D官方教程——Adventure Game学习记录_第17张图片

 

点击Walking→PlayerIdle的指向线,取消勾选Has Exit Time。点+添加条件,自动出来Speed,选择Less,填0.1,即速度小于0.1时播放Idle动画。再点击PlayerIdle→Walking指向性,同样取消存在时间,添加条件选Greater,填0.1

Unity 3D官方教程——Adventure Game学习记录_第18张图片

Unity 3D官方教程——Adventure Game学习记录_第19张图片

 

再对Any State对其他动画的切换条件上加上分别对应其名字的trigger。

Unity 3D官方教程——Adventure Game学习记录_第20张图片

 

注意四个动画到Walking的transition没有设置条件是因为这四个都有默认的Has Exit Time,即这些条件动画播放完了就回到走路状态。

Unity 3D官方教程——Adventure Game学习记录_第21张图片

 

点击PlayerIdle,tag改为Locomotion。再点击Walking,tag改为Locomotion,注意拼写大小写完全正确。这是为了之后在代码里区分动画状态,只有当Locomotion下才能Walking其他的会播放其他动画。

Unity 3D官方教程——Adventure Game学习记录_第22张图片

Unity 3D官方教程——Adventure Game学习记录_第23张图片

 

回到Scene视图,从Models文件夹把Player拽到Hierarchy下,选择Layer为Characters,弹出对话框选择覆盖子对象。Position设为(-0.7, 0, 3.5)Rotation设为(0,180,0)刚好在门口对着保镖。Animator组件的Controller选ClickToMove,添加组件Nav Mesh Agent更改如下选项。

Unity 3D官方教程——Adventure Game学习记录_第24张图片

Nav Mesh Agent对应属性

Unity 3D官方教程——Adventure Game学习记录_第25张图片Unity 3D官方教程——Adventure Game学习记录_第26张图片

 

最后将Player保存到Prefabs文件夹。

-------------------

接下来是移动Player

Assets→Scripts→MonoBevaviours→Player新建C#命名为PlayerMovenments,并把该脚本拖拽到Player预制上,打开并编辑

首先我们要确定Player的移动方式:先由NavMeshAgent导航到鼠标点击点附近,进入一个范围,降低速度并用Movetowards移动,最后移动到离destination非常近的时候,直接设置Player的position为destinationPosition。

Unity 3D官方教程——Adventure Game学习记录_第27张图片

 

Unity 3D官方教程——Adventure Game学习记录_第28张图片

Unity 3D官方教程——Adventure Game学习记录_第29张图片

Unity 3D官方教程——Adventure Game学习记录_第30张图片

Unity 3D官方教程——Adventure Game学习记录_第31张图片

Unity 3D官方教程——Adventure Game学习记录_第32张图片

Unity 3D官方教程——Adventure Game学习记录_第33张图片

Unity 3D官方教程——Adventure Game学习记录_第34张图片

 

保存后回到Unity,打开选中prefab下的player把引用拖进去,然后点击Hierarchy下的SecurityRoom,把引用拖进去并选好函数。

Unity 3D官方教程——Adventure Game学习记录_第35张图片

Unity 3D官方教程——Adventure Game学习记录_第36张图片

 

保存场景测试,鼠标点击地面Player会跟着走动了。

接着编辑PlayerMovement,加上对互动物的反应包括player转向面对互动物。

Unity 3D官方教程——Adventure Game学习记录_第37张图片

 

至于Interactable类,将在之后讲解,回到Unity,点击Hierarchy下的PictureInteractable下的EventTrigger组件将Player拖入并选好函数,接着把Interactable代码组件拖进去。

Unity 3D官方教程——Adventure Game学习记录_第38张图片

 

至此,我们实现了Player在安全屋内走动,点击墙上的画Player会走到画前,并互动。

 

3.Inventory(仓库)

之后我们将创建一个背包系统。

这个系统首先应在场景切换时保持原内容;这个背包系统应该足够简单,但当背包系统设计变化时可扩展

Unity 3D官方教程——Adventure Game学习记录_第39张图片

 

打开Persistent Scene,点击改为2D模式,16:9宽度

Unity 3D官方教程——Adventure Game学习记录_第40张图片

 

双击Hierarchy下的PersistentCanvas,新建空子对象命名为Inventory,把Inventory拖到FadeImage的上方确保FadeImage可以在切换场景时盖住背包。Inventory下新建空对象ItremSlot,ItemSlot下新建Image,并复制,第一个Image命名为BackgroundImage,SourceImage选为InventorySlotBG。

Unity 3D官方教程——Adventure Game学习记录_第41张图片

 

第二个命名为ItemImage,取消勾选其Image组件,将在用时再添加。

Unity 3D官方教程——Adventure Game学习记录_第42张图片

 

之后把ItemSlot拽到Prefabs使成预制件,再在Hierarchy下的ItemSlot复制3次,共有4个,分别改名为ItemSlot0到ItemSlot3。

选择Inventory添加Vertical Layout Group组件。Inventory的Width改为135,Height改为600。修改Anchor为middle & right(不摁alt或shift),然后修改Pos X为-95。

Unity 3D官方教程——Adventure Game学习记录_第43张图片

 

Assets→Scripts→ScriptableObjects→Inventory下有已写好的Item定义脚本,如下

Unity 3D官方教程——Adventure Game学习记录_第44张图片

 

在Scripts→MonoBehaviour→Inventory下新建Inventory脚本(添加装备&删除装备),打开并编辑

Unity 3D官方教程——Adventure Game学习记录_第45张图片

 

然后把该脚本拖拽到Hierarchy下的PersistentCanvas,其实该脚本可以放在任何一个在该场景的gameobject上,但必须存在于此Scene里。

Unity 3D官方教程——Adventure Game学习记录_第46张图片

 

然后打开Scripts→ScriptableObjects→Interaction→Reactions→DelayedReactions下的LostItemReaction和PickedUpReaction脚本,恢复引用Inventory脚本的语句。这是为了装备置换和捡起时把装备加到装备栏。

Unity 3D官方教程——Adventure Game学习记录_第47张图片

Unity 3D官方教程——Adventure Game学习记录_第48张图片

 

之后在Scripts→Editor→Inventory下新建脚本InventoryEditor,打开并编辑

Unity 3D官方教程——Adventure Game学习记录_第49张图片

Unity 3D官方教程——Adventure Game学习记录_第50张图片

 

该脚本是把Inventory脚本序列化了,没有该序列化脚本的情况下Inventory脚本组件将显示为:

Unity 3D官方教程——Adventure Game学习记录_第51张图片

 

序列化后显示为

Unity 3D官方教程——Adventure Game学习记录_第52张图片

 

该序列化脚本的作用不仅仅使Inventory脚本组件在Inspector上整齐了,还把Item和IemImage的索引一 一对应了。

把对应的ItemImage拖入。

Unity 3D官方教程——Adventure Game学习记录_第53张图片

 

保存后,点击测试到Market场景里发现Player可捡装备到装备栏并置换了。

怎样添加Item,菜单栏Assets/Creat下有Item选项

会在Assets文件夹下的Item文件夹里新建一个Item我们可以改名,并拖入它所对应的sprite。

Unity 3D官方教程——Adventure Game学习记录_第54张图片

 

 

 

4.Coditions(各种互动系统的条件)

The Phase将创建一个系统来检查当前的游戏状态。

一个互动的游戏对象将包括

Unity 3D官方教程——Adventure Game学习记录_第55张图片

 

Condition的形式将包括

Unity 3D官方教程——Adventure Game学习记录_第56张图片

 

这一阶段的代码都在Package里写好。第一个脚本Scripts→ScriptableObjects→Interaction→Conditions→Condition脚本

Unity 3D官方教程——Adventure Game学习记录_第57张图片

 

第二个脚本是同文件夹下的AllConditions

Unity 3D官方教程——Adventure Game学习记录_第58张图片

Unity 3D官方教程——Adventure Game学习记录_第59张图片

 

注意到该脚本是继承ResettableScriptableObject的,如下

Unity 3D官方教程——Adventure Game学习记录_第60张图片

 

接着第三个脚本,同文件夹下的ConditionCollection,这个是需要我们编辑的脚本,如下

Unity 3D官方教程——Adventure Game学习记录_第61张图片

 

接下来我们写一个可拥有子编辑器的基础编辑器,Scripts→Editor→Abstracts下EditorWithSubEditors脚本

Unity 3D官方教程——Adventure Game学习记录_第62张图片

Unity 3D官方教程——Adventure Game学习记录_第63张图片

 

该基础编辑器将被继承改写,它应该会做到

Unity 3D官方教程——Adventure Game学习记录_第64张图片

Unity 3D官方教程——Adventure Game学习记录_第65张图片

 

打开Scripts→Editor→Interaction→Conditions下的ConditionCollectionEditor脚本并编辑

Unity 3D官方教程——Adventure Game学习记录_第66张图片

Unity 3D官方教程——Adventure Game学习记录_第67张图片

Unity 3D官方教程——Adventure Game学习记录_第68张图片

Unity 3D官方教程——Adventure Game学习记录_第69张图片

 

保存后回到Unity,在SecurityRoom场景里,点击Hierarchy下的LaserGridInteractable游戏对象,在Interactable组件上,点击Add Collection按钮。填入对应的选项。并把子对象BeamsOffReaction拖入。

Unity 3D官方教程——Adventure Game学习记录_第70张图片

 

我们上面写的一堆脚本都是为了让这个Interactable在Inspector上体现出这种层次并和游戏数据一 一对应。包括添加和移除ConditionCollection,ConditionCollection下添加和移除Condition,添加新的Reaction等等。

 

5.Reactions(条件满足后的反应)

将创建一个系统,当玩家点击一个Interactable对象时,可根据条件和当前游戏状态执行一系列的操作。

1.对象(具体Reaction,Reactions,ReactionCollection,ReactionCollectionEditor)之间的关系

Reactions可能包括如下

Unity 3D官方教程——Adventure Game学习记录_第71张图片

 

根据Reaction的不同类型,有些反应必须有可选的延迟,而另一些必须为即时反应(比如掉出Coin,捡起后再说Oh A coin!)我们还会对Reaction做Inspector的序列化Editor

Unity 3D官方教程——Adventure Game学习记录_第72张图片

 

所有Reaction将被封装,初始化进一个ReactionCollection脚本(包含一个public React 方法)并作为该脚本的一部分被调用。

多态性(polymorphism)写一个基类,比如Roguelike的MovingObject,包含了该类的所有基础功能,然后有若干子类继承并改写,这些子类虽然表现不同,但他们都可归为一类。比如Enemy下有Orc,有Goblin。Goblin和Orc表现形式不同,但他们都继承了Enemy,这种通过基类子类把不同的东西提取相同属性而后加上特有属性,且他们都被归为一类来管理的方式就叫多态性。

当游戏规模变大时,系统反应(比如更多的技能和效果,功能等)会更多,我们不能一个个的重写加上去。比如Player攻击狼人,我们新加了角色吸血鬼,难道在Player里再写入一次攻击吸血鬼吗?我们将新建一个基类Enemy,Player攻击Enemy,新加的角色都继承Enemy。它们各自的特性不同,但共性是被攻击。

在此游戏里,Reaction的具体内容(text reaction,audio reaction...)虽然不同,但共性是被鼠标点击了就执行具体内容,所以把Reaction做成一个父类(共性是预加载内容,并执行各种反应内容)。ReactionCollection则只需对父类的Reaction操作,而无需我们新写一个Reaction就要在ReactionCollection脚本里添加一次其类型。

 

2.制作添加具体Reaction的ReactionCollection编辑器

打开Scripts→Monobehaviours→Interaction下的ReactionCollection脚本

Unity 3D官方教程——Adventure Game学习记录_第73张图片

 

Reaction类将继承自ScriptableObject,它的作用就是我们在ReactionCollection的Inspector面板上明确的知道该Reaction的属性,是audio还是text之类。这样在游戏有很多Reaction时不至于拖拽管理混乱。

Unity 3D官方教程——Adventure Game学习记录_第74张图片

 

接着我们把ReactionCollection脚本序列化,打开Scripts→Editor→Interaction下的ReactionCollectionEditor脚本。

Unity 3D官方教程——Adventure Game学习记录_第75张图片

Unity 3D官方教程——Adventure Game学习记录_第76张图片

Unity 3D官方教程——Adventure Game学习记录_第77张图片

Unity 3D官方教程——Adventure Game学习记录_第78张图片

Unity 3D官方教程——Adventure Game学习记录_第79张图片

Unity 3D官方教程——Adventure Game学习记录_第80张图片

Unity 3D官方教程——Adventure Game学习记录_第81张图片

 

回到Unity,我们随便在某个场景,比如Market上新建一个空对象来测试,在该空对象上添加ReactionCollection脚本组件

会出现这样的Inspector

Unity 3D官方教程——Adventure Game学习记录_第82张图片

 

展开Scripts→ScriptableObjects→Interactions→Reactions文件夹,随便选两个拖到“Drop new Reactions here”可以看到已有的Reaction添加进来了,我们也可以摁右边的“-”来去除该Reaction的引用。我们还可以选择想要的Reaction type,选好后点击“Add Selected Reaction”就添加了新的该类型的Reaction。

Unity 3D官方教程——Adventure Game学习记录_第83张图片

 

展开添加的Reaction我们看到添加对应的具体内容。、

Unity 3D官方教程——Adventure Game学习记录_第84张图片

 

测试完记得删掉刚创建的空对象

 

3.创建具体的Reaction

Scripts→ScriptableObjects→Interaction→Reactions→ImmediateReactions 文件夹下新建脚本命名为TextReacion,打开并编辑

Unity 3D官方教程——Adventure Game学习记录_第85张图片

 

接下来我们把上面的TextReaction序列化,在Scripts→Editor→Interaction→Reactions文件夹下新建脚本命名为TextReactionEditor,打开并编辑

Unity 3D官方教程——Adventure Game学习记录_第86张图片

 

回到Unity,打开SecurityRoom Scene,在Hierarchy下找到PictureInteractable下的子对象DefaultReaction。它上面有一个ReactionCollection组件我们可以把TextReaction(而不是TextReactionEditor)拖拽进去【或者我们可以选择reaction type然后点Add Selected Reaction】,并改写Message为“He looks pretty trustworthy.”

Unity 3D官方教程——Adventure Game学习记录_第87张图片

 

保存场景测试,点击墙上的图片后屏幕下方出现台词。

 

6.Interactables

有了Reaction(反应),有了发生反应的条件(Condition),接下来就可以开始互动了。该阶段将继续创建互动系统,侧重于互动。我们将创建一个系统来定义玩家可与之交互的内容,包括可交互的几何体,使用EventSystem并给出交互系统摘要。

1.Interactable的架构

一个Interactable System将处理玩家的输入,并把对应的Condition和Reaction捆绑在一起。当一个Interactable对象被点击时,Player将移动到场景里一个我们已经标记的好的特殊位置InteractableLocation。移动到InteractableLocation后Player将调用一个public Interact方法,然后根据Conditions和当前game state(游戏状态)调用合适的ReactionCollection。

序列化后的Interactable就像下面这样

Unity 3D官方教程——Adventure Game学习记录_第88张图片

 

Unity 3D官方教程——Adventure Game学习记录_第89张图片

 

Unity 3D官方教程——Adventure Game学习记录_第90张图片

 

Interactable序列化的形式如下

Unity 3D官方教程——Adventure Game学习记录_第91张图片

 

就比如Guard有两个互动状态,当有Glasses & Coffee时,台词为Hi Frank,然后Laser可通过。当只有Glasses时,为Hi Frank you can't access without boss's coffee。Laser不可通过。如果这两种ConditionCollection都不满足时,只有default 反应(Get lost)。

Unity 3D官方教程——Adventure Game学习记录_第92张图片

 

2.开始创建Interactable

Scripts→MonoBehaviours→Interaction文件夹下新建脚本命名为Interactable,打开并编辑。

Unity 3D官方教程——Adventure Game学习记录_第93张图片

 

因为当Player走到指定点时要调用上面的Interact方法,所以打开PlayerMovement脚本,添加如下语句

Unity 3D官方教程——Adventure Game学习记录_第94张图片

 

Unity 3D官方教程——Adventure Game学习记录_第95张图片

 

Unity 3D官方教程——Adventure Game学习记录_第96张图片

 

Unity 3D官方教程——Adventure Game学习记录_第97张图片

 

Unity 3D官方教程——Adventure Game学习记录_第98张图片

 

接下来把上面的Interactable脚本序列化Editor,打开Scripts→Editor→Interaction文件夹下的InteractableEditor脚本

Unity 3D官方教程——Adventure Game学习记录_第99张图片

Unity 3D官方教程——Adventure Game学习记录_第100张图片

 

保存后回到Unity,打开SecurityRoom Scene,Hierarchy下新建空对象命名为Interactable,添加Box Collider和Event Trigger组件,然后添加同名脚本作为其组件。Event Trigger上新加一个Event Type选择为Pointer Click。在新建的该事件类下点“+”添加新事件。

再在新建的该空对象上添加两个子空对象,分别命名为InteractableLocation和DefaultReaction。

选中DefaultReaction子对象,添加ReactionCollection脚本为其组件。

回到Interactable对象上,把InteractableLocation和DefaultReaction子对象拖到对应的位置。

这样,一个初始化的基础Interactable对象设置好了,把该对象拖到Prefabs成预制件。

Unity 3D官方教程——Adventure Game学习记录_第101张图片

 

然后把刚创建的Interactable对象改名为PictureInteractable(也可以先删除Interactable,然后从Prefabs里拖出来一个改名)。修改Positon和BoxCollider的Center & Size。

Unity 3D官方教程——Adventure Game学习记录_第102张图片

 

设置好上面的EventTrigger,拖入Player对象,选择PlayerMovement上的OnInteractableClick方法,然后把Interactable脚本组件拖入

Unity 3D官方教程——Adventure Game学习记录_第103张图片

 

子对象InteractableLocation设为如下

Unity 3D官方教程——Adventure Game学习记录_第104张图片

 

接着设置DefaultReaction

Unity 3D官方教程——Adventure Game学习记录_第105张图片

 

注意PictureInteractable没有特定的ConditionCollection,每次互动都播放刚设置的默认反应。

其他的Interactable设置,DefaultReaction设置,对应的ConditionCollection设置,AudioReaction等等都是一样的道理和操作。如有需要可在完成项目里看对应代码。

 

7.Game State

这一阶段学习如何用Scene Manager创建一个系统来加载场景,和保存当前游戏状态。ScriptableObjects作为临时runtime data存储,删除和lambda表达式(匿名表达式)。

1.架构介绍

这个将要创建的系统必须:

1.重要的信息(比如inventory 的状态)必须在场景切换时保留。

2.场景切换时由淡出淡入的效果。

3.支持多个spwan points,因为可能有很多不同场景切换进此场景(比如a和c场景,切到b场景player出现的点不一样)。

4.在卸载场景(unloading a scene )时,有些信息例如GameObject的位置必须被存储,以便在返回该场景时可以再次使用信息。(比如我们如果已经捡起了Coin,就存储信息,以免那里又有一个coin出现)

 

2.如何实现上述功能(Approach)

1.我们有一个Persistent Scene一直stay loaded at all times。Persistent Scene 将处理loading & unloading 其他场景。需要在所有场景中持续存在的信息比如Inventory就可以存在Persistent Scene里。

2.Persistent Scene并不适合存一切数据,比如一些游戏对象的细节仅存在在某一个特定的场景(比如the bird)。这时候我们用ScriptableObject assets临时性的存这些数据,这样这些特定数据可以loaded again或return to a scene。

3.场景加载架构:

Unity 3D官方教程——Adventure Game学习记录_第106张图片

包括Scene1淡出,Scene2加深fade in

Unity 3D官方教程——Adventure Game学习记录_第107张图片

 

4.save data 架构

比如场景里我们想存Coin的状态。将用一个GameObjectActivitySaver脚本存作一个Scriptable object名为MarketSaveData。

注意,ScriptableObject存数据是temporary(临时的)和runtime only(仅在运行时),它不支持store data between sessions,因为一系列我听不懂的原因^_^。

 

3.Delegate,Events & Lambda Expressions

1.delegate

delegate是一种变量,它可以存储方法而不是data(如bool,int,string)。The basic Action是一个特定类型的Delegate,代表一个没有返回类型和参数的方法。

Unity 3D官方教程——Adventure Game学习记录_第108张图片

Unity 3D官方教程——Adventure Game学习记录_第109张图片

 

Action也可以用作一般类型的delegate,下面的Action就返回空且有一个int 参数

Unity 3D官方教程——Adventure Game学习记录_第110张图片

 

delegate最主要的用处,是他们存方法就像变量(variables)一样,所以delegate可以把方法,像传送变量一样,传送到另一个方法去。

 

例如我们写了一个又长又慢的方法,当有必要时才调用,这时它作为一个方法传递出去并调用是不合算的(每次传进去并调用,将会有一个超长超慢的调用过程)。

所以我们通过delegate来传递该方法,由该方法的父方法决定是否要调用该方法。

你可以通过用 += 或 -=操作符来订阅或取消订阅delegate。这意味着可通过一个delegate添加多个函数,当调用该delegate时将调用多个函数。

Unity 3D官方教程——Adventure Game学习记录_第111张图片

 

2.Events

注意这里我们所说的Events和Unity里的Event System无关,它只是独立的C#内的脚本功能。这里的Event也是一种特殊的delegate。

使用event型的delegate可以在声明时加上关键词event

重点:event一旦被订阅(subscribed to),在摧毁前(destroy)一定要取消订阅(unsubscribeed from)。如果一直保持订阅,GC不会运行,导致内存泄漏(memory leaks)。实现它们的最好方式是在OnEnable()里订阅,在OnDisable()里取消订阅。

调用Events和调用delegate方式相同,这将调用订阅了该事件的所有函数。

Unity 3D官方教程——Adventure Game学习记录_第112张图片

 

event的重点在于触发类(triggering class)不需要告诉所有相关类(concerned classes)来调用特殊的方法。因为相关类可以监听一个event,然后做出相应的反应。

event和delegate的目的在于,比如我们现在将要创建的系统:我们已经有了场景管理器,现在我们需要卸载一个场景的同时,保存一些我们需要的数据。有两种方法可以实现它们,第一种,把场景控制器关联在所有需要保存的地方,然后再一 一“通知”这些地方保存。第二种,我们定义一个卸载场景的event,让这些需要保存的地方监听(订阅)该event,当event开始unload the scene时,保存。

 

3. Lambda Expressions

lambda表达式是一种,将要被存在delegate里的方法的简写方式。它们的语法(syntax)如下

因为我们用lambda简写方法,那用来写lambda的变量也很简短。变量通常是隐式类型的(implicitly typed)

比如,x隐式的和someValue具有相同的类型。我们不知道x的类型,但知道someValue的类型,那么就能确定x的类型。

 

下面是一些用Lambda表达式写的delegate,都非常的简短

 

当Lambda表达式更长或多个表达式时,使用{},注意{}后面还有;。

 

使用Lambda expressions的目的是为了简化我们的代码

Unity 3D官方教程——Adventure Game学习记录_第113张图片

 

4.开始设置Game State

Scripts→MonoBehaviours→SceneCotrol文件夹下,打开SceneController脚本并编辑。

Unity 3D官方教程——Adventure Game学习记录_第114张图片

Unity 3D官方教程——Adventure Game学习记录_第115张图片

Unity 3D官方教程——Adventure Game学习记录_第116张图片

 

将会在Persistent Scene里新建一个空对象挂载该脚本。

Unity 3D官方教程——Adventure Game学习记录_第117张图片

 

接着Scripts→ScriptableObjects→DataPersistent文件夹,打开下面的SaveData并编辑(场景切换时保存一些必要的数据)

Unity 3D官方教程——Adventure Game学习记录_第118张图片

Unity 3D官方教程——Adventure Game学习记录_第119张图片

Unity 3D官方教程——Adventure Game学习记录_第120张图片

Unity 3D官方教程——Adventure Game学习记录_第121张图片

 

现在我们要把真正需要保存的数据(比如PositionSaver)和保存方式(SaveData)之间联系起来。Scripts→MonoBehaviours→DataPersistent文件夹下,打开Saver脚本。

Unity 3D官方教程——Adventure Game学习记录_第122张图片

Unity 3D官方教程——Adventure Game学习记录_第123张图片

 

接下来我们看看使用Saver的具体例子,同文件夹下打开PositionSaver脚本

Unity 3D官方教程——Adventure Game学习记录_第124张图片

 

比如读取Player的初始站位,则是SceneController

 

完毕。

 

 

 

 

你可能感兴趣的:(•【完整项目】)