这篇文章的目的?
这是一本指南式的工具书,记录了作者对原版开发的整体概括。
目标是让读者快速查缺补漏,了解整体情况,以及在困扰怎么做某些东西时能按图索骥。
为此本文尽量简短,降低阅读成本。
所以本文只提供三行以内的实现,更复杂的内容在此仅作为关键词集合和索引,读者需自行检索 Wiki 或香草图书馆等网站获取详细教程。
如果有疏漏,或者错误,可以在下面指出,或者与作者(下称“我”)合作编辑。
本文可能含有自造词汇等私货,或临时捏造一些词汇,请自行甄别。
使用哪些工具?
|| 数据包编辑
◇ VSCode
工具简介
扩展齐全的代码编辑器。也可以打开图片之类的,只要别太大。
可以使用 Git 和 Github 进行源代码管理(备份、团队协作)。
可以使用内置的 liveshare 功能进行合作编辑,类似石墨文档、腾讯文档等云文档的编辑体验。
如果是在服务器上开发,也可以用 ssh-remote 插件远程连接到服务器进行编辑。
- ◇
Datapack Helper Plus by Spyglass 插件(中文名:大憨批)
- 提供函数和各种文件的自动补全
- (虽然名字里是 Datapack 但是不知道为什么模型文件也有补全)
- 没错,中文名真的叫大憨批。或许是 MCBBS 命令/数据包版块喜闻乐见的凑首字母环节。
Insert Numbers Pro 插件
- 在穷举的时候比较有用。可以批量插入命令
- 鼠标中键拖动选中多行,然后
Ctrl+Alt+N 即可弹出补全格式窗口。
Markdown All in one 插件
MCFPP
狐狐 @Alumopper 开发中的高级数据包语言。
- 是原创语言,有接近高级编程语言的语法
- 也可以直接使用数据包的语法,仅作为方便穷举的工具
- 最大的问题没有 VSCode 插件,所以也没有自动补全
Beet/Bolt
伊桑 @ethanout 力荐的开发脚本,可能比 MCFPP 这样的重型工具更简单轻便。
似乎已经是国外主流的数据包脚本语言了。
- 可以用Python和mcfunction的混合语法控制命令和函数
其他
查阅
前置(别人写好的功能)参阅下文有关章节
|| 美术资源制作
◇ Blockbench
工具简介
Mojang 死丢丢都在使用的 MC 体素建模软件。
用于建模、绘制材质、制作动画。也可以画皮肤。除了原版开发,你也可以用它来制作 Yes Steve Model 模型。
- ◇
Animated Java 插件
- 能给输出可在原版 Java 版 MC 运行的骨骼动画包。
其他像是笔刷之类的插件也可以下一点,内置有插件市场。
使用技巧
- 先建模完成,再全选所有元素,按创建纹理,就可以自动生成一张绑定好了 UV 的纹理(旧译:材质)了。
- 元素尺寸尽量不要是精细度的非整数倍,除非你那一块不打算上纹理,保持纯色。
文件-编辑会话 选项理论上可以让你和其他人联机一起做模型,但是实测国内似乎用不了。
文件-转换项目 可以把通用模型 .bbmodel 转换为 Animated Java 模型
- 似乎也有插件可以把
.obj 文件转化为 .bbmodel 文件。
- 因此也有人在
Blender 搅拌机里把动画之类的搅好再传回 Blockbench
Aseprite、 PS 等其他贴图绘制软件
可选。
Blockbench 自带的绘画模式功能可能会有点少。或许可以用插件补全一部分。
总之备一个专门画像素画的软件用来画点像素画、制作 UI 之类的也不错。
Objmc
一个使用着色器驱动,在 MC 里直接渲染 obj 模型及动画的项目
由于着色器的向上兼容性很差,并且还会让玩家没法用 opti 或 modapi 客户端安装光影包,而这个项目的更新并不够迅速,因此大部分情况下还是更推荐使用 Animated Java
◇ Axiom fabric mod
- 做建筑地形的神,上手约等于无门槛,随便试试就知道怎么用了。
- 可以编辑、组合展示实体
- B 站有教程
- 更新很快,最新版本发布后大约 37 天就会更新新版本。
- 如果你一定要追着快照版开发,也可以先升级,后迁移地形地物,问题不大。
至于原版洁癖的问题,我的评价是:发布和游玩层面可以坚持纯净,开发方面也坚持纯原版的话,要做到接近的开发效率就很麻烦了,还得自己开发工具。而且如果不用自己当小六边形了,总不能让来帮忙的美工也学着用自制的都不一定有UI的简易工具吧。
World machine
地形生成工具
- 一般似乎是用于生成灰度图,然后导入到 Axiom 等其他工具,再“印刷”到地图上。
|| 工具网页
数据存在哪?
|| 分数(整数变量)
记分板 /scoreboard
“分数”和“记分项”都不太能指代“一个分数持有者在某个记分项的分数”,所以这里临时用“记分板分数项”(或“记分项”)指代。
- 只能存整数,计算结果向下取整。
- 指向的玩家可以不存在,也可以不是玩家。
- 尽管子命令叫
players 并且自动补全只能补全玩家。
- 所以 Wiki 中使用的词是
分数持有者(Score Holder) 而不是玩家。
- 临时数据用 # 开头可以不在侧边栏显示,同时性能上似乎也有一定优化。
- 除了加减及设置固定数值之外的所有运算,都需要使用
scoreboard players operation 子命令。
operation 只能让分数项与分数项之间进行运算。譬如要运算 a*2,就必须形如 a score *= 2 score
- 因此我一般会在
load 函数中注册大量常数备用。
- 创建一个临时记分板很有用,可以省去思考一些小步骤的分数存在哪里的问题。
- 作为参考,我会使用
_ 作为所有临时存放位置的名称,如score return _ 而小豆娘会使用 int。Dahesor 使用calculator或calc.namespace
- 记分板准则有很多种。
- 一般使用
dummy 来存放变量。
trigger 允许玩家自行修改,但需要使用 scoreboard players enable 赋予玩家
- 其他一些像是
health 等准则会让分数自动变化。包括所有可以在 ESC 菜单的“统计”里找到的内容。
我们一般用 n条scb 来衡量并表示一条命令或一个模块的消耗。这是指一次 scoreboard player add | remove 的能耗,是一个足够小且稳定的基准。
|| NBT(键值对)
1. 纯 NBT
NBT存储 /data modify storage
- 可以存储的数据类型非常多。一般使用 NBT 来存储和管理数据,记分板大部分情况下只用来进行暂存和运算,除了在数据强绑定实体的情况下会用来存数据(如存储分数、实体坐标,且需要随时计算更新)。
- 相对于实体 NBT 而言效率很高。
data modify storage name path set value "233" 的消耗与单条简单记分板相差无几。
- 但是效率与路径的层数、复杂度挂钩。如操作
storage data a.b.c 的消耗会比 storage data a 高一些。
我暂时没有精确的数据,不过暂时理解成每层增加 10%~30% 的损耗就行了。大部分情况下不需要担心这个。
2. 非玩家实体
1.21.5+
所有实体的 NBT 路径 entity @s data
AI生物
entity @s (armorItems旧 1.21.4- | equipments1.21.5+)
物品相关实体
entity @s (item | Item)区别是大小写
3. 玩家
Storage 玩家空间
在 NBT 存储 中建立玩家专属的路径,称之为玩家空间。
如:
VDC>pllib 模块使用 `storage vdc:pllib 0[{ uid:1, name:"VRainbow_",UUID:{...} }] 这样的形式来存储玩家空间。
- 也可以使用宏函数来创建并指引路径,形如
storage proj:player $(name).skill
优点是方便管理和使用。即使玩家下线也能够访问和处理其数据。
缺点是如果人来人往,这个 NBT 存储的文件会越来越大。
- 如果大到一定程度(对于小型私有服务器或局域网联机地图而言,除非数据溢出否则基本上不可能),如 20MB , 会导致游戏周期性地在自动保存时造成一瞬的卡顿,可能持续数百毫秒。
隐形物品
在玩家的物品栏中放置不影响游戏体验的隐形物品,并将数据存放在其中
(用data entity @s <item>.components.minecraft:custom_data.<nbt> if items ... *[custom_data~{}] item modify ...来判定或操作。这里< >是指代某个路径)
- 如
VDC>pllib 模块的前身, 1.15 ~ 1.19 的 EDLib 前置,就是在末影箱中放置两个物品,互为备份。
- 1.20.5+ | 现在更多的是使用
armor.body 或 armor.saddle1.21.5+ 槽位
- 用
item 命令置入并修改其内容
- 打开
保存物品栏 (死亡不掉落) 以避免其意外丢失。如果只存放临时数据,也可以使用消失诅咒。
- 是的,这个槽位也可以用来令一些魔咒生效。因此可以用来附魔一些希望绑定玩家自身而非可穿戴物品的效果。
- 1.21.2+ | 在
equippable 数据组件(物品组件)更新后,修改物品的 equippable.slot 可以允许其放入这两个原本不能放入的格子,因此也可以使用别的物品。
- 在开发中的『悬线Proj.』中,我使用的是命名牌,并将其称为“角色铭牌”。
- 这个方案也可以与玩家空间并行,用于:
- 存储临时数据:不一定更快,但或许方便。如果使用收纳袋等物品原型,还可以用来折叠一些物品的同时又能用
if items *[bundle_contents~[{}]] 判定或使用物品修饰器来操作。
- 存储一些确定是只要玩家下线就不会再用到的数据。
- 反例:玩家的基础信息(用于对照查表)、即使下线了也可以被管理(增删重置、升级版本)的数据。
- 正例:玩家的局内数据、确定不会更新或可以上线后再更新的数据(如折叠的物品栏)。
怎么在需要的时候触发效果(系统入口和广播事件汇总)
|| 高频循环检测 + 条件判定
周期执行方式
简单顺序:tick函数 >> load函数添加的schedule >> 手动添加的schedule >> 进度触发的函数>>魔咒触发的函数
点我查看详情(可能需要科技)
Tick 函数集 (tick.json 函数标签内函数)
- Tick 函数集会每tick执行
- 在游戏的主程序循环里执行的非常早,比
time query gametime 的 gametime 更新还要早。如果不处理,就约等于是在同一 tick 下最后执行的。
- 如果需要进一步区分多个数据包的 tick 函数的执行优先级,可以在 Tick 函数集内调用别的函数标签,其他数据包的 tick 函数再挂在子级函数标签下。
Schedule 循环
/schedule function <This> 1t
在函数中用 schedule 为自身定时,可以令其循环执行。
- 执行顺序与
schedule function 执行的顺序相同。
- 加入条件判定可以自动终止循环
- 也可以用
/schedule clear 来主动终止循环
- 如果你不将
/schedule function 函数在 <This> 执行,而是在 Tick 函数集里定时,那么这个循环每 Tick 都会被后置理论上是,没经过完整测试。
- 可以修改时间参数来延长执行周期
- 可以每隔 1 tick 或数个 tick 执行一个这种循环,并将一些瞬时执行的函数分成多块跨 tick 执行。
- 这可以平滑计算压力,对 tps 火焰图进行削峰处理。说人话就是:降低 1% low帧,但是 tps。
魔咒循环
使用 tick 魔咒效果组件的物品,并将物品放在目标实体的可触发的槽位上(如前文提到的 armor.body)。效果设为执行函数。
- 自带执行上下文
- 可以略过初步筛选实体的步骤,只有需要检查的实体会执行
- 使用物品修饰器
{function:"set_enchantment"} 移除附魔(将等级设为0)或干脆删除物品即可终止循环。
进度循环
- 和魔咒循环类似
- 不需要物品
- 只能用于玩家
- 赋予玩家这个进度而不使用
revoke 重置状态即可终止循环
- 据说
/advancement revoke 其实消耗不算低,在 100 scb 左右。
条件判定
通过这些条件判定该 tick 是否执行特定效果。
execute (if|unless)
最常用的条件判定方式。也可以调用谓词。这里就列出一点容易疏漏的点得了。
if data 如果在整条指令的末尾,会返回 NBT 数量。
补充说明
- 所以可以使用形如
execute store result score return _ if data storage _ List[{type:"b"}] 的命令来获取列表中符合条件的的元素数量。
- 而
data get ... List(注意后面没有[]) 只能得到总的元素数量,如果指定路径的是 List[] 则会报错
[/detail]
if items 的效率要比 if data <target> item{} 要高不少。功能也要强一点。
补充说明
- 使用通配符
* 来指代任意槽位或物品
- 用
~ 替代等于号 = 以模糊匹配。 如 *[custom_data~{ a:b }] 可以匹配到 {a:b, c:d}。反之使用 = 则只能匹配到 {a:b} 而不能匹配到前述组件。
- 一些组件可以指定数值范围而非固定数值:
*[count~{min:1,max:24}]
*[enchantments~[{id:"sharpness",level:{min:3}}]]
if function 可以在句中执行函数,根据函数的返回值决定是否继续执行。
- 不能执行宏函数,要套一层壳
- 没有返回值也不会通过
[/detail]
if/unless 没有 else 和 elif 的说法。但是:
补充说明
你可以新开一个函数(设为 cond.mcf),并在函数开头写上 execute if/unless ... run return run function pass_func,这样 function pass_func 就会在判定通过时执行,而下文就是 else 部分了。(return 运行时会中止函数,不执行后面的内容)
- 也可以
...run return 1 然后在上一层函数或命令中用 ... if function cond run function pass_func 调用这个函数。这样当 if function cond没有通过时,会执行 cond.mcf,而通过时会执行 function pass_func。
只有套娃或者整理强迫症的时候会这样写吧。
if blocks 除了检测区域是否符合特定的结构(用来做多方块结构之类的),也可以指定一个全是空气的工具区域,用来检测目标地点是否完全无遮挡。
execute at @s if blocks ~ ~ ~ ~ 320 ~ x ~ z masked run say 上方无遮挡,其中从 x -64 z 到 x 320 z 的区域是一个空气柱。
目标选择器
- 选择器与
if entity 的抉择:
详情
虽然一般更常见的形式是
execute as @e run function a
#------
# a.mcf
...if entity @s run function...
....scoreboard players operation @s...
但在所有实体都要过一遍判定的情况下,使用 @e 更好。
也就是说clear @a[scores={a=1}]要比execute as @a if score @s a matches 1 run clear @s更好。
|| 这是由于 execute 会创建很多分支,带来额外开销。
我们不建议的其实是
execute as @e[tag=a] if data entity @s item run say 1
execute as @e[tag=a] if data entity @s item run say 2
execute as @e[tag=a] if data entity @s item run say 3
这样的重复判断。
变量
- @a 可以选中死亡的玩家,但 @e[type=player] 不能。这是一种检测玩家是否复活的方法。
- @s 可以抓到世界外(未加载区块)的实体,以及死亡实体。但要在其他选择器不可选中前构成这个上下文。这个技巧在还没有宏的时候被用来实现传送到存档点(如:家坐标)位置一类的效果。
案例
tag @s add temp
execute as 0-0-0-0-3 run function a
#------
# a.mcf
# 坐标 <x y z> 未加载
execute store result entity @s Pos[0] run scoreboard players get @p[tag=temp] home_x
execute store result entity @s Pos[1] run scoreboard players get @p[tag=temp] home_y
execute store result entity @s Pos[2] run scoreboard players get @p[tag=temp] home_z
tp @p[tag=temp] @s
#------
tag @s remove temp
参数
- 进行判定的坐标点和实体都会跟着
/execute 的子命令变化
不一定是执行者或选择目标的位置
distance 参数是球形判定
判定的是实体的原点(碰撞箱底部的对角线交点)在不在以判定点为球心的范围内
- 与
distance 不同,[dx=0.0,dy=0.0,dz=0.0] 是长方体范围,判定的是碰撞箱相交。
判定范围的棱长是 dx+1 dy+1 dz+1,也就是说上述的参数会框定一个 1x1x1 的正方体范围
也就是说,如果你需要在实体的任意部位与判定范围相交即通过,就选择 dxdydz。
- 检测某一点是否在实体的碰撞箱内,可以用两个
distance 相夹的与门判定
形如 execute at @s as @n if entity @s[dx=0, dy=0, dz=0] if entity @s[x=~0.999, y=~-0.999, z=~-0.999, dx=0, dy=0, dz=0]
- 角度相关的,
x_rotation 才是检测俯仰旋转,y_rotation 才是检测左右旋转。 x_rotation 往上看是负数,往下看才是正数。
谓词
在几乎所有数据文件.json文件中都会用到的“判定条件”
Xiao2 按:
谓词是逻辑学里面那个,一阶谓词演算那种。简单来说就是bool函数,返回值为true or false的函数。
predicate直接翻译成“条件函数”得了
只不过我们先接触到mc的predicate,有机会才会学逻辑学或者离散数学什么的,或者java里lambda的predicate
那里确实叫“谓词”
谓词这个翻译太不直观了,我还是更喜欢旧翻译“断言”。更整活一点就“屁瑞迪卡特”。
这个名字可以简单理解为:“做一段描述(省略主语的陈述句),如果当下的情况符合描述则通过,不符合描述则不通过。”
主语上下文context即当下的情况,由调用谓词的组件给出。在很多XX定义格式的子条目下都可以看到战利品上下文的标注,即是这段描述谓词的主语上下文context
配合高频循环检测的使用方法是 /execute (if|unless) predicate。写在内联的战利品表、物品修饰器里也不是不行。
- 可以检测光照等级、伤害类型、天气等通过
exe if/unless 的简单检测无法获取到的参数
- 玩家按键输入的检测也需要依赖谓词
不过现在只能检测运动相关的按键 WASD Space Shift Ctrl
就这点也是 OJNG 更新矿车的时候才顺便施舍的
( entity_properties 的玩家实体子谓词 {"type_specific": {"type":"player", "input":{}})
- 在整个游戏的运行中广泛使用,到了见缝插针的程度。所以原版很多条件判定(只要是数据驱动的)都是用谓词。可以拿到自己的系统里用。
- 解压
version/版本.json 即可拿到原版的数据文件,在 /data 下。
这同时也能拿到原版的内置资源,在 /asset
进度谓词
有一些谓词只在特定的场景下存在。比如进度里的伤害谓词
- 伤害谓词
- 存在于
player_hurt_entity 等与伤害相关的进度里
- 能检测受到的伤害的数值、是否被阻挡、被防御机制降低前的伤害总量等
- 而谓词文件和内联谓词中只有
伤害类型谓词 没有 伤害谓词
记分板准则
trigger 可以被玩家变更数值,但每次变更后都需要用 /scoreboard players enable 赋予玩家一次性权限
health food air level xp 等等准则会自动变更,就不需要每次检测都读取玩家 NBT 了。
- 可以用来做击杀榜、死亡榜、玩家血量显示等简单的分数效果
- 同时,
health 等和玩家状态绑定的分数是不能被 /scoreboard players 修改的
minecraft.开头的都是 统计信息复合准则, 可以伴随对应的 统计信息 自动增加。
- 玩家自身相关的是
minecraft.custom: 开头
- 例:在玩家累计爬梯子或藤蔓 1000 米后, 使用
minecraft.custom:minecraft.climb_one_cm 准则的记分项就会增加到 100000
- 旧版本常用的胡萝卜钓竿右键触发就是用记分板准则+高频检测实现的。
|| 条件触发(广播事件)
一些只在满足特定条件的时候触发的效果。
- 尽量写成这样的形式,在系统平稳运行的时候就不会执行相关的任务。这能够大大降低系统运行时的负载,也就是说大部分情况下是一种优化。
广播事件的意思是,这个事件发生时会进行一次“广播”。
- “广播”会让相关的系统被触发,继而判定是否需要进行一些对应的处理。
函数标签广播
在一些封装好的前置模块里,有时会使用 函数标签 来作为接口。使用者往这个标签里添加函数,就可以使自己的函数在特定流程中被调用。
- 物品栏追踪模块
VDC>inv/trace 会在追踪到玩家物品栏变动时处理变动的信息。在将信息变成方便处理的格式后,就会调用 #_inv:tracer 函数集,并提供一些上下文,让外部系统能够对该玩家进行一些处理。
例如:将玩家拿到光标上的物品放回原来的槽位。
- NBT 合成前置
handcrafting 会在配方完成时调用特定的函数集,使添加配方的数据包可以在配方完成时进行一些特别处理,譬如增加独特 id,譬如添加“盲盒”配方。
- 常用触发器模块
VDC>built_in/tri 会在条件触发时调用对应的函数集,如 #vdc:tri/pl.respawn 函数集会在玩家重生时被触发。
一般是先调用一个条件判定函数,如果触发时的函数符合要求,再执行效果函数。
仅我个人而言,我一般会用 <trigger>.c.mcf 来命名这个判定函数。 <trigger> 是触发器的名称。如 pl.respawn
进度准则
监测一些只能由玩家作为主体的事件。触发后可以由玩家执行函数、给予玩家战利品奖励、给予经验值。
- 触发后用
advancement revoke 移除该函数以再次触发
- 也可以反其道而行之,给予玩家该进度并不移除,来防止玩家在不需要的时候触发该进度。
- 设定一个父系进度,并在主循环里写个
advancement revoke @a from <父系进度> 就可以一次性处理所有需要自动重置的进度。
- 一次
advancement revoke only 的消耗大约是 100 scb ±30 。这个数据非常粗略,仅供大致考量。
基本作用
基本上看看原版有哪些进度就知道可以做出哪些效果了。下面挑一些常用的说说
- 检测玩家物品栏变动
inventory_changed
- 检测玩家造成伤害
player_hurt_entity
- 检测玩家吃东西、用药等
consume_item
- 检测玩家使用物品(长按)
using_item
- 检测玩家右键方块
any_block_use default_block_use item_used_on_block
- 检测玩家合成物品
recipe_crafted
用途
进度一般会用来做这些效果:
- 右键交互:用
consume_item 或 using_item 与 consumable 或 blocks_attacks 等数据组件(物品组件)配合,能检测玩家使用该物品右键。
- 消耗物品准则
consume_item + 消耗品组件consumable 会在玩家长按一定时间后触发。此时也能触发 使用冷却组件 use_cooldown
- 使用物品组件
using_item + 消耗品组件consumable 可以持续监测玩家是否在持有该物品并按住鼠标右键。可以灵活检测单击、长按 n 秒、长按 n 秒后放下等条件。
- 有时会将消耗时间设为近乎无限长,就不用调整了。检测任意时间长按的时候很方便。
- 但是会让手上的动画变得非常缓慢。
- 与交互实体的交互
- 左键: 玩家伤害实体准则
player_hurt_entity + /execute as <interaction> on attacker
- 右键:玩家与实体交互准则
player_interacted_with_entity + /execute as <interaction> on target
- 待补充
魔咒效果组件
- 魔咒的效果与物品绑定。用来写一些与物品相关的效果很合适。
由于Mojang特有的东一块西一块,往往需要组件和魔咒拼一起才能覆盖物品定制需求。有时候还需要进度的参与。
- 有一些功能的实现,虽然在设计层面上与物品无关,却也需要藉由魔咒才能实现,没有独立的命令来直接实现。
- 但是魔咒必须持有或装备才能触发。在这种情况下,可以使用
armor.body马铠 或 armor.saddle马鞍 来触发。
- 对于一般认知下没有这些槽位的实体,这些槽位仍然能置入物品并生效。包括玩家
- 除了本章主题的“条件触发”,魔咒还有很多被动类的效果。不过“装备时生效”的被动也算是条件触发罢。
- 同一个魔咒组件触发的函数等的效果是按列表顺序执行的。
基本作用
魔咒可以做一些装备时生效的被动:
- 免疫伤害(对特定伤害类型无敌)
damage_immunity
- 设置数值
- 射箭消耗的箭数
- 当次近战攻击的基础攻击力
- 护甲减免系数(护甲提供的减伤)和魔法提供的减伤
- 经验修补效率
- 击退效率
- 杀敌时的经验掉落数
- 弹射物数量
- 非玩家生物爆装备的概率
魔咒可以在这些情况下条件触发:
- 装备时高频触发
tick
- 攻击或受到攻击触发
post_attack
- 生成弹射物时触发
projectile_spawned
- 穿刺武器左键
post_piercing_attack1.21.11
- 玩家开始破坏(左键)方块
hit_block
- 移动到其他方块、落地、装备的瞬间、从旁观模式切回来时触发
location_changed
魔咒可以触发这些效果:
(上文提到的条件触发组件都可以用)
(只列出不可替代性较强的效果)
- 执行函数
run_function
- 施加消耗度(令玩家饥饿)
apply_exhaustion
- 施加冲量(改变实体Motion)
apply_impulse
- 一般用来控制玩家的动量。实体的直接
/data 就可以了
- 只能使用局部坐标系
^u ^v ^w。想要使用绝对坐标系或局部坐标 ~x ~y ~z 需要依赖前置。
- 产生爆炸效果
explode
- 点燃实体
ignite
- 生成圆盘或圆柱状的方块结构
replace_disk
- 召唤实体
summon_entity
用途
进度一般会用来做这些效果:
- 左键检测(包括空挥):用
post_piercing_attack 魔咒组件,配合 piercing_weapon 物品组件,可以检测玩家点击左键。这个效果需要主手持有带附魔的物品才能生效。
- 左键方块:在玩家可以破坏指定方块的情况下(指向方块时有框),可以检测到玩家点击这个方块。可以配合
can_destory 物品组件,以及调整挖掘速度的组件或实体属性使用。
- 譬如我的快照介绍视频中随手搓的火焰附加剑点燃火堆、点击地面召唤雪傀儡。
- 检测击中或被击中:用
post_attack 魔咒,可以检测一次攻击的产生。
- 简单的效果例如以前很难完美处理的干预被箭或雪球击中的实体(被雪球击中会跳起来之类的小玩具效果)、玩家挨打时随机传送
- 复杂的比如虚拟血量系统、架空攻防体系
- 进度和魔咒的生效都非常即时。我的意思是触发效果的时候箭还没消失呢
- 效果是顺序执行的,所以写在上面的函数会先触发。
- 控制玩家移动:用
apply_impulse 效果可以完美解决控制玩家动量的问题。这可以用来做冲刺、闪身、二段跳 等效果。一般配合 tick 或 location_changed 魔咒组件使用。
- 影响玩家状态(点燃玩家、令玩家饥饿):这两个别的实现方式效果不好的功能,使用魔咒可以更完美的达成。
怎么设计架空系统结构、管理自定义数据?
怎么实现某种效果
原版可以做出哪些功能 / 效果(可以自定义哪些部分)?
原版做不到哪些功能效果
作品跑起来太卡了怎么优化
不想自己写,去哪找可以直接使用的套件
111