1.13版本免穷举让实体前/后移动

     1.10版本的时候就能利用船做到免穷举让实体前/后移动了,但是这样需要使用很多实体,效率并不是很高,使用起来也并不方便。并且这种方法只能做到在平面上移动,无法上下移动。那么,有没有更好的方法呢?
      众所周知,两点确定一条直线,如果知道了实体面向的方向上的任意两点,那么就可以确定实体面对的方向。1.13的局部坐标可以很方便的做到这一点。将它转化为Motion值就可以让实体沿着面朝的方向移动了。
效果图:

也可以让盔甲架跳起来:



原理讲解:

  1. scoreboard objectives add click minecraft.used:minecraft.carrot_on_a_stick
  2. scoreboard objectives add coordinate1 dummy
  3. scoreboard objectives add coordinate2 dummy

复制代码

      添加三个计分板,click用来触发(当然如果不用萝卜钓竿来触发的话这个计分板可以省略),coordinate1和coordinate2分别来记录实体前1格的坐标值和当前这一格的坐标值。

(以下所有指令均为高频)

  1. execute if entity @a[scores={click=1..100}] run tag @e[type=armor_stand] add move

复制代码

      给盔甲架加上一个move标签,这里偷懒直接用萝卜钓竿来触发。这只是拿盔甲架来做一个演示,实际应用的时候tag后的选择器可以根据需要更改

  1. execute as @e[tag=move] at @s offset ^ ^ ^1 run summon area_effect_cloud ~ ~ ~ {CustomName:"destination"}

复制代码

      在实体眼前1格的位置生成一个名为“destination”的药水云,用来确定实体方向

  1. execute as @e[tag=move] store result score @s coordinate1 run data get entity @e[limit=1,type=area_effect_cloud,name=destination] Pos[0] 100000

复制代码

      将药水云的x坐标存到待移动实体的coordinate1计分板内,为保留精度,乘以100000倍。

  1. execute as @e[tag=move] store result score @s coordinate2 run data get entity @s Pos[0] 100000

复制代码

      将待移动实体的x坐标存进自己的coordinate2计分板内,为保留精度,乘以100000倍

  1. execute as @e[tag=move] run scoreboard players operation @s coordinate1 -= @s coordinate2

复制代码

      用待移动实体的coordinate1计分板减去coordinate2计分板

  1. execute as @e[tag=move] store result entity @s Motion[0] double 0.00001 run scoreboard players get @s coordinate1

复制代码

      得到的值存到待移动实体的x方向Motion上,乘0.00001还原本来的倍数。如果需要将实体运动的速度调快或是调慢的话,就将这个数调大或是调小。

  1. execute as @e[tag=move] store result score @s coordinate1 run data get entity @e[limit=1,type=area_effect_cloud,name=destination] Pos[1] 100000
  2. execute as @e[tag=move] store result score @s coordinate2 run data get entity @s Pos[1] 100000
  3. execute as @e[tag=move] run scoreboard players operation @s coordinate1 -= @s coordinate2
  4. execute as @e[tag=move] store result entity @s Motion[1] double 0.00001 run scoreboard players get @s coordinate1
  5. execute as @e[tag=move] store result score @s coordinate1 run data get entity @e[limit=1,type=area_effect_cloud,name=destination] Pos[2] 100000
  6. execute as @e[tag=move] store result score @s coordinate2 run data get entity @s Pos[2] 100000
  7. execute as @e[tag=move] run scoreboard players operation @s coordinate1 -= @s coordinate2
  8. execute as @e[tag=move] store result entity @s Motion[2] double 0.00001 run scoreboard players get @s coordinate1

复制代码

      与之前四条指令同样的方式处理y轴、z轴

  1. kill @e[name=destination]
  2. tag @e remove move

复制代码

      清掉药水云,移除move标签,初始化

  

      这种方式的另一个好处是用Motion移动代替了高频tp移动,总感觉以前一格格tp移动很不圆滑...并且还容易出bug,特别是对弓箭一类的实体用起来不太方便。于是在这个基础上稍加改进便做成了一把连弩:

不知道为什么箭会在面前卡一下,但其实是射出去的。
原理就是用玩家来做那个“待移动实体”,在面前生成一支箭,获取Motion值之后加到那个箭上。



感谢@pca006132 的优化,其实盔甲架的移动只需要7条指令,道理与前文相同,优化之处是如果把待移动实体的位置看为坐标原点,那么marker的位置就是实体的motion,这样就省去了两个计分板和坐标相减的过程。
指令:

  1. execute if entity @a[scores={click=1..100}] run tag @e[type=armor_stand] add move
  2. execute as @e[tag=move] offset 0.0 0.0 0.0 run tp @e[type=area_effect_cloud,name=marker] ^ ^ ^1
  3. execute as @e[tag=move] store result entity @s Motion[0] double 0.00001 run data get entity @e[limit=1,type=area_effect_cloud,name=marker] Pos[0] 100000
  4. execute as @e[tag=move] store result entity @s Motion[1] double 0.00001 run data get entity @e[limit=1,type=area_effect_cloud,name=marker] Pos[1] 100000
  5. execute as @e[tag=move] store result entity @s Motion[2] double 0.00001 run data get entity @e[limit=1,type=area_effect_cloud,name=marker] Pos[2] 100000
  6. scoreboard players set @a click 0
  7. tag @e remove move

发表评论

您必须 登录 才能发表留言!