Home unity3d How to make the object behave like a child, without making it...

How to make the object behave like a child, without making it such?

Author

Date

Category

I try to move the object B relative to the object, as well as if the object in was a subsidiary with respect to A. It turns out not entirely correctly.

What is the global task? I raise the VR controller an object from the table (for example, a nut) and move it on the scene. It sounds simple. The scene has a gameObject _cursor , the position and rotation of which I get from the input device (VR controller). Using Physics.Overlapsphere I find the collider of the object that I want to move.

and the solution “in the forehead” is to make a moved object with a subsidiary with respect to _cursor . In Oculus assets for Unity, a similar method is implemented. The problem is that the locked object must interact with other scene objects – do not fly through the table and other objects. That is, the collider must be included in it. The problem is that such an object demolisms absolutely all the other non-frozen objects of the scene, having a collider and rigidbody . From this I wanted to get rid.

Solving the following – move an object using rigidbody.moveposition , pre-setting it a fairly small mass. But how to determine where it needs to be moved? After all, I do not want to Transform the target “attract” to _cursor . Initially, the use of “proxy” came to mind – empty GameObject , subsidiary to _cursor . When “grabbing”, this proxy object took the value of transform.position from the captured object. And in the future, the target object by rigidbody.moveposition moved to the proxy position of the object. And in principle, it works. But I want to get rid of an additional bevel object.

Solving the following. When “grabbing” get a vector from Transform Consigned object to Transform Object _Cursor :

vector3 direction = _target.transform.position - _cursor.transform.position;

and also

quaternion _oldrotation = _cursor.transform.rotation;

When updating the frame, I do the following:

Private void update ()
{
  / * Here we get the rotation _cursor relative to the previous frame * /
  Quaternion _difrotation = quaternion.inverse (_oldrotation) * _cursor.transform.rotation;
  _oldrotation = _cursor.transform.rotation;
  / * Here turn the vector by quaternion * /
  direction = _difrotation * direction;
  / *
  * Here we move the object taking into account the position _cursor in the scene space
  * And the rotated vector Direction.
  * To simplify, do not use Rigidbody.moveposition
  * /
  _Target.position = _cursor.transform.position + Direction;
}

The result looks plausible, but there are “nuances”. For clarity, I collected a simplified scene using such an approach. Here REF acts as a _cursor , and base – the movable object. An object Sub – subsidiary to base and need for greater visibility to the problem. And the problem is that while REF rotates around the axes (x, y, z), everything looks perfect.


But it is worth making a random turn, as everything breaks. What is strange, because I use quaternion, which should not depend on rotation through the angles of Euler.


video

What am I doing wrong? And how else can I solve the question made in the title?


Answer 1

Error lies here:

quaternion _difrotation = quaternion.inverse (_oldrotation) * _cursor.transform.rotation;

Consider an example:

new = q * old

where new – quaternion in the new frame, OLD – in the old, and q – rotation between frames.

new = q * old,

Doming Both parts on Inverse (Old) on the right, that is, on the retroactive OLD matrix

new * invester (old) = Q * Old * Inverse (OLD)

Next, considering that Old * Inverse (OLD) This is a single matrix, and that we have the right to put brackets like this:

new * invester (old) = Q * (Old * Inverse (OLD))

Based on the associativity of quaternions

new * invester (old) = q;
Q = New * Inverse (OLD);

Thus, we get:

quaternion _difrotation = _cursor.transform.rotation * quaternion.inverse (_oldrotation);

Given the noncommutativity of the work of quaternions, logical you got another result.

and in the codes you click did not see where Rotation changes _Target (apparently somewhere else).

That’s just in case the code that works:

using unityengine;
Public Class Rotator: Monobehaviour
{
  [SerializeField]
  Private transform _target;
  [SerializeField]
  Private transform _cursor;
  Private Quaternion _oldrotation;
  Private Vector3 Direction;
  Private void Update ()
  {
    direction = _target.transform.position - _cursor.transform.position;
    / * Here we get the rotation _cursor relative to the previous frame * /
    Quaternion _difrotation = _cursor.transform.rotation * quaternion.inverse (_oldrotation); // 1
    _oldrotation = _cursor.transform.rotation;
    / * Here turn the vector by quaternion * /
    direction = _difrotation * direction;
    / *
    * Here we move the object taking into account the position _cursor in the scene space
    * And the rotated vector Direction.
    * To simplify, do not use Rigidbody.moveposition
    * /
    _Target.position = _cursor.transform.position + Direction;
    _target.rotation = _difrotation * _target.rotation; // 2.
  }
}

Programmers, Start Your Engines!

Why spend time searching for the correct question and then entering your answer when you can find it in a second? That's what CompuTicket is all about! Here you'll find thousands of questions and answers from hundreds of computer languages.

Recent questions