简体   繁体   English

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

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

Problem: If I get the movement to work correctly, then the collision meshes are not detected. 问题:如果我使机芯正常工作,则不会检测到碰撞网格。 If I get the collision meshes detected, then the movement doesn't work correctly. 如果我检测到碰撞网格物体,则说明该运动无法正常进行。

Brief summary of project: I have a 3D environment with non-moveable objects (with collider meshes) and a moveable gameobject (rigid body with x2 box colliders) that I am controlling using haptic devices (basically a 3D joystick) through a UDP connection in an C++ app that I have put together and is running while the Unity application runs. 项目的简要说明:我有一个3D环境,其中包含不可移动的对象(带有碰撞器网格)和可移动的游戏对象(带有x2盒子碰撞器的刚体),我通过UDP连接使用触觉设备(基本上是3D操纵杆)进行控制我已经放在一起并在Unity应用程序运行时正在运行的C ++应用程序。 The communication between the haptic devices and unity is perfectly fine. 触觉设备与统一之间的通信非常好。 I am using the position information passed from the haptic device as my variables for moving my gameobject. 我将从触觉设备传递的位置信息用作移动游戏对象的变量。 Again, The position data arrives to Unity just fine; 同样,位置数据也可以很好地到达Unity; the method for using the position data with appropriate conditions and functions within Unity is where I am currently stuck. 目前,我在Unity中使用具有适当条件和功能的位置数据的方法。

Things I've tried: If I use transform.localPosition (hapticDevicePosition); 我尝试过的事情:如果我使用transform.localPosition (hapticDevicePosition); then the movement is great, but it ignores the colliders and passes through everything. 那么运动就很好了,但是它忽略了对撞机并通过了所有物体。 I read online and understand that transform.localPosition will basically move my object on top of other objects without regards to physics. 我在网上阅读并了解到transform.localPosition基本上会将我的对象移到其他对象之上,而与物理无关。 I also read that I may be able to introduce a ray that is like 0.000001 in front of my object such that it prevents movement if the ray interacts with any other object. 我还读到我可以在对象前面引入一个像0.000001的射线,这样如果该射线与任何其他对象相互作用,它就可以防止移动。 This might be a way to still be able to use transform.localPosition? 这可能是仍然可以使用transform.localPosition的方式吗? I'm not sure and I've never used rays so it would be difficult for me to set that script up correctly. 我不确定,而且我从未使用过光线,因此很难正确设置该脚本。

I've tried AddForce . 我已经尝试过AddForce This behaves very oddly. 这表现得很奇怪。 It only gives me 2 force outputs instead of 3...ie, I can only move in 2 of the 3 axis. 它只给我2个力输出而不是3个力输出...即,我只能在3个轴中的2个中移动。 I don't understand why its behaving this way. 我不明白为什么它会这样。 The colliders are detected, however. 但是,将检测到对撞机。

I've tried rb.MovePosition (rb.position + posX + posY + posZ) and various combinations of *Time.timeDelay and *speed as well. 我尝试了rb.MovePosition (rb.position + posX + posY + posZ)以及* Time.timeDelay和* speed的各种组合。 This also doesn't work correctly. 这也无法正常工作。 The colliders are detected, but the movement either doesn't work at all, or is not working correctly. 已检测到对撞机,但是机芯根本不起作用或无法正常工作。

Conclusion: I've played with my script for the last 4 hours and some (not all) of the things that I attempted are commented out so they are still visible (please see code attached below). 结论:最近4个小时我一直在使用脚本,并且我尝试的某些(并非全部)内容已被注释掉,因此它们仍然可见(请参见下面的代码)。 I will be reading more online explanations and trying out different code and update here if I work out a solution. 我将阅读更多在线说明,并尝试其他代码并在此处解决问题时进行更新。 If anyone has some pointers or suggestions, in the meantime, I would greatly appreciate it. 同时,如果有人提出任何建议或建议,我将不胜感激。

Thanks! 谢谢!

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

Also, updated from @Ali Baba's comments: I haven't had time to test the other methods yet, but by using AddForce and playing with the drag and a force modifier variable, I was able to get control over all three axes (actually 6DOF because I also have rotational control from a 2nd external device) and I also have much better control over my gameobject than before (specifically due to the drag and force modifier variable adjustments). 另外,根据@Ali Baba的评论进行了更新:我还没有时间测试其他方法,但是通过使用AddForce并使用拖动和力修改器变量,我可以控制所有三个轴(实际上是6DOF因为我还可以从第二个外部设备进行旋转控制),而且我对游戏对象的控制也比以前更好(特别是由于拖动和力修改器变量的调整)。 This may be the best solution, but I originally needed to get my position to change based on the position of the external devices that I am using. 这可能是最好的解决方案,但是我最初需要根据要使用的外部设备的位置来更改位置。 I'm adding a basic, slimmed down, adjusted code which uses AddForce and allows for keycontrol adjustments of the drag and my force modifier variable in case other beginners see this thread also. 我正在添加一个基本的,精简的,经过调整的代码,该代码使用AddForce并允许对拖动和我的力修改器变量进行关键控制调整,以防其他初学者也看到此线程。 In the meantime, I will try to get the other functions (MovePosition, etc) working and update on the results. 同时,我将尝试使其他功能(MovePosition等)正常工作并更新结果。

Slim, basic drag/variable testing code: 细长的基本阻力/变量测试代码:

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]


    }
}

Instead of placing the gameObject at the exact position of your controller, you could try applying a force in the direction of the position you want your gameObject to be in: 除了将gameObject放置在gameObject的确切位置上之外,您可以尝试在想要gameObject所处位置的方向上施加力:

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

     rb.AddForce (forceDirection);

     transform.localRotation = Quaternion.Euler(realObjectCurrentRot)
 }

The force applied here is linear to the distance between the position of the gameObject and the real object, so this basically behaves like a spring. 此处施加的力与gameObject对象位置和真实对象之间的距离成线性关系,因此它的行为基本上像弹簧。 You should try multiplying the force by different factors and test: 您应该尝试将力乘以不同的因素并进行测试:

 rb.AddForce (forceDirection * 0.5f);

Or scale it quadratically: 或按平方缩放:

 rb.AddForce (forceDirection * forceDirection.magnitude);

Whatever feels best 感觉最好的

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

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