UNITY中FMOD音效插件使用

在UNITY中使用FMOD插件,直接控制音乐,音效。

FMOD下载

FMOD STUDIO的版本与插件要保持一致。

FMOD STUDIO使用教程

UNITY引入package

FMOD - Edit Setting 3个选项:Project,Single Platform Build,Multiple Platform Build

Project路径指定FMOD工程,其余2个路径指定FMOD导出的bank所在文件夹。

可以指定UNITY工程外路径,如果需要多人同步也可以用Assets\路径 (Mac下用 [/])

指定后插件会自动在Assets/StreamingAssets将bank导入。

注意:导出安卓工程时,FMOD的BANK文件没有被加密放在assets\bin文件夹内,而是直接在assets文件夹下

Live Update选项Enabled时,可以直接在FMOD STUDIO中调试音乐音效。

UNITY内代码部分:

using UnityEngine;
using System;
using System.Collections.Generic;
using FMOD.Studio;
using FMODUnity;


public class SoundManager <T>: MonoBehaviour where T: Component{
	protected static T _instance;

	public static T instance {
		get {
			if (_instance.IsNull())
				_instance = FindObjectOfType<T>();

			return _instance;
		}
	}

	public static bool DoesInstanceExist {
		get {
			return instance != null;
		}
	}


	public BGMPathDefinition[] BGMPathDefinitions;
	protected Dictionary<BGMType, string> BGMPathDict;
	protected BGMType currentAmbientAudio;
	//一个声音实例,可控制。
	//循环播放的可以创建一个,要手动release, OneShot 为true播放完自动release.
	//http://www.fmod.org/docs/content/generated/studio_api_EventInstance.html
	//http://www.fmod.org/docs/content/generated/FMOD_Studio_EventDescription_IsOneshot.html
	protected EventInstance BGMEvent;

	用来读取声音在工程里面的设置信息,用不到
	http://www.fmod.org/docs/content/generated/studio_api_EventDescription.html
	//private EventDescription musicDescription;

	protected Dictionary<string, EventInstance> loopingSoundEvents = new Dictionary<string, EventInstance>();

	protected List<EventInstance> pausedSoundEvents;
	protected const int minPathLength = 7;
	protected virtual void Awake() {
		_instance = GetComponent<T>();

		BGMPathDict = new Dictionary<BGMType, string>();
		foreach (var ambientAudioDefinition in BGMPathDefinitions) {
			BGMPathDict.Add(ambientAudioDefinition.ambientAudioType, ambientAudioDefinition.path);
		}
	}

	protected virtual void OnDestroy() {
		StopAndReleaseAll();

		if (BGMEvent != null) {
			BGMEvent.stop(STOP_MODE.IMMEDIATE);
			BGMEvent.release();
		}
		_instance = null;
	}


	public virtual void StopAndReleaseAll() {
		foreach (var sound in loopingSoundEvents.Values) {
			if (sound == null)
				continue;

			sound.stop(STOP_MODE.IMMEDIATE);
			sound.release();
		}

		loopingSoundEvents.Clear();
	}


	public virtual void pauseAll() {
		pausedSoundEvents = new List<EventInstance>();

		foreach (var loopingInstance in loopingSoundEvents.Values) {
			if (loopingInstance == null)
				continue;

			PLAYBACK_STATE state;
			loopingInstance.getPlaybackState(out state);
			if (state == PLAYBACK_STATE.PLAYING
				|| state == PLAYBACK_STATE.STARTING) {
				loopingInstance.setPaused(true);
				pausedSoundEvents.Add(loopingInstance);
			}
		}

		PauseBGM(true);
	}

	public virtual void resumeAll() {
		PauseBGM(!GameController.Instance.MusicEnable);

		if (!GameController.Instance.SFXEnable || pausedSoundEvents == null)
			return;

		foreach (var pausedSound in pausedSoundEvents) {
			pausedSound.setPaused(false);
		}
	}

	#region BGM

	public virtual void PlayBGM(BGMType type) {
		currentAmbientAudio = type;

		if (GameController.Instance.MusicEnable) {
			CheckBGMEventInstance();
		}
	}

	public virtual void PauseBGM(bool pause) {
		if (BGMEvent == null)
			CheckBGMEventInstance();

		if (BGMEvent != null)
			BGMEvent.setPaused(pause);
	}

	protected void CheckBGMEventInstance() {

		if (BGMPathDict.ContainsKey(currentAmbientAudio)) {
			//停止之前的,最好可以通过参数变化背景音乐
			if (BGMEvent != null) {
				BGMEvent.stop(STOP_MODE.IMMEDIATE);
				BGMEvent.release();
			}
			BGMEvent = RuntimeManager.CreateInstance(BGMPathDict[currentAmbientAudio]);
			BGMEvent.start();
		}
	}

	#endregion

	#region SFX

	/// <summary>
	/// 播放一次,不能改变任何参数
	/// </summary>
	public virtual void PlaySoundOnce(string sound) {
		if (!GameController.Instance.SFXEnable || string.IsNullOrEmpty(sound))
			return;

		if (sound.Length < minPathLength) {
			Logger.Warning("Wrong Sound Path:" + sound);
			return;
		}

		RuntimeManager.PlayOneShot(sound);
	}

