简单的有限状态机

最近要做一个动画效果,通过简单的有限状态机可以更好的解决依次播放动画、动画跳过等问题,做了一个简单的表现。

FGUI

动画效果通过FGUI的动效实现;

FGUI代码生成

在发布设置中,打开“允许发布代码”
在这里插入图片描述
但默认生成的代码,并不符合使用习惯,也无法适应自己的ui框架,所以需要在plugIn文件夹中添加自定义的lua文件,根据自己的需要修改代码文件;
导入lua文件后,需要重启FGUI项目才能生效;

FGUI动效

动画效果:从中间向四周依次分发卡牌,再依次收回;

根据效果可知,每个卡牌的终点位置是根据顺序变化的,所以不能写死,因此需要在关键帧上添加标签,用于在运行过程中修改参数;
在这里插入图片描述

读取FGUI文件

加载对应的byte文件:

        GRoot.inst.SetContentScaleFactor(800, 600);
        UIPackage.AddPackage("UI/Test");
        GComponent component = UIPackage.CreateObject("Test", "TestLayer").asCom;
        GRoot.inst.AddChild(component);

执行对应类的方法:

        component.asCom.Logic = new UI_TestLayer();
        m_TestLayer = (UI_TestLayer)component.asCom.Logic;
        m_TestLayer.SetSelfComponent(component);
        m_TestLayer.Init();
        m_TestLayer.Open();

有限状态机

using System.Collections.Generic;
using FairyGUI;

namespace ClientGame.UI
{
    public partial class UI_TestLayer
    {
        private const int STATE_NONE = 0;
        private const int STATE_WAITING = 1;
        private const int STATE_FORWARD = 2;
        private const int STATE_BACK = 3;
        private const int STATE_STOP = 4;

        private int m_state = -1;
        private bool m_isSkip;
        private int m_CurrentImageIndex = -1;
        private List<UI_TestItem> m_TestItems;
        protected override void OnOpen(object data)
        {
            m_state = STATE_NONE;
            m_TestItems = new List<UI_TestItem>()
            {
                m_Item1, m_Item2, m_Item3, m_Item4, m_Item5, m_Item6, m_Item7, m_Item8,
            };
            m_BtnStart.onClick.Set(() =>
            {
                m_state = STATE_FORWARD;
            });
            
            m_BtnSkip.onClick.Set(OnSkipClick);
            SetName();
        }

        private void SetName()
        {
            int index = 0;
            foreach (var item in m_TestItems)
            {
                item.UpdateView(index++);
            }
        }

        public void Update()
        {
            switch (m_state)
            {
                case STATE_FORWARD:
                    OnForward();
                    break;
                case STATE_BACK:
                    OnBack();
                    break;
                case STATE_STOP:
                    OnStop();
                    break;
            }
        }

        private void OnForward()
        {
            if (m_isSkip)
            {
                foreach (var item in m_TestItems)
                {
                    item.StopForwardAnim();
                }

                m_state = STATE_BACK;
                m_isSkip = false;//每次只跳过一个
                m_CurrentImageIndex = -1;
            }
            else
            {
                //结束上一个
                if (0 <= m_CurrentImageIndex && m_CurrentImageIndex < m_TestItems.Count)
                {
                    m_TestItems[m_CurrentImageIndex].StopForwardAnim();
                }

                m_CurrentImageIndex++;
                //播放下一个
                if (0 <= m_CurrentImageIndex && m_CurrentImageIndex < m_TestItems.Count)
                {
                    m_state = STATE_WAITING;
                    m_TestItems[m_CurrentImageIndex].ForwardAnim(() => m_state = STATE_FORWARD);
                }
                else
                {
                    m_CurrentImageIndex = -1;
                    m_state = STATE_BACK;
                }
            }
            
        }

        private void OnBack()
        {
            if (m_isSkip)
            {
                foreach (var item in m_TestItems)
                {
                    item.StopBackwardAnim();
                }

                m_state = STATE_STOP;
                m_isSkip = false;//每次只跳过一个
            }
            else
            {
                //结束上一个
                if (0 <= m_CurrentImageIndex && m_CurrentImageIndex < m_TestItems.Count)
                {
                    m_TestItems[m_CurrentImageIndex].StopBackwardAnim();
                }

                m_CurrentImageIndex++;
                //播放下一个
                if (0 <= m_CurrentImageIndex && m_CurrentImageIndex < m_TestItems.Count)
                {
                    m_state = STATE_WAITING;
                    m_TestItems[m_CurrentImageIndex].BackwardAnim(() => m_state = STATE_BACK);
                }
                else
                {
                    m_CurrentImageIndex = -1;
                    m_state = STATE_STOP;
                }
            }
        }

        private void OnStop()
        {
            m_state = STATE_NONE;
            m_CurrentImageIndex = -1;
        }
        
        private void OnSkipClick(EventContext context)
        {
            m_isSkip = true;
        }

    }
}

动效控制:

using System;
using UnityEngine;

namespace ClientGame.UI
{
    public partial class UI_TestItem
    {
        private int xPostion;
        private int yPostion;
        public void UpdateView(int index)
        {
            UI_TestImage image = m_Image;
            image.UpdateView(index);
            int row = index % 4;
            int col = index / 4;
            xPostion = row * 150;
            yPostion = col * 500;
        }
        
        public void ForwardAnim(Action callback)
        {
            m_Anim.SetValue("end", xPostion, yPostion);
            m_Anim.SetHook("end", () =>
            {
                callback?.Invoke();
            });
            m_Anim.timeScale = 1;
            m_Anim.Play();
        }

        public void StopForwardAnim()
        {
            m_Anim.Stop();
            m_Image.Self.position=new Vector2(xPostion, yPostion);
        }

        public void BackwardAnim(Action callback)
        {
            m_Anim.SetValue("start", xPostion, yPostion);
            m_Anim.SetValue("end", 325, 250);
            m_Anim.SetHook("end", () =>
            {
                callback?.Invoke();
            });
            m_Anim.timeScale = 2;
            m_Anim.Play();
        }
        public void StopBackwardAnim()
        {
            m_Anim.Stop();
            m_Anim.timeScale = 1;
            m_Image.Self.position = new Vector2(325, 250);
        }
        
    }
}

最后效果

正常播放,不跳过:
![请添加图片描述](https://i-blog.csdnimg.cn/direct/8c52f1187e2941dc941a178e1d4bacb7.gif请添加图片描述
点击跳过:
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值