如何在Unity 3D中平滑加速度计和方向传感器的值?

3
我正在开发一款桌面游戏,使用手机作为控制器。该游戏是用Unity 3D开发的,并使用SensoDuino Android应用程序通过蓝牙发送加速度计和方向传感器值。这些值以100毫秒的频率发送。但是,手机移动与其在游戏中的反映之间存在延迟。如何减少延迟并将运动映射到1:1比例,而不会出现任何抖动或跳跃。以下是我正在使用的代码 -
串口连接后,使用以下代码从端口读取数据。
void recData() {
    if ((sp != null) && (sp.IsOpen)) {
        byte tmp;
        string data = "";
        string avalues="";
        tmp = (byte) sp.ReadByte();
        while(tmp !=255) {
            data+=((char)tmp);
            tmp = (byte) sp.ReadByte();
            if((tmp=='>') && (data.Length > 30)){
                avalues = data;
                parseValues(avalues);
                data="";
            }
        }
    }
}

由于Unity不允许从另一个主线程访问主线程上的对象,因此我在parseValues()中设置了一个布尔变量moveObject = true(将传入的字符串转换为浮点数)。在Update()函数中检查此布尔值,如果为true,则使用以下函数移动对象。

void moveObj(float x, float y) {
        speed = 15.0f;
        Vector3 move = Vector3.zero ;
        move.x = x;
        move.y = y;
        move.Normalize();
        // low pass filter
        prevY = (0.8f * prevY) + ((1.0f - 0.8f) * move.y);
        prevX = (0.8f * prevX) + ((1.0f - 0.8f) * move.x);

        transform.Translate((-prevX * speed) * Time.deltaTime,(prevY * speed)* Time.deltaTime, -0.1f, Space.World);
        readyToMove = false;

我尝试使用简单的低通滤波器来平滑数值并使用translate移动物体。问题是没有1:1的运动映射,即存在延迟。如何解决这个问题?如何从另一个线程访问主线程中的对象?


你尝试过一阶滤波器吗? - UserK
1个回答

1
为了解决“卡顿”的问题,您可以使用现有的插值函数。
Vector3.SmoothDamp(transform.position, targetPosition, velocity, time);

替代方案:

Vector3.MoveTowards(start.position, end.position, time);
Vector3.Lerp(start.position, end.position, time);

是因为移动吗?还是因为蓝牙数据速率与Unity的60fps异步?所以标志在“update()”中被检查,因此每秒只检查60次。如果蓝牙每秒发送更多数据会怎样呢?会更流畅吧?如果我将移动代码放在线程中,就会出现主线程错误。 - dil33pm
我对Unity上的串口不是很熟悉,但你可能是对的。串口的波特率是多少?你试过增加它吗? - Seb B.
我试了9600,也试过了19200。如果我能够从另一个线程中调用Unity API就好了...只要有一个免费的插件就好了 :( - dil33pm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接