自己写一个Animation叫GAnimation,用组件的方式添加到Player类中,这不是一个框架,而是一个类似于状态机的东西,我使用的是Animation动画,然后给每个动画定义优先级,比如攻击的优先级小于被攻击,即是说一个人的攻击可以被打断,类似这样的。辅助类有Trigger和GAnimationClip(带动画帧事件)。如何做到同步,如果数据是同步的,那么我只要根据数据来一帧一帧播放,来一个数据包就播放一帧,因为状态机是我写的,所以他的状态转移是确定的(或者说精确的)。现在只要精确播放动画的哪一帧即可,精确的播放只要利用Animation的NormalizeTime,比如我现在播放Idle动画,长度是30帧,现在来一个数据包,那我就播放第一帧,设置的NormalizeTime = 1.0f/30,再来一帧,播放第二帧,NormalizeTime = 2.0f/30,动画的长度和名字均可通过配置管理器加载,这样就可以操纵动画播放到哪里了。因为每一帧都是整数,所以也可以精确触发动画帧事件。这样动画就同步了。

注意:因为网络卡了没有数据包,动画是不该继续播放的,所以Animation在初始化的时候要把每一个AnimationClip的Speed设置为0,这样他就不会自己播放了。附上代码,状态转移那里可以不看,因为我想歪了把配置文件的AnimationState和这里的AnimStatement分开了,其实是可以合并的,很乱。

namespace Eating.Module.Game.Component
{/// <summary>/// 只有第一次get的时候才翻转,而不是每get一次就翻转一次/// </summary>public class Trigger{private bool _isFirstTimeToGet;private bool _val;public bool Value{get{if (_isFirstTimeToGet){_isFirstTimeToGet = !_isFirstTimeToGet;bool temp = _val;_val = !_val;return temp;}return _val;}set{_val = value;_isFirstTimeToGet = true;}}}public class GAnimationClip{//private int _frameCount;public int FrameCount;public int CurFrame;/// <summary>/// 动画帧事件/// </summary>public Dictionary<int, Action> FrameEvent;public bool IsRoop;public GAnimationClip(bool isRoop){CurFrame = 0;FrameEvent = new Dictionary<int, Action>();IsRoop = isRoop;}}public class GAnimation : IComponent{enum AnimStatement{Idle,Attack,Damage,Move,Die,};//父对象的Animationpublic Dictionary<int, string> AnimClipID;//动画播放的信息private  Dictionary<int, GAnimationClip> _animInfo;private bool _isInit = false;private Player _player;private AnimStatement _animStatement;public Trigger IsDamage;public Trigger IsDead;public void Release(){_isInit = false;_player = null;AnimClipID = null;_animInfo = null;}public GAnimationClip GetClip(int ID){return _animInfo[ID];}public void Init(object arg = null){if (_isInit){this.LogWarning("Init() Has Been Inited");return;}IsDamage =new Trigger();IsDead = new Trigger();_animStatement = AnimStatement.Idle;Player player = (Player) arg;if (player == null){this.LogError("Init() arg Is Null!");return;}_isInit = true;_player = player;AnimClipID = ConfigManager.Instance.GetMonsterAnimClipName();_animInfo = ConfigManager.Instance.GetAnimationClipsInfo();}public void UpdateFrame(FClientKey fk = null){HandleAnim(fk);SetPlayerAnimState();}private void SetPlayerAnimState(){_player.AnimName = AnimClipID[GetID(_animStatement)];_player.AnimNormalizeTime = 1.0f * _animInfo[GetID(_animStatement)].CurFrame/ _animInfo[GetID(_animStatement)].FrameCount;}private void HandleAnim(FClientKey fk = null){if (IsDead.Value && _animStatement != AnimStatement.Die){ResetCurStatement();_animStatement = AnimStatement.Die;}if (_animStatement == AnimStatement.Die){PlayCurAnim();}else{//这个做成trigger把if (IsDamage.Value){ResetCurStatement();_animStatement = AnimStatement.Damage;}if (_animStatement == AnimStatement.Damage){bool isEnding = PlayCurAnim();if (isEnding){HandleAttackAnim(fk);}else this.Log("Damage");}else{HandleAttackAnim(fk);}}}private void HandleAttackAnim(FClientKey fk = null){//攻击中 忽略重复的攻击if (_animStatement == AnimStatement.Attack){bool isEnding = PlayCurAnim();if (isEnding){HandleMoveAnim(fk);}}//正在开始攻击else if (fk != null && fk.IsAttack){ResetCurStatement();EnterNewState(AnimStatement.Attack);}//不在攻击中,检查移动else{HandleMoveAnim(fk);}}private void HandleMoveAnim(FClientKey fk = null){//没有移动if (fk == null || (fk.MoveX == 0 && fk.MoveY == 0)){if (_animStatement != AnimStatement.Idle){ResetCurStatement();EnterNewState(AnimStatement.Idle);}else PlayCurAnim();}else{//x和y有值if (_animStatement != AnimStatement.Move){ResetCurStatement();EnterNewState(AnimStatement.Move);}else{PlayCurAnim();}}}//把AnimStatement转化为AnimClipNameDefprivate int GetID(AnimStatement statement){int id = -1;if (statement== AnimStatement.Idle){id = AnimClipNameDef.IDLE;}else if (statement== AnimStatement.Attack){id = AnimClipNameDef.ATTACK;}else if (statement== AnimStatement.Damage){id = AnimClipNameDef.DAMAGE;}else if (statement== AnimStatement.Move){id = AnimClipNameDef.MOVE;}else if (statement== AnimStatement.Die){id = AnimClipNameDef.DEAD;}return id;}private bool PlayCurAnim(){int id = GetID(_animStatement);//如果已经播放完这个动画而且不是一个循环动画//就该播放其他动画了//则通知调用者播放其他动画比如IDLE或者MOVEif (_animInfo[id].CurFrame == _animInfo[id].FrameCount && !_animInfo[id].IsRoop){return true;}_animInfo[id].CurFrame %= _animInfo[id].FrameCount;_animInfo[id].CurFrame++;if (_animInfo[id].FrameEvent.ContainsKey(_animInfo[id].CurFrame)){_animInfo[id].FrameEvent[_animInfo[id].CurFrame].Invoke();}return false;}private void EnterNewState(AnimStatement statement){int id = GetID(statement);if (id == -1){this.LogError("EnterNewState() No Such Statement In AnimClipNameDef. statement:{0}!",statement.ToString());return;}_animStatement = statement;PlayCurAnim();}private void ResetCurStatement(){_animInfo[GetID(_animStatement)].CurFrame = 0;}}
}

