微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么即使没有按下任何一个 3D 对象也会发出声音?

如何解决为什么即使没有按下任何一个 3D 对象也会发出声音?

我和我的朋友正在尝试为手机做一个钢琴应用程序。我们的钢琴键盘“键”是 16 个彼此相邻的 3D 对象。问题是,当我几乎按屏幕上的任何地方时,它会同时播放我放在 3D 对象上的所有音频剪辑。我尝试了多个脚本,但它们都有相同或不同的问题。 这是我当前使用的脚本:

附注。我仍然是 Unity 和 C# 的菜鸟,所以欢迎提供所有帮助。 :)

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Audio;


[RequireComponent(typeof(AudioSource))]
public class key1 : MonoBehavIoUr
{
    AudioSource AudioSource;
    Touch thetouch;
    
    void Start()
    {
        AudioSource = GetComponent<AudioSource>();
    }
    void Update()
    {

        if (Input.touchCount > 0)
        {
            thetouch = Input.GetTouch(0);
            if (thetouch.phase == TouchPhase.Began)
            {
                
               AudioSource.Play();

            }
           if (thetouch.phase == TouchPhase.Ended)
           {

               AudioSource.Stop();
            }
           if (thetouch.phase == TouchPhase.Moved)
            {
               AudioSource.Stop();
            }
           if (thetouch.phase == TouchPhase.Canceled)
            {
               AudioSource.Stop();
            }
        }
    }
}

解决方法

首先,您可能不需要在每个“键”上都有一个 AudioSource。如果您只想播放声音,一个就足够了。但是,如果您想要左侧按键位于左扬声器上的 3D 声音,那么您需要在每个按键上都有一个 AudioSource。

要知道要播放哪个键,您可以从屏幕位置(您单击的位置)到 3D 世界进行简单的光线投射。你只需要做一次光线投射,所以不要在你的关键脚本中做。如果您对 3D 音效感到满意,请将其与 AudioSource 一起移至单独的脚本。

using UnityEngine;
using UnityEngine.Assertions;

public class Piano : MonoBehaviour
{
    AudioSource audioSource;

    private void Awake()
    {
        audioSource = GetComponent<AudioSource>();
        Assert.IsNotNull(audioSource);
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // The user has clicked (or touched) on the screen. Convert it to a position in the 3D world:
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray,out hit))
            {
                // The user has clicked on a Collider. Does it have a Key script on it?
                Key key = hit.collider.GetComponent<Key>();
                if(key != null)
                {
                    // The user clicked on a key. Play the sound (without interrupting previous sounds).
                    audioSource.PlayOneShot(key.clip);
                }
            }
        }
    }
}

按键上的脚本可以很简单:

using UnityEngine;

public class Key : MonoBehaviour
{
    public AudioClip clip;
}

如果您想要 3D 声音,请将 AudioSource 移动到键(每个键一个 AudioSource)。钢琴代码将类似于:

using UnityEngine;

public class Piano : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // The user has clicked (or touched) on the screen. Convert it to a position in the 3D world:
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray,out hit))
            {
                // The user has clicked on a Collider. Does it have a Key script on it?
                Key key = hit.collider.GetComponent<Key>();
                if(key != null)
                {
                    key.Play();
                }
            }
        }
    }
}

和关键脚本:

using UnityEngine;
using UnityEngine.Assertions;

public class Key : MonoBehaviour
{
    // You could also simply add the sound to the audioSource from the editor.
    public AudioClip clip;
    AudioSource audioSource;

    private void Awake()
    {
        audioSource = GetComponent<AudioSource>();
        Assert.IsNotNull(audioSource);
    }

    public void Play()
    {
        audioSource.PlayOneShot(clip);
    }
}

最后是带有 3D 音效的触控版本。它与之前的示例非常相似,但我们现在还可以跟踪按键按下的时间。

和之前一样,我们使用光线投射来获取用户按下的键。但是我们也存储了fingerId,所以我们知道它是哪个手指,并且可以在松开那个手指时松开右键。

在此示例中,声音剪辑与 AudioSource 一起存储。

using UnityEngine;

public class Piano : MonoBehaviour
{
    Key[] allKnownKeys;

    private void Awake()
    {
        allKnownKeys = FindObjectsOfType<Key>();
    }

    void Update()
    {
        foreach (Touch touch in Input.touches)
        {
            if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
            {
                // Get the key using the fingerID (the finger that pressed down the key)
                Key key = GetKey(touch.fingerId);
                // Was it a key that was released?
                if(key != null)
                    key.Stop();
            }
            else if(touch.phase == TouchPhase.Began)
            {
                // New touch on the screen. Convert it to a position in the 3D world:
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
                RaycastHit hit;
                if (Physics.Raycast(ray,out hit))
                {
                    // The user has touched a Collider. Does it have a Key script on it?
                    Key key = hit.collider.GetComponent<Key>();
                    if (key != null)
                    {
                        key.Play(touch.fingerId);
                    }
                }
            }
        }
    }

    /// <summary>
    /// Gets the key which is already "down" (playing).
    /// </summary>
    /// <param name="fingerId"></param>
    /// <returns></returns>
    private Key GetKey(int fingerId)
    {
        foreach (Key key in allKnownKeys)
            if (key.FingerId == fingerId)
                return key;
        return null;        
    }
}

以及触摸版的关键脚本:

using UnityEngine;
using UnityEngine.Assertions;

public class Key : MonoBehaviour
{
    AudioSource audioSource;

    private void Awake()
    {
        audioSource = GetComponent<AudioSource>();
        Assert.IsNotNull(audioSource);
        FingerId = -1;
    }

    public void Play(int fingerId)
    {
        if (FingerId >= 0)
            return; // The key is already "down"
        FingerId = fingerId;
        audioSource.Play();
    }

    public void Stop()
    {
        FingerId = -1;
        audioSource.Stop();
    }

    public int FingerId { get; protected set; }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。