Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

[English](CHANGELOG_EN.md) | 中文

## v1.8.9

- 新增 `ModelSoundStopTrigger` 组件,支持在动画状态机中停止音效播放
- 支持停止指定事件名称的音效
- 支持停止所有正在播放的音效
- 支持使用内置事件名称(如 `idle`)或自定义触发器事件名称
- 支持在状态进入或退出时触发停止操作
- 提供 Unity 编辑器自定义界面,包含条件显示、警告提示和帮助信息

## v1.8.8-fix1

- 修正了 ModelParameterDriver 的参数记录逻辑,以解决编辑器数据锁定的问题,并提升了相关数据的简洁性
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

English | [中文](CHANGELOG.md)

## v1.8.9

- Added `ModelSoundStopTrigger` component, supporting stopping sound playback in animation state machines
- Supports stopping sounds by specified event name
- Supports stopping all currently playing sounds
- Supports using built-in event names (e.g., `idle`) or custom trigger event names
- Supports triggering stop operation on state enter or exit
- Provides Unity editor custom interface with conditional display, warning prompts, and help information

## v1.8.8-fix1

- Fixed ModelParameterDriver parameter recording logic to resolve editor data locking issues and improve data conciseness
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using UnityEngine;

namespace DuckovCustomModel.Core.MonoBehaviours.Animators
{
public class ModelSoundStopTrigger : StateMachineBehaviour
{
[Tooltip("If true, stop all playing sounds. If false, stop the sound specified by eventName.")]
public bool stopAllSounds;

[Tooltip(
"If true, use built-in event name directly (e.g., 'idle') without 'CustomModelSoundTrigger:' prefix. " +
"WARNING: Only use this for built-in event names like 'idle'. For custom triggers, leave this false.")]
public bool useBuiltInEventName;

[Tooltip("Event name of the sound to stop. If empty, a default name will be used (same as ModelSoundTrigger).")]
public string eventName = string.Empty;

[Tooltip("If true, stop the sound when entering this state. If false, stop when exiting.")]
public bool stopOnEnter = true;

public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (stopOnEnter) TriggerStopSound(stopAllSounds, useBuiltInEventName, eventName, animator);
}

public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (!stopOnEnter) TriggerStopSound(stopAllSounds, useBuiltInEventName, eventName, animator);
}

private static void TriggerStopSound(bool stopAll, bool useBuiltIn, string eventName, Animator animator)
{
if (stopAll)
{
OnSoundStopTriggered?.Invoke(string.Empty, animator);
}
else if (useBuiltIn)
{
if (string.IsNullOrWhiteSpace(eventName))
{
Debug.LogWarning("ModelSoundStopTrigger: useBuiltInEventName is true but eventName is empty. " +
"Please specify a built-in event name (e.g., 'idle').");
return;
}

OnSoundStopTriggered?.Invoke(eventName, animator);
}
else
{
var targetEvent = string.IsNullOrWhiteSpace(eventName)
? "CustomModelSoundTrigger"
: eventName;
var finalEventName = $"CustomModelSoundTrigger:{targetEvent}";
OnSoundStopTriggered?.Invoke(finalEventName, animator);
}
}

public static event Action<string, Animator>? OnSoundStopTriggered;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo
}

selectedTag = selectedTag.ToLowerInvariant().Trim();
var finalEventName = string.IsNullOrWhiteSpace(eventName)

var targetEvent = string.IsNullOrWhiteSpace(eventName)
? "CustomModelSoundTrigger"
: eventName;

var finalEventName = $"CustomModelSoundTrigger:{targetEvent}";
OnSoundTriggered?.Invoke(selectedTag, finalEventName, playMode, animator);
}

