Use o componente scrollrect da unidade para implementar a estrutura do sistema props/backpack do brotato

precisar:

1. Uma interface semelhante a uma mochila, que pode ser selecionada quando o mouse está pairando, o wasd pode ser alternado e selecionado e um painel flutuante aparecerá quando selecionado.

2. Há uma barra de rolagem, você pode usar a roda do mouse e o botão direito do mouse para rolar. Ao usar wasd para alternar os adereços selecionados, se os adereços estiverem na linha inferior/superior da interface, eles rolarão automaticamente para baixo/para cima.

concluir

1. Noções básicas de interface

1.1. Interface tipo mochila

É feito com componentes como Scroll Rect e Grid Layout Group.Existem muitos tutoriais relacionados na Internet, então vamos ignorá-lo aqui. Deve-se notar que na implementação descrita aqui, o scroll rect só pode rolar verticalmente, e o tipo de movimento do scroll rect deve ser definido como clamped, e a visibilidade da barra de rolagem deve ser definida como . Ocultar automaticamente e expandir a exibição.

 

1.2 seleção de botão (selecionar)

Precisa atender aos seguintes requisitos:

1. Selecione ao passar o mouse

2.interruptor wasd selecionado

3. Reproduza efeitos sonoros e altere o estilo do botão quando selecionado

Na verdade, os requisitos acima são relativamente simples, o mais importante é o primeiro requisito, seleção de foco do mouse, geralmente uso dois métodos para resolver:

    public void OverSelected(Button btn)
    {
        btn.Select();
        //注意,需要引用 UnityEngine.UI 命名空间才可声明Button变量
    }
    public void OnSelected()
    {
        AudioManager.Instance.PlaySFX(btnAudioClip);
    }

Entre eles, este AudioManager.Instance.PlaySFX(btnAudioClip); é o método de selecionar o efeito sonoro pelo botão play, usando o modo singleton. Para obter detalhes, consulte: gerenciamento de volume global da unidade/configuração de volume global e interface de configuração de volume ( incluindo função mudo) 

O objeto botão cria um componente Event Trigger, monta o script onde este método está localizado sob os eventos PointerEnter e Select do componente Event Trigger, seleciona e chama esses dois métodos e então atribui o componente botão como um parâmetro para o primeiro método,

Quanto à seleção de troca de wasd, ao criar um componente de botão, o padrão de Navegação (navegação) do botão é Automático, mesmo se você usar wasd para alternar automaticamente para o botão mais próximo, também pode definir Navegação como Explícito e, em seguida, personalizar o wasd para mudar para o botão.

Por fim, a alteração do estilo do botão também pode ser resolvida usando apenas o componente de botão e precisa apenas definir a transição.

1.3 Painel de suspensão

 Basicamente, o painel flutuante é ativado/desativado por meio do evento select de EventTrigger. Com base nisso, a posição de ativação do painel flutuante pode ser definida e a configuração do conteúdo do painel flutuante pode ser realizada usando o objeto programável, que é ignorado aqui.

1.4 Não cancele a seleção de outros botões quando o mouse clicar no fundo

Clique no fundo quando o botão estiver selecionado, o fundo será selecionado e o botão será desmarcado. Embora o método de implementação no Tudou Brothers seja: clicar no fundo cancelará a seleção do botão e clicar em wasd selecionará automaticamente um botão; mas se você não quiser cancelar a seleção de outros botões, poderá:

1. Instale o sistema de entrada gratuito Input System.Após a instalação, desmarque Desmarcar no clique de segundo plano no script Input System UI Input Module do objeto EventSystem.

2. Comente a linha 591 no StandaloneInputModule do objeto EventSystem padrão,

DeselectIfSelectionChanged(currentOverGo, pointerEvent);

Recomenda-se copiar todo o script e comentá-lo em vez de alterar diretamente o script original. Em seguida, monte este script no Sistema de Eventos e cancele a ativação do script original. O conteúdo acima vem de http://t.csdn.cn/XthOc

2. Realize a rolagem do painel de controle wasd do Tudou Brothers

Esta é também a parte principal deste artigo, porque parece não haver quase nenhuma discussão sobre a implementação desta função na Internet. Talvez seja muito fácil de implementar? Também pode estar ganhando uma fortuna em voz abafada wwww

Meu método de implementação não pode ser considerado o melhor e mais perfeito. Se houver um método de implementação melhor, por favor, discuta-o.

Vá direto para o código:

using UnityEngine;
using UnityEngine.UI;

