C# 使用shift键从x-y尺寸更改为x-z尺寸以进行拖动-输入延迟问题

C# 使用shift键从x-y尺寸更改为x-z尺寸以进行拖动-输入延迟问题,c#,.net,unity3d,graphics,3d,C#,.net,Unity3d,Graphics,3d,作为我项目的一部分,我开发了一个用户可以使用鼠标移动的球体。由于一次只能考虑两个维度,所以我开发了一种机制,将x-y平面上的拖动更改为x-z平面上的拖动,反之亦然。但是,该程序绝对不是用户友好的,因为在二维平面(即:x-y平面或x-z平面)上拖动时很难控制三维空间中的对象。由于存在严重的输入延迟问题,这一问题只会变得更糟。并不是每按一次shift键就可以换飞机,而且我经常必须多次按shift键才能换飞机 我已尝试将OnMouseDrag()调用的位置更改为update()方法中的不同位置。 这不

作为我项目的一部分,我开发了一个用户可以使用鼠标移动的球体。由于一次只能考虑两个维度,所以我开发了一种机制,将x-y平面上的拖动更改为x-z平面上的拖动,反之亦然。但是,该程序绝对不是用户友好的,因为在二维平面(即:x-y平面或x-z平面)上拖动时很难控制三维空间中的对象。由于存在严重的输入延迟问题,这一问题只会变得更糟。并不是每按一次shift键就可以换飞机,而且我经常必须多次按shift键才能换飞机

我已尝试将OnMouseDrag()调用的位置更改为update()方法中的不同位置。 这不起作用

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

[RequireComponent(typeof(MeshCollider))]

public class UserController : MonoBehaviour
{


bool shiftOn = false;

void OnMouseDrag()
{

    if (Input.GetMouseButton(0))
    {
        if (shiftOn)
        {
            //3D Drag, courtesy of Unity Forums
            float distance_to_screen = Camera.main.WorldToScreenPoint(gameObject.transform.position).z;
            transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance_to_screen));
        }

        else
        {
            //Plane Drag
            float distance_to_screen = Camera.main.WorldToScreenPoint(gameObject.transform.position).z;
            Vector3 pos_move = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance_to_screen));
            transform.position = new Vector3(pos_move.x, transform.position.y, pos_move.z);
        }



    }

}

void changeShift()
{
    shiftOn = !shiftOn;
}

// Update is called once per frame
void Update()
{

    if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
    {
        changeShift();
    }
    OnMouseDrag();



}



}
输入延迟仍然存在。轮班通话通常不注册,我必须按多次。在尝试切换维度时,我很容易失去对球体的控制

如何消除这种输入延迟?有没有更好的处理方法?有没有一种方法可以让你在一次控制所有三维空间的同时,用鼠标拖动三维空间中的对象

欢迎所有回复

非常感谢您的阅读,我期待着您的建议。

如您所知,
Update()
每帧调用一次

因此,当按住shift键时,在每个帧中,
shiftOn
的值会因函数
changeShift()
而改变。因此,如果25/2中有25fps,则没有
shiftOn=true
,因此,对象移动可能会有一些延迟或延迟

因此,我建议您如下更改代码:

void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftShift))
    {
        Debug.Log("Shift Pressed"); //Logs message to the Unity Console.
        shiftOn = true;
    }

    if (Input.GetKeyUp(KeyCode.LeftShift))
    {
        Debug.Log("Shift Released"); //Logs message to the Unity Console.
        shiftOn = false;
    }
}

根据评论进行更新

我认为,为了使对象的移动稍微平滑,您应该将OnMouseDown事件与OnMouserDrag分开。我的意思是,您应该计算
OnMouseDown
内的初始位置,并计算
OnMouseDrag
内的距离和当前位置,以便更新代码如下:

Vector3 Dist;
float PosX;
float Posy; 
void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftShift))
    {
        Debug.Log("Shift Pressed");
        shiftOn = true;
    }

    if (Input.GetKeyUp(KeyCode.LeftShift))
    {
        Debug.Log("Shift Released");
        shiftOn = false;
    }
}

private void OnMouseDown()
{
    if(!shiftOn)
    {
        Dist = Camera.main.WorldToScreenPoint(transform.position);
        PosX = Input.mousePosition.x - Dist.x;
        PosY = Input.mousePosition.y - Dist.y;
    }
}

private void OnMouseDrag()
{
    if(!shiftOn)
    {
        Vector3 CurrentPos = new Vector3(Input.mousePosition.x - PosX, Input.mousePosition.y -PosY, Dist.z);
        Vector3 WorldPos = Camera.main.ScreenToWorldPoint(CurrentPos);
        transform.position = WorldPos;
    }
}
请注意,我编写的示例用于在2D中移动对象,请将其更改为在3D中使用。

正如您所知,
Update()
每帧调用一次

[RequireComponent(typeof(MeshCollider))]
public class UserController : MonoBehaviour
{
    private Vector3 Dist;
    private float PosX = 0.0f;
    private float PosY = 0.0f;
    private float PosZ = 0.0f;
    private bool shiftOn = false;

    private void OnMouseDown()
    {
        Dist = Camera.main.WorldToScreenPoint(transform.position);
        PosX = Input.mousePosition.x - Dist.x;
        PosY = Input.mousePosition.y - Dist.y;
        PosZ = Input.mousePosition.z - Dist.z;
    }
    private void OnMouseDrag()
    {
        if (Input.GetMouseButton(0))
        {
            if (shiftOn) // 3D drag
            {
                transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - PosX, Input.mousePosition.y - PosY, Input.mousePosition.z - PosZ));
            }
            else
            {
                //Plane Drag
                Vector3 pos_move = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - PosX, Input.mousePosition.y - PosY, Input.mousePosition.z - PosZ));
                transform.position = new Vector3(pos_move.x, transform.position.y, pos_move.z);
            }
        }
    }

    // Update is called once per frame
    private void Update()
    {

        if (Input.GetKeyDown(KeyCode.LeftShift)||Input.GetKeyDown(KeyCode.RightShift))
        {
            Debug.Log("Shift Pressed"); //Logs message to the Unity Console.
            shiftOn = true;
        }

        if (Input.GetKeyUp(KeyCode.LeftShift) || Input.GetKeyUp(KeyCode.RightShift))
        {
            Debug.Log("Shift Released"); //Logs message to the Unity Console.
            shiftOn = false;
        }
    }
因此,当按住shift键时,在每个帧中,
shiftOn
的值会因函数
changeShift()
而改变。因此,如果25/2中有25fps,则没有
shiftOn=true
,因此,对象移动可能会有一些延迟或延迟

因此,我建议您如下更改代码:

void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftShift))
    {
        Debug.Log("Shift Pressed"); //Logs message to the Unity Console.
        shiftOn = true;
    }

    if (Input.GetKeyUp(KeyCode.LeftShift))
    {
        Debug.Log("Shift Released"); //Logs message to the Unity Console.
        shiftOn = false;
    }
}

根据评论进行更新

我认为,为了使对象的移动稍微平滑,您应该将OnMouseDown事件与OnMouserDrag分开。我的意思是,您应该计算
OnMouseDown
内的初始位置,并计算
OnMouseDrag
内的距离和当前位置,以便更新代码如下:

Vector3 Dist;
float PosX;
float Posy; 
void Update()
{
    if (Input.GetKeyDown(KeyCode.LeftShift))
    {
        Debug.Log("Shift Pressed");
        shiftOn = true;
    }

    if (Input.GetKeyUp(KeyCode.LeftShift))
    {
        Debug.Log("Shift Released");
        shiftOn = false;
    }
}

