【unity】麦克风声音驱动,控制身体做出不同动作

发布时间:2024年01月17日

1.在角色对象上挂在animator组件,并将动作控制器与其关联
在这里插入图片描述
2.在角色对象上挂在audio source组件。
3.新建voice control脚本,编写代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Animations;
public class VoiceControl : MonoBehaviour
{
    public Animator animator;
    public float volumeThreshold = 0f; // 调整为一个更合理的阈值
    private string talkingParamName = "Talk";
    public AudioSource audioLocal;
    private string device;
    private IEnumerator coroWaitMic;
    private const float coroutineLoggingIfDebug = 5f; // debug log ERROR every 5 seconds while audiodevice error
    const int loopLength = 5;
    const int sampleRate = 16000;
    // Start is called before the first frame update
    void Start()
    {
        // 设置初始动画状态为NotTalking
        
        audioLocal = GameObject.Find("xiaoyang").GetComponent<AudioSource>(); // 1 定位本地音频设备audioLocal
        if (Microphone.devices.Length <= 0)
        {
            Debug.LogError("没有麦克风或麦克风权限未打开");
            throw new Exception("没有麦克风或麦克风权限未打开");
        }
        else
        {
            device = Microphone.devices[0];//获取麦克风名 
        }
        StartMicrophone(device);
        animator.SetBool(talkingParamName, false);
    }
    // Update is called once per frame
    void Update()
    {
        float currentVolume = GetAverageAmplitude();
        Debug.Log($"Current Average Amplitude: {currentVolume}, Volume Threshold: {volumeThreshold}");
        // 根据音量大小切换Talk参数和动画状态
        // 根据当前音量大小决定是否切换动画状态
        if (currentVolume > volumeThreshold)
        {
            animator.SetBool("Talk", true);
            Debug.Log("true执行");
        }
        else
        {
            animator.SetBool("Talk", false);
            Debug.Log("false执行");
        }
    }
    private void StartMicrophone(string mic)
    {
        // Start and wait for the microphone to start recording data
        if (coroWaitMic != null)
            StopCoroutine(coroWaitMic);
        coroWaitMic = WaitForMic(device);
        StartCoroutine(coroWaitMic);
    } // end StartMicrophone()
    IEnumerator WaitForMic(string mic)
    {
        float timeCheck = Time.time;
        if (audioLocal == null)
        {
            Debug.LogWarning("[WaitForMic()] - AudioSource is not present...bailing...");
            yield break;
        }
        audioLocal.clip = Microphone.Start(mic, true, loopLength, sampleRate);
        // Let the Microphone start filling the buffer prior to activating the AudioSource.
        while (!(Microphone.GetPosition(mic) > 0))
        {
            if (Time.time - timeCheck > coroutineLoggingIfDebug)
            {
                Debug.Log("[WaitForMic()] - is waiting for the mic to record.");
                timeCheck = Time.time;
            }
            // Wait for Microphone to start gathering data.
            yield return null;
        }
        audioLocal.Play();
        audioLocal.loop = true;
    } // end WaitForMic() 录音设备开始录音


    private float GetAverageAmplitude()
    {
        float[] data = new float[sampleRate]; // 假设每次读取sampleRate个样本数据,实际项目中可以根据需要调整
        audioLocal.clip.GetData(data, 0); // 获取麦克风实时输入的数据

        float sumOfSquares = 0f;
        for (int i = 0; i < data.Length; i++)
        {
            float sampleValue = Mathf.Abs(data[i]); // 取绝对值计算振幅
            sumOfSquares += Mathf.Pow(sampleValue, 2); // 将样本平方累加,用于计算均方根(RMS)
        }
        float averageAmplitude = Mathf.Sqrt(sumOfSquares / data.Length); // 计算均方根得到平均振幅大小
        Debug.Log($"Current Average Amplitude: {averageAmplitude}, Volume Threshold: {volumeThreshold}");
        return averageAmplitude;
    }
}

4.将动作控制器关联到脚本上
在这里插入图片描述
5.设置音量阈值,使得当达到某个音量值时切换动画
在这里插入图片描述
6.在动作控制器中设置不同的动作状态
(1)添加没说话时和说话时的状态并添加自循环,使动作能够重复播放
在这里插入图片描述
(2)新建布尔参数,用于控制状态
在这里插入图片描述
(3)设置Notalking→talking过渡动画的属性和出发布尔值的条件
在这里插入图片描述
(4)设置talking→Notalking过渡动画的属性和出发布尔值的条件
在这里插入图片描述

文章来源:https://blog.csdn.net/yljwhat/article/details/135657932
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。