13using System.Collections.Generic;
22 [DisallowMultipleComponent]
36 get {
return _interactionControllers; }
39 [Header(
"Interaction Settings")]
42 [Tooltip(
"Beyond this radius, an interaction object will not receive hover or primary "
43 +
"hover callbacks from an interaction controller. (Smaller values are "
44 +
"cheaper.) This value is automatically scaled under the hood by the "
45 +
"Interaction Manager's lossyScale.x, so it's recommended to keep your "
46 +
"Interaction Manager with unit scale underneath your 'Player' Transform if "
47 +
"you expect your player's hands or controllers to ever have non-unit scale.")]
50 [Tooltip(
"Beyond this radius, an interaction object will not be considered for "
51 +
"contact or grasping logic. The radius should be small as an optimization "
52 +
"but certainly not smaller than an interaction controller and not too tight "
53 +
"around the controller to allow good behavior when it is moving quickly "
54 +
"through space. This value is automatically scaled under the hood by the "
55 +
"Interaction Manager's lossyScale.x, so it's recommended to keep your "
56 +
"Interaction Manager with unit scale underneath your 'Player' Transform if "
57 +
"you expect your player's hands or controllers to ever have non-unit scale.")]
61 PreservePosePerController,
62 ReinitializeOnAnyRelease
64 [Tooltip(
"If set to PreservePosePerController, when holding a multi-grasp-enabled object and releasing with a single hand or controller, the object's held pose will adjust to reflect only the remaining holding controllers.\n\nIf set to PreservePosePerController, when any hand or controller releases an object, the remaining controllers will reinitialize their holding pose to match the last-held state of the object, allowing the user to rotate and translate the object more loosely.\n\nPreservePosePerController is the default setting.")]
67 [Header(
"Layer Settings")]
68 [Tooltip(
"Whether or not to create the layers used for interaction when the scene "
69 +
"runs. Interactions require an interaction layer (for objects), a grasped "
70 +
"object layer, and a contact bone layer (for interaction controller 'bone' "
71 +
"colliders). Keep this checked to have these layers created for you, but be "
72 +
"aware that the generated layers will have blank names due to Unity "
82 [Tooltip(
"When automatically generating layers, the Interaction layer (for "
83 +
"interactable objects) will use the same physics collision flags as the "
84 +
"layer specified here.")]
89 [Tooltip(
"The layer for interactable objects (i.e. InteractionBehaviours). Usually "
90 +
"this would have the same collision flags as the Default layer, but it "
91 +
"should be its own layer so interaction controllers don't have to check "
92 +
"collision against all physics objects in the scene.")]
97 [Tooltip(
"The layer objects are moved to when they become grasped, or if they are "
98 +
"otherwise ignoring controller contact. This layer should not collide with "
99 +
"the contact bone layer, but should collide with everything else that the "
100 +
"interaction layer collides with.")]
105 [Tooltip(
"The layer containing the collider 'bones' of the interaction controller. "
106 +
"This layer should collide with anything you'd like to be able to touch, "
107 +
"but it should not collide with the grasped object layer.")]
112 [Header(
"Debug Settings")]
114 [Tooltip(
"Rendering runtime gizmos requires having a Runtime Gizmo Manager somewhere "
116 private bool _drawControllerRuntimeGizmos =
false;
128 #region Scale Support
130 private float _scale = 1F;
153 #region Object Tracking
155 private HashSet<IInteractionBehaviour> _interactionObjects =
new HashSet<IInteractionBehaviour>();
161 get {
return _interactionObjects; }
164 private Dictionary<Rigidbody, IInteractionBehaviour> _interactionObjectBodies;
171 if (_interactionObjectBodies ==
null) {
172 _interactionObjectBodies =
new Dictionary<Rigidbody, IInteractionBehaviour>();
174 return _interactionObjectBodies;
178 private Dictionary<Rigidbody, ContactBone> _contactBoneBodies;
185 if (_contactBoneBodies ==
null) {
186 _contactBoneBodies =
new Dictionary<Rigidbody, ContactBone>();
188 return _contactBoneBodies;
194 #region Singleton Pattern (Optional)
215 if (s_instance ==
null) { s_instance = FindObjectOfType<InteractionManager>(); }
218 set { s_instance = value; }
230 refreshInteractionControllers();
234 refreshInteractionControllers();
236 if (!Application.isPlaying)
return;
238 if (s_instance ==
null) s_instance =
this;
242 setupAutomaticCollisionLayers();
245 _prevPosition = this.transform.position;
246 _prevRotation = this.transform.rotation;
249 if (_drawControllerRuntimeGizmos ==
true) {
250 if (FindObjectOfType<RuntimeGizmoManager>() ==
null) {
251 Debug.LogWarning(
"'_drawControllerRuntimeGizmos' is enabled, but there is no "
252 +
"RuntimeGizmoManager in your scene. Please add one if you'd "
253 +
"like to render gizmos in the editor and in your headset.");
261 if (!Application.isPlaying)
return;
264 foreach (var intController
in _interactionControllers) {
267 intController.EnableSoftContact();
269 if (intController.isGraspingObject) {
270 intController.ReleaseGrasp();
277 refreshInteractionControllers();
286 #if UNITY_2017_2_OR_NEWER
287 var preUpdateAutoSyncTransforms =
Physics.autoSyncTransforms;
288 Physics.autoSyncTransforms =
false;
292 refreshInteractionControllers();
295 if (!Application.isPlaying)
return;
298 using (
new ProfilerSample(
"Interaction Manager FixedUpdate", this.gameObject)) {
300 _scale = this.transform.lossyScale.x;
303 fixedUpdateInteractionControllers();
306 using (
new ProfilerSample(
"FixedUpdateObject per-InteractionBehaviour")) {
307 foreach (var interactionObj
in _interactionObjects) {
308 interactionObj.FixedUpdateObject();
314 using (
new ProfilerSample(
"Apply Soft Contacts")) {
315 if (_drawControllerRuntimeGizmos) {
316 _softContactsToDraw =
new List<PhysicsUtility.SoftContact>(
_softContacts);
326 updateMovingFrameOfReferenceSupport();
329 autoUpdateContactBoneLayerCollision();
334 #if UNITY_2017_2_OR_NEWER
337 Physics.autoSyncTransforms = preUpdateAutoSyncTransforms;
348 #region Controller Interaction State & Callbacks Update
350 private HashSet<InteractionController> _activeControllersBuffer =
new HashSet<InteractionController>();
351 private HashSet<InteractionController> _hoverControllersBuffer =
new HashSet<InteractionController>();
352 private HashSet<InteractionController> _contactControllersBuffer =
new HashSet<InteractionController>();
353 private HashSet<InteractionController> _graspingControllersBuffer =
new HashSet<InteractionController>();
355 private void fixedUpdateInteractionControllers() {
357 _hoverControllersBuffer.Clear();
358 _contactControllersBuffer.Clear();
359 _graspingControllersBuffer.Clear();
360 _activeControllersBuffer.Clear();
362 if (!controller.isActiveAndEnabled)
continue;
364 _activeControllersBuffer.Add(controller);
366 if (controller.hoverEnabled) _hoverControllersBuffer.Add(controller);
367 if (controller.contactEnabled) _contactControllersBuffer.Add(controller);
368 if (controller.graspingEnabled) _graspingControllersBuffer.Add(controller);
371 using (
new ProfilerSample(
"Fixed Update Controllers (General Update)")) {
374 foreach (var controller
in _activeControllersBuffer) {
375 if (!controller.isActiveAndEnabled)
continue;
376 (controller as IInternalInteractionController).FixedUpdateController();
380 using (
new ProfilerSample(
"Fixed Update Controllers (Interaction State and Callbacks)")) {
402 foreach (var controller
in _graspingControllersBuffer) {
403 IInteractionBehaviour suspendedObj;
404 if ((controller as IInternalInteractionController).CheckSuspensionBegin(out suspendedObj)) {
405 suspendedObj.BeginSuspension(controller);
410 foreach (var controller
in _graspingControllersBuffer) {
411 IInteractionBehaviour resumedObj;
412 if ((controller as IInternalInteractionController).CheckSuspensionEnd(out resumedObj)) {
413 resumedObj.EndSuspension(controller);
419 checkEndingGrasps(_graspingControllersBuffer);
420 checkEndingContacts(_contactControllersBuffer);
421 checkEndingPrimaryHovers(_hoverControllersBuffer);
422 checkEndingHovers(_hoverControllersBuffer);
426 checkBeginningHovers(_hoverControllersBuffer);
427 checkBeginningPrimaryHovers(_hoverControllersBuffer);
428 checkBeginningContacts(_contactControllersBuffer);
429 checkBeginningGrasps(_graspingControllersBuffer);
433 checkSustainingHovers(_hoverControllersBuffer);
434 checkSustainingPrimaryHovers(_hoverControllersBuffer);
435 checkSustainingContacts(_contactControllersBuffer);
436 checkSustainingGrasps(_graspingControllersBuffer);
441 #region State-Check Remapping Functions
444 remapInteractionObjectStateChecks(
446 stateCheckFunc: (InteractionController maybeReleasingController, out IInteractionBehaviour maybeReleasedObject) => {
447 return (maybeReleasingController as IInternalInteractionController).CheckGraspEnd(out maybeReleasedObject);
449 actionPerInteractionObject: (releasedObject, releasingIntControllers) => {
450 releasedObject.EndGrasp(releasingIntControllers);
455 remapMultiInteractionObjectStateChecks(
457 multiObjectStateCheckFunc: (InteractionController maybeEndedContactingController, out HashSet<IInteractionBehaviour> endContactedObjects) => {
458 return (maybeEndedContactingController as IInternalInteractionController).CheckContactEnd(out endContactedObjects);
460 actionPerInteractionObject: (endContactedObject, endContactedIntControllers) => {
461 endContactedObject.EndContact(endContactedIntControllers);
466 remapInteractionObjectStateChecks(
468 stateCheckFunc: (InteractionController maybeEndedPrimaryHoveringController, out IInteractionBehaviour endPrimaryHoveredObject) => {
469 return (maybeEndedPrimaryHoveringController as IInternalInteractionController).CheckPrimaryHoverEnd(out endPrimaryHoveredObject);
471 actionPerInteractionObject: (endPrimaryHoveredObject, noLongerPrimaryHoveringControllers) => {
472 endPrimaryHoveredObject.EndPrimaryHover(noLongerPrimaryHoveringControllers);
477 remapMultiInteractionObjectStateChecks(
479 multiObjectStateCheckFunc: (InteractionController maybeEndedHoveringController, out HashSet<IInteractionBehaviour> endHoveredObjects) => {
480 return (maybeEndedHoveringController as IInternalInteractionController).CheckHoverEnd(out endHoveredObjects);
482 actionPerInteractionObject: (endHoveredObject, endHoveringIntControllers) => {
483 endHoveredObject.EndHover(endHoveringIntControllers);
488 remapMultiInteractionObjectStateChecks(
490 multiObjectStateCheckFunc: (InteractionController maybeBeganHoveringController, out HashSet<IInteractionBehaviour> beganHoveredObjects) => {
491 return (maybeBeganHoveringController as IInternalInteractionController).CheckHoverBegin(out beganHoveredObjects);
493 actionPerInteractionObject: (beganHoveredObject, beganHoveringIntControllers) => {
494 beganHoveredObject.BeginHover(beganHoveringIntControllers);
499 remapInteractionObjectStateChecks(
501 stateCheckFunc: (InteractionController maybeBeganPrimaryHoveringController, out IInteractionBehaviour primaryHoveredObject) => {
502 return (maybeBeganPrimaryHoveringController as IInternalInteractionController).CheckPrimaryHoverBegin(out primaryHoveredObject);
504 actionPerInteractionObject: (newlyPrimaryHoveredObject, beganPrimaryHoveringControllers) => {
505 newlyPrimaryHoveredObject.BeginPrimaryHover(beganPrimaryHoveringControllers);
510 remapMultiInteractionObjectStateChecks(
512 multiObjectStateCheckFunc: (InteractionController maybeBeganContactingController, out HashSet<IInteractionBehaviour> beganContactedObjects) => {
513 return (maybeBeganContactingController as IInternalInteractionController).CheckContactBegin(out beganContactedObjects);
515 actionPerInteractionObject: (beganContactedObject, beganContactingIntControllers) => {
516 beganContactedObject.BeginContact(beganContactingIntControllers);
521 remapInteractionObjectStateChecks(
523 stateCheckFunc: (InteractionController maybeBeganGraspingController, out IInteractionBehaviour graspedObject) => {
524 return (maybeBeganGraspingController as IInternalInteractionController).CheckGraspBegin(out graspedObject);
526 actionPerInteractionObject: (newlyGraspedObject, beganGraspingIntControllers) => {
527 newlyGraspedObject.BeginGrasp(beganGraspingIntControllers);
532 remapMultiInteractionObjectStateChecks(
534 multiObjectStateCheckFunc: (InteractionController maybeSustainedHoveringController, out HashSet<IInteractionBehaviour> hoveredObjects) => {
535 return (maybeSustainedHoveringController as IInternalInteractionController).CheckHoverStay(out hoveredObjects);
537 actionPerInteractionObject: (hoveredObject, hoveringIntControllers) => {
538 hoveredObject.StayHovered(hoveringIntControllers);
542 private void checkSustainingPrimaryHovers(ReadonlyHashSet<InteractionController>
interactionControllers) {
543 remapInteractionObjectStateChecks(
545 stateCheckFunc: (InteractionController maybeSustainedPrimaryHoveringController, out IInteractionBehaviour primaryHoveredObject) => {
546 return (maybeSustainedPrimaryHoveringController as IInternalInteractionController).CheckPrimaryHoverStay(out primaryHoveredObject);
548 actionPerInteractionObject: (primaryHoveredObject, primaryHoveringControllers) => {
549 primaryHoveredObject.StayPrimaryHovered(primaryHoveringControllers);
554 remapMultiInteractionObjectStateChecks(
556 multiObjectStateCheckFunc: (InteractionController maybeSustainedContactingController, out HashSet<IInteractionBehaviour> contactedObjects) => {
557 return (maybeSustainedContactingController as IInternalInteractionController).CheckContactStay(out contactedObjects);
559 actionPerInteractionObject: (contactedObject, contactingIntControllers) => {
560 contactedObject.StayContacted(contactingIntControllers);
565 remapInteractionObjectStateChecks(
567 stateCheckFunc: (InteractionController maybeSustainedGraspingController, out IInteractionBehaviour graspedObject) => {
568 return (maybeSustainedGraspingController as IInternalInteractionController).CheckGraspHold(out graspedObject);
570 actionPerInteractionObject: (contactedObject, contactingIntControllers) => {
571 contactedObject.StayGrasped(contactingIntControllers);
575 private delegate
bool StateChangeCheckFunc(InteractionController controller, out IInteractionBehaviour obj);
576 private delegate
bool MultiStateChangeCheckFunc(InteractionController controller, out HashSet<IInteractionBehaviour> objs);
579 private static Dictionary<IInteractionBehaviour, List<InteractionController>> s_objControllersMap =
new Dictionary<IInteractionBehaviour, List<InteractionController>>();
584 private void remapInteractionObjectStateChecks(ReadonlyHashSet<InteractionController> controllers,
585 StateChangeCheckFunc stateCheckFunc,
586 Action<IInteractionBehaviour, List<InteractionController>> actionPerInteractionObject) {
589 if (s_objControllersMap ==
null) s_objControllersMap =
new Dictionary<IInteractionBehaviour, List<InteractionController>>();
590 s_objControllersMap.Clear();
594 foreach (var controller
in controllers) {
595 IInteractionBehaviour objectWhoseStateChanged;
596 if (stateCheckFunc(controller, out objectWhoseStateChanged)) {
597 if (!s_objControllersMap.ContainsKey(objectWhoseStateChanged)) {
598 s_objControllersMap[objectWhoseStateChanged] = Pool<List<InteractionController>>.Spawn();
600 s_objControllersMap[objectWhoseStateChanged].Add(controller);
604 foreach (var objControllesPair
in s_objControllersMap) {
605 actionPerInteractionObject(objControllesPair.Key, objControllesPair.Value);
608 objControllesPair.Value.Clear();
609 Pool<List<InteractionController>>.Recycle(objControllesPair.Value);
616 private void remapMultiInteractionObjectStateChecks(ReadonlyHashSet<InteractionController> controllers,
617 MultiStateChangeCheckFunc multiObjectStateCheckFunc,
618 Action<IInteractionBehaviour, List<InteractionController>> actionPerInteractionObject) {
620 if (s_objControllersMap ==
null) s_objControllersMap =
new Dictionary<IInteractionBehaviour, List<InteractionController>>();
621 s_objControllersMap.Clear();
625 foreach (var controller
in controllers) {
626 HashSet<IInteractionBehaviour> stateChangedObjects;
627 if (multiObjectStateCheckFunc(controller, out stateChangedObjects)) {
628 foreach (var stateChangedObject
in stateChangedObjects) {
629 if (!s_objControllersMap.ContainsKey(stateChangedObject)) {
630 s_objControllersMap[stateChangedObject] = Pool<List<InteractionController>>.Spawn();
632 s_objControllersMap[stateChangedObject].Add(controller);
637 foreach (var objControllersPair
in s_objControllersMap) {
638 actionPerInteractionObject(objControllersPair.Key, objControllersPair.Value);
641 objControllersPair.Value.Clear();
642 Pool<List<InteractionController>>.Recycle(objControllersPair.Value);
648 #region State Notifications
725 #region Object Registration
728 _interactionObjects.Add(interactionObj);
738 bool wasRemovalSuccessful = _interactionObjects.Remove(interactionObj);
739 if (wasRemovalSuccessful) {
740 foreach (var intController
in _interactionControllers) {
741 intController.ReleaseObject(interactionObj);
743 intController.NotifyObjectUnregistered(interactionObj);
747 return wasRemovalSuccessful;
751 return _interactionObjects.Contains(interactionObj);
756 #region Moving Frame of Reference Support
760 return (this.transform.position - _prevPosition).magnitude > 0.0001F
761 || Quaternion.Angle(transform.rotation * Quaternion.Inverse(_prevRotation),
762 Quaternion.identity) > 0.01F;
767 private Vector3 _prevPosition = Vector3.zero;
768 private Quaternion _prevRotation = Quaternion.identity;
770 private void updateMovingFrameOfReferenceSupport() {
771 _prevPosition = this.transform.position;
772 _prevRotation = this.transform.rotation;
782 Vector3 worldDisplacement = this.transform.position - _prevPosition;
783 Quaternion worldRotation = this.transform.rotation * Quaternion.Inverse(_prevRotation);
784 newPosition = ((worldRotation * (position - this.transform.position + worldDisplacement))) + this.transform.position;
785 newRotation = worldRotation * rotation;
795 Vector3 worldDisplacement = this.transform.position - _prevPosition;
796 Quaternion worldRotation = this.transform.rotation * Quaternion.Inverse(_prevRotation);
797 newPosition = ((worldRotation * (position - this.transform.position + worldDisplacement))) + this.transform.position;
802 #region Soft Contact Support
809 =
new List<PhysicsUtility.SoftContact>(80);
816 =
new Dictionary<Rigidbody, PhysicsUtility.Velocities>(5);
821 private List<PhysicsUtility.SoftContact> _softContactsToDraw
822 =
new List<PhysicsUtility.SoftContact>();
826 #region Interaction Controllers
828 private void refreshInteractionControllers() {
829 _interactionControllers.Clear();
831 var tempControllers = Pool<List<InteractionController>>.Spawn();
834 foreach (var controller
in tempControllers) {
835 _interactionControllers.Add(controller);
839 tempControllers.Clear();
840 Pool<List<InteractionController>>.Recycle(tempControllers);
848 #region Automatic Layers
854 for (
int i = 8; i < 32; i++) {
855 string layerName = LayerMask.LayerToName(i);
856 if (
string.IsNullOrEmpty(layerName)) {
871 if (Application.isPlaying) {
874 Debug.LogError(
"InteractionManager Could not find enough free layers for "
875 +
"auto-setup; manual setup is required.", this.gameObject);
881 private void setupAutomaticCollisionLayers() {
882 for (
int i = 0; i < 32; i++) {
902 #region Interaction Object Layer Tracking
904 private Dictionary<SingleLayer, HashSet<IInteractionBehaviour>> _intObjInteractionLayers =
new Dictionary<SingleLayer, HashSet<IInteractionBehaviour>>();
905 private Dictionary<SingleLayer, HashSet<IInteractionBehaviour>> _intObjNoContactLayers =
new Dictionary<SingleLayer, HashSet<IInteractionBehaviour>>();
907 private int _interactionLayerMask = 0;
912 return _interactionLayerMask;
915 private void refreshInteractionLayerMask() {
916 _interactionLayerMask = 0;
919 foreach (var layerObjSetPair
in _intObjInteractionLayers) {
921 if (layerObjSetPair.Value.Count == 0)
continue;
923 _interactionLayerMask = layerObjSetPair.Key.layerMask | _interactionLayerMask;
925 foreach (var layerObjSetPair
in _intObjNoContactLayers) {
927 if (layerObjSetPair.Value.Count == 0)
continue;
929 _interactionLayerMask = layerObjSetPair.Key.layerMask | _interactionLayerMask;
933 private bool[] _contactBoneIgnoreCollisionLayers =
new bool[32];
940 private void autoUpdateContactBoneLayerCollision() {
942 for (
int i = 0; i < 32; i++) {
943 _contactBoneIgnoreCollisionLayers[i] =
true;
948 foreach (var layerObjSetPair
in _intObjInteractionLayers) {
949 bool ignoreLayerCollision;
951 if (layerObjSetPair.Value.Count == 0) {
952 ignoreLayerCollision =
true;
955 ignoreLayerCollision =
false;
958 if (layerObjSetPair.Key.layerIndex < _contactBoneIgnoreCollisionLayers.Length) {
959 _contactBoneIgnoreCollisionLayers[layerObjSetPair.Key.layerIndex] = ignoreLayerCollision;
963 for (
int i = 0; i < 32; i++) {
965 _contactBoneIgnoreCollisionLayers[i]);
969 void IInternalInteractionManager.RefreshLayersNow() {
970 refreshInteractionLayerMask();
973 void IInternalInteractionManager.NotifyIntObjAddedInteractionLayer(IInteractionBehaviour intObj,
int layer,
bool refreshImmediately) {
974 if (!_intObjInteractionLayers.ContainsKey(layer)) {
975 _intObjInteractionLayers[layer] =
new HashSet<IInteractionBehaviour>();
978 _intObjInteractionLayers[layer].Add(intObj);
980 if (refreshImmediately) {
981 refreshInteractionLayerMask();
985 void IInternalInteractionManager.NotifyIntObjRemovedInteractionLayer(IInteractionBehaviour intObj,
int layer,
bool refreshImmediately) {
986 _intObjInteractionLayers[layer].Remove(intObj);
988 if (refreshImmediately) {
989 refreshInteractionLayerMask();
993 void IInternalInteractionManager.NotifyIntObjAddedNoContactLayer(IInteractionBehaviour intObj,
int layer,
bool refreshImmediately) {
994 if (!_intObjNoContactLayers.ContainsKey(layer)) {
995 _intObjNoContactLayers[layer] =
new HashSet<IInteractionBehaviour>();
998 _intObjNoContactLayers[layer].Add(intObj);
1000 if (refreshImmediately) {
1001 refreshInteractionLayerMask();
1005 void IInternalInteractionManager.NotifyIntObjRemovedNoContactLayer(IInteractionBehaviour intObj,
int layer,
bool refreshImmediately) {
1006 _intObjNoContactLayers[layer].Remove(intObj);
1008 if (refreshImmediately) {
1009 refreshInteractionLayerMask();
1017 #region Runtime Gizmos
1020 if (_drawControllerRuntimeGizmos) {
1021 foreach (var controller
in _interactionControllers) {
1022 if (controller !=
null) {
1023 controller.OnDrawRuntimeGizmos(drawer);
1027 foreach (PhysicsUtility.SoftContact contact in _softContactsToDraw) {
1029 drawer.
DrawLine(contact.position, contact.position + (contact.normal * 0.02f));
Dictionary< Rigidbody, ContactBone > contactBoneBodies
Maps a Rigidbody to its attached ContactBone, if the Rigidbody is part of an interaction controller.
Dictionary< Rigidbody, PhysicsUtility.Velocities > _softContactOriginalVelocities
Stores data for implementing Soft Contact for interaction controllers.
SingleLayer templateLayer
float SimulationScale
A scale that can be used to appropriately transform distances that otherwise expect one Unity unit to...
SingleLayer _templateLayer
SingleLayer _interactionNoContactLayer
float WorldHoverActivationRadius
Interaction objects further than this distance from a given controller's hover point will not be cons...
float hoverActivationRadius
List< PhysicsUtility.SoftContact > _softContacts
Stores data for implementing Soft Contact for interaction controllers.
bool UnregisterInteractionBehaviour(IInteractionBehaviour interactionObj)
Returns true if the Interaction Behaviour was registered with this manager; otherwise returns false....
SingleLayer _interactionLayer
ReadonlyHashSet< InteractionController > interactionControllers
Gets the list of interaction controllers managed by this InteractionManager.
SingleLayer contactBoneLayer
Dictionary< Rigidbody, IInteractionBehaviour > interactionObjectBodies
Maps a Rigidbody to its attached interaction object, if the Rigidbody is part of and interaction obje...
SingleLayer _contactBoneLayer
void TransformAheadByFixedUpdate(Vector3 position, out Vector3 newPosition)
Transforms a position ahead by one FixedUpdate based on the prior motion (position AND rotation) of t...
bool autoGenerateLayers
Gets whether auto-generate layers was enabled for this Interaction Manager.
bool IsBehaviourRegistered(IInteractionBehaviour interactionObj)
bool hasMovingFrameOfReference
void TransformAheadByFixedUpdate(Vector3 position, Quaternion rotation, out Vector3 newPosition, out Quaternion newRotation)
Transforms a position and rotation ahead by one FixedUpdate based on the prior motion of the Interact...
float touchActivationRadius
SingleLayer interactionLayer
void generateAutomaticLayers()
Action OnPrePhysicalUpdate
int GetInteractionLayerMask()
Returns a layer mask containing all layers that might contain interaction objects.
void RegisterInteractionBehaviour(IInteractionBehaviour interactionObj)
ReadonlyHashSet< IInteractionBehaviour > interactionObjects
Gets a set of all interaction objects currently registered with this Interaction Manager.
static InteractionManager instance
Often, only one InteractionManager is necessary per Unity scene. This property will contain that Inte...
void OnDrawRuntimeGizmos(RuntimeGizmoDrawer drawer)
Action OnPostPhysicalUpdate
MultiGraspHoldingMode multiGraspHoldingMode
float WorldTouchActivationRadius
Interaction objects further than this distance from a given controller's hover point will not be cons...
SingleLayer interactionNoContactLayer
void DrawLine(Vector3 a, Vector3 b)
Draws a gizmo line that connects the two positions.
void DrawSphere(Vector3 center, float radius)
Draws a filled gizmo sphere at the given position with the given radius.
IInteractionBehaviour is the interface that defines all Interaction objects, specifying the minimum s...
Have your MonoBehaviour implement this interface to be able to draw runtime gizmos....
A simple wrapper around HashSet to provide readonly access. Useful when you want to return a HashSet ...
An object you can use to represent a single Unity layer as a dropdown in the inspector....