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 - mixd

Pages: [1]
1
NGUI 3 Support / SpringDampen Performance optimization
« on: July 05, 2013, 11:15:25 PM »
Noticed this was starting to eat up some CPU cycles and the current implementation seemed odd. This is roughly 4x faster than the current method (rough benchmark).

Original Way:
  1. static public Vector3 SpringDampen (ref Vector3 velocity, float strength, float deltaTime)
  2.         {
  3.                 // Dampening factor applied each millisecond
  4.                 if (deltaTime > 1f) deltaTime = 1f;
  5.                 float dampeningFactor = 1f - strength * 0.001f;
  6.                 int ms = Mathf.RoundToInt(deltaTime * 1000f);
  7.                 Vector3 offset = Vector3.zero;
  8.  
  9.                 // Apply the offset for each millisecond
  10.                 for (int i = 0; i < ms; ++i)
  11.                 {
  12.                         // Mimic 60 FPS the editor runs at
  13.                         offset += velocity * 0.06f;
  14.                         velocity *= dampeningFactor;
  15.                 }
  16.                 return offset;
  17.         }


Faster Way (Use raw math instead of a loop)
  1. static public Vector3 SpringDampen (ref Vector3 velocity, float strength, float deltaTime)
  2.         {
  3.                 // Dampening factor applied each millisecond
  4.                 if (deltaTime > 1f) deltaTime = 1f;
  5.                 float dampeningFactor = 1f - strength * 0.001f;
  6.                 int ms = Mathf.RoundToInt(deltaTime * 1000f);
  7.  
  8.                 float totalDampening = Mathf.Pow(dampeningFactor, ms);
  9.                 Vector3 vTotal = velocity * ((totalDampening - 1f) / Mathf.Log(dampeningFactor));
  10.                 velocity = velocity * totalDampening;
  11.                
  12.                 return vTotal * .06f;
  13.         }

2
Currently while dragging a panel, the drag does not start until the drag threshold is reached. This is fine, however results in a "jump" when the drag starts.

If you observe standard iOS behavior, there is no jump. Anyway here is the code to fix it so dragging panels have no jumpiness. Note that the drag threshold is still preserved as it should be.

In UIDraggablePanel.cs add the following lines:
  1. Vector2 _startOffset;
  2. bool _startOffsetSet = false;

Then in the Drag function, after UICamera.currentTouch.clickNotification = UICamera.ClickNotification.BasedOnDelta; Add the following:
  1. if(!_startOffsetSet)
  2. {
  3.         _startOffset = UICamera.currentTouch.totalDelta;
  4.         _startOffsetSet = true;
  5. }

Then also in the Drag function, update this line and move it below the code you just added (just added - _startOffset to it)
  1. Ray ray = UICamera.currentCamera.ScreenPointToRay(UICamera.currentTouch.pos - _startOffset);

Then in the OnPress function in the "else" block, add the following:
  1. _startOffsetSet = false;


