C# 为什么即使不按任何一个3D对象材质,它们也会发出声音?
我和我的朋友正在尝试为手机制作一个钢琴应用程序。我们的钢琴键盘“键”是16个彼此相邻的3D对象。问题是,当我在屏幕上几乎任何地方按下时,它会同时播放我放在3D对象上的所有音频剪辑。我尝试了多个脚本,但它们都有相同的问题或不同的解决方案。 以下是我当前使用的脚本: 顺便说一句,我仍然是Unity和C的不速之客,所以欢迎大家的帮助。:)C# 为什么即使不按任何一个3D对象材质,它们也会发出声音?,c#,visual-studio,unity3d,game-development,C#,Visual Studio,Unity3d,Game Development,我和我的朋友正在尝试为手机制作一个钢琴应用程序。我们的钢琴键盘“键”是16个彼此相邻的3D对象。问题是,当我在屏幕上几乎任何地方按下时,它会同时播放我放在3D对象上的所有音频剪辑。我尝试了多个脚本,但它们都有相同的问题或不同的解决方案。 以下是我当前使用的脚本: 顺便说一句,我仍然是Unity和C的不速之客,所以欢迎大家的帮助。:) 使用UnityEngine; 使用系统集合; 使用UnityEngine.UI; 使用UnityEngine.Audio; [所需组件(类型(音频源))] 公共类关
使用UnityEngine;
使用系统集合;
使用UnityEngine.UI;
使用UnityEngine.Audio;
[所需组件(类型(音频源))]
公共类关键1:单一行为
{
声源;声源;
触摸触摸;
void Start()
{
AudioSource=GetComponent();
}
无效更新()
{
如果(Input.touchCount>0)
{
theTouch=Input.GetTouch(0);
如果(触摸阶段==触摸阶段开始)
{
AudioSource.Play();
}
如果(触摸阶段==触摸阶段结束)
{
AudioSource.Stop();
}
if(touch.phase==touch.Moved)
{
AudioSource.Stop();
}
如果(touch.phase==touch.phase.cancelled)
{
AudioSource.Stop();
}
}
}
}
首先,您可能不需要在每个“键”上都使用音频源。如果你只想播放声音,一个就足够了。然而,如果你想要3D声音,左边的按键在你的左扬声器上,那么你需要在每个按键上都有一个音频源
要知道播放哪个键,可以从屏幕位置(单击的位置)向3D世界进行简单的光线投射。您只需要执行一次光线投射,因此不要在关键脚本中执行。如果您对没有3D声音感到满意,请将其与音频源一起移动到单独的脚本中
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);
}
}
}
}
}
如果您想要3D声音,请将音频源移动到按键(每个按键上有一个音频源)。然后钢琴代码将类似于:
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();
}
}
}
}
}
使用UnityEngine;
公共课钢琴:独奏
{
无效更新()
{
if(Input.GetMouseButtonDown(0))
{
//用户已单击(或触摸)屏幕。将其转换为3D世界中的某个位置:
Ray-Ray=Camera.main.screenpointoray(输入.鼠标位置);
雷卡斯特击中;
如果(物理.光线投射(光线,出击))
{
//用户已单击碰撞器。它是否有关键脚本?
Key=hit.collider.GetComponent();
if(key!=null)
{
键。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);
}
}
使用UnityEngine;
使用UnityEngine.Assertions;
公共类密钥:MonoBehavior
{
//您也可以简单地从编辑器向音频源添加声音。
公共音频剪辑;
声源;声源;
私人空间
{
audioSource=GetComponent();
Assert.IsNotNull(音频源);
}
公共游戏
{
音频源:PlayOneShot(剪辑);
}
}
最后,一个3D声音的触摸版。这与前面的示例非常相似,但我们现在还跟踪按键按下的时间 与之前一样,我们使用光线投射来获取用户按下的键。但是我们也存储了fingerId,这样我们就知道它是哪根手指,并且可以在释放手指时释放右键 在本例中,声音片段与音频源一起存储
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;
}
}
使用UnityEngine;
公共课钢琴:独奏
{
关键[]所有知识;
私人空间
{
allKnownKeys=FindObjectsOfType();
}
无效更新()
{
foreach(输入触摸,触摸)
{
如果(touch.phase==TouchPhase.end | | touch.phase==TouchPhase.cancelled)
{
//使用fingerID(按下按键的手指)获取按键
Key=GetKey(touch.fingerId);
//这是一把被释放的钥匙吗?
if(key!=null)
键。停止();
}
else if(touch.phase==TouchPhase.start)
{
//屏幕上的新触摸。将其转换为3D世界中的一个位置:
光线=摄影机.main.screenpointoray(触摸.位置);
雷卡斯特击中;
如果(物理.光线投射(光线,出击))
{
//用户触摸了碰撞器。碰撞器上是否有关键脚本?
Key=hit.collider.GetComponent();
if(key!=null)
{
键。播放(触摸。fingerId);
}
}
}
}
}
///
///获取已“向下”(播放)的键。
///
///
///
私钥GetKey(int fingerId)
{
foreach(allKnownKeys中的键)
if(key.FingerId==FingerId)
返回键;
返回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; }
}
使用UnityEngine;
使用UnityEngine.Assertions;
公共类密钥:MonoBehavior
{
声源;声源;
私人空间
{
audioSource=GetComponent();
Assert.IsNotNull(音频源);
FingerId=-1;
}
公共无效播放(int fingerId)
{
如果(FingerId>=0)
return;//键已“关闭”
FingerId=FingerId;
audioSource.Play();
}
公共停车场()
{
FingerId=-1;
audioSource.Stop();
}
public int FingerId{get;protected set;}
}
因为我猜所有键都有这个,而您的脚本只检查
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; }
}