public class ScrollRectT : MonoBehaviour
{
    [Header("基本对象:滚动板、滚动条、排布")]
    [SerializeField] ScrollRect scrollRect;//操控上下滚动
    [SerializeField] Scrollbar ChoosingBar;//设置步数
    [SerializeField] GameObject GridLayerPanel;//GridLayoutGroup的对象,获取子物体、动态增长

    [Header("显示步数")]
    [SerializeField] int ViewableLength;//原显示行数
    private int ChoosingLengthTemp;//额外增长的格数=子物体/单行物体-原显示行数

    [Header("原排布板尺寸与单个步长")]
    [SerializeField] Vector2 PanelSize;//用于动态增长
    [SerializeField] float stepLength;//一格步长

    [Header("滚轮适配")]
    [SerializeField] CanvasGroup LeftCanvasGroup;//使用canvas group解决滚轮操控问题
    [SerializeField] float scrollwheelDelayTime;//滚轮延迟时间

    [Header("mask上下边界")]//需要在编辑模式下获取
    [SerializeField] float TopBoarder;
    [SerializeField] float BottomBoarder;

    [Header("编辑模式")]
    [SerializeField] bool editing;
    [SerializeField] GameObject topBtn;
    [SerializeField] GameObject btmBtn;
    private float stepLengthTemp=0;

    void Awake()
    {
        //ChoosingLengthTemp:额外增长的格数=子物体/单行物体-原显示行数
        //另外,gridlayoutgroup需要设置单行子物体数量
        ChoosingLengthTemp = Mathf.CeilToInt(1f * GridLayerPanel.transform.childCount / GridLayerPanel.GetComponent<GridLayoutGroup>().constraintCount) - ViewableLength;
        if (ChoosingLengthTemp <= 0) ChoosingLengthTemp = 0;
        else //有额外增长格数,需要对GridLayerPanel进行向下动态增长
        {
            GridLayerPanel.GetComponent<RectTransform>().sizeDelta = new Vector2(PanelSize.x, PanelSize.y + ChoosingLengthTemp * stepLength);
            GridLayerPanel.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, ChoosingLengthTemp * stepLength / 2);
        }
        //基于scrollbar的步数实现滚动功能,但需要注意的是步数numberOfSteps<2时步数将重新自动设定
        ChoosingBar.numberOfSteps = (ChoosingLengthTemp + 1 > 2) ? ChoosingLengthTemp + 1 : 2;
        
        //将面板置顶
        scrollRect.verticalNormalizedPosition = 1f;

#if UNITY_EDITOR
        //仅编辑器中调用,使用InvokeRepeating每秒调用一次编辑函数
        if (editing) if (editing) InvokeRepeating("Editing", 0f, 1f);
#endif
    }

    void Update()
    {
        //适配鼠标滚轮
            if (Input.GetAxis("Mouse ScrollWheel") != 0)
            {
                LeftCanvasGroup.blocksRaycasts = false;
                Invoke("ReTrueRaycast", scrollwheelDelayTime);//延迟重新激活blocksRaycasts
        }
    }

#if UNITY_EDITOR
    void Editing()
    {
        if (editing)
        {
            Debug.Log("top: " + topBtn.transform.position.y);
            Debug.Log("bottom: " + btmBtn.transform.position.y);
            if (stepLengthTemp == 0)
            {
                //通过数学方法直接求出步长
                stepLength = (topBtn.transform.position.y - btmBtn.transform.position.y) / ViewableLength;
                Debug.Log(stepLength);
            }
        }
    }
#endif

    public void ScrollBTNOnSelected(GameObject gameObject)
    {
        //获取按键gameObject的世界坐标,并由此判断其相对于Mask的位置,以此实现滚动
        if (gameObject.transform.position.y < BottomBoarder)//在mask以下,下滚一步
        {
            scrollRect.verticalNormalizedPosition -= 1f / (ChoosingBar.numberOfSteps-1);
            //用ChoosingBar.value-= 1f / (ChoosingBar.numberOfSteps-1);也行
        }
        else if (gameObject.transform.position.y > TopBoarder)//在mask以上,上滚一步
        {
            scrollRect.verticalNormalizedPosition += 1f / (ChoosingBar.numberOfSteps-1);
        }    

    }

    private void ReTrueRaycast()
    {
        LeftCanvasGroup.blocksRaycasts = true;
    }
}

Você pode ler os comentários da parte do código, então não vou explicar em detalhes aqui.

Instruções:

1. Configure a parte da moldura vermelha conforme mostrado na figura

2. Crie objetos filhos

