Minecraft Forge 1.20.1战斗音乐模组音效无法播放问题求助
Minecraft Forge 1.20.1战斗音乐模组音效无法播放排查求助
正在开发一款类似《原神》的Minecraft Forge 1.20.1战斗音乐模组,核心需求:玩家被敌对生物攻击时播放战斗音乐,当玩家15格范围内无敌对生物时停止音乐。当前攻击检测与逻辑触发均正常(日志能输出"Attempting to play custom sound"及正确的敌对生物数量),但实际无声音播放。
代码模块说明
1. onAttack方法
负责检测被攻击实体是否为LocalPlayer,验证世界难度非和平模式,调用getEntities获取附近敌对生物数量,数量大于0时触发playCustomSound:
@SubscribeEvent public void onAttack(final LivingAttackEvent event) { LivingEntity entity = event.getEntity(); if (entity instanceof LocalPlayer player) { Minecraft mc = Minecraft.getInstance(); SoundManager manager = mc.getSoundManager(); if (mc.level != null && mc.level.getDifficulty() != Difficulty.PEACEFUL) { int hostileMobs = getEntities(player); LOGGER.info("Hostile Mobs Nearby: " + hostileMobs); if (hostileMobs > 0) { if (!manager.isActive(lastSound)) { LOGGER.info("Attempting to play custom sound"); playCustomSound(); // Call the custom method to play the sound decaySeconds = 0; } } else { LOGGER.info("No hostile mobs nearby"); // If there are no hostile mobs within 15 blocks, stop the sound if (manager.isActive(lastSound)) { LOGGER.info("Stopping the custom sound"); manager.stop(lastSound); lastSound = null; } } } } }
2. getEntities方法
正常工作,可返回正确的敌对生物数量:
private int getEntities(LocalPlayer player) { return player.clientLevel.getEntitiesOfClass(Monster.class, new AABB(-12D, -10D, -12D, 12D, 10D, 12D).move(player.getX(), player.getY(), player.getZ()), mob -> mob.canAttack(player)).size(); }
3. playCustomSound方法
疑似问题所在。已确认ModSounds中注册的UNIV_BRAWL SoundEvent可通过/playsound命令正常播放,但调用此方法无声音输出:
private void playCustomSound() { Minecraft mc = Minecraft.getInstance(); SoundManager manager = mc.getSoundManager(); // Replace with your registered SoundEvent SoundEvent soundEvent = ModSounds.UNIV_BRAWL.get(); if (soundEvent == null) { LOGGER.error("SoundEvent is null. Make sure it's properly registered."); return; } ResourceLocation soundLocation = soundEvent.getLocation(); LOGGER.info("Attempting to play sound: " + soundLocation.toString()); SimpleSoundInstance soundInstance = SimpleSoundInstance.forMusic(soundEvent); manager.play(soundInstance); }
ModSounds类片段
public static final DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, "battlemusic"); public static final RegistryObject<SoundEvent> UNIV_BRAWL = SOUNDS.register( "combatmusic", () -> SoundEvent.createVariableRangeEvent(new ResourceLocation(battlemusic.MOD_ID, "univ_brawl"))); public static void register(IEventBus eventBus) { SOUNDS.register(eventBus); }
主类battlemusic
@Mod("battlemusic") public class battlemusic { public static final String MOD_ID = "battlemusic"; public static final Logger LOGGER = LogUtils.getLogger(); public int decaySeconds = 0; public SimpleSoundInstance lastSound; public battlemusic() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); ModCreativeModTabs.register(modEventBus); ModItems.register(modEventBus); ModSounds.register(modEventBus); modEventBus.addListener(this::commonSetup); modEventBus.addListener(this::addCreative); MinecraftForge.EVENT_BUS.register(this); } private void commonSetup(final FMLCommonSetupEvent event) { // Add your common setup code here } private void addCreative(BuildCreativeModeTabContentsEvent event) { if (event.getTabKey() == CreativeModeTabs.INGREDIENTS) { // Add your creative tab contents here } } }
排查与修复建议
- 保存SoundInstance引用:当前
playCustomSound创建的SimpleSoundInstance未赋值给lastSound,导致后续manager.isActive(lastSound)判断始终为false(lastSound一直为null),且无法正确停止音乐。修改playCustomSound:private void playCustomSound() { Minecraft mc = Minecraft.getInstance(); SoundManager manager = mc.getSoundManager(); SoundEvent soundEvent = ModSounds.UNIV_BRAWL.get(); if (soundEvent == null) { LOGGER.error("SoundEvent is null. Make sure it's properly registered."); return; } ResourceLocation soundLocation = soundEvent.getLocation(); LOGGER.info("Attempting to play sound: " + soundLocation.toString()); lastSound = SimpleSoundInstance.forMusic(soundEvent); // 赋值给类成员lastSound manager.play(lastSound); } - 确保在客户端主线程执行播放:部分事件可能在非主线程触发,用
mc.execute包裹播放逻辑,确保在客户端主线程执行:mc.execute(() -> { lastSound = SimpleSoundInstance.forMusic(soundEvent); manager.play(lastSound); }); - 验证SoundInstance参数配置:
forMusic默认创建的实例可能不符合需求,可手动指定参数(如循环、衰减类型等):lastSound = new SimpleSoundInstance( soundEvent, SoundSource.MUSIC, 1.0F, // 音量 1.0F, // 音调 true, // 是否循环 0, // 延迟 SoundInstance.AttenuationType.NONE, // 衰减类型 mc.player.getX(), mc.player.getY(), mc.player.getZ(), true // 相对玩家位置 ); - 确认SoundEvent注册一致性:在
playCustomSound中添加日志打印SoundEvent的注册表名称,确认与注册信息一致:LOGGER.info("SoundEvent registry name: " + soundEvent.getRegistryName()); - 调试SoundManager状态:播放后立即打印
manager.isActive(lastSound),确认SoundManager是否真正接收到播放请求。
内容的提问来源于stack exchange,提问作者Meya
相关产品推荐
相关产品推荐

