Unity: ошибка 3D-движения / обнаружения столкновений (AddForce, MovePosition, transform.localPosition) - PullRequest
4 голосов
/ 11 апреля 2019

Проблема: Если я заставлю движение работать правильно, то столкновительные сетки не будут обнаружены.Если я обнаружу сетки столкновений, то движение будет работать некорректно.

Краткое описание проекта: У меня есть трехмерная среда с неподвижными объектами (с сетками коллайдеров) иподвижный игровой объект (твердое тело с коробочными коллайдерами x2), которым я управляю, используя тактильные устройства (в основном 3D-джойстик) через соединение UDP в приложении C ++, которое я собрал и которое работает во время работы приложения Unity.Связь между тактильными устройствами и единством в порядке.Я использую информацию о местоположении, передаваемую из тактильного устройства, в качестве переменных для перемещения моего игрового объекта.Опять же, данные о местоположении поступают в Unity просто отлично;метод использования данных о местоположении с соответствующими условиями и функциями в Unity - вот где я застрял.

Вещи, которые я пытался: Если я использую transform.localPosition (hapticDevicePosition);тогда движение велико, но оно игнорирует коллайдеры и проходит через все.Я читаю онлайн и понимаю, что transform.localPosition будет в основном перемещать мой объект поверх других объектов безотносительно к физике.Я также читал, что, возможно, я смогу ввести луч, который равен 0,000001, перед моим объектом, так что он предотвращает движение, если луч взаимодействует с любым другим объектом.Это может быть способ по-прежнему иметь возможность использовать transform.localPosition?Я не уверен, и я никогда не использовал лучи, поэтому мне было бы трудно правильно настроить этот скрипт.

Я пробовал AddForce .Это ведет себя очень странно.Это дает мне только 2 выхода силы вместо 3 ... т.е. я могу двигаться только в 2 из 3 осей.Я не понимаю, почему так себя ведет.Однако обнаружены коллайдеры.

Я пробовал 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);
         }
     }
 }

Кроме того, обновлено из комментариев @ Али Али Бабы: у меня еще не было времени протестировать другие методы, но с помощью AddForce и игры с перетаскиванием и переменной модификатора силы я смогполучить контроль над всеми тремя осями (на самом деле 6DOF, потому что у меня также есть управление вращением от 2-го внешнего устройства), и у меня также намного лучший контроль над моим игровым объектом, чем раньше (особенно из-за настроек переменной модификатора перетаскивания и изменения силы).Это может быть лучшим решением, но изначально мне нужно было изменить свою позицию в зависимости от положения внешних устройств, которые я использую.Я добавляю базовый, уменьшенный, скорректированный код, который использует 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]


    }
}

1 Ответ

1 голос
/ 11 апреля 2019

Вместо того, чтобы поместить 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);

Что бы вы ни чувствовали лучше

...