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.
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.
}
}