Crie um número cumulativo de subobjetos de linha única * número de linhas de exibição + 1 subobjeto, conforme mostrado na figura, criei 26 subobjetos para obter a posição aproximada dos limites superior e inferior da máscara.

3. Inicie o modo de edição

Verifique a edição, pendure um subobjeto na primeira linha e um subobjeto na última linha no botão superior e no botão btm respectivamente, execute e arraste o painel para as posições de limite superior e inferior para obter dados.

 

Pode-se ver que o limite superior de Mask é ligeiramente maior que 796 e menor que 946, e o limite inferior é ligeiramente menor que 196 e maior que 46. Portanto, precisamos apenas definir os limites superior e inferior para um número que esteja a uma certa distância dos lados esquerdo e direito do intervalo, de modo a reduzir a ocorrência de erros. Afinal, esse método de implementação parece muito nativo...

Na verdade, esse valor não precisa ser particularmente específico, porque o método de controle de rolagem é relativamente rígido e o erro não será particularmente grande

4. Basicamente concluído

Nessa hora, um pequeno gênio vai perguntar: Hein? Esse é o fim? Então, para que serve o seu adaptador de roda de rolagem?

Dito ao que interessa, vamos começar com a adaptação da roda.

Depois de concluir as etapas acima, você pode encontrar um problema muito doloroso: Quando o mouse é colocado no botão, devido à seleção de foco do mouse que mencionei acima, o botão é selecionado em vez do scrollrect, então role a roda Não há como para rolar a barra de rolagem.

Para isso, mais um CanvasGroup precisa ser pendurado no objeto GridLayoutGroup .

Grupos de tela fornecem controle centralizado sobre certos aspectos de um grupo inteiro de elementos de interface do usuário sem ter que lidar com cada elemento individualmente. As propriedades do Canvas Group afetam o objeto do jogo em que ele está e todos os objetos filhos.

Propriedades do grupo de telas:

Alfa A opacidade dos elementos da interface do usuário neste grupo. O valor está entre 0 e 1, onde 0 é totalmente transparente e 1 é totalmente opaco.
Interacionável Determina se este componente aceita entrada. Quando definido como falso, a interação é desativada
Blcok Raycasts Se é possível receber detecção de raios gráficos, quando definido como falso, a detecção de raios gráficos não é aceitável
Ignorar grupo pai Ignore e substitua as configurações do CanvasGroup no objeto pai, marque-o para ignorar

 Quando o bloco raycast está desabilitado, o botão ui não pode receber a detecção de raio gráfico do mouse. Neste momento, o mouse pode selecionar automaticamente o scrollrect atrás dele, e a roda de rolagem pode funcionar normalmente. Portanto, podemos fazer a roda de rolagem funcionar corretamente desativando dinamicamente o bloco raycast.

void Update()
    {
        //适配鼠标滚轮
            if (Input.GetAxis("Mouse ScrollWheel") != 0)
            {
                LeftCanvasGroup.blocksRaycasts = false;
                Invoke("ReTrueRaycast", scrollwheelDelayTime);//延迟重新激活blocksRaycasts
        }

    }

private void ReTrueRaycast()
    {
        LeftCanvasGroup.blocksRaycasts = true;
    }

 Depois de configurar o Canvas Group e o tempo de ativação atrasada (defino 0,15s), a roda do mouse pode funcionar normalmente.

Embora o efeito dessa implementação não seja perfeito, esse método de implementação ainda pode ser usado.

fim:

Talvez alguns amigos encontrem uma pequena falha: a função para realizar a rolagem já cumpriu o papel de limitar o número de passos de rolagem, por que você precisa definir o número de passos da barra de rolagem?

É isso mesmo, eu não percebi até que estava escrevendo este artigo também.

Na verdade, definir o número de etapas da barra de rolagem ainda pode desempenhar um certo papel na restrição, evitando erros extraviados ao usar o wasd após usar a roda do mouse

No entanto, a barra de rolagem de Tudou Brothers não tem um limite estrito para o número de etapas (embora as pessoas usem godot em vez de unidade), e a roda do mouse pode fazer com que os botões fiquem presos na borda da máscara.

Depois de descobrir esse problema, experimentei e coloquei os limites superior e inferior em 800 e 190 (um pouco maior/menor que o valor obtido, ou seja, voltará ao normal desde que desvie um pouco), e depois limitei o tamanho da barra de rolagem, assim como os irmãos batata Efeito geral.

 

Acho que você gosta

Origin blog.csdn.net/weixin_56487870/article/details/130611317
Recomendado
Clasificación