2017-12-13 19:08:27 DebussyEzio 阅读数 994

今天工作中遇到了一个问题,unity3d中加载了一个音频数组 audioclip[],怎么依次播放这个音频数组.目前想到了三种方案,写下来一起看看,有什么不足请指出和改进
源码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class AnimManager : MonoBehaviour {


    private AudioSource myAudioSource;

    private string resourcePath;

    private UnityEngine.Object[] resObjs;

    private AudioClip[] audios;

    // Use this for initialization
    void Start () {

       if (myAudioSource == null)
        {
            myAudioSource = this.gameObject.AddComponent<AudioSource>();
        }
        resToAudios();

    }

     //根据输入索引播放音频  这是第二种方案的方法
     #region第二种
     private void PlayAudio(int index)
     {
        //这里为了程序严谨需要做一个index的判断,我懒得写了.  
         myAudioSource.clip = null;

        myAudioSource.clip = audios[index];

        myAudioSource.Play();

       // myAudioSource.PlayOneShot(audios[index]);

         myAudioSource.loop = false;

        currentIndex++;
     }

    //一个临时索引
    private int currentIndex = 0;
    //播放的方法
    public void PlayAudio()
    {
        if (!myAudioSource.isPlaying)
        {
            PlayAudio(currentIndex);
        }
    }
     //void Update()
    //{
    //    PlayAudio();
    //}
    #endregion

    //在resources路径下加载资源,这里只是做一个resources路径下的演示,具体的加载资源的方式不在此处讨论.
    private void LoadAllAudios()
    {
        resourcePath = SceneManager.GetActiveScene().name;
        resObjs = Resources.LoadAll(resourcePath,typeof(AudioClip));
    }
   //将加载出来的资源obj转换成为想获取的audioclip类型,此处最好写为泛型,具体方式不赘述.
    private void resToAudios()
    {
        LoadAllAudios();
        audios = new AudioClip[resObjs.Length];
        for (int i = 0; i < resObjs.Length; i++)
        {

            audios[i] = resObjs[i] as AudioClip;
        }
    }

    //这是第一种方式,用协程加载,
    #region
    IEnumerator IEPlayAudio(int index)
    {
        if (index >= audios.Length)
        {
            index = audios.Length - 1;
        }
        currentIndex = index;

        myAudioSource.clip = null;

        myAudioSource.clip = audios[currentIndex];

        myAudioSource.Play();

        // myAudioSource.PlayOneShot(audios[index]);

        myAudioSource.loop = false;

        yield return new WaitForSeconds(myAudioSource.clip.length);

        currentIndex++;
        if (currentIndex != audios.Length)
        {
           //递归   播放
            StartCoroutine(IEPlayAudio(currentIndex));
        }
        else
        {
            StopAllCoroutines();
        }
    }



    public void SelectedAudio(int index)
    {
        StopAllCoroutines();
        StartCoroutine(IEPlayAudio(index));
    }
    #endregion
}

第三种方式就是通过读配置表的方式了,需要填写配置表,做一个计时器,或者获取动画播放的帧数,第几帧或者第几秒播放那个音频..读表方式很多种,此处也不再赘述,有疑问可以Q我599580970.

2015-06-16 19:54:33 lfh719852029 阅读数 614

这几天都有要学习一些有关于unity3d中有关可用数组存储这方面的知识,同时有在网上收集一些资料。


Unity3D中可用的数组类型:

原文(转载):http://blog.csdn.net/jbjwpzyl3611421/article/details/11113529

(给大家看三篇文档Dictionary,HashTable)原帖:http://tieba.baidu.com/p/2696435222

(Hashtable和Dictionary学习笔记)原文:http://www.unitymanual.com/blog-46104-1756.html

