疑难杂症:Can Hear Object 无法监听到声音
但是 BD 并不完全是一个无代码的行为控制插件,在部分时候还是需要根据自己项目的实际情况进行微改造的,比如现在我说到的就是 Can Hear Object 遇到的一些问题。
Can Hear Object
是一个侦听 Audio Source
的组件,如果侦听的 Transform
上不包含 Audio Source
组件则不会生效。
这在某些动态生成的 Transform
例如:枪械中,就很难简单的通过无代码的方式去设计,但我们可以修改其源码,让获取 Audio Source
的代码对所有 Children
生效。
但为了提高遍历的效率,尽可能地原子化到最接近动态 Transform
的那个对象上。
具体修改的源码如下,打开 Can Hear Object Task 类,找到相关代码,其核心是 MovementUtility.WithinHearingRange
函数。
查看该函数的代码,可以发现,默认的侦听逻辑是只针对 Transform
本身,我们只需要注释掉原来的代码,改成成包含子对象即可:
public static GameObject WithinHearingRange(Transform transform, Vector3 positionOffset, float audibilityThreshold, GameObject targetObject, ref float audibility)
{
AudioSource[] colliderAudioSource;
// Check to see if the hit agent has an audio source and that audio source is playing
// if ((colliderAudioSource = GetComponentsForType<AudioSource>(targetObject)) != null) {
if ((colliderAudioSource = targetObject.GetComponentsInChildren<AudioSource>(targetObject)) != null) {
for (int i = 0; i < colliderAudioSource.Length; ++i) {
if (colliderAudioSource[i].isPlaying) {
var distance = Vector3.Distance(transform.position, targetObject.transform.position);
if (distance >= colliderAudioSource[i].maxDistance) {
audibility = 0;
} else {
if (colliderAudioSource[i].rolloffMode == AudioRolloffMode.Logarithmic) {
audibility = 1 / (1 + colliderAudioSource[i].maxDistance * (distance - 1));
} else { // linear
audibility = colliderAudioSource[i].volume * Mathf.Clamp01((distance - colliderAudioSource[i].minDistance) / (colliderAudioSource[i].maxDistance - colliderAudioSource[i].minDistance));
}
}
if (audibility > audibilityThreshold) {
return targetObject;
}
}
}
}
return null;
}
这样,针对子对象的动态侦听就实现了。