使用 USS 样式在 Unity UI 工具包中循环转换

问题描述 投票:0回答:1

最近 Unity 发布了他们新的 UI 工具包,到目前为止它一直很棒。我的文档中有一个倒计时元素,我计划在数字达到阈值后将其设置为脉冲

这是当前的过渡:

我怎样才能无限循环播放动画

当前的 USS 代码如下。我尝试过类似的 css 属性,例如

animation-iteration-count: infinite;
但到目前为止没有运气,而且文档似乎还不完整。

#timer-countdown:hover {
    scale: 1.2 1.1;
    color: rgba(255, 170, 170, 255);
    transition-duration: 1s;
    transition-timing-function: ease-in-out-cubic;
}
unity3d animation
1个回答
4
投票

我在论坛和其他地方看到的关于 Unity 的建议是在 C# 中控制动画和其他行为,而 uss 还不够发达。

A gif showing a rotating circle. Expanding, retracting and looping endlessly

简单的解决方案

为每次转换结束时注册回调,并切换活动的类。注意:每个班级应该只有 1 个转换。

    //Put this in the constructor, call once. 
    RegisterCallback<TransitionEndEvent>((e) => PlayNext());
    ToggleInClassList("$"{previousClass}");

    public void PlayNext()
    {
        // These should be "offset": One is off while the other is on. 
        ToggleInClassList("$"{previousClass}");
        ToggleInClassList($"{nextClass}");
    }

自定义元素解决方案

稍微更完整的解决方案是创建自定义视觉元素。

using UnityEngine;
using UnityEngine.UIElements;

public class LoopingAnimation : VisualElement
{
        #region boilerplate

        // Required for the UI Builder
        public new class UxmlFactory : UxmlFactory<LoopingAnimation, UxmlTraits>     
        {}

        public new class UxmlTraits : VisualElement.UxmlTraits
        {
            UxmlStringAttributeDescription m_className = new UxmlStringAttributeDescription { name = "class-name", defaultValue = "animation-class" };
            UxmlIntAttributeDescription m_classCount = new UxmlIntAttributeDescription { name = "classCount", defaultValue = 1 };
            public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
            {
                base.Init(ve, bag, cc);
                var ate = ve as LoopingAnimation;
                ate.className = m_className.GetValueFromBag(bag, cc);
                ate.classCount = m_classCount.GetValueFromBag(bag, cc);
            }
        }
        #endregion

        int index = 0;

        public bool isPlaying = true;
        public string className { get; set; }
        public int classCount { get; set; }

        public VisualElement child = new VisualElement() { name = 

“动画目标”};

        public LoopingAnimation() : base()
        {
            RegisterCallback<GeometryChangedEvent>(OnGeometryChangedEvent);
        }

        void OnGeometryChangedEvent(GeometryChangedEvent e)
        {
            Add(child);
            RegisterCallback<TransitionEndEvent>((e) => PlayNext());
            RegisterCallback<PointerEnterEvent>((e) => Play()); //Only here to get the ball rolling in Preview Mode
            UnregisterCallback<GeometryChangedEvent>(OnGeometryChangedEvent);
        }

        public void PlayNext()
        {
            if(!isPlaying ) return;
            Debug.Log($"Looping {index} {className}{index %classCount}");
            child.RemoveFromClassList($"{className}{index %classCount}");
            index++;
            child.AddToClassList($"{className}{index %classCount}");
        }

        public void Play()
        {
            isPlaying = true;
            style.display = DisplayStyle.Flex;
            PlayNext();
        }

        public void Stop()
        {
            isPlaying = false;
            child.ClearClassList();
            style.display = DisplayStyle.None;
        }
}

使用方法

在 UI Builder 中,将此元素拖放到场景中。在右侧的检查器中,插入这些值:

  • 动画要使用的类名(只支持1个类名)
  • 班级数:这是您要使用的带有转换的班级数量。

类名像这样递增:

  • 班级名0
  • 班级名称1
  • 班级名称2

您可以在预览模式下编辑和测试动画(!)

例子USS

    #animation-target {
        width: 100%;
        height: 100%;
        background-color: rgba(255, 32, 32, 0.25);
        border-top-left-radius: 50%;
        border-bottom-left-radius: 50%;
        border-top-right-radius: 50%;
        border-bottom-right-radius: 50%;
    }

    .animation-0 {
        background-color: rgb(229, 107, 107);
        transition-duration: 800ms;
        transition-property: scale;
        border-left-width: 21px;
        border-right-width: 21px;
        border-top-width: 21px;
        border-bottom-width: 21px;
        scale: 2 2;
        transition-timing-function: ease-out-sine;
        border-right-color: rgb(0, 26, 255);
    }

    .animation-1 {
        background-color: rgb(229, 107, 107);
        transition-duration: 800ms;
        border-left-color: rgb(255, 0, 0);
        transition-property: scale;
        border-left-width: 21px;
        border-right-width: 21px;
        border-top-width: 21px;
        border-bottom-width: 21px;
        scale: 1 1;
        transition-timing-function: ease-in-sine;
        transition-delay: 0s;
    }

    .animation-2 {
        rotate: 180deg;
        transition-property: rotate;
        transition-duration: 600ms;
        border-left-width: 21px;
        border-right-width: 21px;
        border-top-width: 21px;
        border-bottom-width: 21px;
        border-left-color: rgba(0, 22, 255, 255);
    }

已知限制:

  • 每节课只有 1 次转换!如果你添加更多,他们会弄乱顺序或永远不会玩。
  • 如果两个后续动画影响同一个属性,并且值没有改变,则循环结束。如果先前的属性值与目标过渡值匹配,Unity 不会播放过渡。
© www.soinside.com 2019 - 2024. All rights reserved.