简体   繁体   English

iPhone上不规则的iOS触摸率

[英]Irregular iOS Touch Rate on iPhone

I posted this question three days ago, but I received the feedback that the question was not clear so I would like to ask again.我三天前发了这个问题,但收到反馈说问题不清楚,所以我想再问一次。 Also, the scope of the problem has changed as I researched it further (no Unity issue!)此外,随着我进一步研究,问题的 scope 发生了变化(没有 Unity 问题!)

I'm making a game for iOS where you rotate an object left and right by touching the left or right side of the screen.我正在为 iOS 制作游戏,您可以通过触摸屏幕的左侧或右侧来左右旋转 object。 The Object rotates as long as the display is touched and stops rotating when the touch ends.只要触摸显示屏,Object 就会旋转,并在触摸结束时停止旋转。 When I run the game on an actual iPad/iPhone for a while every few touches the Rotation of the Objects stutters for about 2 seconds.当我在实际的 iPad/iPhone 上运行游戏一段时间时,每隔几次触摸对象的旋转就会卡顿约 2 秒。 This happends in about 5% of the touches.这发生在大约 5% 的触摸中。 All other touches work perfectly smooth.所有其他触摸都非常流畅。 All other Game Actions work fine at the set frame rate of 60 fps.所有其他游戏动作在设定的 60 fps 帧速率下都可以正常工作。 The only thing that doesn't move smoothly is the rotated object, while the rest of the game is all running perfectly smooth.唯一不流畅的是旋转的object,而游戏的rest都运行得非常流畅。 I tried to visualize the problem on the attached image.我试图在所附图像上可视化问题。 See here看这里

It visually looks like the Touch Refresh Rate is freezed for two seconds.它在视觉上看起来像触摸刷新率被冻结了两秒钟。

What may be the cause for this and how do I fix this?这可能是什么原因,我该如何解决?

I created the game with the game engine Unity.我使用游戏引擎 Unity 创建了游戏。 I use these versions: - Unity: 2019.3.15f1 - Xcode: 11 - Device: iPhone x - iOS Version: 13.5.1我使用这些版本: - Unity:2019.3.15f1 - Xcode:11 - 设备:iPhone x - iOS 版本:13.5.1

After a lot of research I found out, that this is not an issue related to Unity.经过大量研究后,我发现这与 Unity 无关。 Also, there is no issue when building the game on an Android device.此外,在 Android 设备上构建游戏时也没有问题。

Steps to reproduce:重现步骤:

int rotation
private void FixedUpdate(){

  for (int i = 0; i < Input.touchCount; i++)
        {
            Vector3 touchPos = Camera.main.ScreenToWorldPoint(Input.touches[i].position);
            if (touchPos.x < 0)
            {
                    rotation += 10;
            }
            else if (touchPos.x > 0)
            {
                    rotation -= 10;
            }
        }
        transform.Rotate(0, 0, rotation);
        rotation = 0;
}
  1. Coding the Touch Input via c# in Unity (see above)在 Unity 中通过 c# 对触摸输入进行编码(见上文)

  2. Building the Project on iOS Platform (creating an xcodeproject)在 iOS 平台上构建项目(创建 xcodeproject)

  3. Open the Project in XCode and running it on the iPhone打开 XCode 中的项目并在 iPhone 上运行

Does anybody have a solution for this?有人对此有解决方案吗?

Any "Input" class should be called in Update(), instead of FixedUpdate().任何“输入”class 都应该在 Update() 中调用,而不是在 FixedUpdate() 中调用。

The Input data loss is expected if you are trying to get them in FixedUpdate().如果您尝试在 FixedUpdate() 中获取输入数据,则预计会丢失输入数据。

Just for example, FixedUpdate can be execute twice in one frame, or skipped in one frame.例如,FixedUpdate 可以在一帧中执行两次,或者在一帧中跳过。 That's how it causes data lost or inaccurate.这就是它导致数据丢失或不准确的方式。

The proper solution will be sth like below.正确的解决方案将如下所示。

int rotation
private void Update()
{
    for (int i = 0; i < Input.touchCount; i++)
    {
        Vector3 touchPos = Camera.main.ScreenToWorldPoint(Input.touches[i].position);
        if (touchPos.x < 0)
        {
            rotation += 10 * time.deltaTime;
        }
        else if (touchPos.x > 0)
        {
            rotation -= 10 * time.deltaTime;
        }
    }
    transform.Rotate(0, 0, rotation);
    rotation = 0;
}

and please be noted that your current rotation direction is determined by a ray casting from camera.请注意,您当前的旋转方向是由相机的光线投射决定的。

If you want to rotate left/right by screen space, this should work better.如果您想按屏幕空间向左/向右旋转,这应该会更好。

private void Update()
{
    int rotation = 0;
    for (int i = 0; i < Input.touchCount; i++)
    {
        if (Input.touches[i].position.x < Screen.width/2)
        {
            rotation += 10 * time.deltaTime;
        }
        else
        {
            rotation -= 10 * time.deltaTime;
        }
    }
    transform.Rotate(0, 0, rotation);
}

In general, I prefer a simple rotation script by checking last touch.一般来说,我更喜欢通过检查最后一次触摸来使用简单的旋转脚本。

private void Update()
{
    if(Input.touchCount > 0)
    {
        if (Input.touches[Input.touchCount-1].position.x < Screen.width/2)
        {
            transform.Rotate(0, 0, 10f * time.deltaTime);
        }
        else
        {
            transform.Rotate(0, 0, -10f * time.deltaTime);
        }
    }
}

Or, if you really want to sync the input with FixedUpdate(), you can do sth like below.或者,如果你真的想用 FixedUpdate() 同步输入,你可以像下面那样做。

bool HasTouch = false;
float SpeedRot = 0;
private void Update()
{
    if(Input.touchCount > 0)
    {
        HasTouch = true;
        if (Input.touches[Input.touchCount-1].position.x < Screen.width/2)
        {
            SpeedRot = 10f;
        }
        else
        {
            SpeedRot = -10f;
        }
    }
    else
    {
        HasTouch = false;
    }
}

private void FixedUpdate()
{
    if(HasTouch) transform.Rotate(0, 0, SpeedRot * Time.fixedDeltaTime);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM