Fabric 1.21.11:GeckoLib CannonSeatEntity碰撞盒与交互优化求助
Fabric 1.21.11大炮模组:座椅实体碰撞与交互优化方案
开发背景
基于Fabric 1.21.11开发Minecraft模组,包含一款使用自定义GeckoLib(5.4.4)BlockEntity模型的大炮方块。点击大炮时会生成独立的隐形座椅实体CannonSeatEntity(继承自Entity),用于实现玩家骑乘功能。
当前状态
- 已通过Mixin移除实体白色轮廓线
- 实体仍存在1x1x1的隐形碰撞盒,玩家无法穿过
核心问题
CannonSeatEntity始终以完整立方体碰撞盒阻挡玩家移动,不符合设计需求。
已尝试无效方案
- 重写
getVisualShape()返回Shapes.empty() - 重写
getDimensions()(getBoundingBox()为final方法无法修改) - 对
LevelRenderer使用Mixin修改轮廓渲染 - 设置
setInvisible(true) - 开启
noPhysics = true - 重写
isPickable()返回false - 在
EntityType.Builder中设置极小尺寸
需求目标
- 完全移除座椅实体的物理碰撞盒,不阻挡玩家移动
- 保留玩家骑乘大炮的功能
- 创建匹配自定义3D GeckoLib模型的非立方体
VoxelShape - 实现大炮模型全域可点击,点击任意位置均可触发骑乘
解决方案
1. 彻底移除座椅实体碰撞
在CannonSeatEntity中重写以下核心方法:
// 禁止实体被推动 @Override public boolean isPushable() { return false; } // 设置极小的剔除包围盒 @Override protected AABB getBoundingBoxForCulling() { return AABB.ofSize(this.position(), 0.0, 0.0, 0.0); } // 返回空碰撞形状 @Override public VoxelShape getCollisionShape(EntityCollisionContext context) { return Shapes.empty(); } // 拒绝与任何实体发生碰撞 @Override public boolean canCollideWith(Entity other) { return false; }
同时在构建实体类型时,强制设置极小尺寸:
EntityType.Builder.<CannonSeatEntity>of(CannonSeatEntity::new, EntityCategory.MISC) .setDimensions(0.0F, 0.0F) .setTrackingRange(10) .setUpdateInterval(20) .build("cannon_seat");
2. 保留骑乘功能的直接绑定
座椅实体无需依赖碰撞盒触发骑乘,在点击大炮时直接调用玩家的骑乘方法:
// 点击大炮时的触发逻辑 public void triggerRide(Player player, BlockPos pos) { Level level = player.level(); if (!level.isClientSide()) { CannonSeatEntity seat = new CannonSeatEntity(ModEntities.CANNON_SEAT.get(), level); // 调整坐标匹配大炮模型的骑乘位置 seat.setPos(pos.getX() + 0.5, pos.getY() + 0.2, pos.getZ() + 0.5); level.addFreshEntity(seat); player.startRiding(seat); } }
3. 实现大炮模型全域点击判定
由于大炮是BlockEntity,重写方块的use()方法,通过自定义VoxelShape匹配模型轮廓:
@Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!level.isClientSide()) { CannonBlockEntity be = (CannonBlockEntity) level.getBlockEntity(pos); if (be != null) { // 手动构建匹配大炮模型的VoxelShape(可组合多个小立方体模拟外形) VoxelShape cannonShape = Shapes.or( Shapes.box(0.2, 0, 0.2, 0.8, 0.6, 0.8), Shapes.box(0.3, 0.6, 0.3, 0.7, 1.2, 0.7) ); // 转换点击坐标为方块本地坐标并检查是否在模型形状内 Vec3 localHit = hit.getLocation().subtract(pos.getX(), pos.getY(), pos.getZ()); if (cannonShape.bounds().contains(localHit)) { triggerRide(player, pos); return InteractionResult.SUCCESS; } } } return super.use(state, level, pos, player, hand, hit); }
若GeckoLib模型内置碰撞数据,可直接从模型实例中提取对应VoxelShape替代手动构建。
4. 额外物理特性禁用
在CannonSeatEntity构造方法中关闭冗余物理特性:
public CannonSeatEntity(EntityType<? extends CannonSeatEntity> type, Level level) { super(type, level); this.noPhysics = true; this.setInvisible(true); this.setInvulnerable(true); this.setNoGravity(true); }
内容的提问来源于stack exchange,提问作者Krysztok




