Unity字符串性能问题

前言

分享一些通过书籍和网络学到的知识
每次动态创建一个string,C#都会在堆内存分配一个内存用来分配字符串,因为C#没有对字符串的缓存机制,会导致每次连接、切割、组合的时候都会申请新的内存,并且抛弃原来的内存,等待GC,而GC又会消耗很多CPU空间,例如对于a = “ax”; c = “b” + a + “c”,会造成一定程度的性能浪费。因为这里的+操作符是在运行时进行的,而不是在编译时。所以,每次+操作都会创建一个新的字符串对象,而不是改变原来的对象。这样就会产生两个无用的中间对象,“bax"和"baxc”,占用内存空间,如果不注意的话就会导致程序卡顿逐步增加,降低运行效率,有几种办法提高字符串效率,注意StringFormat和用+拼接还有$语法糖都会有一定效率问题,提高效率还是尽量用StringBuilder,但是为了可读性字符串比较短而且低频没必要的话就语法糖就好。

id-字符串字典池

自己建一个Key-字符串的缓存池,拼的时候从池子里面找减少GC
Dict<int,string>

Dictionary<int,string> strCache;
string strName = null;
if(!strCache.TryGetValue(id, out strName))
{
ResData resData = GetDataById(ID);
string strName = "This is " + resData,Name;
strCache.Add(id,strName);
}
return strName;

做一个定长的字符串池,用指针来拼接字符串

将指针指向目标字符串,把strA和strB分别拼在前置位和后置位,减少内存的分配和释放次数

public unsafe string Concat(string strA, string strB)  
{  
    int a_length = strA.Length;  
    int b_length = strB.Length;  
    int sum_length = a_length + b_length;  
    string strResult = null;  
    if (!cacheStr.TryGetValue(sum_length, out strResult))  
    // 如果不存在 sum_length 长度的缓存字符串,那么直接连接后存入缓存  
    {  
        strResult = strA + strB;        cacheStr.Add(sum_length, strResult);  
        return strResult;  
    }    //字符串再利用  
    fixed (char* strA_ptr = strA)  
    {        fixed (char* strB_ptr = strB)  
        {            fixed (char* strResult_ptr = strResult)  
            {                memcopy((byte*)strResult_ptr, (byte*)strA_ptr, a_length * sizeof(char));  
                memcopy((byte*)strResult_ptr+a_length,(byte*)strB_ptr,b_length * sizeof(char));  
            }        }    }    return strResult;  
}

memcopy函数

public unsafe void memcopy(byte* dest, byte* src, int len)  
{  
    while((--len)>=0)  
    {dest[len] = src[len];}}

StringBuilder

同样可以解决多次创建字符串反复拼接时候的GC问题,StringBuilder是可变的,也就是说它可以在原有的字符串上进行修改,而不需要创建新的字符串对象,这样可以节省内存空间和提高效率。StringBuilder支持链式调用,可以方便地进行多个字符串操作,例如builder.Append(“a”).Append(“b”).Append(“c”)。StringBuilder可以动态地调整其容量,当字符串长度超过当前容量时,它会自动扩展容量,而不会抛出异常。
缺点是tringBuilder是线程不安全的,也就是说在多线程环境下,如果多个线程同时对同一个StringBuilder对象进行修改,可能会导致数据不一致或者错误。StringBuilder的ToString方法需要遍历其内部的字符数组,将其拼接成一个新的字符串对象,这个过程可能会消耗一定的时间和资源。StringBuilder只会在toString时创建一次字符串,相比于之前的多次创建字符串给CPU性能压力减少很大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity中可以通过串口接收数据。首先,需要在Unity的脚本中引入System.IO.Ports库,该库提供了使用串口的相关功能。 首先,在脚本中定义一个SerialPort对象,用于与串口进行通信。可以通过指定串口的名称、波特率、数据位、校验位等参数来配置串口。 接下来,在需要接收数据的地方,使用SerialPort对象的ReadLine()方法读取串口接收到的数据。该方法会一直等待串口有数据可读并读取一行数据。 读取到的数据可以在Unity中进一步处理或展示,例如可以将数据显示在UI界面上、做数据分析或进行其他操作。 需要注意的是,在使用完毕后,要及时关闭串口,以免占用系统资源。可以使用SerialPort对象的Close()方法来关闭串口连接。 总结起来,Unity中通过引入System.IO.Ports库,配置和打开串口后,可以通过SerialPort对象的ReadLine()方法来接收来自串口的数据,并进行进一步的处理和展示。使用完毕后,要记得关闭串口连接。 ### 回答2: 在Unity中实现串口接收数据的方法如下: 1. 首先,在Unity中创建一个脚本,用于管理串口数据的接收和处理。 2. 在脚本中使用SerialPort类来打开串口。你需要指定串口名称和波特率。 3. 接下来,你可以使用SerialPort类的Read方法来读取串口数据。你可以选择在Update函数中不断读取数据,或者通过协程来进行读取。 4. 读取到的串口数据将以字节数组的形式返回。你可以使用Encoding类来将字节数组转换为字符串,以便进一步处理。 5. 在处理串口数据前,你可能需要对其进行一些预处理,例如去除空格或特殊字符,或者将数据转换为特定的格式。 6. 处理完数据后,你可以根据需要在Unity场景中进行相关操作,例如更新游戏对象的位置、状态等等。 7. 当你不再需要使用串口时,记得调用SerialPort类的Close方法来关闭串口连接,以释放资源。 需要注意的是,在使用串口接收数据时,要确保你的设备与电脑正确连接,并且串口名称和波特率设置正确。在测试时,可以使用调试工具或者其他串口通信软件模拟发送数据,以验证接收功能是否正常工作。此外,尽量避免在主线程中进行长时间的串口读取操作,以免影响游戏的帧率和响应性能。可以考虑使用线程或协程来实现串口数据的异步读取和处理。 ### 回答3: Unity是一种跨平台的游戏开发引擎,可以在不同操作系统进行开发。在Unity中,通过使用SerialPort类可以实现串口通信,并实现数据的接收。 首先,需要在Unity中引入System.IO命名空间,以便使用SerialPort类。接下来,创建一个SerialPort对象,指定串口号、波特率、数据位、停止位等参数。然后,调用SerialPort类的Open()方法打开串口。 为了接收数据,可以使用Unity的Update()函数来实现数据的实时接收。在Update()函数中,可以使用SerialPort类的ReadLine()方法或Read()方法来接收串口数据。ReadLine()方法会一次性读取一行数据,而Read()方法会读取指定长度的数据。 接收到的数据可以存储在一个字符串或字节数组中,然后可以对数据进行解析和处理。例如,可以将接收到的字符串转换成数字、判断特定的数据或命令等。 在整个过程中,需要注意处理好异常情况。在数据接收完毕后,务必调用SerialPort类的Close()方法来关闭串口。同时,在程序退出时,需要保证释放SerialPort对象的资源。 总之,Unity可以方便地实现串口数据的接收,通过使用SerialPort类,指定串口参数并调用相关函数即可。接收到的数据可以在Unity中进一步处理和应用。同时,需要注意异常处理和资源释放,以确保程序的正常运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值