feat:上传历史教程

This commit is contained in:
Othniel su
2024-11-07 18:36:06 +08:00
parent 2a701d54e7
commit da2cc1d4fb
4615 changed files with 66207 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
---
front: https://nie.res.netease.com/r/pic/20220408/67103a4f-1246-40d2-ae22-a7ba0518e16c.png
hard: 入门
time: 5分钟
selection: true
---
# 玩法地图为什么需要新手引导?
玩法地图相较于普通的玩法组件会更加局限、规整,正因为这样,玩法地图才需好的引导;引导都有哪些好处?为什么需要新手引导?
### 玩家可以更好、更快的了解核心玩法
最重要的一点,引导需要能够让玩家了解地图的玩法,不需要花费大量的学习时间明白地图是怎么玩的;也可以让玩家对地图的玩法记忆更深刻。
### 融入地图背景,增强游戏代入感
合理的使用新手引导,可以让玩家对地图的背景更加了解,有更清晰的认知;同时利用一些剧情和带有背景色彩的文字描述使玩家融入到地图的故事中,增强代入感。
![1](./images/1.png)
例如在季度玩法《三打白骨精》中,就利用剧情通过和其它玩法人物进行对话了解玩法背景,可以使玩家在第一时间知道自己身处西游的世界,扮演悟空西天取经。
### 新手引导很重要,但并不是所有玩法地图都需要
如果是以开放生存为核心玩法的地图,其乐趣就是需要玩家在世界中漫无目的的探索,并在探索时不断发现新的玩法,那么是否需要新手引导就取决于玩法地图的作者来判断;但不建议有核心玩法的玩法地图完全舍弃新手引导。
![2](./images/2.png)
以[《我的海滨农场》](../../20-玩法地图教程/第00章示例下载/示例下载.md)为例,其主要玩法是玩家在小岛上通过种植庄稼、养殖畜牧并且在规定时间内赚到足够的钱才可以获得胜利!这一目标点则需要新手引导告知给玩家。
![3](./images/3.png)
### 明确游戏内容,在游戏的初期吸引玩家继续
在新手引导部分展露一些出彩、亮点的游戏内容可以大程度的吸引玩家继续游戏,并对后续的游戏内容报以期待。

View File

@@ -0,0 +1,67 @@
---
front:
hard: 入门
time: 10分钟
---
# 可以用什么形式进行新手引导?
引导的形式可以有很多,每个开发者都有自己对引导独特的理解,怎么能将引导最大程度的发挥其作用是需要开发者们用心设计的;本节将介绍多种引导形式并展开举例。
常见的玩法地图引导形式可以有引导关卡、NPC对话、剧情任务、镜头语言、引导手册、其它
## 引导关卡
将一些游戏玩法的内容拆解并在关卡内一步步引导玩家进行操作,熟络游戏核心玩法。通常引导关卡都会在正式开始游戏前出现;若游戏玩法复杂,且不仅只有一条核心玩法,那引导关卡也可以有多个,并在不同的游戏阶段出现。
![4](./images/4.png)
在[《我的海滨农场》](../../20-玩法地图教程/第08章在开头添加引导关卡/课程01.使用MODSDK自定义NPC的聊天对话.md)中玩家会先出现在新手小岛中玩家需要与NPC对话简单了解地图的玩法背景然后在NPC的指引下完成一些简单的操作种菜、采集石头、升级建筑这些都是在正式游戏时的循环玩法。
![5](./images/5.png)
完成这些简单的操作后,玩家才可以乘坐小船离开新手岛屿并正式开始游戏。
## NPC对话
在一些RPG / 生存类型的玩法地图中经常会有一些与剧情或故事背景相关的人物NPC可以通过这些NPC对话提示玩家需要注意的游戏内容同时添加对话剧情也可以带入游戏的背景增强玩家对地图的代入感。
![6](./images/6.png)
![8](./images/8.png)
## 剧情任务
这一引导形式应该会被大部分玩家及开发者熟知,很多的地图和除我的世界以外的游戏都或多或少的有剧情任务。
而由剧情任务作为主线贯穿整个玩法的地图,不需要过多的引导,玩家可以根据任务提示一步步摸索游玩,当然任务提示也算是引导的一种。
![8.5](./images/8.5.png)
## 镜头语言
通过控制玩家的摄像头,利用镜头语言来传达信息并引导玩家。
例如直接控制玩家看向某个地方,直接的引导玩家目标地点;虽然比较生硬,但也最直观、简便。
## 引导手册
在游戏大厅放置引导手册,将游戏内容列举在手册中供玩家翻阅;在开始游戏前就可以了解到几乎所有的游戏内容。相对其它引导形式来说,这是最简单的引导之一,也很受开发者和玩家青睐。非常适用于小游戏地图。
![7](./images/7.png)
当然也可以在游戏时提供引导手册,玩家可以在游玩的过程中随时翻阅。
## 其它
在一些需要玩家等待的地方委婉的添加引导如PVP地图中玩家在死亡、复活阶段添加有关玩法技巧的提示。
![9](./images/9.png)
或者适当添加跳跃性的文字提示,每隔一段时间或是玩家游玩到某个阶段,在玩家屏幕上显示。
虽然很生硬直接,但适当的与其它引导形式相结合,就会产生不同的效果。

