Minecraft命令递归函数实现激光武器如何限制递归次数控制射程
解决方案
方案一:单激光场景(仅适合单人/不会同时触发多束激光的场景)
你不需要给递归函数本身绑定实体,记分板支持给虚拟玩家存储数值,无需对应实体存在,命名前缀加#即可避免和真实玩家重名,实现步骤如下:
- 首次使用前运行一次命令创建计数用记分板:
scoreboard objectives add raycast_count dummy - 在你触发激光发射的上游函数中,调用
raycast前先重置虚拟玩家计数:scoreboard players set #raycast_counter raycast_count 0 - 修改你的
raycast.mcfunction代码,增加计数判断逻辑:
# 每次进入函数先给计数+1 scoreboard players add #raycast_counter raycast_count 1 playsound block.iron_trapdoor.open master @a playsound block.respawn_anchor.deplete master @a playsound entity.generic.explode master @a playsound entity.generic.extinguish_fire master @a particle small_flame ~ ~ ~ 0 0 0 0 100 normal @a # 递归判断增加分数未超过100的条件 execute if block ~ ~ ~ air unless entity @e[distance=0.1..0.3,type=!armor_stand,type=!item_frame,type=!item,type=!player,type=!area_effect_cloud] unless score #raycast_counter raycast_count matches 101.. positioned ^ ^ ^0.5 run function datapack:raycast
方案二:多激光兼容场景(推荐,支持多人/多激光同时发射)
方案一的虚拟玩家是全局计数,多束激光同时发射会出现计数冲突,你可以用1.17版本新增的marker实体(无碰撞、无渲染、性能消耗极低)作为每束激光的计数载体:
- 同样先创建计数记分板:
scoreboard objectives add raycast_count dummy - 触发激光发射的上游函数修改为先生成计数用marker,再以marker为主体调用raycast:
# 在玩家视线位置生成标记实体 execute at @p anchored eyes run summon minecraft:marker ~ ~ ~ {Tags:["raycast_marker"],Invulnerable:1b,Invisible:1b,NoGravity:1b} # 初始化标记实体的计数 execute as @e[tag=raycast_marker,limit=1,sort=nearest] run scoreboard players set @s raycast_count 0 # 以标记实体为主体执行射线检测 execute as @e[tag=raycast_marker,limit=1,sort=nearest] at @s run function datapack:raycast
- 修改
raycast.mcfunction代码:
# 给当前执行的标记实体计数+1 scoreboard players add @s raycast_count 1 playsound block.iron_trapdoor.open master @a playsound block.respawn_anchor.deplete master @a playsound entity.generic.explode master @a playsound entity.generic.extinguish_fire master @a particle small_flame ~ ~ ~ 0 0 0 0 100 normal @a # 递归判断增加计数未超过100的条件 execute if block ~ ~ ~ air unless entity @e[distance=0.1..0.3,type=!armor_stand,type=!item_frame,type=!item,type=!player,type=!area_effect_cloud,type=!marker] unless score @s raycast_count matches 101.. positioned ^ ^ ^0.5 run function datapack:raycast # 递归终止时清除标记实体 execute unless block ~ ~ ~ air run kill @s execute if entity @e[distance=0.1..0.3,type=!armor_stand,type=!item_frame,type=!item,type=!player,type=!area_effect_cloud,type=!marker] run kill @s execute if score @s raycast_count matches 101.. run kill @s
可选方案:1.19.4+版本可用函数传参实现
如果你的服务端/客户端版本高于等于1.19.4,还可以通过自定义存储传递计数参数,无需记分板和实体:
- 调用函数前将当前计数写入自定义存储,每次递归调用时将计数+1写入存储再调用函数
- 函数开头读取存储的计数值,大于等于100时终止递归即可
内容的提问来源于stack exchange,提问作者hfanatic
相关产品推荐
相关产品推荐

