Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - seandanger

Pages: [1]
1
Has anyone come across this?  I've used UIEventListener.Get to add delegates successfully so many times, all of a sudden this particular one always throws this error (even though the function does get called).

  1. public Class SomeComponent : MonoBehaviour
  2. {
  3.     void Start()
  4.     {
  5.         UIEventListener.Get(this.gameObject).onClick += OnClicked;
  6.     }
  7.  
  8.     private void OnClicked(GameObject go)
  9.     {
  10.         Debug.Log("OnClicked");
  11.     }
  12. }
  13.  

Clicking this GameObject in game will print this in the console:
Quote
Failed to call function OnClick of class SomeComponent
Calling function OnClick with no parameters but the function requires 1.

OnClicked

Everything still works but I have no idea why Unity is throwing this error.  Anyone see this before?

This thread may be relevant too: http://answers.unity3d.com/questions/55194/suggested-workaround-for-sendmessage-bug.html

2
Hey everyone,

I've seen a few threads in the past mentioning this issue, and having struggled with it myself, I decided to post a guide on the solution that I've come up with.  I quickly want to point out that I have not yet battle tested this code or profiled it, or spent extra time optimizing, and I in no way guarantee its fitness or reliability.  So use at your own risk!  That said, it seems to be performing admirably in my game so far.  Carrying on...

The problem
Items outside of the clip area on a UIDraggablePanel are still active.  I think most people probably don't want their buttons clickable when they aren't visible.  The typical NGUI solution is to put blocking colliders around your clipping area, above (in the z dimension) your clipped content.  This works just fine but requires some extra labor and for some is annoying to deal with, especially in instances (like in my own game) where multiple UIDraggablePanels are adjacent to one another.

The code based solution
I've written a component that monitors whether or not it is within the clipping rect of a UIDraggablePanel.  When its state (in-bounds, or out-of-bounds) changes, it fires a delegate.  You also get to define the rectangle you want to use for determining whether or not your component is considered in bounds.

Here's an illustration showing how it works:


If you don't want to use delegates, you can also add in your own code here.  Either way, you can write your own code that handles what to do in this situation.  I've included some examples via in line comments.  I'm currently using it to automatically disable / enable the collider of the GameObject the component is attached to.

