FPS项目脚步声——Unity随手记(2021.1.22)

今天实现的内容:

制作脚步声,学习了一下ScriptableObject的原理。脚本声音资源采用ScriptableObject的方式储存应用。当角色着地并正在发生位移时,播放脚步声。

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

[CreateAssetMenu(menuName = "FPS/Footstep Audio Data")]
public class FootstepAudioData : ScriptableObject
{
    
    
    public List<FootstepAudio> footstepAudios = new List<FootstepAudio>();
}

[System.Serializable]
public class FootstepAudio
{
    
    
    // 用于标记踩在什么表面上
    public string Tag;
    // 声音片段列表
    public List<AudioClip> AudioClips = new List<AudioClip>();
    // 声音间隔
    public float walkVoiceInterval;
    //public float sprintingVoiceInterval;
    //public float CrouchingVoiceInterval;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerFootstepListener : MonoBehaviour
{
    
    
    public FootstepAudioData footstepAudioData;
    public AudioSource footstepAudioSource;

    private CharacterController characterController;
    private Transform footstepTransform;
    private float timePassed = 0;
    private FPCharacterControllerMovement movement;

    // 角色移动或者发生较大幅度位移时 播放脚步声
    // 根据角色踩踏的不同材质播放不同的声音
    // 具体实现方式采用Physics API

    private void Start()
    {
    
    
        characterController = GetComponent<CharacterController>();
        footstepTransform = transform;
        movement = GetComponent<FPCharacterControllerMovement>();
    }

    private void FixedUpdate()
    {
    
    
        // 角色处于地面
        if(characterController.isGrounded)
        {
    
    
            // 角色正在移动
            if(characterController.velocity.normalized.sqrMagnitude > 0.1f)
            {
    
    
                // 设置下一次播放的时间
                timePassed += Time.deltaTime;

                // 播放移动声音
                if(Physics.Linecast(footstepTransform.position,
                    footstepTransform.position + Vector3.down * characterController.height,
                    out RaycastHit temp_hitInfo)) //检测当前踩踏在什么地面上
                {
    
    
                    #if UNITY_EDITOR
                    Debug.Log(temp_hitInfo.collider.tag);
                    Debug.DrawRay(footstepTransform.position,
                    -footstepTransform.up * characterController.height, Color.red);
                    #endif

                    // 对于所有类型的脚步声
                    foreach (var temp_audioElement in footstepAudioData.footstepAudios)
                    {
    
    
                        // 找到匹配的类型
                        if (temp_hitInfo.collider.CompareTag(temp_audioElement.Tag))
                        {
    
    
                            // 用于保存实际要用的声音播放间隔
                            float temp_VoiceInterval = 0;
                            if (movement.m_isSprinting && movement.m_isCrouched) //是否在蹲下时冲刺
                            {
    
    
                                temp_VoiceInterval = temp_audioElement.walkVoiceInterval;
                            }
                            else if(movement.m_isCrouched) //是否蹲下
                            {
    
    
                                temp_VoiceInterval = temp_audioElement.walkVoiceInterval * 2;
                            }
                            else if (movement.m_isSprinting) //是否在冲刺
                            {
    
    
                                temp_VoiceInterval = temp_audioElement.walkVoiceInterval / 2;
                            }
                            else // 那就只是在走了
                            {
    
    
                                temp_VoiceInterval = temp_audioElement.walkVoiceInterval;
                            }
                            Debug.Log(temp_VoiceInterval);
                            // 如果到了下一次播放时间
                            if (timePassed >= temp_VoiceInterval)
                            {
    
    
                                // 获取这个类型脚步声的素材总数
                                int temp_audioCount = temp_audioElement.AudioClips.Count;
                                // 随机获取一个
                                int temp_audioIndex = UnityEngine.Random.Range(0, temp_audioCount);
                                // 获取到对应的声音片段
                                AudioClip temp_footstepAudioClip = temp_audioElement.AudioClips[temp_audioIndex];
                                // 播放音效
                                footstepAudioSource.clip = temp_footstepAudioClip;
                                footstepAudioSource.Play();
                                timePassed = 0;
                                // 找到了就行了 直接跳出循环
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

}

FootstepAudioData负责用于生成存储音效资源的ScriptableObject,PlayerFootstepListener用于角色所处地面的判断,找到对应的音效,随机获取音效,并播放音效。音效有播放间隔,来勉强达到听起来还算真实的效果吗,还实现了不同的运动状态对应不同的音效播放间隔。

效果:移动时的脚步声以及BUG


BUG以及缺陷:

有时会莫名其妙的检测不出地面的Tag。但其实是我的射线检测写错了,检测的end点应该为角色往下的点,而不是原点往下。以上代码以改正为正确的。
蹲下时没有脚步声了。应该是射线检测不到地面了。
最大的缺陷,这个音效真的很难听,算了,学会功能的实现就好。


值得注意的:

如何判断移动状态?我直接引用了之前的移动控制脚本,脚本中有描述运动状态的bool值,这一点和老师做的不一样。


猜你喜欢

转载自blog.csdn.net/qq_37856544/article/details/112993447
今日推荐