【问题标题】:Dragging an object with raycast is laggy使用 raycast 拖动对象是滞后的
【发布时间】:2019-06-06 18:21:02
【问题描述】:

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

当快速拖动对象时,鼠标指针会离开图层光线投射的区域,因此对象不再移动。

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

但为了让项目更简单,我打开了一个新的 2D 项目并制作了一个圆圈并为其分配了以下脚本,并在其上附加了一个球体对撞机(主要目标在 3D 空间中)。

// 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(),但结果相同。

【问题讨论】:

标签: unity3d raycasting


【解决方案1】:

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

Fixed Timestep: 与帧速率无关的间隔,指示何时执行物理计算和 FixedUpdate() 事件。 https://docs.unity3d.com/Manual/class-TimeManager.html

编辑

这段代码:

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

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

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

编辑 2

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

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

    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;
            }
        }
    }

记得在开始时将您的Camera.main 兑现到一个变量中,因为它不是高性能的并且在后台执行此操作: GameObject.FindGameObjectsWithTag("MainCamera").GetComponent&lt;Camera&gt;();

【讨论】:

  • 我将函数设置为FixedUpdate(),然后我设置Fixed TimeStep = 0.0001,但还是同样的问题。
  • @YoussofHammoud 恢复时间步长并将您的代码保留在 FixedUpdate() 中,尝试我对答案所做的 EDIT
  • 感谢您的回答,但如果我有多个对象怎么办?我认为这种技术行不通。顺便说一句,好主意。
  • 在编辑中,我将DraggingObject.position 排除在ScreenToWorldPoint 参数之外。并添加了 deltaPosition。
  • 如果它解决了您的问题,请接受它,否则请告诉我您遇到的问题,以便我为您提供帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-23
  • 1970-01-01
  • 2012-01-23
  • 2017-05-18
  • 1970-01-01
相关资源
最近更新 更多