View File

@@ -0,0 +1,371 @@
---
front:
hard: 进阶
time: 40分钟
---
# 为小游戏地图添加引导
我们来制作一个小游戏玩法地图DEMO并且为这个地图的大厅中添加一些引导。
点击[链接](https://g79.gdl.netease.com/Jungle_Demo.zip)可下载本章地图Demo。
## 在大厅添加NPC
先简单制作一个大厅场景地图名为《丛林激流》是一个轻松的“水上竞速”玩法地图而游戏场景设定是游乐园风格所以在大厅添加了多个游乐园会出现的小摊引导NPC将放置于此。
![10](./images/10.png)
在大厅内添加多个小动物形态的NPC熊猫、鹦鹉、狼。
> 有游戏背景或世界观的玩法地图,将所有的游戏元素风格统一化也是很重要的;
![11](./images/11.png)
## 制作UI添加引导手册
引导手册可以有很多方式体现最简单的方法就是将引导文字写在【书与笔】上并放在游戏比较“显眼”的位置即可。不过这次我们放置了NPC所以需要制作UI在玩家与NPC交互的时候显示UI。
![12](./images/12.png)
打开我的世界开发工作台的界面编辑器,制作引导手册界面和欢迎界面;
![13](./images/13.png)
欢迎界面主要填充一些对于地图的基本介绍和简单引导;当然,实际需要什么内容,还是根据引导设计和开发者习惯来决定。
引导手册则需要多页,将玩法内容罗列在此供玩家翻阅、学习。大部分情况下,小游戏地图不怎么需要引导手册,因为无论是场景还是玩法都是有局限性的,玩家在游玩的过程中必定会发现和体验到,全部的内容被玩家了解后,在真正游玩的时候可能会丧失一定的新鲜感。
![14](./images/14.png)
![15](./images/15.png)
**制作好UI后我们需要将UI与NPC“连接”起来**
创建UI的脚本文件FlumeRideInfoUI.py并继承ScreenNode类
```python
# -*- coding: utf-8 -*-
import mod.client.extraClientApi as clientApi
ViewBinder = clientApi.GetViewBinderCls()
ViewRequest = clientApi.GetViewViewRequestCls()
ScreenNode = clientApi.GetScreenNodeCls()
class FlumeRideInfoUI(ScreenNode):
def __init__(self, namespace, name, param):
ScreenNode.__init__(self, namespace, name, param)
```
创建FlumeRideServerSystem.py、FlumeRideClientSystem.py
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
ServerSystem = serverApi.GetServerSystemCls()
class FlumeRideServerSystem(ServerSystem):
def __init__(self, namespace, systemName):
ServerSystem.__init__(self, namespace, systemName)
# 提前将放在大厅的NPC生物ID获取到并保存在这里用于判断玩家交互的NPC
self.npcIdList = {"panda": "-85899345885", "panda2": "-158913789845", "parrot": "-158913789915", "wolf": "-158913789911"}
nameSpace, systemName = serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName()
# 监听PlayerAttackEntityEvent事件
self.ListenForEvent(nameSpace, systemName, "PlayerAttackEntityEvent", self, self.PlayerAttackEntityEvent)
# 玩家攻击生物时触发
def PlayerAttackEntityEvent(self, args):
# 由事件获取到的玩家攻击的生物ID
playerId = args['playerId']
entityId = args['victimId']
# 判断不同的NPC生物
if entityId == self.npcIdList["panda"]:
# 发送事件到客户端打开UI传输字典参数UIType用来判断玩家交互的生物以打开不同UI
self.NotifyToClient(playerId, "OpenGameInfoUI", {"UIType": "panda"})
elif entityId == self.npcIdList["panda2"]:
pass
elif entityId == self.npcIdList["parrot"]:
pass
elif entityId == self.npcIdList["wolf"]:
self.NotifyToClient(playerId, "OpenGameInfoUI", {"UIType": "wolf"})
```
在服务端脚本添加玩家攻击生物的事件并判断如果是大厅的NPC就传输事件到客户端创建UI。
```python
# -*- coding: utf-8 -*-
import mod.client.extraClientApi as clientApi
ClientSystem = clientApi.GetClientSystemCls()
class FlumeRideClientSystem(ClientSystem):
def __init__(self, namespace, systemName):
ClientSystem.__init__(self, namespace, systemName)
print "Client初始化"
nameSpace, systemName = clientApi.GetEngineNamespace(), clientApi.GetEngineSystemName()
# 监听UiInitFinished事件
self.ListenForEvent(nameSpace, systemName, "UiInitFinished", self, self.UiInitFinished)
# 监听由FlumeRideServerSystem传过来的OpenGameInfoUI事件
self.ListenForEvent("FlumeRide", "FlumeRideServerSystem", "OpenGameInfoUI", self, self.OpenUI)
# 由FlumeRideServerSystem传过来的OpenGameInfoUI事件
# 当玩家与NPC交互时判断交互的NPC类型并打开对应的UI
def OpenUI(self, args):
UIType = args['UIType']
if UIType == "panda":
clientApi.PushScreen("FlumeRide", "FlumeRideGameInfo")
elif UIType == "wolf":
clientApi.PushScreen("FlumeRide", "FlumeRideGameBook_1")
# UI初始化完成将UI注册
def UiInitFinished(self, args):
clientApi.RegisterUI("FlumeRide", "FlumeRideGameInfo", "Script_FlumeRide.uiScript.FlumeRideInfoUI.FlumeRideInfoUI", "GameInfo.main")
clientApi.RegisterUI("FlumeRide", "FlumeRideGameBook_1", "Script_FlumeRide.uiScript.FlumeRideInfoUI.FlumeRideInfoUI", "GameBook.main")
clientApi.RegisterUI("FlumeRide", "FlumeRideGameBook_2", "Script_FlumeRide.uiScript.FlumeRideInfoUI.FlumeRideInfoUI", "GameBook_2.main")
```
现在我们攻击大厅的生物就可以打开UI界面了。
<img src="./images/16.gif" alt="16" style="zoom:120%;" />
简单修改UI文件将关闭按钮和引导手册的翻页按钮与FlumeRideInfoUI.py脚本文件中的某个函数绑定。
```json
// ...
// UI文件
// 关闭按钮控件
"GameInfoButton@common.button" : {
// ···
// 绑定按钮按下时触发的函数 %ScreenNode脚本.函数名
"$pressed_button_name" : "%FlumeRideInfoUI.ClickedCloseButton",
// 需要删除
"button_mappings" : [],
// ...
},
// 翻页按钮同理
```
```python
# -*- coding: utf-8 -*-
# ...
class FlumeRideInfoUI(ScreenNode):
def __init__(self, namespace, name, param):
ScreenNode.__init__(self, namespace, name, param)
# 绑定关闭按钮
@ViewBinder.binding(ViewBinder.BF_ButtonClickUp)
def ClickedCloseButton(self, args):
clientApi.PopScreen()
# 绑定翻页按钮
@ViewBinder.binding(ViewBinder.BF_ButtonClickUp)
def ClickedPageTurnButton(self, args):
GameBook1UI = clientApi.GetUI("FlumeRide", "FlumeRideGameBook_1")
GameBook2UI = clientApi.GetUI("FlumeRide", "FlumeRideGameBook_2")
if GameBook1UI:
clientApi.PopScreen()
clientApi.PushScreen("FlumeRide", "FlumeRideGameBook_2")
elif GameBook2UI:
clientApi.PopScreen()
clientApi.PushScreen("FlumeRide", "FlumeRideGameBook_1")
```
<img src="./images/17.gif" alt="17" style="zoom:120%;" />
## 添加NPC对话
接下来为另一位NPC添加对话简单描述一下地图背景和引导即可。
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
ServerSystem = serverApi.GetServerSystemCls()
commandComp = serverApi.GetEngineCompFactory().CreateCommand(serverApi.GetLevelId())
class FlumeRideServerSystem(ServerSystem):
def __init__(self, namespace, systemName):
ServerSystem.__init__(self, namespace, systemName)
# ...
# 监听PlayerAttackEntityEvent事件
self.ListenForEvent(nameSpace, systemName, "PlayerAttackEntityEvent", self, self.PlayerAttackEntityEvent)
# 监听ClientLoadAddonsFinishServerEvent事件
self.ListenForEvent(nameSpace, systemName, "ClientLoadAddonsFinishServerEvent", self, self.DataInit)
# 玩家客户端加载完毕时触发,创建玩家数据
def DataInit(self, args):
# 由事件获取的玩家ID
playerId = args['playerId']
# 获取玩家的数据
playerDataComp = serverApi.GetEngineCompFactory().CreateExtraData(playerId)
pandaMsgData = playerDataComp.GetExtraData("pandaMsg")
# 如果这个玩家没有数据,就设置一个
if not pandaMsgData:
playerDataComp.SetExtraData("pandaMsg", 0) # 用来判断玩家的对话阶段
# 玩家攻击生物时触发
def PlayerAttackEntityEvent(self, args):
def Panda2Guide():
# 获取玩家的名称
playerNameComp = serverApi.GetEngineCompFactory().CreateName(playerId)
playerName = playerNameComp.GetName()
# 获取玩家的pandaMsg数据
playerDataComp = serverApi.GetEngineCompFactory().CreateExtraData(playerId)
pandaMsg = playerDataComp.GetExtraData("pandaMsg")
commandComp.SetCommand("playsound random.orb " + playerName + " ~ ~ ~ 3 1 1")
# 根据玩家当前的对话阶段,触发不同的对话分支
if pandaMsg == 0:
# 使用指令接口生成对话
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f《丛林激流》欢迎你 §a(1/6)"}]}')
elif pandaMsg == 1:
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f丛林的小动物们和人类一起建造了这里 §a(2/6)"}]}')
elif pandaMsg == 2:
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f今天是激流游乐园开业的第一天 §a(3/6)"}]}')
elif pandaMsg == 3:
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f鹦鹉小姐会教你如何在水赛道上更加灵活 §a(4/6)"}]}')
elif pandaMsg == 4:
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f关于丛林激流的一切还可以问问狼先生,他什么都知道 §a(5/6)"}]}')
elif pandaMsg == 5:
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f当然,不要忘了叫上小伙伴一起享受这快乐的游戏时光! §a(6/6)"}]}')
# 到最后一条对话就重置数据并且return
playerDataComp.SetExtraData("pandaMsg", 0)
return
# 更新当前数据+1
pandaMsg += 1
playerDataComp.SetExtraData("pandaMsg", pandaMsg)
playerId = args['playerId']
entityId = args['victimId']
if entityId == self.npcIdList["panda"]:
# ...
elif entityId == self.npcIdList["panda2"]:
Panda2Guide()
elif entityId == self.npcIdList["parrot"]:
# ...
elif entityId == self.npcIdList["wolf"]:
# ...
```
<img src="./images/18.gif" alt="18" style="zoom:120%;" />
使用【指令】实现这种对话效果表现力较为薄弱如果用UI代替会更好但是实现起来会非常简单如果对UI不熟练可以使用这种方法。
## 控制镜头介绍内容
还剩最后一位NPC鹦鹉它将带领玩家观赏和讲解游戏中的场景和内容。
<img src="./images/19.gif" alt="19" style="zoom:120%;" />
```python
# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
ServerSystem = serverApi.GetServerSystemCls()
timerComp = serverApi.GetEngineCompFactory().CreateGame(serverApi.GetLevelId())
commandComp = serverApi.GetEngineCompFactory().CreateCommand(serverApi.GetLevelId())
class FlumeRideServerSystem(ServerSystem):
def __init__(self, namespace, systemName):
ServerSystem.__init__(self, namespace, systemName)
# ...
def DataInit(self, args):
# ...
if not pandaMsgData:
playerDataComp.SetExtraData("pandaMsg", 0)
# 添加新的数据用于判断鹦鹉讲解的阶段
playerDataComp.SetExtraData("parrotMsg", 0)
def PlayerAttackEntityEvent(self, args):
def ParrotGuide():
# 获取玩家的名称
playerNameComp = serverApi.GetEngineCompFactory().CreateName(playerId)
playerName = playerNameComp.GetName()
# 获取玩家的parrotMsg数据
playerDataComp = serverApi.GetEngineCompFactory().CreateExtraData(playerId)
parrotMsg = playerDataComp.GetExtraData("parrotMsg")
# 根据玩家当前的讲解阶段,触发不同的讲解分支
if parrotMsg == 0:
# 传送玩家
commandComp.SetCommand("tp " + playerName + " 29.5 80 -242.5 -20.4 31.4")
# 发送事件到客户端用于锁定玩家的控制
self.NotifyToClient(playerId, "PlayerCamera", {"Camera": "Lock"})
# 使用指令接口生成对话
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"鹦鹉 §e§l| §r§f这是摩托艇,你需要驾驶它驰骋在丛林河道上 §a(1/3)"}]}')
elif parrotMsg == 1:
commandComp.SetCommand("tp " + playerName + " 23.6 79 -252.5 54.1 16.4")
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"鹦鹉 §e§l| §r§f在丛林中,你会看到幸运Q块,用弩射击它将会发生随机的事件 §a(2/3)"}]}')
elif parrotMsg == 2:
commandComp.SetCommand("tp " + playerName + " 33.4 112 -136.4 -162.6 -7.8")
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"鹦鹉 §e§l| §r§f熟练操控摩托艇,精准射击幸运Q块,在丛林中激流吧! §a(3/3)"}]}')
elif parrotMsg == 3:
commandComp.SetCommand("tp " + playerName + " 22 68 -254 -114.8 0.9")
# 讲解结束后,解锁玩家的控制
self.NotifyToClient(playerId, "PlayerCamera", {"Camera": "UnLock"})
# 重置阶段数据并return
playerDataComp.SetExtraData("parrotMsg", 0)
return
commandComp.SetCommand("playsound random.orb " + playerName + " ~ ~ ~ 3 1 1")
# 更新当前数据+1
parrotMsg += 1
playerDataComp.SetExtraData("parrotMsg", parrotMsg)
playerId = args['playerId']
entityId = args['victimId']
if entityId == self.npcIdList["panda"]:
# ...
elif entityId == self.npcIdList["panda2"]:
# ...
elif entityId == self.npcIdList["parrot"]:
# 触发四次ParrotGuide利用定时器接口实现延迟触发
ParrotGuide()
timerComp.AddTimer(10, ParrotGuide)
timerComp.AddTimer(20, ParrotGuide)
timerComp.AddTimer(30, ParrotGuide)
elif entityId == self.npcIdList["wolf"]:
# ...
```
```python
# -*- coding: utf-8 -*-
import mod.client.extraClientApi as clientApi
ClientSystem = clientApi.GetClientSystemCls()
class FlumeRideClientSystem(ClientSystem):
def __init__(self, namespace, systemName):
ClientSystem.__init__(self, namespace, systemName)
# 监听由FlumeRideServerSystem传过来的PlayerCamera事件
self.ListenForEvent("FlumeRide", "FlumeRideServerSystem", "PlayerCamera", self, self.PlayerCamera)
# 用于锁定和解锁玩家控制
def PlayerCamera(self, args):
# 获取玩家控制接口
controlComp = clientApi.GetEngineCompFactory().CreateOperation(clientApi.GetLevelId())
if args["Camera"] == "Lock":
controlComp.SetCanAll(False)
elif args["Camera"] == "UnLock":
controlComp.SetCanAll(True)
```
这种形式非常直观、生动;镜头可以是静态的,也可以制作成动态;镜头内的方块、生物等内容也可以通过动画加强表现力。非常适合用来设计引导!
## 其它
在一些可交互或者有玩法内容的实体、方块上添加标识,会更加直观:
![20](./images/20.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

View File

@@ -0,0 +1,37 @@
---
front:
hard: 入门
time: 5分钟
---
# 什么样的玩法需要新手引导?
几乎所有的玩法组件都需要新手引导的帮助,才能让玩家们有更好的游戏体验;也有部分玩法并不需要新手引导,那到底什么样的玩法需要新手引导呢?
## 存在核心玩法,玩家在游戏时会产生活动循环
这样的组件会有一个核心玩法,玩家将围绕核心玩法展开,在此基础上添加多种元素;将各种各样的元素结合起来,不断地扩充玩法。
例如端游版的“工业”模组,玩家需要通过建造机器寻找量产资源、减少资源消耗的方法。找到最优解和与他人不同的玩法是工业模组的魅力所在。
![1](./images/1.png)
工业中大量的机器、矿物等元素,如果没有新手引导,很多玩家可能会在开始游戏的初期就困难重重,甚至无法游玩导致被劝退,因此这样的玩法就很需要新手引导。
## 打造新手引导体验的目的
如果仅仅是为了能够让玩家更快的了解游戏内容,可能就没有太多必要费尽心思打造尽可能完美的新手引导;其实新手引导的目的还有很多:
- 给玩家留下良好的第一印象
- 能够使玩家掌握要领并快速体验游戏,而不是被劝退
- 尽可能吸引玩家继续游玩
其实这些目的总结来说就是能够让玩家有更好的游戏体验。当引导不足或根本没有时,玩家会因无法理解而举步维艰,游戏进度不能推进;若引导过度,不能以正常的玩家视角体验游戏,像培训一样被一步一步的指导。
## 玩法不足以支撑一个核心玩法时,不一定需要新手引导
一些体量比较小的组件,有时不一定需要新手引导。比如:更多的武器、更多的怪物等,在大多数情况下,这类的组件通常只有一条主线玩法,玩家也仅根据这条线游玩。即采集 > 合成 > 提升能力;游戏流程较短,玩家需要理解的信息量也就很少。
![2](./images/2.png)
比如,“更多的熔炉”模组添加了额外的特殊熔炉,使用原版的普通熔炉和其它材料合成活动,特殊熔炉在普通熔炉的基础上增加了格数和烧制速度。其内容基本时采用原版的合成、采集、创造背包直接获取的方式,玩家可以很直接就能了解到所有内容,因此这里如果要做新手引导,则就需要实际考虑是否有必要了。

View File

@@ -0,0 +1,65 @@
---
front:
hard: 进阶
time: 10分钟
---
# 新手引导过去在我的世界玩法中的体现
原版我的世界中,玩家基本按照采集 > 合成 > 强化能力 的方式循环往复。所以,组件如果也按照这种方式去设计游戏内容,玩家就可以自然的用我的世界本身的玩法引导自己;比如某个“更多的武器”模组,添加了数十种新的武器,当玩家收集到材料后就可以合成这些武器,从而强化能力。
![3](./images/3.png)
## 玩法手册
将所有玩法的内容和攻略放在一本书中供任何人参阅,比起各式各样妙趣横生的引导方式,更加的直接,全面。于是,玩法手册这一引导方式被非常多的作者和玩家喜爱,我们可以在很多大体量的端游版模组、手游版组件中看到这类引导形式。
![4](./images/4.png)
比如在端游版的“植物魔法”模组中,使用树苗和一本书可以合成一个植物魔法辞典,打开辞典,里面记录了关于这个模组玩法的方方面面。
![5](./images/5.png)
在打开辞典的第一页,首先介绍了辞典的使用方式,“你可以通过页面下方的箭头、鼠标滚轮或键盘上的方向键来浏览这本书”,简单的一句话,其实也是很重要的引导;毕竟,如果连书都不会看,又怎么能看懂书上的内容呢?
![6](./images/6.png)
目录的功能也很重要,玩家可以通过目录精准找到自己想要学习的内容;同时也将内容分为一个个小的章节,通过标题来展示。
![7](./images/7.png)
玩法手册中,常见的形式分为:文字信息、步骤图文、内嵌合成表、实体纸娃娃。
这些形式也作用于不同的玩法上,比如内嵌合成表可以非常直观的展示物品的合成配方:
![8](./images/8.png)
## 规则型成就系统
在端游版中,我的世界有一个存在了很久的系统:成就。打开成就菜单,可以看到由一条或多条线连接的成就,每个成就会有图标、标题和目标,玩家则可以根据成就推动游戏进度。
![9](./images/9.png)
在端游版的“暮色森林”模组中,也有同样的成就系统,完成时会在右上角进行提示;打开成就栏可以看到所有的游戏流程目标。
![11](./images/11.png)
但是,与达成目标型的成就系统相比,不强调保持玩家对玩法的新鲜感;而常被用来介绍游戏流程。为玩家如何实现目标做出限制,推动玩家去一一解决问题探索更多未知的可能。
![12](./images/12.png)
## 任务手册
任务手册在端游版的一些大型整合包中颇为常见,它不仅仅作为引导,大多数情况下也作为独立的任务系统在游戏中推动游戏发展,这些任务可能涉及多个模组的内容。
![13](./images/13.png)
这种引导方式对安排玩家的学习顺序提供了帮助。一个整合包带有多款模组玩法时,需要注意玩家能够接受新信息的能力和学习速度。
![14](./images/14.png)
在游戏初期,通常会有一些非常简单、易于完成的任务;完成这些任务才可以继续向前推进,否则就无法继续游戏流程,有非常强烈的指导性,能够让玩家在游戏中有明确的目标;在整个游戏过程中都受到引导。

View File

@@ -0,0 +1,48 @@
---
front: https://nie.res.netease.com/r/pic/20220408/7838f1a5-09a4-4a2b-9ec8-641d2dc39b03.png
hard: 进阶
time: 5分钟
selection: true
---
# 小型玩法的引导核心
接下来,将玩法分为:小型、中型和大型,来分析一下不同体量的玩法要怎么区分,并且如何恰当的建立引导核心。
## 小型玩法的标准
**大部分情况下,玩法设计的内容都很贴近我的世界游戏本身;**在游玩的过程中,可以根据我的世界原版的游戏知识去理解组件的内容。(很多开发者在设计玩法时也会自然的向原版靠拢)
![15](./images/15.png)
**包含两个及以上的玩法点,并且存在玩法循环;**原版游戏中,最浅显易懂的一条玩法循环就是:探索 > 收集 > 合成 > 强化能力。我的世界最有魅力的地方在于玩法与玩法之间是相乘的关系,简单的玩法经过反应就可以有非常多的新玩法出现;如红石和各个方块、生物之间的配合。
![16](./images/16.png)
对于一个小型的玩法来说,其主要有两个及以上的玩法点并且可以产生一条循环;还是拿“突变生物”模组举例,这个模组的核心玩法和循环在于:发现并与突变怪物战斗 > 获得怪物的战利品 > 合成装备强化自身。
## 小型玩法的引导
小型玩法的引导不需要过多的设计,因为其玩法本身需要玩家理解的内容较少,深度也较浅;如果玩法也很贴近原版风格,过度的引导甚至会使玩家的新鲜感骤降。所以,就要尽量依赖原版的引导设计:
![17](./images/17.png)
比如玩法中有新增的生物,设计生物会在某种情况下自然生成;如在夜晚会和怪物们一同生成,那么玩家在游玩的过程中,能够直接发现这种生物,就可以对生物进行攻击或交互等行为。这就很贴近原版体系。
![18](./images/18.png)
如果玩法中新增的生物并不会自然生成,而是使用某种特殊的方式召唤生成,若生成方式比较复杂,可以使用浅显易懂的玩法手册,引导玩家;
------
总而言之,对于小型玩法而言,可以先整理组件中的玩法点并将之归纳进原版体系,用原版玩法去解释玩家付出努力后得到的回报;

View File

@@ -0,0 +1,31 @@
---
front:
hard: 进阶
time: 5分钟
---
# 中型玩法的引导核心
中型与小型玩法最大的区别就是**“是否有自创的游戏体系”**,一部分或所有的玩法内容脱离原版我的世界的玩法,形成玩法循环;同时玩法的流程更加线性、流畅。
![19](./images/19.png)
“等价交换”模组中添加了新的“货币”EMC值使用交换桌可以将游戏内的物品转换为EMC值也可以使用EMC值来转换成任意物品。探索收集 > 转换EMC > 使用EMC
## 中型玩法的引导
自创、创新的游戏体系,在被玩家慢慢发掘时,会有非常大的惊喜和乐趣。所以,引导的核心需要使人产生行为反射,使用分阶段的方式清楚的传达它,有助于玩家在游玩的过程中慢慢领悟玩法。
![20](./images/20.png)
所以,将引导藏在一个个目标下,但不把所有目标以开始就告诉玩家;使用规则型的成就系统,是一个非常好的引导方式。
![21](./images/21.png)
在不同时期隐式的提供成就引导,玩家可以在探索的过程中慢慢发现玩法,并且循序渐进,最终深入并理解所有玩法。
------
总之就是将玩法拆成一个个需要玩家去实现的目标,不一定要固化,完全使用规则性成就;发挥创意,以此为核心改编引导形式也是完全适合的。

View File

@@ -0,0 +1,52 @@
---
front: https://nie.res.netease.com/r/pic/20220408/b5370e55-389a-40c4-af25-d9599ec8bbfc.png
hard: 进阶
time: 5分钟
selection: true
---
# 大型玩法的引导核心
分别介绍完了小型和中型的玩法标准及其可能的引导方式;大型玩法因为内容较多,需要注意的引导设计也较复杂。
## 大型玩法标准:
- 带有较为较为清晰的世界观
- 玩法不断扩展、堆叠,形成多条以上的玩法循环
- 游戏流程存在交叉、跳转
- 可以根据玩家的要求自由灵活地调整玩法达成的目的
- 大量运用自创的游戏体系
![22](./images/22.png)
“暮色森林”是一个老牌的大型玩法模组,以独特、清晰的世界观一直被我的世界玩家们称赞和反复体验。所以,一个大型玩法是否带有较为清晰的世界观还是比较重要的。
玩法循环、玩法流程在前面的小型和中型玩法中已经详细介绍过,这里不多赘述;
创新的游戏体系也是非常重要的评判标准,玩法过于平淡或“低创”,也很难被归并到大型玩法中。
<img src="./images/23.png" alt="23"/>
**神秘时代模组中的特殊收集方式*
## 大型玩法的引导
大型玩法需要解释的设定非常多,有一定的内容深度。全部直白地交给玩家吸收不一定能达到最好的效果,所以核心玩法应被作为优先引导的部分。在体验后续的玩法中,更多依赖设计上的反馈,引导不一定总会在线。
![24](./images/24.png)
“暮色森林”中,较为直观的引导就是【进度】的成就系统,将每个游戏的关键节点归列成一个个的成就。
![25](./images/25.png)
“神秘时代”模组在前期,任务手册中只会有一些针对核心玩法的任务,随着玩家熟悉核心玩法后,后面的多个阶段利用游戏设计让玩家记住机制。
![26](./images/26.png)
**神秘时代模组中获得特定物品时出现的引导提示*
------
在游戏内容越多的情况下,游戏引导过多容易适得其反;提供必要的核心玩法引导以外,学习适应游戏和改变规则的方法应在实际游戏中潜移默化地影响玩家,这是引导设计相对理想的状态。
如何设计好新手引导,需要开发者不断地研究、尝试。

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB