c# - 旋转我正在查看的对象 (ARFoundation)

标签 c# android unity-game-engine augmented-reality

2 个项目被放置在 AR 中。我想在屏幕中间旋转这些项目中的 1 个(使用触摸控件和 Raycast)。

我希望在相机注视物体时执行代码的所有旋转部分。

这是我在放置在场景中的对象上使用的脚本,移动功能起作用,因为只有在您点击对象所在的屏幕并将其拖走(光线转换到碰撞器)时才会激活该功能。但是,当我在任何地方滑动时,我的旋转适用于场景中的所有对象,因为如果我在对撞机上滑动,我会移动对象,因此对于旋转,我必须留在该对撞机之外。

public class MoveObject : MonoBehaviour
{
    public bool holding;
    private Component rotator;
    int doubleTap = 0;

    void Start()
    {
        holding = false;
    }

    void Update()
    {
        if (holding)
        {
            Move();
        }

        // One finger
        if (Input.touchCount == 1)
        {
            // Tap on Object
            if (Input.GetTouch(0).phase == TouchPhase.Began)
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
                RaycastHit hitTouch;

                if (Physics.Raycast(ray, out hitTouch, 100f))
                {
                    if (hitTouch.transform == transform)
                    {
                        holding = true;
                    }
                }
            }
            // Release
            if (Input.GetTouch(0).phase == TouchPhase.Ended)
            {
                holding = false;
            }
        }

        if (Input.touchCount == 1 && !holding) //THIS is the rotation part
        {
            // GET TOUCH 0
            Touch touch0 = Input.GetTouch(0);

            // APPLY ROTATION
            if (touch0.phase == TouchPhase.Moved)
            {
                transform.Rotate(0f, touch0.deltaPosition.x * 0.5f, 0f);
            }
        }
    }

    void Move()
    {
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
        // The GameObject this script attached should be on layer "Surface"
        if (Physics.Raycast(ray, out hit, 30.0f, 
        LayerMask.GetMask("Surface")))
        {
            transform.position = new Vector3(hit.point.x,
                                             transform.position.y,
                                             hit.point.z);
        }
    }
}

最佳答案

您可能需要另一个类似于 holding 的标志,以确保您不会旋转屏幕中心在滑动过程中经过的对象,例如当相机移动和物体穿过屏幕的中心。

您可以使用 Camera.ViewportPointToRay输入 new Vector3(0.5f, 0.5f, 0) 以创建一条来自屏幕中心的光线。从那里开始,该过程类似于您的持有代码。

此外,通过稍微重新排列,您可以重新使用已用于检查此对象是否被触摸的光线转换,因为它还会检查是否有任何对象被触摸。仅当第一个光线转换没有接触到任何东西时才检查开始旋转可以避免在该对象位于屏幕中心但另一个物体被触摸的情况下旋转(和不必要的光线转换)。

作为旁注,它是 recommended to cache the result of Camera.main因为每次您引用它时它都会在内部执行 FindGameObjectsWithTag,这会增加额外的计算时间。

总的来说,它可能看起来像这样:

private bool rotating;
private Camera cam;

void Start()
{
    holding = false;
    rotating = false;
    cam = Camera.main;
}

void Update()
{
    // One finger
    if (Input.touchCount == 1)
    {
        Touch touch0 = Input.GetTouch(0);

        if (touch0.phase == TouchPhase.Began)
        {
            Ray ray;
            RaycastHit hitTouch;

            // test hold start
            ray = cam.ScreenPointToRay(touch0.position);
            if (Physics.Raycast(ray, out hitTouch, 100f))
            {
                if (hitTouch.transform == transform)
                {
                    holding = true;
                }
            }
            else  // avoid rotating/raycasting again in situation 
                  // where this object may be in center of screen 
                  // but this or other object was touched.
            {
                // test rotate start
                ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
                if (Physics.Raycast(ray, out hitTouch, 100f)))
                {
                    if (hitTouch.transform == transform)
                    {
                        rotating = true;
                    }
                }
            } 
        }
        else if (touch0.phase == TouchPhase.Moved)
        {
            if (holding)
            {
                Move();
            }
            else if (rotating)
            {
                transform.Rotate(0f, touch0.deltaPosition.x * 0.5f, 0f);
            }
        }
        // Release
        else if (touch0.phase == TouchPhase.Ended)
        {
            holding = false;
            rotating = false;
        }
    }
}

关于c# - 旋转我正在查看的对象 (ARFoundation),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57790059/

相关文章:

c# - 不使用 Alter 命令,删除级联行

c# - 此代码片段是否使用 Repository 或 Adapter 模式?

android device.getUuids 返回 null

c# - 保存游戏登录信息

java - Unity3D 四元数 libGDX 等效项

unity-game-engine - 从命令行激活 Unity

使用 ToBase64String 的 C# 字符串编码

c# - 正则表达式将字符串中的多个连字符替换为一个连字符? ASP.NET C#

android - 通过室内地理围栏控制飞利浦色相灯泡

android - 删除固定数量的数字