How to use
You'll need to modify two NGUI files in order to get the component to compile:

  • Add the following function to the UIPanel class in UIPanel.cs:
  1.         /// <summary>
  2.         /// Returns a Rect which describes the clipping area of this panel in Screen (pixel) coordinates.
  3.         /// This is the same area that is drawn with a magenta outline in the Scene gizmos.
  4.         /// </summary>
  5.         public Rect ClippingRectScreen
  6.         {
  7.                 get
  8.                 {
  9.                         Rect r = new Rect();
  10.                         Vector2 size = new Vector2(mClipRange.z, mClipRange.w);
  11.  
  12.                         if (size.x == 0f) size.x = mScreenSize.x;
  13.                         if (size.y == 0f) size.y = mScreenSize.y;
  14.                                                                
  15.                         Vector3 screenPos = UICamera.currentCamera.WorldToScreenPoint(transform.position);
  16.                                                                
  17.                         r.width = size.x;
  18.                         r.height = size.y;
  19.                         r.center = new Vector2(mClipRange.x + screenPos.x, mClipRange.y + screenPos.y);
  20.                                                                
  21.                         return r;
  22.                 }
  23.         }
  24.  
  • Add the following function to the UIDraggablePanel class in UIDraggablePanel.cs:
  1.         /// <summary>
  2.         /// Returns a Rect which describes the clipping area of this panel in Screen (pixel) coordinates.
  3.         /// This is the same area that is drawn with a magenta outline in the Scene gizmos.
  4.         /// </summary>
  5.         public Rect ClippingRectScreen
  6.         {
  7.                 get
  8.                 {
  9.                         return mPanel.ClippingRectScreen;
  10.                 }
  11.         }
  12.  

    Now you're ready to use the component, which is attached.  It uses a simple Axis Aligned Bounding Box hit test (not a Raycast) to determine whether or not the component is within the clip rect of the panel.  The component's "hit rectangle" (named boundsRect) is defined explicitly on the component, though you can have the component simply match the dimensions of the collider on the same GameObject if you choose.  The rect is shown via a Gizmo -- a pink box in the scene view.  I've found that having the rect around 50-60% of the size of the collider results in the behavior I'm looking for.

    It's relatively short and fairly heavily documented in-line, so read in there if you'd like to know more about it, or modify it.  If you want to use a different type of collision test, for example, you can use my code as a starting point for how to get the 2 rectangles in question.

    I hope this helps some people!  Also feel free to check out my company's site or my twitter if you're interested, where I periodically post about Unity gamedev topics.

    3
    I have a vertically-oriented UIDraggablePanel in my scene.  After dragging the contents downward, they snap back up into position as expected.  There is a minor problem though, as the calculated position the DraggablePanel moves back toward is slightly higher than it was previously, each time.  This result is my panel has a "resting position" many pixels above its original resting position.  Ideally, it would not do this and instead go no higher than its original position (which in my case, is y == 0.0f).

    Here's a small video demonstrating it, sorry for the blurriness, but you should get the idea: http://www.youtube.com/watch?v=PFQFwgxhilA

    I'll look into a workaround for now, just wanted to see if anyone knew about it or if ArenMook was working on it, or if I possibly have my panel setup incorrectly.  I'll update if I find my own fix.

    @Aren So far, it looks like the problem comes from SpringPanel over-shooting the panel's position when it returns.

    EDIT: The opposite also happens when dragging the panel beyond its upper limits so that it snaps back down slightly too far each time.

    4
    NGUI 3 Support / [Solved] Centering a UITable
    « on: August 15, 2012, 10:51:48 PM »
    After struggling with it for way too long, I've come up with a way to center a UITable that I thought others might find useful.

    The problem I had was getting a GameObject with a UITable component to center its contents.  I was adding items dynamically at runtime to the UITable, so manual positioning was not an option.  To solve the problem, I was trying to add the item, then get the dimensions of the object, calculate the center, and then set the position.

    What tripped me up was really 2 things:

    1.  You have to call UITable.Reposition() yourself.

    Easy enough -- it makes total sense that if you add items in the editor and then have to click "Reposition Now" that you would definitely need to call the equivalent in your code after adding items.  Simple mistake I'm blaming on lack of sleep :)

    2.  UITable.Reposition() might not (in my case, absolutely never) happens immediately.

    Due to the way I was adding items to my UITable, Reposition() was actually setting a flag, exiting early, and waiting for a proper Reposition() to occur later.  Somewhat clear after stepping through the code, but I think it would be nice if the online reference docs included a note about this behavior, as that's what I was going off initially.  The solution I used was to add a delegate to the UITable's onReposition event, then I handle my reposition code.

    How about the reposition code?  I went ahead and wrapped it up into a Component I called CenterUITable.  Here's the code if anyone is interested.  You can just drop this on the GameObject your UITable is in and it'll handle the rest.  You can also toggle whether x, y, or both gets centered.

    Hope it helps!

    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CenterUITable : MonoBehaviour
    5. {
    6.         public bool centerOnX = true;
    7.         public bool centerOnY = false;
    8.         public GameObject uiTableGameObject;
    9.        
    10.         private UITable _uiTable;
    11.        
    12.         void Start ()
    13.         {
    14.                 // find UITable on this gameObject if not explicitly set
    15.                 if (uiTableGameObject == null)
    16.                         uiTableGameObject = this.gameObject;
    17.                
    18.                 _uiTable = uiTableGameObject.GetComponent<UITable>();
    19.                
    20.                 if (_uiTable == null)
    21.                 {
    22.                         Debug.LogWarning("uiTableGameObject does not have a UITable Component at Start() time!  Destroying.");
    23.                         Destroy(this);
    24.                         return;
    25.                 }
    26.                
    27.                 _uiTable.onReposition += Reposition;
    28.         }
    29.        
    30.         void Reposition()
    31.         {
    32.                 // do the actual repositioning
    33.                 Bounds bounds = NGUIMath.CalculateRelativeWidgetBounds(_uiTable.transform);
    34.                 Vector3 pos = _uiTable.transform.localPosition;
    35.                
    36.                 if (centerOnX)
    37.                         pos.x = -bounds.center.x;
    38.                
    39.                 if (centerOnY)
    40.                         pos.y = -bounds.center.y;
    41.                
    42.                 _uiTable.transform.localPosition = pos;
    43.         }
    44.        
    45.         void OnDestroy()
    46.         {
    47.                 if (_uiTable)
    48.                         _uiTable.onReposition -= Reposition;
    49.         }
    50. }
    51.  

    5
    NGUI 3 Support / Joystick, DPad, + more with NGUI available
    « on: June 13, 2012, 01:46:48 PM »
    Hello all, I hope it's appropriate to post here since the old "Showcase" forum is disabled, but I'd like to announce that my company has just released Virtual Controls Suite, which is a set of control components for touch screen devices.

    I use NGUI myself and so of course made the package fully functional with NGUI.  So, if you're looking for ready to use and fully customizable analog joysticks, dpad, and buttons for your game, check it out!

    Product page on our website with more info: http://bitbybitstudios.com/portfolio/virtual-controls-suite/
    Asset store link: http://u3d.as/content/bit-by-bit-studios/virtual-controls-suite

    -Sean

    Pages: [1]