Created
June 20, 2019 20:49
-
-
Save partlyhuman/1b85c93b1b17441cf088b24cce83c663 to your computer and use it in GitHub Desktop.
Unity Scroll to Selected by Asher Vollmer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
using UnityEngine.EventSystems; | |
[RequireComponent( typeof( ScrollRect ) )] | |
public class ScrollToSelected : MonoBehaviour | |
{ | |
[ Header( "Required: Children must have a Y Pivot of 1!" ) ] | |
public float scrollSpeed = 10f; | |
ScrollRect m_ScrollRect; | |
RectTransform m_RectTransform; | |
RectTransform m_ContentRectTransform; | |
RectTransform m_SelectedRectTransform; | |
void Awake() { | |
m_ScrollRect = GetComponent<ScrollRect>(); | |
m_RectTransform = GetComponent<RectTransform>(); | |
m_ContentRectTransform = m_ScrollRect.content; | |
} | |
void Update() | |
{ | |
UpdateScrollToSelected(); | |
} | |
void UpdateScrollToSelected() | |
{ | |
GameObject selected = EventSystem.current.currentSelectedGameObject; | |
if ( selected == null ) | |
return; | |
if ( selected.transform.parent != m_ContentRectTransform.transform ) | |
return; | |
m_SelectedRectTransform = selected.GetComponent<RectTransform>(); | |
float contentHeightDifference = GetContentHeightDifference(); | |
float selectedTop = m_SelectedRectTransform.anchoredPosition.y; | |
float selectedBottom = selectedTop - m_SelectedRectTransform.rect.height; | |
float viewportTop = NormalizedToPosition( m_ScrollRect.verticalNormalizedPosition, contentHeightDifference ); | |
float viewportBottom = viewportTop - m_ScrollRect.viewport.rect.height; | |
if ( selectedTop > viewportTop ) | |
{ | |
float goalY = selectedTop; | |
m_ScrollRect.verticalNormalizedPosition = Mathf.Lerp( | |
m_ScrollRect.verticalNormalizedPosition, | |
PositionToNormalized( goalY, contentHeightDifference ), | |
scrollSpeed * Time.deltaTime | |
); | |
} | |
else if ( selectedBottom < viewportBottom && !Mathf.Approximately( selectedTop, selectedBottom ) ) | |
{ | |
float diff = selectedBottom - viewportBottom; | |
float goalY = viewportTop + diff; | |
m_ScrollRect.verticalNormalizedPosition = Mathf.Lerp( | |
m_ScrollRect.verticalNormalizedPosition, | |
PositionToNormalized( goalY, contentHeightDifference ), | |
scrollSpeed * Time.deltaTime | |
); | |
} | |
} | |
float GetContentHeightDifference () | |
{ | |
return m_ContentRectTransform.rect.height - m_RectTransform.rect.height; | |
} | |
float NormalizedToPosition ( float normPos, float contentHeightDifference ) | |
{ | |
return ( normPos - 1.0f ) * contentHeightDifference; | |
} | |
float PositionToNormalized ( float pos, float contentHeightDifference ) | |
{ | |
return ( pos / contentHeightDifference ) + 1.0f; | |
} | |
public bool IsClippingTop () | |
{ | |
return m_ScrollRect.verticalNormalizedPosition < 1.0f; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment