first commit
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualGrasp.Onboarding
|
||||
{
|
||||
/**
|
||||
* ManageContainerObject shows as a tutorial on how to use the VG_Controller.OnObjectFullyReleased
|
||||
* and VG_Controller.OnObjectGrasped combined with Unity's physical joints to manage a
|
||||
* container object to hold the contained physical objects stably without falling off.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vgonboarding_task3." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class ManageContainerObject : MonoBehaviour
|
||||
{
|
||||
/// A set off objects that are actively colliding with this one.
|
||||
private HashSet<Transform> m_collisions = new HashSet<Transform>();
|
||||
/// A map of objects with ArticulationBody to their original parents.
|
||||
private Dictionary<Transform, Transform> m_parentCache = new Dictionary<Transform, Transform>();
|
||||
/// A map of objects with Rigidbody to the fixed joints connecting to this container object
|
||||
private Dictionary<Transform, FixedJoint> m_attachJoints = new Dictionary<Transform, FixedJoint>();
|
||||
/// If dot product between velocity and down is large enough (ie. vectors are aligned).
|
||||
public float m_dropAlignment = 0.8f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Register the some grasp event listeners
|
||||
VG_Controller.OnObjectFullyReleased.AddListener(OnObjectFullyReleased);
|
||||
VG_Controller.OnObjectGrasped.AddListener(OnObjectGrasped);
|
||||
}
|
||||
|
||||
private void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
// See if the object in collision is actually held by a hand (and is not a hand itself).
|
||||
bool valid_object = true;
|
||||
foreach (VG_HandStatus hand in VG_Controller.GetHands())
|
||||
{
|
||||
if (hand.m_hand == collision.transform)
|
||||
valid_object &= false;
|
||||
if (hand.m_selectedObject == collision.transform && hand.IsHolding())
|
||||
valid_object &= false;
|
||||
}
|
||||
|
||||
if (valid_object && // If it's valid ...
|
||||
(collision.rigidbody != null || collision.gameObject.TryGetComponent(out ArticulationBody ab)) && // and has a rigid body or articulation body ...
|
||||
Vector3.Dot(collision.relativeVelocity.normalized, Vector3.down) > m_dropAlignment) // .. and if the object is dropped from somewhat above.
|
||||
{
|
||||
Attach(collision.transform);
|
||||
m_collisions.Add(collision.transform);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollisionExit(Collision collision)
|
||||
{
|
||||
m_collisions.Remove(collision.transform);
|
||||
}
|
||||
|
||||
private void OnObjectFullyReleased(VG_HandStatus hand)
|
||||
{
|
||||
if (m_collisions.Contains(hand.m_selectedObject))
|
||||
Attach(hand.m_selectedObject);
|
||||
}
|
||||
|
||||
private void OnObjectGrasped(VG_HandStatus hand)
|
||||
{
|
||||
Unattach(hand.m_selectedObject);
|
||||
}
|
||||
|
||||
void Attach(Transform attachedObject)
|
||||
{
|
||||
if (attachedObject.gameObject.TryGetComponent<Rigidbody>(out Rigidbody rb))
|
||||
{
|
||||
if (!attachedObject.gameObject.TryGetComponent<FixedJoint>(out FixedJoint joint))
|
||||
{
|
||||
joint = attachedObject.gameObject.AddComponent<FixedJoint>();
|
||||
m_attachJoints[attachedObject] = joint;
|
||||
if (transform.gameObject.TryGetComponent<Rigidbody>(out Rigidbody container_rb))
|
||||
joint.connectedBody = container_rb;
|
||||
else if (transform.gameObject.TryGetComponent<ArticulationBody>(out ArticulationBody container_ab))
|
||||
joint.connectedArticulationBody = container_ab;
|
||||
}
|
||||
}
|
||||
else if (attachedObject.gameObject.TryGetComponent<ArticulationBody>(out ArticulationBody ab))
|
||||
{
|
||||
if (transform.gameObject.TryGetComponent<ArticulationBody>(out ArticulationBody container_ab))
|
||||
{
|
||||
m_parentCache[attachedObject] = attachedObject.parent;
|
||||
attachedObject.SetParent(transform);
|
||||
ab.jointType = ArticulationJointType.FixedJoint;
|
||||
}
|
||||
else
|
||||
Debug.LogError("Can not attach object " + attachedObject.name + " with ArticulationBody to " + transform.name + " without ArticulationBody.");
|
||||
}
|
||||
}
|
||||
|
||||
void Unattach(Transform attachedObject)
|
||||
{
|
||||
if (attachedObject.gameObject.TryGetComponent<Rigidbody>(out Rigidbody rb))
|
||||
{
|
||||
if (!m_attachJoints.ContainsKey(attachedObject))
|
||||
return;
|
||||
DestroyImmediate(m_attachJoints[attachedObject]);
|
||||
m_attachJoints.Remove(attachedObject);
|
||||
}
|
||||
else if (attachedObject.gameObject.TryGetComponent<ArticulationBody>(out ArticulationBody ab))
|
||||
{
|
||||
if (!transform.gameObject.TryGetComponent<ArticulationBody>(out ArticulationBody container_ab))
|
||||
return;
|
||||
if (attachedObject.parent != transform)
|
||||
return;
|
||||
|
||||
attachedObject.SetParent(m_parentCache[attachedObject]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user