	/ <summary>
	/ 目标位置播放一次(位置不变)
	/ </summary>
	//public void PlaySoundOnce(string Event, Vector3 position) {
	//	if (GameController.Instance.SFXEnable)
	//		RuntimeManager.PlayOneShot(Event, position);
	//}

	/ <summary>
	/ 播放一次,位置在attach上(跟着attach移动)
	/ </summary>
	//public void PlaySoundOnce(string Event, GameObject attach) {
	//	if (GameController.Instance.SFXEnable)
	//		RuntimeManager.PlayOneShotAttached(Event, attach);
	//}

	/// <summary>
	/// 循环播放,要Fmod工程内OneShot为false
	/// </summary>
	public virtual EventInstance PlayLoopSounds(string sound) {
		if (!GameController.Instance.SFXEnable || string.IsNullOrEmpty(sound))
			return null;

		if (sound.Length < minPathLength) {
			Logger.Warning("Wrong Sound Path:" + sound);
			return null;
		}

		if (HavaEventInstance(sound)) {
			loopingSoundEvents[sound].start();
			return loopingSoundEvents[sound];
		}

		var newInstance = RuntimeManager.CreateInstance(sound);

		newInstance.start();
		loopingSoundEvents[sound] = newInstance;

		return newInstance;
	}

	/// <summary>
	/// 暂停指定循环音效
	/// </summary>
	public bool PauseSound(string sound, bool pause = true) {
		if (HavaEventInstance(sound)) {
			var result = loopingSoundEvents[sound].setPaused(pause && GameController.Instance.SFXEnable);
			return result == FMOD.RESULT.OK;
		}

		return false;
	}
	/// <summary>
	/// 停止指定循环音效,并释放
	/// </summary>
	public bool StopSound(string sound) {
		if (HavaEventInstance(sound)) {
			var result = loopingSoundEvents[sound].stop(STOP_MODE.IMMEDIATE);
			loopingSoundEvents[sound].release();
			loopingSoundEvents.Remove(sound);
			return result == FMOD.RESULT.OK;
		}

		return false;
	}

	protected bool HavaEventInstance(string sound) {
		return !string.IsNullOrEmpty(sound) && loopingSoundEvents.ContainsKey(sound) && !loopingSoundEvents[sound].IsNull();
	}
	#endregion

	//void OnApplicationPause(bool didPause) {
	//	if (didPause) {
	//		pauseAll();
	//	}
	//	else {
	//		resumeAll();
	//	}
	//}

	void OnApplicationFocus(bool focus) {
		if (focus) {
			resumeAll();
		}
		else {
			pauseAll();
		}
	}
}


[Serializable]
public class BGMPathDefinition {
	public BGMType ambientAudioType;

	[EventRef]
	public string path;
}

public enum BGMType {
	Mainmenu = 0,
	IngameRunning = 20,
}

FMOD STUDIO的版本与插件要保持一致。
FMOD STUDIO的版本与插件要保持一致。
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
智慧农业是一种结合了现代信息技术,包括物联网、大数据、云计算等,对农业生产过程进行智能化管理和监控的新模式。它通过各种传感器和设备采集农业生产的关键数据,如大气、土壤和水质参数,以及生物生长状态等,实现远程诊断和精准调控。智慧农业的核心价值在于提高农业生产效率,保障食品安全,实现资源的可持续利用,并为农业产业的转型升级提供支持。 智慧农业的实现依赖于多个子系统,包括但不限于设施蔬菜精细化种植管理系统、农业技术资料库、数据采集系统、防伪防串货系统、食品安全与质量追溯系统、应急追溯系统、灾情疫情防控系统、农业工作管理系统、远程诊断系统、监控心、环境监测系统、智能环境控制系统等。这些系统共同构成了一个综合的信息管理和服务平台,使得农业生产者能够基于数据做出更加科学的决策。 数据采集是智慧农业的基础。通过手工录入、传感器自动采集、移动端录入、条码/RFID扫描录入、拍照录入以及GPS和遥感技术等多种方式,智慧农业系统能够全面收集农业生产过程的各种数据。这些数据不仅包括环境参数,还涵盖了生长状态、加工保存、检验检疫等环节,为农业生产提供了全面的数据支持。 智慧农业的应用前景广阔,它不仅能够提升农业生产的管理水平,还能够通过各种应用系统,如库房管理、无公害监控、物资管理、成本控制等,为农业生产者提供全面的服务。此外,智慧农业还能够支持政府监管,通过发病报告、投入品报告、死亡报告等,加强农业产品的安全管理和质量控制。 面对智慧农业的建设和发展,存在一些挑战,如投资成本高、生产过程标准化难度大、数据采集和监测的技术难题等。为了克服这些挑战,需要政府、企业和相关机构的共同努力,通过政策支持、技术创新和教育培训等手段,推动智慧农业的健康发展。智慧农业的建设需要明确建设目的,选择合适的系统模块,并制定合理的设备布署方案,以实现农业生产的智能化、精准化和高效化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值