@@ -177,6 +177,10 @@ public bool IgnoreCollidersNotInFOV
177
177
set => ignoreCollidersNotInFOV = value ;
178
178
}
179
179
180
+ [ SerializeField ]
181
+ private int nearInteractableCacheCapacity = 50 ;
182
+ private LRUCache < int , NearInteractionGrabbable > nearInteractionGrabbableCache ;
183
+
180
184
private SpherePointerQueryInfo queryBufferNearObjectRadius ;
181
185
private SpherePointerQueryInfo queryBufferInteractionRadius ;
182
186
@@ -201,6 +205,7 @@ private void Awake()
201
205
{
202
206
queryBufferNearObjectRadius = new SpherePointerQueryInfo ( sceneQueryBufferSize , Mathf . Max ( NearObjectRadius , SphereCastRadius ) , NearObjectSectorAngle , PullbackDistance , nearObjectSmoothingFactor , true ) ;
203
207
queryBufferInteractionRadius = new SpherePointerQueryInfo ( sceneQueryBufferSize , SphereCastRadius , 360.0f , 0.0f , 0.0f ) ;
208
+ nearInteractionGrabbableCache = new LRUCache < int , NearInteractionGrabbable > ( nearInteractableCacheCapacity ) ;
204
209
}
205
210
206
211
private static readonly ProfilerMarker OnPreSceneQueryPerfMarker = new ProfilerMarker ( "[MRTK] SpherePointer.OnPreSceneQuery" ) ;
@@ -233,7 +238,7 @@ public override void OnPreSceneQuery()
233
238
{
234
239
// First update queryBufferNearObjectRadius to see if there is a grabbable in the near interaction range
235
240
queryBufferNearObjectRadius . TryUpdateQueryBufferForLayerMask ( PrioritizedLayerMasksOverride [ i ] , pointerPosition - pointerAxis * PullbackDistance , triggerInteraction ) ;
236
- if ( queryBufferNearObjectRadius . HasValidGrabbable ( pointerPosition - pointerAxis * PullbackDistance , pointerAxis , ignoreCollidersNotInFOV ) )
241
+ if ( queryBufferNearObjectRadius . HasValidGrabbable ( pointerPosition - pointerAxis * PullbackDistance , pointerAxis , ignoreCollidersNotInFOV , nearInteractionGrabbableCache ) )
237
242
{
238
243
break ;
239
244
}
@@ -246,9 +251,9 @@ public override void OnPreSceneQuery()
246
251
{
247
252
// Then update queryBufferInteractionRadius to see if there is a grabbable that can be interacted with
248
253
queryBufferInteractionRadius . TryUpdateQueryBufferForLayerMask ( PrioritizedLayerMasksOverride [ i ] , pointerPosition , triggerInteraction ) ;
249
- if ( queryBufferInteractionRadius . HasValidGrabbable ( pointerPosition , pointerAxis , ignoreCollidersNotInFOV ) )
254
+ if ( queryBufferInteractionRadius . HasValidGrabbable ( pointerPosition , pointerAxis , ignoreCollidersNotInFOV , nearInteractionGrabbableCache ) )
250
255
{
251
- hitObject = queryBufferInteractionRadius . GetClosestValidGrabbable ( pointerPosition , pointerAxis , IgnoreCollidersNotInFOV , out hitPoint ) ;
256
+ hitObject = queryBufferInteractionRadius . GetClosestValidGrabbable ( pointerPosition , pointerAxis , IgnoreCollidersNotInFOV , out hitPoint , nearInteractionGrabbableCache ) ;
252
257
if ( hitObject != null )
253
258
{
254
259
hitDistance = ( pointerPosition - hitPoint ) . magnitude ;
@@ -462,15 +467,15 @@ public SpherePointerQueryInfo(int bufferSize, float radius, float angle, float m
462
467
ignoreBoundsHandlesForQuery = ignoreBoundsHandles ;
463
468
}
464
469
465
- public bool HasValidGrabbable ( Vector3 pointerPosition , Vector3 pointerAxis , bool ignoreCollidersNotInFOV )
470
+ public bool HasValidGrabbable ( Vector3 pointerPosition , Vector3 pointerAxis , bool ignoreCollidersNotInFOV , LRUCache < int , NearInteractionGrabbable > componentCache )
466
471
{
467
472
Vector3 grabbablePosition = pointerPosition ;
468
473
NearInteractionGrabbable currentGrabbable = null ;
469
474
470
475
for ( int i = 0 ; i < numColliders ; i ++ )
471
476
{
472
477
Collider collider = queryBuffer [ i ] ;
473
- if ( IsColliderValidGrabbable ( collider , ignoreCollidersNotInFOV , out currentGrabbable )
478
+ if ( IsColliderValidGrabbable ( collider , ignoreCollidersNotInFOV , out currentGrabbable , componentCache )
474
479
&& IsColliderPositionValid ( collider , pointerPosition , pointerAxis , queryAngle , queryMinDistance , out grabbablePosition ) )
475
480
{
476
481
if ( currentGrabbable != null )
@@ -491,7 +496,7 @@ public bool HasValidGrabbable(Vector3 pointerPosition, Vector3 pointerAxis, bool
491
496
492
497
/// <param name="pointerPosition">The position of the pointer to query against.</param>
493
498
/// <param name="ignoreCollidersNotInFOV">Whether to ignore colliders that are not visible.</param>
494
- public GameObject GetClosestValidGrabbable ( Vector3 pointerPosition , Vector3 pointerAxis , bool ignoreCollidersNotInFOV , out Vector3 hitPosition )
499
+ public GameObject GetClosestValidGrabbable ( Vector3 pointerPosition , Vector3 pointerAxis , bool ignoreCollidersNotInFOV , out Vector3 hitPosition , LRUCache < int , NearInteractionGrabbable > componentCache )
495
500
{
496
501
Vector3 colliderHitPoint = pointerPosition ; ;
497
502
NearInteractionGrabbable currentGrabbable = null ;
@@ -504,7 +509,7 @@ public GameObject GetClosestValidGrabbable(Vector3 pointerPosition, Vector3 poin
504
509
for ( int i = 0 ; i < numColliders ; i ++ )
505
510
{
506
511
Collider collider = queryBuffer [ i ] ;
507
- if ( IsColliderValidGrabbable ( collider , ignoreCollidersNotInFOV , out currentGrabbable )
512
+ if ( IsColliderValidGrabbable ( collider , ignoreCollidersNotInFOV , out currentGrabbable , componentCache )
508
513
&& IsColliderPositionValid ( collider , pointerPosition , pointerAxis , queryAngle , queryMinDistance , out colliderHitPoint ) )
509
514
{
510
515
float currentDistance = ( pointerPosition - colliderHitPoint ) . sqrMagnitude ;
@@ -576,13 +581,24 @@ public void TryUpdateQueryBufferForLayerMask(LayerMask layerMask, Vector3 pointe
576
581
}
577
582
}
578
583
579
- public bool IsColliderValidGrabbable ( Collider collider , bool ignoreCollidersNotInFOV , out NearInteractionGrabbable currentGrabbable )
584
+ public bool IsColliderValidGrabbable ( Collider collider , bool ignoreCollidersNotInFOV , out NearInteractionGrabbable currentGrabbable , LRUCache < int , NearInteractionGrabbable > componentCache )
580
585
{
581
586
// Check if the collider has a grabbable component which is valid
582
- currentGrabbable = collider . GetComponent < NearInteractionGrabbable > ( ) ;
587
+ int instanceId = collider . gameObject . GetInstanceID ( ) ;
588
+ if ( ! componentCache . TryGetValue ( instanceId , out currentGrabbable ) )
589
+ {
590
+ currentGrabbable = collider . gameObject . GetComponent < NearInteractionGrabbable > ( ) ;
591
+ if ( currentGrabbable != null )
592
+ {
593
+ componentCache . Add ( instanceId , currentGrabbable ) ;
594
+ }
595
+ }
596
+
583
597
bool isValidGrabbable = ( currentGrabbable != null ) && ! ( ignoreBoundsHandlesForQuery && currentGrabbable . IsBoundsHandles ) ;
584
598
if ( ! isValidGrabbable )
585
599
{
600
+ // Remove it from the cache if the grabbable is no longer valid for the object
601
+ componentCache . Remove ( instanceId ) ;
586
602
return false ;
587
603
}
588
604
0 commit comments