private void OnMouseDown()
{
    if(!shiftOn)
    {
        Dist = Camera.main.WorldToScreenPoint(transform.position);
        PosX = Input.mousePosition.x - Dist.x;
        PosY = Input.mousePosition.y - Dist.y;
    }
}

private void OnMouseDrag()
{
    if(!shiftOn)
    {
        Vector3 CurrentPos = new Vector3(Input.mousePosition.x - PosX, Input.mousePosition.y -PosY, Dist.z);
        Vector3 WorldPos = Camera.main.ScreenToWorldPoint(CurrentPos);
        transform.position = WorldPos;
    }
}

请注意,我写的示例是在2D中移动对象,请将其更改为在3D中使用。

感谢您,穆罕默德!控制仍然非常困难,因为球体经常移动得太快,但至少延迟问题得到了解决。@IDebarshi如果对您有帮助,您可以接受答案。(通过单击答案左侧VoteUp/Down上的勾号)。还有,谢谢你,穆罕默德!我想给你看我的代码。我认为您的解决方案有效,但我不能完全确定我是否正确实施了它。@IDebarshi您正在计算
OnMouseDown
中的初始位置,即
Dist
PosX
PosY
PosZ
。然后在
OnMouseDrag
中,您应该使用这些点并计算移动距离。我看不到这些变量在代码中的用法。请使用我的完整示例,看看它是否适用于2D模式。请仔细阅读。我看到了你的代码,请从答案中删除,因为它不起作用,穆罕默德,只是更新了它。它看起来平滑多了。非常感谢你!谢谢你,穆罕默德!控制仍然非常困难,因为球体经常移动得太快,但至少延迟问题得到了解决。@IDebarshi如果对您有帮助,您可以接受答案。(通过单击答案左侧VoteUp/Down上的勾号)。还有,谢谢你,穆罕默德!我想给你看我的代码。我认为您的解决方案有效,但我不能完全确定我是否正确实施了它。@IDebarshi您正在计算
OnMouseDown
中的初始位置,即
Dist
PosX
PosY
PosZ
。然后在
OnMouseDrag
中,您应该使用这些点并计算移动距离。我看不到这些变量在代码中的用法。请使用我的完整示例,看看它是否适用于2D模式。请仔细阅读。我看到了你的代码,请从答案中删除,因为它不起作用,穆罕默德,只是更新了它。它看起来平滑多了。非常感谢你!
[RequireComponent(typeof(MeshCollider))]
public class UserController : MonoBehaviour
{
    private Vector3 Dist;
    private float PosX = 0.0f;
    private float PosY = 0.0f;
    private float PosZ = 0.0f;
    private bool shiftOn = false;

    private void OnMouseDown()
    {
        Dist = Camera.main.WorldToScreenPoint(transform.position);
        PosX = Input.mousePosition.x - Dist.x;
        PosY = Input.mousePosition.y - Dist.y;
        PosZ = Input.mousePosition.z - Dist.z;
    }
    private void OnMouseDrag()
    {
        if (Input.GetMouseButton(0))
        {
            if (shiftOn) // 3D drag
            {
                transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - PosX, Input.mousePosition.y - PosY, Input.mousePosition.z - PosZ));
            }
            else
            {
                //Plane Drag
                Vector3 pos_move = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - PosX, Input.mousePosition.y - PosY, Input.mousePosition.z - PosZ));
                transform.position = new Vector3(pos_move.x, transform.position.y, pos_move.z);
            }
        }
    }

    // Update is called once per frame
    private void Update()
    {

        if (Input.GetKeyDown(KeyCode.LeftShift)||Input.GetKeyDown(KeyCode.RightShift))
        {
            Debug.Log("Shift Pressed"); //Logs message to the Unity Console.
            shiftOn = true;
        }

        if (Input.GetKeyUp(KeyCode.LeftShift) || Input.GetKeyUp(KeyCode.RightShift))
        {
            Debug.Log("Shift Released"); //Logs message to the Unity Console.
            shiftOn = false;
        }
    }