Expand Down
2 changes: 1 addition & 1 deletion DuckovCustomModel/Constant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public static class Constant
{
public const string ModID = "DuckovCustomModel";
public const string ModName = "Duckov Custom Model";
public const string ModVersion = "1.8.8-fix1";
public const string ModVersion = "1.8.9";
public const string HarmonyId = "com.ritsukage.DuckovCustomModel";
}
}
16 changes: 15 additions & 1 deletion DuckovCustomModel/MonoBehaviours/ModelHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ private void LateUpdate()
private void OnDestroy()
{
ModelSoundTrigger.OnSoundTriggered -= OnSoundTriggered;
ModelSoundStopTrigger.OnSoundStopTriggered -= OnSoundStopTriggered;

Health.OnHurt -= OnGlobalHurt;
Health.OnDead -= OnGlobalDead;
Expand Down Expand Up @@ -231,6 +232,7 @@ public void Initialize(CharacterMainControl characterMainControl, ModelTarget ta
Health.OnDead += OnGlobalDead;

ModelSoundTrigger.OnSoundTriggered += OnSoundTriggered;
ModelSoundStopTrigger.OnSoundStopTriggered += OnSoundStopTriggered;

ModLogger.Log("ModelHandler initialized successfully.");
IsInitialized = true;
Expand Down Expand Up @@ -1248,7 +1250,19 @@ private void OnSoundTriggered(string soundTag, string eventName, SoundPlayMode p
var soundPath = GetRandomSoundByTag(soundTag, out var skippedByProbability);
if (string.IsNullOrEmpty(soundPath) || skippedByProbability) return;

PlaySound($"CustomModelSoundTrigger:{eventName}", soundPath, playMode: playMode);
PlaySound(eventName, soundPath, playMode: playMode);
}

private void OnSoundStopTriggered(string eventName, Animator animator)
{
if (animator == null) return;
if (CustomModelInstance == null) return;
if (animator.gameObject != CustomModelInstance) return;

if (string.IsNullOrEmpty(eventName))
StopAllSounds();
else
StopSound(eventName);
}
Comment thread
BAKAOLC marked this conversation as resolved.

private void ScheduleNextIdleAudio()
Expand Down
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,22 @@ Animator Controller 可以使用以下参数:
- `playMode`:音效播放模式(Normal、StopPrevious、SkipIfPlaying、UseTempObject)
- `eventName`:事件名称,用于音效播放管理(可选,为空时使用默认名称)

#### ModelSoundStopTrigger

在动画状态进入或退出时停止音效播放。

- `stopAllSounds`:是否停止所有正在播放的音效(true:停止所有,false:停止指定事件名称的音效)
- `useBuiltInEventName`:是否使用内置事件名称(true:直接使用内置事件名称如 `idle`,false:使用自定义触发器事件名称)
- `eventName`:事件名称
- 当 `stopAllSounds` 为 false 且 `useBuiltInEventName` 为 false 时:自定义触发器事件名称(可选,为空时使用默认名称 `CustomModelSoundTrigger`)
- 当 `stopAllSounds` 为 false 且 `useBuiltInEventName` 为 true 时:内置事件名称(必需,如 `idle`)
- `stopOnEnter`:是否在状态进入时停止(true:进入时停止,false:退出时停止)

**注意事项**:
- 当 `useBuiltInEventName` 为 true 时,必须指定 `eventName`,否则会显示警告
- 自定义触发器的事件名称格式为 `CustomModelSoundTrigger:{eventName}`,与 `ModelSoundTrigger` 保持一致
- 内置事件名称(如 `idle`)直接使用,不添加前缀

#### ModelDialogueTrigger

在动画状态进入时触发对话播放。
Expand Down Expand Up @@ -746,9 +762,14 @@ Animator Controller 可以使用以下参数:
#### 动画状态机触发

- 可以在动画状态机中使用 `ModelSoundTrigger` 组件在状态进入时触发音效
- 支持配置多个音效标签,可选择随机或顺序播放
- 支持配置音效播放模式,提供更精细的音效控制
- 音效标签可以是任意自定义标签,不再限制于预定义标签
- 支持配置多个音效标签,可选择随机或顺序播放
- 支持配置音效播放模式,提供更精细的音效控制
- 音效标签可以是任意自定义标签,不再限制于预定义标签
- 可以在动画状态机中使用 `ModelSoundStopTrigger` 组件停止音效播放
- 支持停止指定事件名称的音效(自定义触发器或内置事件名称如 `idle`)
- 支持停止所有正在播放的音效
- 支持在状态进入或退出时触发停止操作
- 在 Unity 编辑器中提供友好的配置界面,包含条件显示和警告提示

### 音效文件要求

Expand Down
27 changes: 24 additions & 3 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,22 @@ Triggers sound effect playback when animation state enters.
- `playMode`: Sound playback mode (Normal, StopPrevious, SkipIfPlaying, UseTempObject)
- `eventName`: Event name for sound playback management (optional, uses default name if empty)

#### ModelSoundStopTrigger

Stops sound effect playback when animation state enters or exits.

- `stopAllSounds`: Whether to stop all currently playing sounds (true: stop all, false: stop sound by specified event name)
- `useBuiltInEventName`: Whether to use built-in event name (true: use built-in event name like `idle` directly, false: use custom trigger event name)
- `eventName`: Event name
- When `stopAllSounds` is false and `useBuiltInEventName` is false: Custom trigger event name (optional, uses default name `CustomModelSoundTrigger` if empty)
- When `stopAllSounds` is false and `useBuiltInEventName` is true: Built-in event name (required, e.g., `idle`)
- `stopOnEnter`: Whether to stop on state enter (true: stop on enter, false: stop on exit)

**Notes**:
- When `useBuiltInEventName` is true, `eventName` must be specified, otherwise a warning will be displayed
- Custom trigger event names use the format `CustomModelSoundTrigger:{eventName}`, consistent with `ModelSoundTrigger`
- Built-in event names (e.g., `idle`) are used directly without prefix

#### ModelDialogueTrigger

Triggers dialogue playback when animation state enters.
Expand Down Expand Up @@ -746,9 +762,14 @@ Sounds can be configured in `ModelInfo` within `bundleinfo.json`:
#### Animation State Machine Trigger

- Can use `ModelSoundTrigger` component in animation state machines to trigger sounds when states are entered
- Supports configuring multiple sound tags, can choose random or sequential playback
- Supports configuring sound playback modes for finer audio control
- Sound tags can be any custom tags, no longer restricted to predefined tags
- Supports configuring multiple sound tags, can choose random or sequential playback
- Supports configuring sound playback modes for finer audio control
- Sound tags can be any custom tags, no longer restricted to predefined tags
- Can use `ModelSoundStopTrigger` component in animation state machines to stop sound playback
- Supports stopping sounds by specified event name (custom triggers or built-in event names like `idle`)
- Supports stopping all currently playing sounds
- Supports triggering stop operation on state enter or exit
- Provides user-friendly configuration interface in Unity editor with conditional display and warning prompts

### Sound File Requirements

Expand Down
Loading