繁体   English   中英

Unity:3D运动/碰撞检测失败(AddForce,MovePosition,transform.localPosition)

[英]Unity: 3D movement/Collision detection failure (AddForce, MovePosition, transform.localPosition)

问题:如果我使机芯正常工作,则不会检测到碰撞网格。 如果我检测到碰撞网格物体,则说明该运动无法正常进行。

项目的简要说明:我有一个3D环境,其中包含不可移动的对象(带有碰撞器网格)和可移动的游戏对象(带有x2盒子碰撞器的刚体),我通过UDP连接使用触觉设备(基本上是3D操纵杆)进行控制我已经放在一起并在Unity应用程序运行时正在运行的C ++应用程序。 触觉设备与统一之间的通信非常好。 我将从触觉设备传递的位置信息用作移动游戏对象的变量。 同样,位置数据也可以很好地到达Unity; 目前,我在Unity中使用具有适当条件和功能的位置数据的方法。

我尝试过的事情:如果我使用transform.localPosition (hapticDevicePosition); 那么运动就很好了,但是它忽略了对撞机并通过了所有物体。 我在网上阅读并了解到transform.localPosition基本上会将我的对象移到其他对象之上,而与物理无关。 我还读到我可以在对象前面引入一个像0.000001的射线,这样如果该射线与任何其他对象相互作用,它就可以防止移动。 这可能是仍然可以使用transform.localPosition的方式吗? 我不确定,而且我从未使用过光线,因此很难正确设置该脚本。

我已经尝试过AddForce 这表现得很奇怪。 它只给我2个力输出而不是3个力输出...即,我只能在3个轴中的2个中移动。 我不明白为什么它会这样。 但是,将检测到对撞机。

我尝试了rb.MovePosition (rb.position + posX + posY + posZ)以及* Time.timeDelay和* speed的各种组合。 这也无法正常工作。 已检测到对撞机,但是机芯根本不起作用或无法正常工作。

结论:最近4个小时我一直在使用脚本,并且我尝试的某些(并非全部)内容已被注释掉,因此它们仍然可见(请参见下面的代码)。 我将阅读更多在线说明,并尝试其他代码并在此处解决问题时进行更新。 同时,如果有人提出任何建议或建议,我将不胜感激。

谢谢!

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

 public class FalconPegControl_2 : MonoBehaviour {

     // Define needed variables
     private TestUDPConnection udpListener;

     public Vector3 realObjectCurrentPos;
     private Vector3 realObjectLastPos;

     public Vector3 realObjectCurrentRot;
     private Vector3 realObjectLastRot;

     public Vector3 realObjectPosChange;
     public Vector3 realObjectRotChange;

     private Quaternion rotation;
     //public float pi = 3.14f;

     private Rigidbody rb;
     private int control = 0;
     public bool collisionOccurred = false;

     //public float thrust = 1000; 

     //public CalibrationManager calibrationManager;

     // Use this for initialization
     void Start () {
         udpListener = GetComponentInParent<TestUDPConnection>();
         collisionOccurred = false;
         rb = GetComponent<Rigidbody> ();
         SharedRefs.falconPegControl = this;
     }

     public void OffControl ()
     {
         control = 0;
     }

     public void CollisionDuplicateFix ()
     {
         collisionOccurred = true;
     }

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

         //WITHOUT UNITY AXIS CONVERSION:
         //realObjectCurrentPos[0] = udpListener.xPosReal; //[m]
         //realObjectCurrentPos[1] = udpListener.yPosReal; //[m]
         //realObjectCurrentPos[2] = udpListener.zPosReal; //[m]

         //===============================
         //Unity axis conversions:
         //CHAI3D --> Unity
         //(x, y, z) --> (x, -z, y)
         //CHAI3D: realObjectCurrentPos[0], [1], [2] is CHIA3D (x, y, z)
         //Also, to compensate for the workspace available to the Falcon Device (~0.04, ~0.06, ~0.06)
         //adding a value of x10 allows it to reach the default hemisphere successfully
         //updated comment: the sign values that work (-, +, -)
         //===============================

         //Unity conversion for rotation (using Falcon devices)
         //Since one falcon is for translation and the other is for rotation,
         //the rotation information is a conversion of translational information
         //in other words, max range of (~0.04, ~0.06, ~0.06) has been converted into a max range of (90, 90, 90)
         //using basic algebra (i.e., (90/0.04))
         //thus giving the user the full range of 180 degrees (from 90 degrees to -90 degrees)

         realObjectCurrentPos[0] = udpListener.xPosReal * (-5); //[m]
         realObjectCurrentPos[1] = udpListener.zPosReal * (5); //[m]
         realObjectCurrentPos[2] = udpListener.yPosReal * (-5); //[m]


         realObjectCurrentRot [0] = udpListener.xRot * (90f / 0.04f); //degrees
         realObjectCurrentRot [1] = udpListener.yRot * (90f / 0.06f); //degrees
         realObjectCurrentRot [2] = udpListener.zRot * (90f / 0.06f); //degrees


         if (Input.GetKeyDown ("1")) {
             control = 1;
             SharedRefs.stopWatch.startTimer ();
         }

         if (Input.GetKeyDown ("space")) 
         {
             OffControl ();
         }

         if (control==1)
         {

             Vector3 posUnity = new Vector3 (realObjectCurrentPos[0], realObjectCurrentPos[1], realObjectCurrentPos[2]);
             rb.AddForce (posUnity);

             //Vector3 tempVect = new Vector3(realObjectCurrentPos[0], realObjectCurrentPos[1], realObjectCurrentPos[2]);                 
             //Vector3 startPoint = new Vector3 (0f, 0.0225f, 0f);
             //tempVect = tempVect * speed * Time.deltaTime;

             //transform.localPosition = realObjectCurrentPos; //[m]



             //var unityX = Vector3.Scale (posTemp, Vector3.right);
             //var unityY = Vector3.Scale (posTemp, Vector3.up);
             //var unityZ = Vector3.Scale (posTemp, Vector3.forward);

             //Vector3 unityX = new Vector3 (Vector3.Scale (posTemp, Vector3.right), Vector3.Scale (posTemp, Vector3.up), Vector3.Scale (posTemp, Vector3.forward));
             //Vector3 unityY = new Vector3 (Vector3.Scale (posTemp, Vector3.up));
             //Vector3 unityZ = new Vector3 (Vector3.Scale (posTemp, Vector3.forward));

             //rb.MovePosition (rb.position + unityX + unityY + unityZ);
             //transform.localPosition = (startPoint + tempVect); //[m]

             transform.localRotation = Quaternion.Euler(realObjectCurrentRot); //[m]

             realObjectLastPos = realObjectCurrentPos;//[m]
             realObjectLastRot = realObjectCurrentRot;//[m]

             realObjectPosChange = realObjectCurrentPos - realObjectLastPos; //[m]
             realObjectRotChange = realObjectCurrentRot - realObjectLastRot;


         }
         else if (control==0) 
         {
             Vector3 stop = new Vector3 (0, 0, 0);
             rb.constraints =  RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotationZ;
             rb.constraints =  RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezeRotationX;
             rb.constraints =  RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezeRotationX;
             rb.velocity = (stop);
         }
     }
 }

