Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Scripts] Useful 4.6 Scripts Collection

Discussion in 'UGUI & TextMesh Pro' started by Melang, Aug 24, 2014.

  1. AriathTheSage

    AriathTheSage

    Joined:
    Aug 25, 2014
    Posts:
    13
    Here is my little sand grain :) .

    UITextField, an InputField with public Append methods:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. /// <summary>
    6. /// UI TextField
    7. /// NOTE: This is temporary, until Unity InputField has a public Append method.
    8. /// </summary>
    9. public class UITextField : InputField
    10. {
    11.     /// <summary>
    12.     /// Appends the given char to the text field
    13.     /// </summary>
    14.     /// <param name="input">Char to append</param>
    15.     new public void Append (char input)
    16.     {
    17.         base.Append(input);
    18.     }
    19.  
    20.  
    21.     /// <summary>
    22.     /// Appends the given string to the text field
    23.     /// </summary>
    24.     /// <param name="input">String to append</param>
    25.     new public void Append (string input)
    26.     {
    27.         base.Append(input);
    28.     }
    29. }

    And here is my UIButton, a Button with some added events:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Events;
    4. using UnityEngine.EventSystems;
    5. using UnityEngine.UI;
    6. using System.Collections;
    7.  
    8.  
    9. /// <summary>
    10. /// UIButton
    11. /// </summary>
    12. public class UIButton : Button, IPointerDownHandler, IPointerUpHandler
    13. {
    14.     #region Sub-Classes
    15.     [System.Serializable]
    16.     public class UIButtonEvent : UnityEvent<PointerEventData.InputButton> { }
    17.     #endregion
    18.  
    19.  
    20.     #region Events
    21.     public UIButtonEvent OnButtonClick;
    22.     public UIButtonEvent OnButtonPress;
    23.     public UIButtonEvent OnButtonRelease;
    24.     #endregion
    25.    
    26.  
    27.  
    28.     public override void OnPointerClick(PointerEventData eventData)
    29.     {
    30.         base.OnSubmit(eventData);
    31.  
    32.         if (OnButtonClick != null)
    33.         {
    34.             OnButtonClick.Invoke(eventData.button);
    35.         }
    36.     }
    37.    
    38.  
    39.     void IPointerDownHandler.OnPointerDown (PointerEventData eventData)
    40.     {
    41.         DoStateTransition(SelectionState.Pressed, false);
    42.  
    43.         if (OnButtonPress != null)
    44.         {
    45.             OnButtonPress.Invoke(eventData.button);
    46.         }
    47.     }
    48.  
    49.  
    50.     void IPointerUpHandler.OnPointerUp (PointerEventData eventData)
    51.     {
    52.         DoStateTransition(SelectionState.Normal, false);        
    53.  
    54.         if (OnButtonRelease != null)
    55.         {
    56.             OnButtonRelease.Invoke(eventData.button);
    57.         }
    58.     }    
    59. }
    60.  
    BTW, i think this thread should be pinned :) .

    See ya!


    P.D: I forgot the UIButtonEditor :S :
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEditor.UI;
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. /// <summary>
    7. /// UIButtonEditor
    8. /// </summary>
    9. [CustomEditor(typeof(UIButton), true)]
    10. public class UIButtonEditor : ButtonEditor
    11. {
    12.     public override void OnInspectorGUI ()
    13.     {
    14.         this.serializedObject.Update();
    15.         base.OnInspectorGUI();
    16.         EditorGUILayout.PropertyField(this.serializedObject.FindProperty("OnButtonClick"));
    17.         EditorGUILayout.PropertyField(this.serializedObject.FindProperty("OnButtonPress"));
    18.         EditorGUILayout.PropertyField(this.serializedObject.FindProperty("OnButtonRelease"));
    19.         this.serializedObject.ApplyModifiedProperties();
    20.     }
    21. }
     
    Last edited: Oct 4, 2014
    ArkadiuszR and dakka like this.
  2. afoutsjr

    afoutsjr

    Joined:
    Aug 15, 2012
    Posts:
    7
    Updated TabNavigation.cs script for Unity 3.6 Beta 20.

    In the Start method:

    OLD
    Code (CSharp):
    1. system = EventSystemManager.currentSystem;
    NEW
    Code (CSharp):
    1. system = EventSystem.current;
    In the Update method:

    OLD
    Code (CSharp):
    1. Selectable next = system.currentSelectedObject.GetComponent<Selectable>().FindSelectableOnDown();
    NEW
    Code (CSharp):
    1. Selectable next = system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();

    Here is the complete UPDATED script:

    Code (CSharp):
    1. //Author: Melang http://forum.unity3d.com/members/melang.593409/
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using UnityEngine.EventSystems;
    5. using System.Collections;
    6.  
    7. public class TabNavigation : MonoBehaviour {
    8.  
    9.     EventSystem system;
    10.  
    11.     void Start ()
    12.     {
    13.         system = EventSystem.current;
    14.    
    15.     }
    16.  
    17.     public void Update()
    18.     {
    19.         if (Input.GetKeyDown(KeyCode.Tab))
    20.         {
    21.             Selectable next = system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();
    22.  
    23.        
    24.             if (next!= null) {
    25.            
    26.                 InputField inputfield = next.GetComponent<InputField>();
    27.                 if (inputfield !=null) inputfield.OnPointerClick(new PointerEventData(system));  //if it's an input field, also set the text caret
    28.            
    29.                 system.SetSelectedGameObject(next.gameObject, new BaseEventData(system));
    30.             }
    31.             //else Debug.Log("next nagivation element not found");
    32.         }
    33.     }
    34. }
     
  3. ChoMPi

    ChoMPi

    Joined:
    Jul 11, 2013
    Posts:
    112
  4. Breyer

    Breyer

    Joined:
    Nov 10, 2012
    Posts:
    412
    IMPORTANT UPDATE to interactable text: one of the user found huge bug which cause my plugin doesn't work after build. I fixed this today and uploaded files in previous my post. You have to download 2 files, next 2 files (Handler on end of string) werent changed so these arent required.
     
  5. omatase

    omatase

    Joined:
    Jul 31, 2014
    Posts:
    159
    I took Melang's original TabNavigation script and updated it so that it would also support Shift + Tab for going back a step in the navigation as well as fixed a null reference exception if system.currentSelectedGameObject returned null. It also has the updates that afoutsjr put in above and includes some code to autoselect the "firstSelectedGameObject" automatically since that doesn't seem to work in the latest version of 4.6.

    Code (CSharp):
    1. //Author: Melang http://forum.unity3d.com/members/melang.593409/
    2. //Updated omatase 10-18-14 - support for Shift + Tab as well
    3. //                         - bug fix to prevent crash if no control selected
    4. //                         - updated to support new semantics for EventSystem in later 4.6 builds
    5. //                         - autoselect "firstSelectedGameObject" since it doesn't seem to work automatically
    6. using UnityEngine;
    7. using UnityEngine.UI;
    8. using UnityEngine.EventSystems;
    9. using System.Collections;
    10.  
    11. public class TabNavigationHelper : MonoBehaviour
    12. {
    13.     private EventSystem _system;
    14.    
    15.     void Start()
    16.     {
    17.         _system = EventSystem.current;
    18.     }
    19.  
    20.     public void Update()
    21.     {
    22.         Selectable next = null;
    23.  
    24.         if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKey(KeyCode.LeftShift))
    25.         {
    26.             if (_system.currentSelectedGameObject != null)
    27.             {
    28.                 next = _system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnUp();
    29.             }
    30.             else
    31.             {
    32.                 next = _system.firstSelectedGameObject.GetComponent<Selectable>();
    33.             }
    34.         }
    35.         else if (Input.GetKeyDown(KeyCode.Tab))
    36.         {
    37.             if (_system.currentSelectedGameObject != null)
    38.             {
    39.                 next = _system.currentSelectedGameObject.GetComponent<Selectable>().FindSelectableOnDown();
    40.             }
    41.             else
    42.             {
    43.                 next = _system.firstSelectedGameObject.GetComponent<Selectable>();
    44.             }
    45.         }
    46.         else if (_system.currentSelectedGameObject == null)
    47.         {
    48.             next = _system.firstSelectedGameObject.GetComponent<Selectable>();
    49.         }
    50.  
    51.         selectGameObject(next);
    52.     }
    53.  
    54.     private void selectGameObject(Selectable selectable)
    55.     {
    56.         if (selectable != null)
    57.         {
    58.             InputField inputfield = selectable.GetComponent<InputField>();
    59.             if (inputfield != null) inputfield.OnPointerClick(new PointerEventData(_system));  //if it's an input field, also set the text caret
    60.  
    61.             _system.SetSelectedGameObject(selectable.gameObject, new BaseEventData(_system));
    62.         }
    63.     }
    64. }
    65.  
     
    Last edited: Oct 19, 2014
    rakkarage likes this.
  6. Melang

    Melang

    Joined:
    Mar 30, 2014
    Posts:
    166
    Another version of Outline - this time it's an attempt to make it more smooth and without the "holes" it gets when X and Y are relatively large. It does that by using the same principle as the built-in Outline, but draws 2 times more copies of the effect (8 from 4). It also scales with Best Fit, just like my previous script BestFitOutline. nicer outline.png

    I wonder if it's possible to create a "true" outline effect, and not just copy the letters around...
     

    Attached Files:

    Last edited: Oct 22, 2014
  7. TheFuntastic

    TheFuntastic

    Joined:
    Feb 11, 2013
    Posts:
    17
  8. Squi_Beta

    Squi_Beta

    Joined:
    Dec 11, 2013
    Posts:
    5
    UIWindowBase doesn't work if you put "Render Mode" to "Camera"
     
  9. Melang

    Melang

    Joined:
    Mar 30, 2014
    Posts:
    166
    Squi_Beta, check out this post and the ones after it - I believe there were versions of UIWindowBase posted that work with all render modes.
     
  10. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    The Accordion Type Layout gives a AOT Cross Compilation Error when trying to build to iOS , does anyone know how to fix it?
    The error seems to be happening when having the "UIAccordianElement.cs" script in the project folder.

    Thanks!
     
  11. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    513
    [QUOTE="Melang, post: 1746852, member: 593409"
    • UIWindowBase by Riolis - create draggable windows in 1 click - just drag this script to a panel with your window. Approved by Tim C :cool:
    • [/QUOTE]
    Here is an updated UIWindowBase that i found more useful being able to drag a panel based on a game object child such as a tittle bar area. Stops the entire outer panel from dragging.
    Free to use.
    Code (CSharp):
    1.  
    2. /////////////////////////////////////////////////////////////////////////////////
    3. //
    4. //    dg_VLDragPanel.cs
    5. //    © Digitech Gamez. All Rights Reserved.
    6. //    http://www.virtuoso-life.com
    7. //
    8. //    description:    drag a panel around the screen using a define
    9. //                      gameobject child
    10. //
    11. /////////////////////////////////////////////////////////////////////////////////
    12. using UnityEngine;
    13. using UnityEngine.UI;
    14. using UnityEngine.EventSystems;
    15. using System.Collections;
    16.  
    17. public class dg_VLDragPanel : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
    18. {
    19.     public GameObject m_targetDragObject;
    20.  
    21.     RectTransform m_transform = null;
    22.     private bool _isDragging = false;
    23.  
    24.     // Use this for initialization
    25.     void Start () {
    26.         m_transform = GetComponent<RectTransform>();
    27.     }
    28.  
    29.     public void OnDrag(PointerEventData eventData)
    30.     {
    31.         if (_isDragging)
    32.             m_transform.position += new Vector3(eventData.delta.x, eventData.delta.y);
    33.     }
    34.  
    35.     public void OnBeginDrag(PointerEventData eventData)
    36.     {
    37.        
    38.         if (eventData.pointerCurrentRaycast.gameObject == null)
    39.             return;
    40.  
    41.         if (eventData.pointerCurrentRaycast.gameObject.name == m_targetDragObject.name)
    42.             _isDragging = true;
    43.     }
    44.  
    45.     public void OnEndDrag(PointerEventData eventData)
    46.     {
    47.         _isDragging = false;
    48.     }
    49. }
     
    Keyjin likes this.
  12. bdovaz

    bdovaz

    Joined:
    Dec 10, 2011
    Posts:
    1,028
    Your approach comparing gameObjects it's really wrong. Use an instance comparer:

    http://docs.unity3d.com/ScriptReference/Object-operator_eq.html

    With your approach what if you have other gameObject with the same name in your scene?
     
  13. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    513
  14. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    I have created an script to center on an item of a scroll rect. It uses the item rect transform so it ignores child count, position and distance. Also it can center on both the vertical and the horizontal position so it also works for maps or skill trees.

    Last version:
    http://pastebin.com/EgU1Us9L

    Thread:
    http://forum.unity3d.com/threads/how-to-position-scrollrect-to-another-item.268794/#post-1852698

    Usage:
    1. Add the script to a scroll rect
    2. Assign the mask rect transform
    3. If you are not using GoKit delete the goto* line and uncomment the previous one so it builds (see below)
    4. Call CenterOnItem(RectTransform target) to center on an item

    *Delete the goto line and uncomment the other
    Code (csharp):
    1.  
    2. //_sr.normalizedPosition = normalizedPosition;
    3. Go.to(_sr, AnimTime, new GoTweenConfig().vector2Prop("normalizedPosition", normalizedPosition));
    4.  
     
  15. -JohnMore-

    -JohnMore-

    Joined:
    Jun 16, 2013
    Posts:
    64
    Hi,

    I have been working with some users on the forum (hi @kujo @mimminito) and we got a nice new version of the script for centering items inside a 2D scroll rect.
    It is easier to read and uses the scrollrect configuration to keep the content within the scrollrect bounds. It allows for instant or animated movement. A nice feature is that you can have a mask or another rect transform as the target area, so the selected item can be centered inside that area instead of the center of the scrollrect.

    This is the post with the last version. If anyone wants to give it a try it is realy easy to use.
    http://forum.unity3d.com/threads/how-to-position-scrollrect-to-another-item.268794/#post-1857286

    1. Add the script to your scrollrect
    2. Assign the mask recttransform to its property. The selected items will be centered in this object so you can choose any object of any size and in any position. For example, you can have a full screen scrollrect and assign a different recttransform so the item is centered at the top left corner.
    3. When you want to center on an item, call: {scriptReference}.CenterOnItem(item.trasnform as RectTransform)
    4. Done! :)
     
    Senshi likes this.
  16. Raimis

    Raimis

    Joined:
    Aug 27, 2014
    Posts:
    160
    After migrating from b19 to f3 (rc3) we had an issue with layout falling apart because of some random error in anchor deserialization for RectTransform. Since it's about 30 screens, manual work was not an option. Not sure if this will ever come handy to anyone, but I made a quick script to help us solve the problem. Not a nice solution, but given that it's one time thing, still does the job. Open project on other computer (didn't try on the same one, might work as well) with b19 and add recttransformserialized to root of the project. Hit serialize. Copy the content of textbox. Open same scene on rc3 (or any other to be honest), add the same comp to the root, paste the text to the textbox and press deserialize. The scene should now look ok. Please note that the script is rather limited and scene hierarchy has to be identical in order for it to work. If you swap anything, it won't fail, but it won't work either as idx was added to names in the dictionary to avoid name collisions.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. [ExecuteInEditMode]
    6. public class RectTransformSerialized : MonoBehaviour {
    7.  
    8.     [SerializeField, Multiline]
    9.     private string serializedValue;
    10.  
    11.     private Dictionary<string, RectData> data;
    12.  
    13.  
    14.     public void Serialize()
    15.     {
    16.         data = new Dictionary<string, RectData>();
    17.         SerializeTransform(transform, "");
    18.         serializedValue = Newtonsoft.Json.JsonConvert.SerializeObject(data);
    19.         Debug.Log("serialized data: " + data.Count);
    20.     }
    21.  
    22.     private void SerializeTransform(Transform transform, string prefix)
    23.     {
    24.         var myName = prefix + "_" + transform.name;
    25.         var rect = transform.GetComponent<RectTransform>();
    26.         if (rect != null)
    27.         {
    28.             data.Add(myName, new RectData()
    29.             {
    30.                 AnchoredPos = rect.anchoredPosition,
    31.                 AnchroMin = rect.anchorMin,
    32.                 AnchorMax = rect.anchorMax,
    33.                 Pivot = rect.pivot,
    34.                 SizeDelta = rect.sizeDelta,
    35.                 OffsetMax = rect.offsetMax,
    36.                 OffsetMin = rect.offsetMin
    37.             });
    38.         }
    39.  
    40.         for (var i = 0; i< transform.childCount; i++)
    41.         {
    42.             SerializeTransform(transform.GetChild(i), myName + i);
    43.         }
    44.     }
    45.  
    46.     public void Deserialize()
    47.     {
    48.  
    49.         data = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, RectData>>(serializedValue);
    50.         Debug.Log("deserialized data: " + data.Count);
    51.         DeserializeTransform(transform, "");
    52.     }
    53.  
    54.     private void DeserializeTransform(Transform transform, string prefix)
    55.     {
    56.         var myName = prefix + "_" + transform.name;
    57.  
    58.         var rect = transform.GetComponent<RectTransform>();
    59.         if (rect != null)
    60.         {
    61.             if (data.ContainsKey(myName))
    62.             {
    63.                 var rectData = data[myName];
    64.                 rect.pivot = rectData.Pivot;
    65.                 rect.anchorMin = rectData.AnchroMin;
    66.                 rect.anchorMax = rectData.AnchorMax;
    67.                 rect.sizeDelta = rectData.SizeDelta;
    68.                 rect.anchoredPosition = rectData.AnchoredPos;
    69.                 rect.offsetMin = rectData.OffsetMin;
    70.                 rect.offsetMax = rectData.OffsetMax;              
    71.             }
    72.         }
    73.  
    74.         for (var i = 0; i < transform.childCount; i++)
    75.         {
    76.             DeserializeTransform(transform.GetChild(i), myName + i);
    77.         }
    78.     }
    79. }
    80.  
    81. public class RectData
    82. {
    83.     public Vector2 AnchoredPos;
    84.     public Vector2 AnchroMin;
    85.     public Vector2 AnchorMax;
    86.     public Vector2 Pivot;
    87.     public Vector2 SizeDelta;
    88.     public Vector2 OffsetMin;
    89.     public Vector2 OffsetMax;
    90. }


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Collections;
    4.  
    5.  
    6. [CustomEditor(typeof(RectTransformSerialized))]
    7. public class RectTransformSerializedDrawer : Editor{
    8.  
    9.     public override void OnInspectorGUI()
    10.     {
    11.         DrawDefaultInspector();
    12.         RectTransformSerialized myScript = (RectTransformSerialized)target;
    13.  
    14.         if (GUILayout.Button("Serialize"))
    15.         {
    16.             myScript.Serialize();
    17.         }
    18.  
    19.         if (GUILayout.Button("Deserialize"))
    20.         {
    21.             myScript.Deserialize();
    22.         }
    23.     }
    24. }
     
  17. Erisat

    Erisat

    Joined:
    Jan 31, 2013
    Posts:
    88
  18. shkar-noori

    shkar-noori

    Joined:
    Jun 10, 2013
    Posts:
    833
    [UI.ComboBox] a scrollable, dynamic and customizable drop-down control. hope you find it useful
     
  19. Deeperbeige

    Deeperbeige

    Joined:
    May 12, 2013
    Posts:
    17
  20. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    As part of the run up to my forthcoming Unity UI book http://t.co/YgJxoPgboq Unity3D UI Essentials

    I've started a repo with a collection of these scripts here https://bitbucket.org/ddreaper/unity-ui-extensions
    All attributions are included with each script, where they came from and who was involved.
    In most cases I've pulled together fixes from many places and include fixes of my own (mostly to update to the latest UI releases)

    Will keep adding and extending the repository over time as I either find or build new scripts.

    Feel free to fork and submit new scripts / fixes to the repo. I've even included a .UnityPackage for the scripts that are there and will update it over time.

    P.S. I see there have been updates since I last looked at this thread, so I got more work to do :D
     
    GregMeach, Senshi and rakkarage like this.
  21. Kaz_Yamof

    Kaz_Yamof

    Joined:
    Jan 17, 2013
    Posts:
    28
    shkar-noori, Freezy and judah4 like this.
  22. WestHill

    WestHill

    Joined:
    Oct 29, 2012
    Posts:
    174
  23. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    234
    Not sure how to explain this one

    Just create a scroll panel that scales with the resolution and you might see the problem.

    Here is my contribution
    uGUI SizePerChild

    It's a layout element that increases it's Rect size to accommodate more children, while keeping a nice style when the parent can not be filled completely yet.
    It was created to allow flexible width and height to rescale items based on different resolutions.

    It still needs a nice example package to show the original behavior vs the one created by the script.
    But for now this is all I have to share ;-)
     
    Last edited: Jan 19, 2015
  24. ChoMPi

    ChoMPi

    Joined:
    Jul 11, 2013
    Posts:
    112
    I've made a little script that let's you flip graphics vertically, horizontally or both without changing scales to negative values.

    [Script] Flippable for UI Graphics
     
  25. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    Great stuff guys, I'll add these to the repo (if you haven't already) as soon as I get a free minute!
     
  26. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
  27. WestHill

    WestHill

    Joined:
    Oct 29, 2012
    Posts:
    174
  28. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    Thanks for the clarification. Will note that in the readme on the repo
     
  29. Breyer

    Breyer

    Joined:
    Nov 10, 2012
    Posts:
    412
    Clarification: my asset work with image but not with local mode + sliced/tiled (in fact work but in strange way, so using my ext with sliced/tiled on local mode is not recommended)
     
  30. Helical

    Helical

    Joined:
    Mar 2, 2014
    Posts:
    50
    Anyone know of any scripts that help create UI elements and have them attached to world objects? like little life bars attached to enemies near and far? Or chat bubble that pop from an NPC? These should know how to always face the camera / screen if desired and be auto resizable when the objects are far away.
     
  31. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    This question came up on a few other posts. Hence why I pestered @Adam Buckner to do a post about the UI demo he did at the end of his slider presentation. A great example where you could either create World Space canvases on 3D entities or build a custom Screen Space layer with elements drawn relative to 3D elements. (http://unity3d.com/learn/tutorials/...ing-archive/creating-scroll-lists-at-run-time)
    But looking at the Live training schedule, there are some very interesting sessions coming up.
     
  32. Helical

    Helical

    Joined:
    Mar 2, 2014
    Posts:
    50
    I already made my own system sort of work. However its complex and I dont think its sharable. Making a cavas for each world element that needs a lifebar seems wastefull. Even if the canvases are spawned in runtime only when you need them. I still don't like the idea of having more then 3 canvases in your game at any point in time.

    On the other side of the coin. Having one canvas designated to have the gui elements relative to the places you want them to be in world space, requires runtime calculation of their position on screen, and desired size. and this task is becoming problematic for average developers like me. took me hours just to program the lifebar appear on top of a box.
     
  33. BinaryX

    BinaryX

    Joined:
    Aug 4, 2014
    Posts:
    55
    Hello,

    There was a post on this forum about a horizontal scroll snapping script. I took the script and extended it a bit.

    The .unitypackage file has the basic functionality. It features normal scrolling plus a fast swipe feature. All the pages are in one place, because they get re-positioned based on the screen size.

    Additionally, you can add buttons to control the browsing through pages , like in this example : Just create the buttons and drag them into their slots. No need for adding OnClick event (it's added automatically) or to name them in a specific way.

    "The MyScrollRect component is a copy of the Scroll Rect UI component, in which I added some code to call the OnDrag and OnDragEnd functions straight from the script, without the need for adding an Event Trigger component (it didn't work as intended for me)." - this is no longer relevant thanks to @SimonDarksideJ



    You can also add pagination bullets. "Pagination" is just an empty gameObject, a container for the toggles. Each toggle corresponds to each page. There's no need for special naming, first toggle corresponds to first page, last one to last page. It only affects the tick, you can remove the label of the toggle if you want.

    You can add a level package on each page like in this example :

    NOTICE : I recommend to keep the BackImage in each page, but set its alpha to 0, just so you can swipe in between the buttons as well.

    If anyone's interested, the Canvas Scaler in these examples is set to "Scale with Screen Size", 1024x768 and Match the width.

    I'm pretty sure that the solution I made is not the most efficient or not the prettiest, so i ask everyone who can improve it, please do so and post it on this topic.

    Have a great day


    LATER EDIT : Be sure to uncheck "Inertia" property from the Scroll Rect.
     

    Attached Files:

    Last edited: Feb 3, 2015
  34. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    @BinaryX I've taken your script and updated it slightly to remove the need for a custom ScrollRect, just needed to add the interfaces for dragging and move your code around. Will get this in to the next batch of updated for the UI Extensions repo.
    *Edit, just updated again slightly to remove the need to double assign the container object.

    Code below for reference:
    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using UnityEngine.EventSystems;
    5. using UnityEngine.UI;
    6.  
    7. [RequireComponent(typeof(ScrollRect))]
    8. public class HorizontalScrollSnap : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
    9. {
    10. private Transform _screensContainer;
    11.  
    12. private int _screens = 1;
    13. private int _startingScreen = 1;
    14.  
    15. private bool _fastSwipeTimer = false;
    16. private int _fastSwipeCounter = 0;
    17. private int _fastSwipeTarget = 30;
    18.  
    19.  
    20. private System.Collections.Generic.List<Vector3> _positions;
    21. private ScrollRect _scroll_rect;
    22. private Vector3 _lerp_target;
    23. private bool _lerp;
    24.  
    25. private int _containerSize;
    26.  
    27. [Tooltip("The gameobject that contains toggles which suggest pagination. THIS CAN BE MISSING")]
    28. public GameObject Pagination;
    29.  
    30. [Tooltip("Button to go to the next page. (optional)")]
    31. public GameObject NextButton;
    32. [Tooltip("Button to go to the previous page. (optional)")]
    33. public GameObject PrevButton;
    34.  
    35. public Boolean UseFastSwipe = true;
    36. public int FastSwipeThreshold = 100;
    37.  
    38. private bool _startDrag = true;
    39. private Vector3 _startPosition = new Vector3();
    40. private int _currentScreen;
    41.  
    42. // Use this for initialization
    43. void Start()
    44. {
    45. _scroll_rect = gameObject.GetComponent<ScrollRect>();
    46. _screensContainer = _scroll_rect.content;
    47. DistributePages();
    48.  
    49. _screens = _screensContainer.childCount;
    50.  
    51. _lerp = false;
    52.  
    53. _positions = new System.Collections.Generic.List<Vector3>();
    54.  
    55. if (_screens > 0)
    56. {
    57. for (int i = 0; i < _screens; ++i)
    58. {
    59. _scroll_rect.horizontalNormalizedPosition = (float)i / (float)(_screens - 1);
    60. _positions.Add(_screensContainer.localPosition);
    61. }
    62. }
    63.  
    64. _scroll_rect.horizontalNormalizedPosition = (float)(_startingScreen - 1) / (float)(_screens - 1);
    65.  
    66. _containerSize = (int)_screensContainer.gameObject.GetComponent<RectTransform>().offsetMax.x;
    67.  
    68. ChangeBulletsInfo(CurrentScreen());
    69.  
    70. if (NextButton)
    71. NextButton.GetComponent<Button>().onClick.AddListener(() => { NextScreen(); });
    72.  
    73. if (PrevButton)
    74. PrevButton.GetComponent<Button>().onClick.AddListener(() => { PreviousScreen(); });
    75. }
    76.  
    77. void Update()
    78. {
    79. if (_lerp)
    80. {
    81. _screensContainer.localPosition = Vector3.Lerp(_screensContainer.localPosition, _lerp_target, 7.5f * Time.deltaTime);
    82. if (Vector3.Distance(_screensContainer.localPosition, _lerp_target) < 0.005f)
    83. {
    84. _lerp = false;
    85. }
    86.  
    87. //change the info bullets at the bottom of the screen. Just for visual effect
    88. if (Vector3.Distance(_screensContainer.localPosition, _lerp_target) < 10f)
    89. {
    90. ChangeBulletsInfo(CurrentScreen());
    91. }
    92. }
    93.  
    94. if (_fastSwipeTimer)
    95. {
    96. _fastSwipeCounter++;
    97. }
    98.  
    99. }
    100.  
    101. private bool fastSwipe = false; //to determine if a fast swipe was performed
    102.  
    103.  
    104. //Function for switching screens with buttons
    105. public void NextScreen()
    106. {
    107. if (CurrentScreen() < _screens - 1)
    108. {
    109. _lerp = true;
    110. _lerp_target = _positions[CurrentScreen() + 1];
    111.  
    112. ChangeBulletsInfo(CurrentScreen() + 1);
    113. }
    114. }
    115.  
    116. //Function for switching screens with buttons
    117. public void PreviousScreen()
    118. {
    119. if (CurrentScreen() > 0)
    120. {
    121. _lerp = true;
    122. _lerp_target = _positions[CurrentScreen() - 1];
    123.  
    124. ChangeBulletsInfo(CurrentScreen() - 1);
    125. }
    126. }
    127.  
    128. //Because the CurrentScreen function is not so reliable, these are the functions used for swipes
    129. private void NextScreenCommand()
    130. {
    131. if (_currentScreen < _screens - 1)
    132. {
    133. _lerp = true;
    134. _lerp_target = _positions[_currentScreen + 1];
    135.  
    136. ChangeBulletsInfo(_currentScreen + 1);
    137. }
    138. }
    139.  
    140. //Because the CurrentScreen function is not so reliable, these are the functions used for swipes
    141. private void PrevScreenCommand()
    142. {
    143. if (_currentScreen > 0)
    144. {
    145. _lerp = true;
    146. _lerp_target = _positions[_currentScreen - 1];
    147.  
    148. ChangeBulletsInfo(_currentScreen - 1);
    149. }
    150. }
    151.  
    152.  
    153. //find the closest registered point to the releasing point
    154. private Vector3 FindClosestFrom(Vector3 start, System.Collections.Generic.List<Vector3> positions)
    155. {
    156. Vector3 closest = Vector3.zero;
    157. float distance = Mathf.Infinity;
    158.  
    159. foreach (Vector3 position in _positions)
    160. {
    161. if (Vector3.Distance(start, position) < distance)
    162. {
    163. distance = Vector3.Distance(start, position);
    164. closest = position;
    165. }
    166. }
    167.  
    168. return closest;
    169. }
    170.  
    171.  
    172. //returns the current screen that the is seeing
    173. public int CurrentScreen()
    174. {
    175. float absPoz = Math.Abs(_screensContainer.gameObject.GetComponent<RectTransform>().offsetMin.x);
    176.  
    177. absPoz = Mathf.Clamp(absPoz, 1, _containerSize - 1);
    178.  
    179. float calc = ( absPoz / _containerSize) * _screens;
    180.  
    181. return (int) calc;
    182. }
    183.  
    184. //changes the bullets on the bottom of the page - pagination
    185. private void ChangeBulletsInfo(int currentScreen)
    186. {
    187. if (Pagination)
    188. for (int i = 0; i < Pagination.transform.childCount; i++)
    189. {
    190. Pagination.transform.GetChild(i).GetComponent<Toggle>().isOn = (currentScreen == i)
    191. ? true
    192. : false;
    193. }
    194. }
    195. //used for changing between screen resolutions
    196. private void DistributePages()
    197. {
    198. int _offset = 0;
    199. int _step = Screen.width;
    200. int _dimension = 0;
    201. int currentXPosition = 0;
    202. for (int i = 0; i < _screensContainer.transform.childCount; i++)
    203. {
    204. RectTransform child = _screensContainer.transform.GetChild(i).gameObject.GetComponent<RectTransform>();
    205. currentXPosition = _offset + i * _step;
    206. child.anchoredPosition = new Vector2(currentXPosition, 0f);
    207. child.sizeDelta = new Vector2( gameObject.GetComponent<RectTransform>().sizeDelta.x, gameObject.GetComponent<RectTransform>().sizeDelta.y );
    208. }
    209. _dimension = currentXPosition + _offset * -1;
    210. _screensContainer.GetComponent<RectTransform>().offsetMax = new Vector2(_dimension, 0f);
    211. }
    212.  
    213. #region Interfaces
    214. public void OnBeginDrag(PointerEventData eventData)
    215. {
    216. _startPosition = _screensContainer.localPosition;
    217. _fastSwipeCounter = 0;
    218. _fastSwipeTimer = true;
    219. _currentScreen = CurrentScreen();
    220. }
    221.  
    222. public void OnEndDrag(PointerEventData eventData)
    223. {
    224. _startDrag = true;
    225. if (_scroll_rect.horizontal)
    226. {
    227. if (UseFastSwipe)
    228. {
    229. fastSwipe = false;
    230. _fastSwipeTimer = false;
    231. if (_fastSwipeCounter <= _fastSwipeTarget)
    232. {
    233. if (Math.Abs(_startPosition.x - _screensContainer.localPosition.x) > FastSwipeThreshold)
    234. {
    235. fastSwipe = true;
    236. }
    237. }
    238. if (fastSwipe)
    239. {
    240. if (_startPosition.x - _screensContainer.localPosition.x > 0)
    241. {
    242. NextScreenCommand();
    243. }
    244. else
    245. {
    246. PrevScreenCommand();
    247. }
    248. }
    249. else
    250. {
    251. _lerp = true;
    252. _lerp_target = FindClosestFrom(_screensContainer.localPosition, _positions);
    253. }
    254. }
    255. else
    256. {
    257. _lerp = true;
    258. _lerp_target = FindClosestFrom(_screensContainer.localPosition, _positions);
    259. }
    260. }
    261. }
    262.  
    263. public void OnDrag(PointerEventData eventData)
    264. {
    265. _lerp = false;
    266. if (_startDrag)
    267. {
    268. OnBeginDrag(eventData);
    269. _startDrag = false;
    270. }
    271. }
    272. #endregion
    273. }
     
    Last edited: Feb 2, 2015
    catch_up and SweatyChair like this.
  35. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    Just release V1.0.0.1 of the Unity UI Extensions collection, with many of the scripts from this post.
    All tidied, cleaned and unified in to one huge collection of controls / effect and components.
    Plus Editor menu's where applicable.
    https://bitbucket.org/ddreaper/unity-ui-extensions

    Additionally, there is a .UnityPackage to download and install them all (with EditorMenu Options)
    https://bitbucket.org/ddreaper/unity-ui-extensions/downloads/UnityUIExtensions.unitypackage

    Got more scripts or updates, then post them to the repo :D
     
  36. kennyb

    kennyb

    Joined:
    Feb 23, 2015
    Posts:
    14
    I needed a more comprehensive clamp-inside-canvas script that will clamp the ENTIRE RectTransform and not just the upper-left-hand corner. Here's the result of a few hours of fiddling.

    It has a limitation that you can't use any of the streching anchor types, the "sizeDelta" of the RectTransform needs to actually match its pixel width and height. I'm sure it could be make to work with the other types with a little bit of modification.

    Code (CSharp):
    1.  
    2. // CAVEAT: this function will not work on RectTransforms with elastic anchors (min != max)
    3.     public static Vector2 ClampToCanvas(RectTransform canvas, RectTransform window, Vector2 screenPosition)
    4.     {
    5.         Vector2 worldPosition = screenPosition;
    6.         Vector2 min = Vector2.zero;
    7.         Vector2 max = canvas.sizeDelta;
    8.         Vector2 size = window.sizeDelta;
    9.  
    10.         // scale everything by the canvas scale
    11.         max.x *= canvas.localScale.x;
    12.         max.y *= canvas.localScale.y;
    13.         size.x *= canvas.localScale.x;
    14.         size.y *= canvas.localScale.y;
    15.  
    16.         min.x += size.x * window.anchorMin.x;
    17.         min.y += size.y * window.anchorMin.y;
    18.      
    19.         max.x -= size.x * (1f - window.anchorMax.x);
    20.         max.y -= size.y * (1f - window.anchorMax.y);
    21.      
    22.         worldPosition.x = Mathf.Clamp(worldPosition.x, min.x, max.x);
    23.         worldPosition.y = Mathf.Clamp(worldPosition.y, min.y, max.y);
    24.      
    25.         return worldPosition;
    26.     }
    27.  
     
  37. Dinosaurs

    Dinosaurs

    Joined:
    Aug 11, 2013
    Posts:
    17
    I was using Melang's Nicer Outline script but whenever I try to compile an iOS build with that script in my project, the build fails with an AOT Cross Compiler Failed error. Has anyone else had that problem or know of a solution? Nothing in the script jumps out at me as potentially problematic.
     
  38. vuong_vin

    vuong_vin

    Joined:
    Sep 17, 2014
    Posts:
    18
    Look awesome, love it.
    If i want make a curved for a Scroll Rect, Could i do same with your text? Thanks
     
  39. Breyer

    Breyer

    Joined:
    Nov 10, 2012
    Posts:
    412
  40. zero3growlithe

    zero3growlithe

    Joined:
    Jul 7, 2012
    Posts:
    15
    Here's my script that scrolls the ScrollRect to actual selection so you can create long list of, for example levels, which can be selected using gamepad. The script moves the scrollRect smoothly to the next selection when it is off-screen.

    *********Action video:*********


    If there is need for a grid version of this scrolling script I can try to make one :)

    USAGE:
    Simply place the script on the ScrollRect that contains the selectable children we'll be scroling to and drag'n'drop the RectTransform of the options "container" that we'll be scrolling.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4. using UnityEngine.EventSystems;
    5.  
    6. public class UIScrollToSelection : MonoBehaviour {
    7.  
    8. /* ### VARIABLES ============================================================== */
    9.  
    10.     // settings
    11.     public float scrollSpeed = 10f;
    12.  
    13.     [SerializeField]
    14.     private RectTransform layoutListGroup;
    15.  
    16.     // temporary variables
    17.     private RectTransform targetScrollObject;
    18.     private bool scrollToSelection = true;
    19.  
    20.     // references
    21.     private RectTransform scrollWindow;
    22.     private RectTransform currentCanvas;
    23.     private ScrollRect targetScrollRect;
    24.  
    25.  
    26. /* ### MAIN METHODS =========================================================== */
    27.     // Use this for initialization
    28.     private void Start () {
    29.         targetScrollRect = GetComponent<ScrollRect>();
    30.         scrollWindow = targetScrollRect.GetComponent<RectTransform>();
    31.         currentCanvas = transform.root.GetComponent<RectTransform>();
    32.     }
    33.  
    34.     // Update is called once per frame
    35.     private void Update () {
    36.         ScrollRectToLevelSelection();
    37.     }
    38.  
    39.     private void ScrollRectToLevelSelection (){
    40.         // check main references
    41.         bool referencesAreIncorrect =
    42.             (targetScrollRect == null || layoutListGroup == null || scrollWindow == null);
    43.         if (referencesAreIncorrect == true){
    44.             return;
    45.         }
    46.  
    47.         // get calculation references
    48.         EventSystem events = EventSystem.current;
    49.         RectTransform selection = events.currentSelectedGameObject != null ?
    50.             events.currentSelectedGameObject.GetComponent<RectTransform>() :
    51.             null;
    52.         RectTransform lastSelection = events.lastSelectedGameObject != null ?
    53.             events.lastSelectedGameObject.GetComponent<RectTransform>() :
    54.             selection;
    55.  
    56.         if (selection != targetScrollObject)
    57.             scrollToSelection = true;
    58.  
    59.         // check if scrolling is possible
    60.         bool isScrollDirectionUnknown =
    61.             (selection == null || lastSelection == null || scrollToSelection == false);
    62.  
    63.         if (isScrollDirectionUnknown == true || selection.transform.parent != layoutListGroup.transform)
    64.             return;
    65.  
    66.         // move the current scroll rect to correct position
    67.         float selectionPos = -selection.anchoredPosition.y;
    68.         int direction =    (int)Mathf.Sign(selection.anchoredPosition.y - lastSelection.anchoredPosition.y);
    69.  
    70.         float elementHeight = layoutListGroup.sizeDelta.y / layoutListGroup.transform.childCount;
    71.         float maskHeight = currentCanvas.sizeDelta.y + scrollWindow.sizeDelta.y;
    72.         float listPixelAnchor = layoutListGroup.anchoredPosition.y;
    73.  
    74.         // get the element offset value depending on the cursor move direction
    75.         float offlimitsValue = 0;
    76.         if (direction > 0 && selectionPos < listPixelAnchor)
    77.         {
    78.             offlimitsValue = listPixelAnchor - selectionPos;
    79.         }
    80.         if (direction < 0 && selectionPos + elementHeight > listPixelAnchor + maskHeight)
    81.         {
    82.             offlimitsValue = (listPixelAnchor + maskHeight) - (selectionPos + elementHeight);
    83.         }
    84.         // move the target scroll rect
    85.         targetScrollRect.verticalNormalizedPosition +=
    86.             (offlimitsValue / layoutListGroup.sizeDelta.y) * Time.deltaTime * scrollSpeed;
    87.         // check if we reached our destination
    88.         if (Mathf.Abs(offlimitsValue) < 2f)
    89.             scrollToSelection = false;
    90.         // save last object we were "heading to" to prevent blocking
    91.         targetScrollObject = selection;
    92.     }
    93.  
    94. /* ### ENUMS ================================================================== */
    95.  
    96.  
    97. /* ### CUSTOM TYPES =========================================================== */
    98.  
    99.  
    100. }
     
    Last edited: Mar 10, 2015
    tkamruzzaman likes this.
  41. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    Nice one @zero3growlithe
    You ok with that going in the UI Extensions collection?
     
  42. zero3growlithe

    zero3growlithe

    Joined:
    Jul 7, 2012
    Posts:
    15
  43. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,688
    Right @zero3growlithe I'll add that to the list to include with the next update. Or you can fork the project yourself and submit a PR :D
    Great contribution.
     
  44. zero3growlithe

    zero3growlithe

    Joined:
    Jul 7, 2012
    Posts:
    15
    Alright, pull request sent.
     
  45. kaiber

    kaiber

    Joined:
    Mar 4, 2013
    Posts:
    15
    Any ideas how to extend the horizontal snapping script to allow a looping list? As in, after scrolling off the edge either side you go back to the first /last item respectively? Its the last bit of functionality I need for my app and I can't quite figure it out.
     
  46. zero3growlithe

    zero3growlithe

    Joined:
    Jul 7, 2012
    Posts:
    15
    You can change the Navigation mode for the first and last button in inspector to Explicit and simply make the last button point to the first one and first one to last one. Although I don't know how this Horizontal Snapping script works but I guess it will handle it :)
     
  47. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    This script is also causing WebGL builds to fail. I have previously used it with Web Player and Android without errors, but I haven't tried iOS.

    I've sent a message to Melang, hopefully it's a fixable issue.
     
  48. RichCodes

    RichCodes

    Joined:
    Apr 3, 2013
    Posts:
    142
    This thread made most of my UI headaches go away. I could hug you guys.
    Thanks to all who add scripts here!
     
    Senshi, zero3growlithe and judah4 like this.
  49. JohnTube

    JohnTube

    Joined:
    Sep 29, 2014
    Posts:
    66
    SimonDarksideJ likes this.
  50. Ges

    Ges

    Joined:
    Apr 23, 2014
    Posts:
    31
    Hey. I modify standard image. Now it can:
    -Use filled type with no sprite (useful with mask)
    -Rotate (If use transform rotate you cannot correct use anchors). Work on simple, sliced, tiled fully. Radial fill not work(if rotated).

    Link: https://bitbucket.org/snippets/MatkovIvan/9oRL

    For flip you may use script posted above.
    Any improvement suggestions are most welcome.

    PS. Sorry for my English.
    PSS. Of course you can add this script to UI Collection.
     
    SimonDarksideJ likes this.