Audio Source
发声的组件
AudioClip 声音片段
Output 混音
Mute 静音
Play On Awake 是否在游戏开始时候播放
Loop 循环播放
Volume 音量
Spatial Blend 2D 3D
3D Sound Settings
Min Distance 在这个声音内是饱满的无缺陷
Max Distance 最远能听的最大声音
Audio Listener
听声音的组件
CS的小例子
首先要分成三个脚本
第一个脚本控制每把枪
第二个脚本要管理这些枪
第三个脚本解决狂点按键,从而引发声音不同步问题
using System;
using UnityEngine;
public class FPSGun : MonoBehaviour
{
[Header("声音片段")]
[Header("开火")]
public AudioClip fireClip;
[Header("切枪")]
public AudioClip readyClip;
[Header("换弹")]
public AudioClip reloadClip;
[Header("火花特效")]
public GameObject muzzleFlash;
private Animator _animator;
private void Awake()
{
_animator = GetComponent<Animator>();
}
private void OnEnable()
{
//播放切枪声音
AudioSource.PlayClipAtPoint(readyClip,transform.position);
}
/// <summary>
/// 开火
/// </summary>
public void Fire()
{
//开火名称转成哈希
int fire = Animator.StringToHash("Fire");
//播放开火动画
_animator.SetTrigger(fire);
//播放声音
//AudioSource.PlayClipAtPoint(fireClip,transform.position);
}
/// <summary>
/// 换弹
/// </summary>
public void Reload()
{
int reload = Animator.StringToHash("Reload");
_animator.SetTrigger(reload);
//AudioSource.PlayClipAtPoint(reloadClip,transform.position);
}
/// <summary>
/// 播放开火特效
/// </summary>
public void PlayerFireEffect()
{
//播放特效
muzzleFlash.SetActive(true);
//延时关闭特效
Invoke("UnEffect", 0.1f);
}
/// <summary>
/// 关闭火花特效
/// </summary>
public void UnEffect()
{
muzzleFlash.SetActive(false);
}
}
using System.Collections.Generic;
using UnityEngine;
public class FPSGunManager : MonoBehaviour
{
//管理枪支
private List<FPSGun> managerdGuns;
//当前用的枪
private FPSGun currentGun;
//当前枪的编号
private int index = 0;
private void Awake()
{
managerdGuns = new List<FPSGun>();
}
private void Start()
{
//有多少把枪就有多少子对象
for (int i = 0; i < transform.childCount; i++)
{
//添加每一把枪
managerdGuns.Add(transform.GetChild(i).GetComponent<FPSGun>());
}
//枪的数量大于0 说明肯定有一把枪
if (managerdGuns.Count > 0)
{
//当前使用的枪是列表里的第0个
currentGun = managerdGuns[index];
}
}
private void Update()
{
//当前是否有一把枪,如果没有就跳过
if (!currentGun)
return;
//当前枪 按下鼠标左键
if (Input.GetButtonDown("Fire"))
{
//当前使用的枪开枪(调用FPSGun脚本)
currentGun.Fire();
}
//当前枪 按下键盘r键
if (Input.GetButtonDown("Reload"))
{
//让当前枪换弹(调用FPSGun脚本)
currentGun.Reload();
}
//当前枪 按下键盘q键
if (Input.GetButtonDown("Switch"))
{
//切换枪
//第一步:先把当前枪设为非激活
currentGun.gameObject.SetActive(false);
//第二步:激活新枪
//下一把枪 ++index 使用前要先判断是否越界
index = ++index % managerdGuns.Count;
//更新当前枪
currentGun = managerdGuns[index];
//激活新枪
currentGun.gameObject.SetActive(true);
}
}
}
using UnityEngine;
public class PlayerAudioAndEffect : StateMachineBehaviour
{
public bool fire = true;
public bool reload = true;
//Animator播放动画的animator
//AnimatorStateInfo当前动画的状态信息
//layerIndex层号
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
FPSGun currentGun = animator.GetComponent<FPSGun>();
if (fire)
{
//获取开火声音
AudioClip fireClip = currentGun.fireClip;
//播放声音
AudioSource.PlayClipAtPoint(fireClip,animator.transform.position);
//播放特效
currentGun.PlayerFireEffect();
}
if (reload)
{
//获取换弹声音
AudioClip reloadClip = currentGun.reloadClip;
//播放声音
AudioSource.PlayClipAtPoint(reloadClip,animator.transform.position);
}
}
// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
//override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
// OnStateExit is called when a transition ends and the state machine finishes evaluating this state
//override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
// OnStateMove is called right after Animator.OnAnimatorMove(). Code that processes and affects root motion should be implemented here
//override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
// OnStateIK is called right after Animator.OnAnimatorIK(). Code that sets up animation IK (inverse kinematics) should be implemented here.
//override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
//
//}
}