另外,根据@Ali Baba的评论进行了更新:我还没有时间测试其他方法,但是通过使用AddForce并使用拖动和力修改器变量,我可以控制所有三个轴(实际上是6DOF因为我还可以从第二个外部设备进行旋转控制),而且我对游戏对象的控制也比以前更好(特别是由于拖动和力修改器变量的调整)。 这可能是最好的解决方案,但是我最初需要根据要使用的外部设备的位置来更改位置。 我正在添加一个基本的,精简的,经过调整的代码,该代码使用AddForce并允许对拖动和我的力修改器变量进行关键控制调整,以防其他初学者也看到此线程。 同时,我将尝试使其他功能(MovePosition等)正常工作并更新结果。

细长的基本阻力/变量测试代码:

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

public class Real_Controller : MonoBehaviour {

    // Define needed variables
    private TestUDPConnection udpListener;
    public Vector3 realObjectCurrentPos;
    public Vector3 realObjectCurrentRot;
    private Quaternion rotation;
    private Rigidbody rb;
    private float increaseForce = 23;

    // Use this for initialization
    void Start () {
        udpListener = GetComponentInParent<TestUDPConnection>();
        rb = GetComponent<Rigidbody> ();
        rb.drag = 1.24f;
    }

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

        if (Input.GetKeyDown ("q")) 
        {
            rb.drag -= 0.1f;
            Debug.Log ("drag is: " + rb.drag);
        }

        if (Input.GetKeyDown ("w")) 
        {
            rb.drag += 0.1f;
            Debug.Log ("drag is: " + rb.drag);
        }

        if (Input.GetKeyDown ("a")) {
            increaseForce -= 1f;
            Debug.Log ("increased force is: " + increaseForce);
        }

        if (Input.GetKeyDown ("s")) {
            increaseForce += 1f;
            Debug.Log ("increase force is: " + increaseForce);
        }



        realObjectCurrentPos[0] = udpListener.xPosReal * (-increaseForce); //[m]
        realObjectCurrentPos[1] = udpListener.zPosReal * (increaseForce); //[m]
        realObjectCurrentPos[2] = udpListener.yPosReal * (-increaseForce); //[m]



        Vector3 forceDirection = realObjectCurrentPos - transform.localPosition;
        rb.AddForce (forceDirection * forceDirection.magnitude);



        realObjectCurrentRot [0] = udpListener.xRot * (90f / 0.04f); //degrees
        realObjectCurrentRot [1] = udpListener.yRot * (90f / 0.06f); //degrees
        realObjectCurrentRot [2] = udpListener.zRot * (90f / 0.06f); //degrees


        transform.localRotation = Quaternion.Euler(realObjectCurrentRot); //[m]


    }
}

除了将gameObject放置在gameObject的确切位置上之外,您可以尝试在想要gameObject所处位置的方向上施加力:

 if (control==1)
 {
     Vector3 forceDirection = realObjectCurrentPos - transform.localPosition;

     rb.AddForce (forceDirection);

     transform.localRotation = Quaternion.Euler(realObjectCurrentRot)
 }

此处施加的力与gameObject对象位置和真实对象之间的距离成线性关系,因此它的行为基本上像弹簧。 您应该尝试将力乘以不同的因素并进行测试:

 rb.AddForce (forceDirection * 0.5f);

或按平方缩放:

 rb.AddForce (forceDirection * forceDirection.magnitude);

感觉最好的

暂无
暂无

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

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