贪吃小怪兽介绍之动画同步相关推荐

  1. 贪吃小怪兽介绍之整体框架

    整体框架如下所示,分为三层,上层只能依赖下层. UI层:处理每个面板的UI,比如登录界面就有UILoginPage来管理,(继承于UIBase,UIBase继承于MonoBehavior) 功能模块: ...

  2. 怎么制作小怪兽打凹凸曼的游戏~

    我们将制作名为'小怪兽打凹凸曼'游戏 首先请安装 Construct 2 附上网址:https://www.scirra.com/construct2/releases/r244 第一步,新建工程: ...

  3. 贝灵机器人智能点读笔好吗_小怪兽AI智能点读笔笔值不值得买,看完你就不用纠结了...

    小怪兽AI智能点读笔笔值不值得买,看完你就不用纠结了 2020-08-26 16:17:46 7点赞 4收藏 0评论 小编注:此篇文章来自即可瓜分10万金币,周边好礼达标就有,邀新任务奖励无上限,点击 ...

  4. 奥特曼和小怪兽的故事

    "妈妈,妈妈,"小怪兽问,"我什么时候才能长大呢?" 正做饭的怪兽妈妈和蔼地问:"干吗想长大呀,做妈妈的乖宝宝不好吗?" "长大了 ...

  5. 每个成功的奥特曼背后都有一个默默挨打的小怪兽

    (一) "妈妈,妈妈,"小怪兽问,"我什么时候才能长大呢?" 正做饭的怪兽妈妈和蔼地问:"干吗想长大呀,做妈妈的乖宝宝不好吗?" " ...

  6. android ios 画图 app,手残党也能自画“小怪兽”?这些画图app你必须知道!

    原标题:手残党也能自画"小怪兽"?这些画图app你必须知道! 如今,手机在手,所有事情都变得越来越简单,画画也是. 年轻人的流行主题总是来得又快,走得也急.这个现象在大家的朋友圈中 ...

  7. 照着做,你也可以战胜算法小怪兽

    >点击上方"Java Dev"关注< 看看你有多少好友也关注了我 Photo From Internet 说起学习算法,相信每个程序员都有一段故事,有的人可能是痛苦的, ...

  8. 联想计算机 i7,聊聊 联想 小新pro13 i7 10710 低压6核小怪兽

    聊聊 联想 小新pro13 i7 10710 低压6核小怪兽 2020-02-21 14:12:25 26点赞 32收藏 40评论 追加修改(2020-02-21 14:56:20): 本文低压107 ...

  9. 每个成功的奥特曼背后都有一个默默挨打的小怪兽_陕南赤子_新浪博客

    (一) "妈妈,妈妈,"小怪兽问,"我什么时候才能长大呢?" 正做饭的怪兽妈妈和蔼地问:"干吗想长大呀,做妈妈的乖宝宝不好吗?" " ...

最新文章

  1. mac如何修改php.ini,mac 如何修改php.ini
  2. deepin--安装Anaconda
  3. 秘鲁国家馆中国电商平台 美食周对话国际农民丰收节贸易会
  4. Linux硬盘分区的格式化
  5. UCloud UFile——对象存储UFile SDK基本使用
  6. 想成为BAT中的一员,你总要去学点什么(一)
  7. linux系统redis单机版安装及设置解决DENIED Redis is running in protected mode because protected mode is enabled问题
  8. 扫地机器人 杂牌_国内扫地机器人哪个牌子好?
  9. c语言 异或_C语言位运算实例讲解
  10. [转载]在安装win7系统时如何不产生100M的系统保留分区
  11. 经济型EtherCAT运动控制器(三):PLC实现多轴直线插补与电子凸轮
  12. MFC调试工具——之BoundsChecker用法
  13. 这份Java日志格式规范,拿走不谢!
  14. 20162327WJH第一次实验——线性结构
  15. 中兴光纤猫 F460 V3.0破解
  16. 在App Store和Google Play上推广应用程序
  17. MySQL_15_MySQL底层SQL查询成本计算
  18. 数据科学中的计量经济学技术
  19. 厦门计算机中专学校,厦门有哪些中专学校
  20. SQL查询初学者指南读书笔记(四)where从句

热门文章

  1. [MDP]的案例gridworld
  2. 工作总结——RestTemplate请求时间过长问题
  3. 用JS获取URL的方法(超级简单)
  4. 寺库收割“两大佬”,左手LVMH右手京东 | 一点财经
  5. 未转变者服务器中文版,未转变者最新版
  6. 指标综合评价(定性指标定量化、指标正相关化、赋权重)
  7. 下载MMD模型(包含原神、崩坏等模型)
  8. java刷新页面_刷新页面的几种方法
  9. react如何刷新当前页面_react怎么强制刷新页面?
  10. 如何在采源宝获利?具体步骤