Спонтанно я вижу в основном 3 варианта, если вы не хотите, чтобы это был просто ребенок:
ограничивает движение объекта зависимостью от другого объекта. Это несколько похоже на Parenting, но реализуется через физику, а не иерархию Transform. Наилучшие сценарии их использования - это когда у вас есть объекты, которые вы хотите легко отделить друг от друга, или соедините движение двух объектов без родительских элементов.
Поэтому, когда вы берете объект, делайте что-то вроде
var fixedJoint = grabbedObject.AddComponent<FixedJoint>();
fixedJoint.connectedBody = controllerObject.GetComponent<RigidBody>();
//disable autoconfigure anchor
fixedJoint.autoConfigureConnectedAnchor = false;
// And set offsets depending on the current relative positions
// Get the position of the object in the controllers local coordinates
fixedJoint.connectedAnchor = controllerObject.transform.InverseTransformPoint(grabbedObject.transform.position);
// And get the controllers position relative to the object
fixedJoint.anchor = gtabbedObject.transform.InverseTransformPoint(controller.transform.posotion);
И когда вы отпускаете объект, удаляйте это соединение, например,
Destroy(grabbedObject.GetComponent<FixedJoint>());
2. Рассчитать преобразования
Получая относительное смещение положения, вы также можете использовать вид искусственного родительства, просто добавив смещение по компонентам, используя локальную систему координат контроллеров.
Имейте компонент, подобный этому, на захватываемых объектах
public class CopyTransforms : MonoBehaviour
{
private Transform target;
private Transform startOffset;
private RigidBody rb;
private void Awake()
{
rb = GetComponent<RigidBody>();
}
// Call this In the moment you grab the object
public void Grab(Transform grabber)
{
target = grabber;
offset = transform.position - target.position;
}
// Call this when releasing
public void Release()
{
target = null;
}
// If dealing with rigidbodies you should use fixedupdate
private void FixedUpdate()
{
if(!target) return;
// Apply rotation
rb.MoveRotation(target.rotation);
var targetPosition = target.position + target.right * offset.x + target.up * offset.y + target.forward * target.z;
rb.MovePosition(targetPosition);
}
}
3. Использовать поддельное воспитание детей
Идея состоит в том, чтобы под контроллером был пустой объект.
В тот момент, когда вы захватываете, вы устанавливаете положение этого пустого объекта в положение, в котором находится ваш захваченный объект -> В будущем, когда контроллер будет перемещен, этот пустой объект будет находиться там, где должен быть ваш захваченный объект. Так что вам просто нужно применить его преобразования и сделать
var emptyObject = new GameObject("empty");
emptyObject.transform.SetParent(controllerObject.trasform, false);
emptyObject.transform.rotation = grabbedObject.transform.rotation;
emptyObject.transform.position = grabbedObject.transform.position;
Теперь вам нужно просто скопировать его преобразования, например, в
void Update()
{
grabbedObject.transform.rotation = emptyObject.transform.rotation;
grabbedObject.transform.position = emptyObject.transform.position;
}
или в FixedUpdate
как раньше.
Примечание: напечатано на смартфоне, поэтому никаких гарантий, но я надеюсь, что идея проясняется.