(C#中数组、ArrayList和List三者的区别)原文:http://blog.csdn.net/zhang_xinxiu/article/details/8657431


第一篇比较基础说的也比较详细,就贴一下:(我这边只贴关于C#的代码)

Built-in array   
ArrayList   
Hashtable   
Generic List   
Generic Dictionary   
2D Array 

1. 内置数组build-in-Array:

例如:int[] myArray = new int[10];

优点:最高效,唯一能在unity监视面板中看到的数组 
缺点:数组成员只能是同一种类型;数组长度不可变,但是可确定数组最大长度,用不到的留空, 
尽量用这种数组。 


(写法和c有些差,一般用的最多的数组,最重要的问题就是长度不可变,在不确定长度或者数组可能有较多的扩充的时候最好换别的数组来存储)


2. ArrayList:

ArrayList是命名空间System.Collections下的一部分,在使用该类时必须进行引用,同时继承了IList接口,提供了数据存储和检索。ArrayList对象的大小是按照其中存储的数据来动态扩充与收缩的。所以,在声明ArrayList对象时并不需要指定它的长度。

例如:ArrayList array = new ArrayList ();

优点:数组长度是动态的。

缺点:

(1)在ArrayList中插入不同类型的数据是允许的,在我们使用ArrayList处理数据时,很可能会报类型不匹配的错误,也就是ArrayList不是类型安全的。

(2)因为ArrayList会把所有插入其中的数据当作为object类型来处理,在存储或检索值类型时通常发生装箱和取消装箱操作,带来很大的性能耗损。

装箱和拆箱:

装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。 
(1)装箱在值类型向引用类型转换时发生
(2)拆箱在引用类型向值类型转换时发生

(装箱很耗性能,拆箱性能可以忽略不计)

例如:

int i=1
object o=i;//装箱
int b=(int)o;//拆箱


3.Generic List:因为ArrayList存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念。List类是ArrayList类的泛型等效类,它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。

例如:List<int> a = new <int>();

优点:节省资源,不易出错 
比较重要的是Generic List不能在iPhone中使用! 
c#中使用:必须声明using System.Collections.Generic; 命名空间 


后面有关Hashtable和Dictionary可以查看第2、3篇转载的文章

4.Generic Dictionary 

Dictionary<string, string>是一个泛型 他本身有集合的功能有时候可以把它看成数组, 他的结构是这样的:Dictionary<[key], [value]> ,
他的特点是存入对象是需要与[key]值一一对应的存入该泛型, 通过某一个一定的[key]去找到对应的值,[key]不能重复,它的单个数组是KeyValuePair<key, value>,[value]可以是string,int 和一个类等等.

例如:Dictionary<string, string> dic = new Dictionary<string, string>();

优点:有泛型优势,且读取速度较快,容量利用更充分,推荐单线程使用

缺点:Dictionary使用索引器取值时,如果键不存在就会引发异常,可使用ContarnsKey()来判断,经常取值最好用TryGetValue方法来获取集合中对应的键值。

不能在iPhone中使用! 

注意:遍历键值对用KeyValuePair 


5、Hashtable

Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中keyvalue键值对均为object类型,所以Hashtable可以支持任何类型的keyvalue键值对.

例如:Hashtable hash = new Hashtable ();

优点:多线程程序中推荐使用Hashtable,默认的Hashtable允许单线程写入,多线程读取,对Hashtable进一步调用Synchronized()可以获得完全线程安全的类型,而Dictionary非线程安全,必须人为使用Lock语句进行保护,效率大减。

缺点:Hashtable的元素属于Object类型,所以在存储或检索值类型时通常发生装箱和拆箱操作。

注意:遍历哈希表遍历哈希表需要用到DictionaryEntry Object 


差不多就到这,好不容易项目终于结束了,虽然不是商业用途,但是和上一个项目一样都没有得到预想的结果,就这样不了了之,什么时候才能做出像样的作品,再过几天就要去实习,还有很多东西要学,加油!



2014-06-11 16:50:52 zhengkangchen 阅读数 23476

网上大多数Unity教程只讲述了如何在Unity里播放音乐,如何通过拖拽添加音频文件之后就没有继续了
但在游戏中有时候一个对象需要播放好几种声音,这个时候我们就需要用代码进行控制,教程上推拽给AudioClip赋值的方法就显得不是那么实用了
所以本篇将重点讲述如何在Unity中创建一个最简化的音频播放器,并通过代码进行动态加载与播放

①创建一个Empty对象 点击菜单栏[GameObject]–>Create Empty 命名为Audio

②选取这个空对象 点击菜单栏[Component]–>Audio–>Audio Source 这样就在场景里创建了如图所示的一个喇叭

③创建资源文件夹命名为Resources,并把BeiTown.mp3文件拖入其中,注意一定要将资源文件夹名设为Resources,否则Resources.Load方法将无法找到资源文件

④创建脚本
接下来开始创建脚本

MusicPlayer.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using UnityEngine;
using System.Collections;

public class MusicPlayer : MonoBehaviour {

    public AudioSource Sound;

    public void Play(string str)
    {
        Sound.clip = (AudioClip)Resources.Load(str, typeof(AudioClip));//调用Resources方法加载AudioClip资源
        Sound.Play();
    }

}

MusicTest.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using UnityEngine;
using System.Collections;

public class MusicTest : MonoBehaviour {

    private MusicPlayer music;

    void Start () {
    
        music = (GetComponent("MusicPlayer") as MusicPlayer);//获取播放器对象

    }

    void OnGUI()
    {
        if(GUI.Button(new Rect(101010050)"PLAY")){

            music.Play("BeiTown");//调用播放器Play方法

        }

    }

}

⑤将脚步绑定到AudioSource音源对象上,并将Audio对象赋给MusicPlayer脚本里的Sound对象,以便MusicPlayer对其进行操作

⑥点击播放按钮

这个时候就能听到声音了,但是细心的朋友会发现左右耳朵的声音并不是一样大的,这是因为我们的声音监听绑定在了主摄像机上,这就照成了声音可能是从一个方向传来的3D效果,如果不想要这个效果也好办
选取Audio对象,点击菜单栏[Commponent]–>Audio–>Audio Listener
为Audio对象创建一个声音监听,并勾选它

重新点击播放按钮,这个时候发现依然没有改变,控制台出现如下警告:There are 2 audio listeners in the scene. Please ensure there is always exactly one audio listener in the scene.
不要着急,Main Camera 主摄像机上的Audio Listen 取消勾选了么
Unity默认一个scene里同时只能有一个声音监听,其实这也很好理解,在自然情况下,人类也不可能做到两只耳朵听取不同范围的声音(借助设备除外)
将其他的Audio Listener取消后,只保留Audio上的Audio Listener,点击Play按钮,一切正常!

其他的暂停,停止,等等操作这里就不再添加了,感兴趣的朋友可以自己参考API进行操作,本文主要描述如何动态加载一首音乐,并将该类进行封装,同时最简化的代码也利于大家观看理解。
今天就到这里吧,意在分享,与君共勉之。

2017-04-11 11:24:15 daka2012 阅读数 373

简介:在unity3d中创建公用的音频管理器,实现音频播放,并根据游戏设置中的音频开关控制音乐及音效播放

在unity3d中给gameObject添加AudioSource组件即可实现音频播放功能,但不利于统一管理,尤其是当场景中物件较多时,很难逐一开启或者关闭

最近的项目中需要可设置音乐与音效开关,为了方便统一管理自己写了一个音频管理器,主要用于以下功能:

1.将音效进行分类,每一类使用一个公用的音效播放器,统一管理场景中的音乐\音效,避免为每个物件重复添加AudioSource组件

2.避免多个2D音效同时播放,造成音效混杂刺耳

3.方便在游戏设置中对音乐/音效进行统一开关处理

4.避免因物件被销毁或禁止时造成附带音效不能正常播放

代码如下,兹以备份

using System.Collections.Generic;
using UnityEngine;

public class AM
{
    public class AudioPlayer : MonoBehaviour
    {
        public AudioSource myaudio { get; set; }
        public AudioType type { get; set; }
    }
    public enum AudioType
    {
        Sound = 0,
        Music = 1,
    }
    private static AMHelper am = (new GameObject("AMHelper")).AddComponent();
    public static Dictionary apDic = new Dictionary();
    public static int maxnum = 10;
    public static int musicOpen { get; set; }
    public static int soundOpen { get; set; }

    public static AudioPlayer AddAudioPlayer(string name, AudioType type = AudioType.Sound)
    {
        if (apDic.Count >= maxnum)
        {
            throw new System.Exception(string.Format("音频播放器数量超过{0}个限制!!!!!", maxnum));
        }
        if (apDic.ContainsKey(name))
        {
            Debug.Log(string.Format("{0}音频播放器已存在,无需添加", name));
            return apDic[name];
        }
        AudioPlayer newap = (new GameObject(name)).AddComponent() as AudioPlayer;
        apDic.Add(name, newap);
        newap.myaudio = newap.gameObject.AddComponent() as AudioSource;
        newap.type = type;
        newap.myaudio.playOnAwake = false;
        newap.transform.parent = am.transform;
        return newap;
    }

    public static void RemoveAduioPlayer(string name)
    {
        AudioPlayer audioFMS = apDic[name];
        apDic.Remove(name);
        Object.Destroy(audioFMS.gameObject);
    }

    public static bool AudioIsOpen(AudioPlayer ap)
    {
        if (musicOpen.GetPref(PrefKeys.musicOpen) == 0 && ap.type == AudioType.Music) return false;
        else if (soundOpen.GetPref(PrefKeys.soundOpen) == 0 && ap.type == AudioType.Sound) return false;
        else return true;
    }

    //音频播放(可响应音乐/音效开关控制)
    public static void Play(string apname, string clippath, bool setloop = false)
    {
        AudioPlayer ap = apDic[apname];
        //判断音频或者音效开关是否打开
        if (!AudioIsOpen(ap)) return;

        //如果是打开的才执行下面的播放
        if (!ap.myaudio.isPlaying || ap.myaudio.loop != setloop)
        {
            ap.myaudio.clip = Resources.Load(clippath);
            ap.myaudio.Play();
        }
        else ap.myaudio.PlayOneShot(Resources.Load(clippath));
        ap.myaudio.loop = setloop;
    }

    public static void Continue(string apname)
    {
        AudioPlayer ap = apDic[apname];
        //判断音频或者音效开关是否打开
        if (!AudioIsOpen(ap)) return;

        //如果是打开的才执行下面的播放
        ap.myaudio.Play();
    }

    public static AudioSource GetAudio(string apname)
    {
        AudioPlayer getap = null;
        if(apDic.TryGetValue(apname,out getap)) return getap.myaudio;
        else throw new System.Exception("没有这个播放器");
    }

    public static void CleanUp()
    {
        if (apDic.Count == 0) return;
        foreach(KeyValuePair pair in apDic)
        {
            Object.Destroy(pair.Value.gameObject);
            apDic.Remove(pair.Key);
        }
    }
}

public class AMHelper : MonoBehaviour
{
    public void Awake()
    {
        DontDestroyOnLoad(gameObject);
    }
}

Unity3D音频的制作

阅读数 1035

没有更多推荐了,返回首页