Unityにシンプルな折りたたみメニューを実装する



Implement Simple Collapsible Menu Unity



アニメーションなし 画像

アニメーション付き

実装コード

public class Nodes : BaseNode { /// /// Only allocate once in memory /// private static Text text public override void Start() { text = GameObject.Find('Canvas/CurrentClickNodeText').GetComponent<Text>() base.Start() GetComponent<Button>().onClick.AddListener(() => { SwitchNode() Text txt = transform.GetChild(0).GetComponent<Text>() text.text = txt.text }) } } public abstract class BaseNode : MonoBehaviour { /// /// The parent container of the current node group /// public RectTransform parentRectTransform /// /// If the current node has child nodes /// public List<BaseNode> childNodes /// /// Which is the last selected node /// public static BaseNode CurrentNode { get private set } /// /// Whether the current node is opened /// private bool isOpen = false /// /// Calculate the target size of the container /// private float EndContainerWidth /// /// Calculate the initial size of the container /// private float StartContainerWidth /// /// Elastic speed, change can change the elastic speed, you can manually change /// [Range(0.0f, 1f)] private float EleasticSpeed = 0.5f public virtual void Start() { if (parentRectTransform != null) { StartContainerWidth = parentRectTransform.rect.width if (this.childNodes != null && this.childNodes.Count != 0) { float space = parentRectTransform.GetComponent<HorizontalLayoutGroup>().spacing for (int i = 0 i < this.childNodes.Count i++) { EndContainerWidth += childNodes[i].GetComponent<RectTransform>().rect.width + space } EndContainerWidth += this.parentRectTransform.rect.width } } } /// /// When the button is clicked, the switch of the node is switched, and the size of the parent container is changed /// public void SwitchNode() { if (CurrentNode != null && CurrentNode.childNodes.Count != 0) { // If you click on the node itself if (CurrentNode == this && CurrentNode.childNodes != null) { this.isOpen = !isOpen StartCoroutine(CotainerSiwtch(isOpen, CurrentNode)) foreach (var node in CurrentNode.childNodes) { // Close the last opened Node //node.gameObject.SetActive(isOpen) node.isOpen = false } CurrentNode = null return } else { if (this.childNodes.Count == 0) return StartCoroutine(CotainerSiwtch(false, CurrentNode)) foreach (var node in CurrentNode.childNodes) { // Close all child nodes of the current node //node.gameObject.SetActive(false) node.isOpen = false } CurrentNode.isOpen = false CurrentNode = null } } if (this.childNodes != null && this.childNodes.Count != 0) { this.isOpen = !isOpen StartCoroutine(CotainerSiwtch(this.isOpen, this)) foreach (var node in this.childNodes) { // The current object needs to be enabled //node.gameObject.SetActive(this.isOpen) node.isOpen = this.isOpen } CurrentNode = this CurrentNode.childNodes = this.childNodes } } /// /// Container switch to control the opening and closing of the container /// /// /// private IEnumerator CotainerSiwtch(bool open, BaseNode nodes) { if (this.parentRectTransform != null) { float t = 0 float targetValue = open ? EndContainerWidth : StartContainerWidth while (t < EleasticSpeed) { yield return null float value = Mathf.Lerp(nodes.parentRectTransform.sizeDelta.x, targetValue, t / EleasticSpeed) t += Time.deltaTime nodes.parentRectTransform.sizeDelta = new Vector2(value, nodes.parentRectTransform.sizeDelta.y) } } }

デモアドレス、以下のコードをスキャン->履歴情報->現在の記事の終わりを見つけて取得

その他のコンテンツについては、次のWebサイトをご覧ください。