使用光线投射拖动对象是滞后的

Dragging an object with raycast is laggy

当使用光线投射缓慢拖动对象时,对象移动时会有一点滞后。

快速拖动对象时,鼠标指针会超出图层光线投射范围,因此对象不再移动。

主要项目是在平面上拖动立方体。

但是为了使项目更简单,我打开了一个新的 2D 项目并做了一个圆并为其分配了以下脚本,并附加了一个球体碰撞器(主要目标是 3D space).

// If some one wrote:
private Vector2 deltaPos;
    void Update () {
        Vector2 touchPos;
        if (Input.GetMouseButtonDown (0)) {                                                     // Clicking the Target              
            RaycastHit hit;
            var ray = Camera.main.ScreenPointToRay (Input.mousePosition);

            if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {

                touchPos = new Vector3 (hit.point.x, hit.point.y);
                deltaPos.x = touchPos.x - transform.position.x;
                deltaPos.y = touchPos.y - transform.position.y;
                Debug.Log ("You Clicked Me");
            }
        }
        if (Input.GetMouseButton (0)) {
            RaycastHit hit;
            var ray = Camera.main.ScreenPointToRay (Input.mousePosition);

            if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
                transform.position = new Vector2 (hit.point.x - deltaPos.x, hit.point.y - deltaPos.y);
            }
        }
    }

本想有规律地拖动球体,结果是快速移动时指针超出了球体碰撞器,因此圆圈停止移动。

我找到了这个 article,然后我将 void 从 Update() 更改为 FixedUpdate(),但结果相同。

尝试将物理代码放入为物理计算构建的 FixedUpdate() 函数中。然后如果它很慢,你可以在物理设置中更改Fixed Timestep

Fixed Timestep: A framerate-independent interval that dictates when physics calculations and FixedUpdate() events are performed. https://docs.unity3d.com/Manual/class-TimeManager.html

编辑

此代码:

if (Physics.Raycast (ray, out hit, Mathf.Infinity))

检查光线投射是否击中了什么东西,因此当指针离开球体时没有其他东西可以击中,所以 if 条件 returns false 并且你不能移动它,解决问题添加一个大的四边形或平面作为 child 到你的相机并确保它完美地填充相机视图,并且它在你所有其他场景元素的后面。

你也可以制作一个脚本来为你设置这个平面。

编辑 2

作为解决问题的另一种方法,您可以使用 flags.

将此添加到您的相机,或根据您的需要对其进行编辑。

    public class DragObjects : MonoBehaviour
    {
        Camera thisCamera;
        private Transform DraggingObject;
        bool DraggingFlag = false;
        RaycastHit raycast;
        Ray ray;
        Vector3 deltaPosition;

        void Start()
        {
            thisCamera = GetComponent<Camera>();
        }
        void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                ray = thisCamera.ScreenPointToRay(Input.mousePosition);
                if (Physics.Raycast(ray, out raycast, Mathf.Infinity))
                {
                    DraggingObject = raycast.collider.transform;
                    DraggingFlag = true;
                    deltaPosition = thisCamera.ScreenToWorldPoint (Input.mousePosition) - DraggingObject.position;
                }
            }
            else if (Input.GetMouseButton(0))
            {
                if (DraggingFlag)
                {
                    DraggingObject.position = new Vector3 (thisCamera.ScreenToWorldPoint (Input.mousePosition).x - deltaPosition.x, thisCamera.ScreenToWorldPoint (Input.mousePosition).y - deltaPosition.y, DraggingObject.position.z);
                }
            }
            else if (Input.GetMouseButtonUp(0))
            {
                DraggingFlag = false;
            }
        }
    }

Remember to cash your Camera.main in a variable at the start, because it is not performant and does this in the background: GameObject.FindGameObjectsWithTag("MainCamera").GetComponent<Camera>();