- Home /
rb.AddForce, rb.MovePosition, transform.localPosition: no solution working for 3D motion+collision
Hello everyone.
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. 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.
Things I've tried:
If I use 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. I also read that I may be able to introduce a raycast that is like 0.000001 in front of my object such that it prevents movement if the ray interacts with any other object. This might be a way to still be able to use transform.localPosition? I'm not sure and I've never used raycasting so it would be difficult for me to set that script up correctly.
I've tried AddForce. This behaves very oddly. It only gives me 2 force outputs instead of 3...i.e., I can only move in 1 of the 3 axis. 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. 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). If anyone has some pointers or suggestions, 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);
}
}
}
Edit: I meant to say that AddForce currently only allows me to move in TWO of the three axis.
Have you tried using a CharacterController? I don't know if it will fit into your project but it's used for controlling an object with a rigidbody that has collisions with the world.
Your answer
![](https://koobas.hobune.stream/wayback/20220612195242im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Stop movement of rigid bodies 2D after collision 1 Answer
Rigidbody2D.AddForce works only once? 1 Answer
how to make an object move like the one it is in contact(moving using Animator) with in unity? 1 Answer
Ignoring the transform.y position on movement 2 Answers
Implementing Counter-Movement 0 Answers