Question by
CameronStewart21 · Apr 19, 2020 at 07:13 AM ·
c#scrollviewrecttransformmenu screenarrow-keys
How could I navigate horizontally through a scroll view using left and right arrow keys?
I have a working horizontal scroll view to be used as a scrollable "skills menu" for a basketball game I am creating. My issue is, that this game is going to be for PC, and therefore I feel that scrolling through this using only the mouse is not effective and I would like to use the arrow keys to select through each option in the scroll view. Perhaps there is a better way of implementing this system as opposed to a scroll view but so far I have it working well enough, it scales dynamically, and snaps to the nearest option.
Here is my entire script for the scrollview.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using TMPro;
public class SkillScrolling : MonoBehaviour
{
[Header("Controllers")]
public int skillCount;
[Range(0, 500)]
public int offset;
[Range(0f,20f)]
public float snapSpeed;
[Range(0f, 10f)]
public float scaleOffset;
[Range(0f, 20f)]
public float scaleSpeed;
[Header("Other Objects")]
public TextMeshProUGUI skillText;
public GameObject skillPrefab;
public string[] skillTypes;
private GameObject[] instSkills;
private Vector2[] skillPos;
private Vector2[] skillScale;
private RectTransform contentRect;
private Vector2 contentPos;
public int selectedSkillID;
public bool isScrolling = false;
// Start is called before the first frame update
void Start()
{
skillText = skillPrefab.GetComponentInChildren<TextMeshProUGUI>();
contentRect = GetComponent<RectTransform>();
instSkills = new GameObject[skillCount];
skillPos = new Vector2[skillCount];
skillScale = new Vector2[skillCount];
//instantiates the amount of skills specified and alligns them/sets them apart using an offset.
for (int i = 0; i < skillCount; i++)
{
skillText.text = skillTypes[i];
instSkills[i] = Instantiate(skillPrefab, transform, false);
if (i == 0) continue;
instSkills[i].transform.localPosition = new Vector2(instSkills[i-1].transform.localPosition.x + skillPrefab.GetComponent<RectTransform>().sizeDelta.x + offset, instSkills[i].transform.localPosition.y);
skillPos[i] = -instSkills[i].transform.localPosition;
}
}
// Update is called once per frame
void Update()
{
float nearestPos = float.MaxValue;
for (int i = 0; i < skillCount; i++)
{
//distance between one skill selection and the next one.
float distance = Mathf.Abs(contentRect.anchoredPosition.x - skillPos[i].x);
//check if the distance is less than the nearest position.
if (distance < nearestPos)
{
nearestPos = distance; //distance becomes relative to nearest position.
selectedSkillID = i; //identifies which selection is nearest.
}
float scale = Mathf.Clamp(1 / (distance / offset) * scaleOffset, 0.5f, 1f); //restricts the scale size of the unselected options.
//smoothly steps through the scale of the items to produce a growing and shrinking effect.
skillScale[i].x = Mathf.SmoothStep(instSkills[i].transform.localScale.x, scale, scaleSpeed + .3f * Time.unscaledDeltaTime);
skillScale[i].y = Mathf.SmoothStep(instSkills[i].transform.localScale.y, scale, scaleSpeed + .3f * Time.unscaledDeltaTime);
//sets the scale of the current item.
instSkills[i].transform.localScale = skillScale[i];
}
if (isScrolling) return;
//smoothly steps through the snapping into the position of the nearest item.
contentPos.x = Mathf.SmoothStep(contentRect.anchoredPosition.x, skillPos[selectedSkillID].x, snapSpeed * Time.unscaledDeltaTime);
contentRect.anchoredPosition = contentPos;
if (Input.GetKeyDown(KeyCode.LeftArrow) && selectedSkillID > 0)
{
selectedSkillID -= 1;
}
if (Input.GetKeyDown(KeyCode.RightArrow) && selectedSkillID < 6)
{
selectedSkillID += 1;
}
}
//checks if is scrolling or not.
public void Scrolling(bool scroll)
{
isScrolling = scroll;
}
}
Thanks!
Comment