【Unity3d开发笔记】FPS 声源:移动&跳跃&着地&射击的声音逻辑
FPS游戏中基本的声源包括
位移(
移动 +
跳跃 +
着地)和
射击。处理好它们的关键在于播放音源的时机,以下是个人的一种处理思路。
【实现思路】
- 给角色装配两个声源AudioSource,一个用于处理枪声(
fireSource
),另一个处理位移(stepSource
) - 对于枪声的音源,只需在按下射击键并且射击成立时播放即可
- 对于位移的音源,由于跳跃和着地的频率相对移动低很多,因此我们可以将前两者的优先级设置得更高,这意味着在跑动时若按下跳跃键,则跳跃声会覆盖跑动声,处理方法是在移动音源播放的判断加个
if(!audio2.isPlaying)
的条件,借此降低其优先级。 - 处理在空中的状态,在空中玩家很可能按移动键,也可能按下跳跃键,这些情况下是不能播放相应声音的,而且还得添加个“落地”判断,以在着地时播放着地音效
- 落地判断使用了
Physics.CheckSphere(...)
函数,用一个无形小球放在脚底来与地面相交,看是否碰撞,以此来确定是否着地 - 注意:下面代码中使用了是否着地(
isGrounded
)与是否在空中(isOnJumping
)两个布尔变量,看似两个意义没区别,但是由于实现情况不同,两个变量代表的意义是有很大差别的; - 下面代码前两个判断(判断1和判断2)条件的顺序是不能换的!!因此,需要注意每一个判断的先后顺序。
【相关代码】
以下省去了无关音频的代码,由于枪声的音源处理独立于位移,比较容易,因此下面代码没有涉及枪声音源,重点关注声源播放的判断条件。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : BasePlayer {
private Animator anim; //动画
[HideInInspector]
public Vector3 moveY = Vector3.zero; //移动速度
private bool isGrounded = true;//着地检测
private bool isOnJumping = false; //在跳跃过程中 (空中)
private float groundDistance = 0.2f; //着地碰撞检测球形半径
[SerializeField]
private LayerMask groundMask;
public AudioClip[] stepClips = new AudioClip[3]; //脚步声
[SerializeField]
private AudioSource stepSource; //位移声源
enum AudioType //位移音乐枚举
{
Step = 0,
Jump = 1,
Land = 2
}
void Start()
{
anim = GetComponent<Animator>();
groundCheckPos = transform.Find("Root_LocPos"); //找到脚跟
}
void Update()
{
//。。。一些无关于音频的逻辑
//地面检测
isGrounded = Physics.CheckSphere(groundCheckPos.position,
groundDistance, groundMask);
if (isGrounded && isOnJumping) //判断 1
{
stepSource.PlayOneShot(stepClips[(int)AudioType.Land]);
Debug.Log("Landed");
}
if (isGrounded && moveY.y < 0) //判断 2
{
//Debug.Log("isGrounded");
moveY.y = -2f;
isOnJumping = false;
}
else if (!isGrounded)
{
if (!anim.IsInTransition(0))
{
anim.SetBool("isJumping", false);
}
}
//跳跃
if (Input.GetButtonDown("Jump") && isGrounded)
{
isOnJumping = true;
//。。。。
if (!anim.IsInTransition(0))
{
anim.SetBool("isJumping", true);
stepSource.PlayOneShot(stepClips[(int)AudioType.Jump]);
}
}
//处理平面移动
float _xMov = Input.GetAxis("Horizontal");
float _zMov = Input.GetAxis("Vertical");
if (isMoving(_xMov, _zMov)) //移动时播放脚步声
{
if (!stepSource.isPlaying && !isOnJumping)
{
stepSource.PlayOneShot(stepClips[(int)AudioType.Step]);
}
}
// 其余代码
}
//是否在跑动
bool isMoving(float horz, float vert)
{
return horz != 0|| vert != 0;
}
//其余代码
}
本人只是个Unity3d萌新,如果以上描述有啥不妥之处或者有其他不错的思路也欢迎各位大佬们留言分享~