⠀蛋⠀
我想获取玩家视线所对的生物。于是我使用
World.rayTraceResult()
于是我将它单独写到一个类里面。
  1. public Entity getEntity(){
  2.         result = this.player.getWorld().rayTraceEntities(this.playerEye.add(this.playerEyeDirection) ,
  3.                 this.playerEyeDirection , 20.0);
  4.         if (result != null){ // Hit到东西了
  5.             if (result.getHitBlock() != null){ // Hit到方块了
  6.                 if (this.blockDistanceIsFarther(result.getHitBlock().getLocation() ,
  7.                         Objects.requireNonNull(result.getHitEntity()).getLocation() , this.playerEye)){ // 方块距离比较远吗?
  8.                     return result.getHitEntity();
  9.                 } else {
  10.                     if (this.whetherItIsVisualSquare(result.getHitBlock().getType())){ //是否是透明方块
  11.                         return result.getHitEntity();
  12.                     }
  13.                 }
  14.                 return null;
  15.             }
  16.             return result.getHitEntity(); // 只Hit到实体
  17.         }
  18.         return null; // 没Hit到东西
  19.     }
复制代码

之后,我就调用这个方法。但是,会出现一个BUG。
当你离生物体太近,会出现
hit到东西了,但返回的是null
我以为是bukkit自带的BUG,于是我就再写了一次。
  1. RayTraceResult result = player.getWorld().rayTraceEntities(player.getEyeLocation().add(player.getEyeLocation().getDirection()) ,
  2.                                     player.getEyeLocation().getDirection() , 20.0);
  3.                             if (result != null){
  4.                                 player.sendMessage(result.getHitEntity().toString());
  5.                             }
复制代码

但是,无论你靠得多近,返回的都是实体,并没有出现 hit到东西了,返回null的情况。

注:这里的返回null是指 result 是 null 的,但判断时,result却不是null。

byxiaobai
之前帖子里的这个代码使用会出现问题吗
  1. Player player;
  2. World world = player.getWorld();
  3. Location location = player.getEyeLocation();
  4. Vector direction = location.getDirection();
  5. location.add(direction);
  6. RayTraceResult rayTraceEntities = world.rayTraceEntities(location, location.getDirection(), 10.0D);
  7. Entity hitEntity = rayTraceEntities.getHitEntity();
复制代码

⠀蛋⠀
byxiaobai 发表于 2021-7-23 13:29
之前帖子里的这个代码使用会出现问题吗

不会,如果你把代码写到另一个类
然后实例化这个类,调用这个类的方法就会

结冰的离季
本帖最后由 结冰的离季 于 2021-7-23 19:06 编辑

你要知道为什么我用的是rayTraceEntities,因为他只会检查实体,同样rayTraceBlocks只会检查方块,但你的代码中使用了rayTraceEntities但还执行result.getHitBlock()得到的结果肯定不对。要同时检查block和entity的话应该用rayTrace。

至于太近的问题,还是起始位置的关系,玩家眼睛位置是位于头部中心,如果从玩家眼部位置为起始点的话,有可能第一个结果就是玩家本身,正好direction是一个单位向量,我把eyelocation加上direction之后就刚好是玩家前面一个方块的位置,但是玩家的头部的长度一半是小于一个方块的长度的,所以如果太近的话起始点并没有接触到实体,是有可能为null的。

以下是CraftBukkit的代码实现。点击查看
  1. @Override
  2.     public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<Entity> filter) {
  3.         Validate.notNull(start, "Start location is null!");
  4.         Validate.isTrue(this.equals(start.getWorld()), "Start location is from different world!");
  5.         start.checkFinite();

  6.         Validate.notNull(direction, "Direction is null!");
  7.         direction.checkFinite();

  8.         Validate.isTrue(direction.lengthSquared() > 0, "Direction's magnitude is 0!");

  9.         if (maxDistance < 0.0D) {
  10.             return null;
  11.         }

  12.         Vector startPos = start.toVector();
  13.         Vector dir = direction.clone().normalize().multiply(maxDistance);
  14.         BoundingBox aabb = BoundingBox.of(startPos, startPos).expandDirectional(dir).expand(raySize);
  15.         Collection<Entity> entities = this.getNearbyEntities(aabb, filter);

  16.         Entity nearestHitEntity = null;
  17.         RayTraceResult nearestHitResult = null;
  18.         double nearestDistanceSq = Double.MAX_VALUE;

  19.         for (Entity entity : entities) {
  20.             BoundingBox boundingBox = entity.getBoundingBox().expand(raySize);
  21.             RayTraceResult hitResult = boundingBox.rayTrace(startPos, direction, maxDistance);

  22.             if (hitResult != null) {
  23.                 double distanceSq = startPos.distanceSquared(hitResult.getHitPosition());

  24.                 if (distanceSq < nearestDistanceSq) {
  25.                     nearestHitEntity = entity;
  26.                     nearestHitResult = hitResult;
  27.                     nearestDistanceSq = distanceSq;
  28.                 }
  29.             }
  30.         }

  31.         return (nearestHitEntity == null) ? null : new RayTraceResult(nearestHitResult.getHitPosition(), nearestHitEntity, nearestHitResult.getHitBlockFace());
  32.     }
复制代码


通过查看CraftBukkit的源代码可以知道,他的原理还是getNearbyEntities 然后进行逐个判断,所以他的检查顺序并不是从这条光线的起始位置开始,而是getNearbyEntities返回集合中的第一个结果,而根据我的经验,getNearbyEntities中的第一个Entity永远是最新生成的实体,这就是导致了我们的结果不同的原因。


同时通过这个代码可知,rayTraceEntities 中的 RayTraceResult 的gethitBlock是没有经过初始化的



⠀蛋⠀
结冰的离季 发表于 2021-7-23 18:36
你要知道为什么我用的是rayTraceEntities,因为他只会检查实体,同样rayTraceBlocks只会检查方块,但你的代 ...

前辈,我明白了。
难怪他会出现明明已经不是null了,却在执行时返回null的情况。
谢谢!

qwders
厉害我基本都不会这东西的

qwders
我想问怎么做的可以教我吗

qwders
你们谁可以教我我什么都不会

qwders
你们都好厉害但是我不会啊

第一页 上一页 下一页 最后一页