Author Topic: Script to disable clipped UIPanel colliders  (Read 3526 times)

sirival

  • Guest
Script to disable clipped UIPanel colliders
« on: December 12, 2012, 05:54:02 AM »
Hello,

As far as I know if you have a UIPanel that has clipping enabled, the only way to avoid clicking on buttons that are outside the clipping range is to add big colliders to the sides of the UIPanel so that you cannot click on these buttons. This solution does not work well if you have a lot of clippable UIPanels all around the place. So this is a script that automatically disables any colliders that are outside the clipping range of a clippable UIPanel:

  1. using UnityEngine;
  2.  
  3. /// <remarks>
  4. /// This script disables colliders that are outside of a UIPanel's clipping range
  5. /// or enables them if they intersect it. This only works for UIPanels that are not dragged around.
  6. /// </remarks>
  7. public class UIColliderClipper : MonoBehaviour
  8. {
  9.     #region Inspector Data
  10.  
  11.     /// <summary>
  12.     /// Indicates the number of frames that need to
  13.     /// pass before updating the colliders
  14.     /// </summary>
  15.     public int UpdateRate = 5;
  16.    
  17.     /// <summary>
  18.     /// The panel that contains the clipping range
  19.     /// </summary>
  20.     public UIPanel ClippingPanel;
  21.    
  22.     /// <summary>
  23.     /// The transform of the parent that contains the colliders
  24.     /// </summary>
  25.     public Transform Container;
  26.  
  27.     #endregion
  28.  
  29.     #region Data
  30.  
  31.     private int _frames;
  32.     private Bounds _panelBounds;
  33.     private Vector3 _lastContainerPosition;
  34.     private int _widgetCount;
  35.  
  36.     #endregion
  37.  
  38.     /// <summary>
  39.     /// Initialization
  40.     /// </summary>
  41.     void Start()
  42.     {
  43.         _panelBounds = GetPanelBounds();
  44.         _lastContainerPosition = new Vector3( Mathf.Infinity, Mathf.Infinity, Mathf.Infinity );
  45.         _widgetCount = ClippingPanel.widgets.size;
  46.     }
  47.  
  48.     /// <summary>
  49.     /// Disables / Enables colliders based on their collider bounds in respect to the clipping range
  50.     /// </summary>
  51.         void Update ()
  52.         {
  53.             _frames++;
  54.         if ( _frames < UpdateRate )
  55.             return;
  56.             _frames = 0;
  57.  
  58.         // check if the parent container has moved...
  59.         if ( !Approximately( Container.localPosition, _lastContainerPosition ) )
  60.         {
  61.             _lastContainerPosition = Container.localPosition;
  62.         }
  63.         else
  64.         {
  65.             //... or if new children were added to the panel
  66.             if( _widgetCount != ClippingPanel.widgets.size )
  67.             {
  68.                 _widgetCount = ClippingPanel.widgets.size;
  69.             }
  70.             else
  71.             {
  72.                 return;    
  73.             }
  74.         }
  75.  
  76.         // update colliders
  77.         var widgetColliders = GetComponentsInChildren<BoxCollider>();
  78.         for ( int i = 0; i < widgetColliders.Length; i++ )
  79.         {
  80.             var bounds = GetWidgetBounds( widgetColliders[i] );
  81.             widgetColliders[i].enabled = bounds.Intersects( _panelBounds );
  82.         }
  83.         }
  84.  
  85.     /// <summary>
  86.     /// Returns true if the two vectors are approximately equal
  87.     /// </summary>    
  88.     private static bool Approximately( Vector3 lhs, Vector3 rhs )
  89.     {
  90.         if ( Mathf.Approximately( lhs.x, rhs.x ) &&
  91.             Mathf.Approximately( lhs.y, rhs.y ) &&
  92.             Mathf.Approximately( lhs.z, rhs.z ) )
  93.         {
  94.             return true;
  95.         }
  96.  
  97.         return false;
  98.     }
  99.  
  100.     /// <summary>
  101.     /// Gets the bounds of a transform based on a center and a size
  102.     /// in local coordinates
  103.     /// </summary>
  104.     private static Bounds GetBounds( Transform transform, Vector3 localCenter, Vector3 localSize )
  105.     {
  106.         var center = transform.position;
  107.         center += Vector3.Scale( transform.lossyScale, localCenter);
  108.         center.z = 0;
  109.  
  110.         var size = Vector3.Scale( transform.lossyScale, localSize);
  111.         size.z = 0;
  112.  
  113.         return new Bounds( center, size );
  114.     }
  115.  
  116.     /// <summary>
  117.     /// Gets the bounds of the UIPanel
  118.     /// </summary>
  119.     /// <returns></returns>
  120.     private Bounds GetPanelBounds()
  121.     {
  122.         return GetBounds( ClippingPanel.cachedTransform,
  123.                           new Vector3( ClippingPanel.clipRange.x, ClippingPanel.clipRange.y, 0 ),
  124.                           new Vector3( ClippingPanel.clipRange.z, ClippingPanel.clipRange.w ) );
  125.     }
  126.    
  127.     /// <summary>
  128.     /// Gets the bounds of a widget
  129.     /// </summary>
  130.     private Bounds GetWidgetBounds( BoxCollider widgetCollider )
  131.     {
  132.         return GetBounds( widgetCollider.transform, widgetCollider.center, widgetCollider.size );
  133.     }
  134.    
  135. }
  136.  
  137.  
  138.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Script to disable clipped UIPanel colliders
« Reply #1 on: December 12, 2012, 12:37:54 PM »
Not anymore. This is now built-in.

sirival

  • Guest
Re: Script to disable clipped UIPanel colliders
« Reply #2 on: December 12, 2012, 01:09:22 PM »
Oh lol! And how do we turn it on?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Script to disable clipped UIPanel colliders
« Reply #3 on: December 12, 2012, 03:00:05 PM »
UICamera.clipRaycasts. It's on by default.