Overall looks like this:
  1. public void Press (bool pressed)
  2.         {
  3.                 if (enabled && NGUITools.GetActive(gameObject))
  4.                 {
  5.                         if (!pressed && mDragID == UICamera.currentTouchID) mDragID = -10;
  6.  
  7.                         mCalculatedBounds = false;
  8.                         mShouldMove = shouldMove;
  9.                         if (!mShouldMove) return;
  10.                         mPressed = pressed;
  11.  
  12.                         if (pressed)
  13.                         {
  14.                                 // Remove all momentum on press
  15.                                 mMomentum = Vector3.zero;
  16.                                 mScroll = 0f;
  17.  
  18.                                 // Disable the spring movement
  19.                                 DisableSpring();
  20.  
  21.                                 // Remember the hit position
  22.                                 mLastPos = UICamera.lastHit.point;
  23.  
  24.                                 // Create the plane to drag along
  25.                                 mPlane = new Plane(mTrans.rotation * Vector3.back, mLastPos);
  26.                         }
  27.                         else
  28.                         {
  29.                                 _startOffsetSet = false;
  30.                                 if (restrictWithinPanel && mPanel.clipping != UIDrawCall.Clipping.None && dragEffect == DragEffect.MomentumAndSpring)
  31.                                 {
  32.                                         RestrictWithinBounds(false);
  33.                                 }
  34.                                 if (onDragFinished != null) onDragFinished();
  35.                         }
  36.                 }
  37.         }
  38.  
  39.         /// <summary>
  40.         /// Drag the object along the plane.
  41.         /// </summary>
  42.  
  43.        
  44.         Vector2 _startOffset;
  45.         bool _startOffsetSet = false;
  46.        
  47.         public void Drag (Vector2 delta)
  48.         {
  49.                 if (enabled && NGUITools.GetActive(gameObject) && mShouldMove)
  50.                 {
  51.                         if (mDragID == -10) mDragID = UICamera.currentTouchID;
  52.                         UICamera.currentTouch.clickNotification = UICamera.ClickNotification.BasedOnDelta;
  53.                        
  54.                         if(!_startOffsetSet)
  55.                         {
  56.                                 _startOffset = UICamera.currentTouch.totalDelta;
  57.                                 _startOffsetSet = true;
  58.                         }
  59.  
  60.                         Ray ray = UICamera.currentCamera.ScreenPointToRay(UICamera.currentTouch.pos - _startOffset);
  61.                         float dist = 0f;
  62.                        

3
I found myself needing to know when a click was canceled in order to update the UI.  This is important in some situations so that the user knows what will happen when they lift their finger.
The new events are called "OnClickDisabled" and "OnClickEnabled". It has been tested on both regular as well as draggable buttons.

I purposely made as few changes to the code as possible. If this makes it into a release version there is some consolidation that can be done to keep it as elegant as the existing code.

Anyway here is the addition:

in UICamera.cs

1. add this as a private variable
  1. bool _clickFlagEnabled = true;

2. insert this after the existing code "Notify(currentTouch.pressed, "OnDrag", currentTouch.delta);"
  1. if (_clickFlagEnabled && (isDisabled || currentTouch.pressed != currentTouch.current))
  2. {
  3.         Notify(currentTouch.pressed, "OnClickDisabled", currentTouch.delta);
  4.         _clickFlagEnabled = false;
  5. }
  6. else if(!_clickFlagEnabled && (!isDisabled && currentTouch.pressed == currentTouch.current))
  7. {
  8.         Notify(currentTouch.pressed, "OnClickEnabled", currentTouch.delta);
  9.         _clickFlagEnabled = true;
  10. }

3. insert this after the existing code "currentTouch.pressed = null;"
  1. _clickFlagEnabled = true;

4
NGUI 3 Support / iOS Scrolling Emulation
« on: November 18, 2012, 07:02:31 PM »
I would ask for this as a feature request, but I'll leave that up to Aren. Here is some code that anyone can drop in their project to make your scrolling windows feel more like native iOS scrolling. The change is subtle yet makes a huge improvement!

[in]
UIDraggablePanel.cs

[change]
  1. // Move the panel
  2. MoveAbsolute(offset);

[to]
  1. // Move the panel
  2. Vector3 constraint = mPanel.CalculateConstrainOffset(bounds.min, bounds.max);
  3. if (constraint.magnitude > 0.001f)
  4. {
  5.         MoveAbsolute(offset / 2f);
  6.         mMomentum /= 2f;
  7. }
  8. else
  9. {
  10.         MoveAbsolute(offset);
  11. }

5
NGUI 3 Support / iOS Scrolling Emulation
« on: April 19, 2012, 10:38:28 PM »
This is the only (slightly hacky) way I could come up with to simulate iOS scrolling, WITHOUT changing the core NGUI library. There is currently one flaw which I am unable to solve due to the access level of the underlying momentum.

Known issues: (This would be GREAT if an update gave better access to allow mods like this, or simply built it in)
1) iOS dampens "momentum" down to half of whatever it was at the point of impact. This is currently not possible without modifying the core NGUI library.

Instructions:
1) Add this component to any game object that has a UIDraggablePanel attached to it, and it will magically make your draggable lists more like iOS.

Code:
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class UIDraggablePanelDamper : MonoBehaviour {
  5.  
  6.         public float dampeningFactor = 0.5f;
  7.        
  8.         UIPanel mPanel;
  9.         UIDraggablePanel draggablePanel;
  10.         Vector3 originalScale;
  11.  
  12.         void Start () {
  13.                 draggablePanel = GetComponent<UIDraggablePanel>();
  14.                 mPanel = GetComponent<UIPanel>();
  15.                 originalScale = draggablePanel.scale;
  16.         }
  17.  
  18.         void Update () {
  19.                 Vector3 constraint = mPanel.CalculateConstrainOffset(draggablePanel.bounds.min, draggablePanel.bounds.max);
  20.                 bool outOfBounds = constraint.magnitude > 0.001f;
  21.                 draggablePanel.scale = outOfBounds ?  originalScale * dampeningFactor : originalScale;
  22.         }
  23. }
  24.  

Pages: [1]