sapi语音朗读的简单用法(Unity中)

运行环境:win10, Unity5.6.2f1/Unity2018.2.6f1(两个版本都试了,可以)

using SpeechLib;

//...
    SpVoice voice = new SpVoice();

书接上文Unity中使用Windows的sapi进行语音朗读
上文例子中的代码只是最最简单的使用方法,实际用时是有问题的。
这样直接

voice.Speak(str);

如上简单粗暴的使用,会卡住当前Unity程序的主线程,在朗读完毕之前会一直卡,包括关闭Unity程序,也还是会一直读完内容

首先解决卡主线程的问题
自然就想到了开子线程

Thread t=new Thread(()=>{
    voice.Speak(str);
});
t.Start();

这样让它朗读文字,的确不卡主线程了
但是,关闭Unity程序时,依然还是会一直读完内容

那好,在关闭时先让voice停止

private void OnApplicationQuit()
{
    voice.Pause();
}

的确有用,关程序时,马上就不朗读了,但是,程序会卡住一会儿,才会关闭。

所以还是有问题

最终解决方案:

  1. 不需要开子线程
  2. 根据我的需求,不需要暂停,只要停止,那么不用voice.Pause()了

代码:

  1. 朗读停止

    voice.Speak(string.Empty, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);

    执行上面语句,朗读即刻停止,在程序关闭时可调用上述语句,比如加在OnApplicationQuit()方法中。

2.不开子线程,使朗读不卡

voice.Speak(str, SpeechVoiceSpeakFlags.SVSFlagsAsync);

所以说voice.Speak方法,用两个参数的,第二个参数非常重要

SVSFPurgeBeforeSpeak

如果正在朗读,则停止,然后朗读当前的内容

SVSFlagsAsync

这个看名字就知道,异步,不会卡主线程。

这样一来,不用开子线程直接异步朗读,不卡主线程,而且可以随时停止,实测关闭Unity程序(发布出的Windows端程序)时也不会卡住,立即关闭

原文地址:https://blog.51cto.com/shuxiayeshou/2366405

时间: 2024-11-09 00:10:05

sapi语音朗读的简单用法(Unity中)的相关文章

3D语音天气球——在Unity中使用Android语音服务

转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 这个项目准备分四部分介绍: 一:创建可旋转的"3D球":3D语音天气球(源码分享)--创建可旋转的3D球 二:通过天气服务,从网络获取时实天气信息并动态生成"3D球":3D语音天气球(源码分享)--通过天气服务动态创建3D球 三:Android语音服务和Unity的消息传递 四:Unity3D端和Android端的结合 前两篇文章已经介绍了如何创

Android中资源文件中的字符串数组string-array简单用法

在Android中,用string-array是一种简单的提取XML资源文件数据的方法. 例子如下: 把相应的数据放到values文件夹的strings.xml文件里,或是其他自定义的xml中都可以,以下操作方法相同. <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="sports"> <item>足球<

java中Object.equals()简单用法

/* equals()方法默认的比较两个对象的引用! */ class Child { int num; public Child(int x){ num = x; } //人文的抛出运行时异常的好处是:可以自定义错误信息! /*public boolean equals(Object o) throws ClassCastException{ if(!(o instanceof Child)) throw new ClassCastException("中文提示:类型错误"); Ch

unity中简单的血条自作

unity中制作血条有很多方法,多数用NGUI:这里我就说说一个简单的血条制作方法吧: 这个血条制作不像NGUI一样,它是靠一段代码就可以实现的,但看起来比较效果比较差,还是看代码吧:  public Texture2D bg;     //血条的背景,需要在外面进行拖拽赋值:  public Texture2D blood;   //血条  float Life=100;            //总的生命值:    public Transform m_Transform;  //绑定血条的

Android中AsyncTask的简单用法【转】

在开发Android移动客户端的时候往往要使用多线程来进行操作,我们通常会将耗时的操作放在单独的线程执行,避免其占用主线程而给用户带来不好的用户体验.但是在子线程中无法去操作主线程(UI 线程),在子线程中操作UI线程会出现错误.因此android提供了一个类Handler来在子线程中来更新UI线程,用发消息的机制更新UI界面,呈现给用户.这样就解决了子线程更新UI的问题.但是费时的任务操作总会启动一些匿名的子线程,太多的子线程给系统带来巨大的负担,随之带来一些性能问题.因此android提供了

非常简单的语音朗读功能

不知道大家有没有发现,在System.Speech.Synthesis命名空间下有一个SpeechSynthesizer类,它可以指定的文本内容进行语音朗读,而且,这个类用起来也严重简单,简单到什么程度? 试试看. 首先,新建一个项目,随便你建什么项目,反正能测试即可. 然后,添加对System.Speech程序集的引用. 引入System.Speech.Synthesis命名空间,最后,看好了,几行代码搞定. private void button1_Click(object sender,

从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能讲讲其用法: 1.sort入门: 使用sort需要包含algorithm头文件,完整代码如下 #include<iostream> #include<vector> #include<algorithm>//貌似可以不用,但最好加上. using namespace std

IOS 中block结构的简单用法

自从block出现之后,很多API都开始采用这样的结构,由此可见,block确实有许多优势存在,这里将一些简单用法总结如下: 一.如何声明一个block变量 我们通过^符号来声明block类型,形式如下: void (^myBlock)(); 其中第一个void是返回值,可以是任意类型,中间括号中^后面的是这个block变量的名字,我把它命名为myBlock,最后一个括号中是参数,如果多参数,可以写成如下样式: int (^myBlock)(int,int); 同样,你也可以给参数起名字: in

在Unity中实现简单的伪时间同步

在Unity中实现简单的伪时间同步,只是读取数据库所在电脑的当前时间 代码如下: using UnityEngine; using System.Collections; using System.Runtime.InteropServices; using System.Data; using System.Data.SqlClient; public class ChangeTime { //Kernel32.dll在32位系统和64位系统有区别,64位系统中需要设置为以管理员身份运行 [D