[Unity] GameFramework 学习记录 6:计时器
一开始我想不断传递 Delegate
public class TimerHandler{private float _elapsedTime;public float ElapsedTime{get => _elapsedTime;set{if (value >= Duration){if (CallBack != null) CallBack(Args);}}}private float _duration;public float Duration => _duration;private bool _isLoop;public bool IsLoop => _isLoop;private Delegate _callback;public Delegate CallBack => _callback;private object[] _args;public object[] Args => _args;public TimerHandler(float duration, bool isLoop, Delegate callback, params object[] args){_duration = duration;_isLoop = isLoop;_callback = callback;_args = args;}}
这样是不对了,问了别人,别人说我要定义 delegate 类型
public class TimerHandler{private float _elapsedTime;public float ElapsedTime{get => _elapsedTime;set{if (value >= Duration){if (CallBack != null) CallBack(Args);}}}private float _duration;public float Duration => _duration;private bool _isLoop;public bool IsLoop => _isLoop;public delegate void CallBackDelegate(params object[] args);public CallBackDelegate Callback;private object[] _args;public object[] Args => _args;public TimerHandler(float duration, bool isLoop, CallBackDelegate callback, params object[] args){_duration = duration;_isLoop = isLoop;Callback = callback;_args = args;}}
其中 if (CallBack != null) CallBack(Args);
中的 CallBack
报错,说是 Cannot resolve symbol ‘CallBack’
但是我明明已经定义了
我在别的地方试验:
public TimerHandler(float duration, bool isLoop, CallBackDelegate callback, params object[] args){_duration = duration;_isLoop = isLoop;Callback = callback;_args = args;Callback(args);}}
这之中的 Callback(args);
就没有报错,怪
最后写成
Assets/GameMain/Scripts/Utility/ListRemovableInForEach.cs
using System;
using System.Collections;
using System.Collections.Generic;namespace OaksMayFall
{public class RList<T>{private ListRemovableInForEach<T> collection = new ListRemovableInForEach<T>();public IEnumerator GetEnumerator(){return collection;}public void Remove(T t){collection.Remove(t);}public void Add(T t){collection.Add(t);}}public class ListRemovableInForEach<T> : IEnumerator{private List<T> list = new List<T>();public object current = null;public object Current{get { return current; }}private int icout = 0;public bool MoveNext(){if (icout >= list.Count){return false;}else{current = list[icout];icout++;return true;}}public void Reset(){icout = 0;}public void Add(T t){list.Add(t);}public void Remove(T t){if (list.Contains(t)){if (list.IndexOf(t) <= icout){icout--;}list.Remove(t);}}}
}
Assets/GameMain/Scripts/Timer/TimerHandler.cs
namespace OaksMayFall
{public class TimerHandler{private bool _isPasue;public bool IsPasue => _isPasue;private bool _isStop;public bool IsStop => _isStop;private float _elapsedTime;public float ElapsedTime{get => _elapsedTime;set{if (!_isStop && !_isPasue) _elapsedTime = value;if (_elapsedTime >= _duration)Stop();}}private float _duration;public float Duration => _duration;private bool _isLoop;public bool IsLoop => _isLoop;public delegate void CallBackDelegate(params object[] args);private CallBackDelegate _callback;private object[] _args;public static RList<TimerHandler> TimerHandlerList;public TimerHandler(float duration, bool isLoop, CallBackDelegate callback, params object[] args){_isPasue = true;_isStop = false;_duration = duration;_isLoop = isLoop;_callback = callback;_args = args;TimerHandlerList.Add(this);}public void Reset(){_elapsedTime = 0;}public void Start(){_isPasue = false;}public void Pause(){_isPasue = true;}public void Stop(){_callback?.Invoke(_args);if (_isLoop){_elapsedTime -= _duration;}else{_isPasue = true;_isStop = true;TimerHandlerList.Remove(this);}}}
}
Assets/GameMain/Scripts/Timer/TimerComponent.cs
using System;
using System.Collections.Generic;
using System.Timers;
using UnityEngine;
using UnityGameFramework.Runtime;namespace OaksMayFall
{public class TimerComponent : GameFrameworkComponent{private float _timeScale = 1f;public float TimeScale => _timeScale;public TimerHandler CreateTimer(float duration, bool isLoop, TimerHandler.CallBackDelegate callback, params object[] args){return new TimerHandler(duration, isLoop, callback, args);}public TimerHandler CreateTimer(float duration, bool isLoop, TimerHandler.CallBackDelegate callback){return new TimerHandler(duration, isLoop, callback, null);}private void Update(){foreach (TimerHandler timerHandler in TimerHandler.TimerHandlerList){timerHandler.ElapsedTime += Time.deltaTime * _timeScale;}}}
}
运行的时候会报错……提示我使用了空指针
debug 之后是 TimerHandler.TimerHandlerList == null
哦我错了,应该是要 public static RList<TimerHandler> TimerHandlerList = new RList<TimerHandler>();
然后我想用计时器做冷却时间
Assets/GameMain/Scripts/Utility/ThirdPersonLocomotion.cs
// 攻击相关/// <summary>/// 攻击计时器/// </summary>private bool _isAttacking = false;/// <summary>/// 攻击的冷却时间/// </summary>private float _attackTimeout = 1f;/// <summary>/// 是否能够攻击/// </summary>private bool ShouldAttack{get{if (_userInput.Attack && !_isAttacking){_isAttacking = true;var timer = GameEntry.Timer.CreateTimer(_attackTimeout, false,delegate(object[] args) { _isAttacking = false; });timer.Start();return true;}else{return false;}}}/// <summary>/// 设置动画状态机参数/// </summary>public void SetAnimatorValue(){// 着地_userAnimator.SetBool(_animIDGrounded, _isGrounded);// 跳跃if (_isGrounded)_userAnimator.SetBool(_animIDFreeFall, false);// 自由下落else_userAnimator.SetBool(_animIDFreeFall, true);// 移动_moveAnimBlend = Mathf.SmoothDamp(_moveAnimBlend, _horizontalVelocity.magnitude, ref _moveAnimBlendSmoothVelocity, _moveAnimBlendSmoothTime);_userAnimator.SetFloat(_animIDSpeed, _moveAnimBlend);// 攻击if (ShouldAttack){Attack();}}
结果是只能攻击一次
看上去像是委托没有执行……
debug 发现 TimerComponent 里面只遍历了新创建的计时器一次
在 TimerComponent 的 OnUpdate 中打印
我是从这里抄的迭代器
https://www.cnblogs.com/willingtolove/p/12051649.html#%E6%96%B9%E6%B3%95%E4%B8%89%E9%80%9A%E8%BF%87%E6%B3%9B%E5%9E%8B%E7%B1%BB%E5%AE%9E%E7%8E%B0ienumerator
本来还想再找找有没有别的迭代器的实现方案,现在想想还是自己改把
因为他就是在迭代的时候没有把自己的计数器重置为 0,所以还要我手动重置
Assets/GameMain/Scripts/Timer/TimerComponent.cs
private void Update(){foreach (TimerHandler timerHandler in TimerHandler.TimerHandlerList){Debug.Log(timerHandler.ElapsedTime);timerHandler.ElapsedTime += Time.deltaTime * _timeScale;}TimerHandler.TimerHandlerList.collection.Reset();}
然后,就感觉,可以直接在迭代器里面改
Assets/GameMain/Scripts/Utility/ListRemovableInForEach.cs
public bool MoveNext(){if (icout >= list.Count){Reset();return false;}else{current = list[icout];icout++;return true;}}
这样就好了
最终代码
Assets/GameMain/Scripts/Utility/ListRemovableInForEach.cs
using System;
using System.Collections;
using System.Collections.Generic;namespace OaksMayFall
{public class RList<T>{public ListRemovableInForEach<T> collection = new ListRemovableInForEach<T>();public IEnumerator GetEnumerator(){return collection;}public void Remove(T t){collection.Remove(t);}public void Add(T t){collection.Add(t);}}public class ListRemovableInForEach<T> : IEnumerator{public List<T> list = new List<T>();public object current = null;public object Current{get { return current; }}private int icout = 0;public bool MoveNext(){if (icout >= list.Count){Reset();return false;}else{current = list[icout];icout++;return true;}}public void Reset(){icout = 0;}public void Add(T t){list.Add(t);}public void Remove(T t){if (list.Contains(t)){if (list.IndexOf(t) <= icout){icout--;}list.Remove(t);}}}
}
Assets/GameMain/Scripts/Timer/TimerHandler.cs
namespace OaksMayFall
{public class TimerHandler{private bool _isPasue;public bool IsPasue => _isPasue;private bool _isStop;public bool IsStop => _isStop;private float _elapsedTime;public float ElapsedTime{get => _elapsedTime;set{if (!_isStop && !_isPasue) _elapsedTime = value;if (_elapsedTime >= _duration)Stop();}}private float _duration;public float Duration => _duration;private bool _isLoop;public bool IsLoop => _isLoop;public delegate void CallBackDelegate(params object[] args);private CallBackDelegate _callback;private object[] _args;public static RList<TimerHandler> TimerHandlerList = new RList<TimerHandler>();public TimerHandler(float duration, bool isLoop, CallBackDelegate callback, params object[] args){_isPasue = true;_isStop = false;_duration = duration;_isLoop = isLoop;_callback = callback;_args = args;TimerHandlerList.Add(this);}public void Reset(){_elapsedTime = 0;}public void Start(){_isPasue = false;}public void Pause(){_isPasue = true;}public void Stop(){_callback?.Invoke(_args);if (_isLoop){_elapsedTime -= _duration;}else{_isPasue = true;_isStop = true;TimerHandlerList.Remove(this);}}}
}
Assets/GameMain/Scripts/Timer/TimerComponent.cs
using System;
using System.Collections.Generic;
using System.Timers;
using UnityEngine;
using UnityGameFramework.Runtime;namespace OaksMayFall
{public class TimerComponent : GameFrameworkComponent{private float _timeScale = 1f;public float TimeScale => _timeScale;public TimerHandler CreateTimer(float duration, bool isLoop, TimerHandler.CallBackDelegate callback, params object[] args){return new TimerHandler(duration, isLoop, callback, args);}public TimerHandler CreateTimer(float duration, bool isLoop, TimerHandler.CallBackDelegate callback){return new TimerHandler(duration, isLoop, callback, null);}private void Update(){foreach (TimerHandler timerHandler in TimerHandler.TimerHandlerList){Debug.Log(timerHandler.ElapsedTime);timerHandler.ElapsedTime += Time.deltaTime * _timeScale;}}}
}
应用
原来我还需要在运动逻辑里面做计时,现在不用了,现在是统一交到一个地方,还方便统一控制时间缩放
截个图感受一下,如果在一堆代码中删掉计时的部分,看上去会更清爽
现在没有计时相关了
但是其实是把计时器放到了属性里面
不可能完全去掉,但是放到属性这里更好找了
[Unity] GameFramework 学习记录 6:计时器相关推荐
- [Unity] GameFramework 学习记录 1
下载框架作者的示例工程 https://github.com/EllanJiang/StarForce 移动到 unity 空项目中 然后再下载 Gameframework https://githu ...
- [Unity] GameFramework 学习记录 5
jetbrain rider 可以反编译 原来在 visual studio 看不到的,写在 dll 里面的,接口的实现,经过反编译之后就能看到 这样就不用费心思多开一个阅读源码的 IDE 窗口了 牛 ...
- [Unity] GameFramework 学习记录 4:第三人称控制器
我想知道 UEntity 数据表中的编号跟每个实体表自己的编号之间是否需要统一,现在看来好像不需要统一,但是我也不知道是不是因为我还没看到这两个表有交互的时候 哦我才注意到,这个实体表是用来定义资源的 ...
- [Unity] GameFramework 学习记录 3
首先要仿照飞船的创建流程创建一个主角 首先直接导入 Starter Assets - Third Person Character Controller 太爽了 我看看啊 他这个是除了 ThirdPe ...
- [Unity] GameFramework 学习记录 2
嗯--要开始尝试做自己的事了 一开始策划给我列了这些 工程仓库搭建 工程程序框架 第三人称相机实现 主角基础移动实现 主角闪避实现 主角战斗实现 主角能量条实现 近战敌人战斗实现 远程敌人战斗实现 U ...
- Unity+Hololens学习记录-射线应用
Unity+Hololens学习记录-射线应用 前言 射线介绍: 射线应用元素介绍: Ray RaycastHit Raycast 射线应用实例: 射线碰撞信息获取 Camera发出Ray Gaze射 ...
- Unity Shader 学习记录(3) —— CG语言和Shader文件
1 什么是语义 赋给shader的输入输出的字符串,表达了参数的含义.语义告诉shader从哪里获取数据,又把数据输出到哪里. 2 Shader的三种debug方法 1 假色彩图像 2 VStudio ...
- unity shader 学习记录
记录下我学习unity shader的过程,并把我看到过的高质量教程推荐给大家! 借助插件shaderforge来熟悉着色的效果,并对照着shaderforge自动生成的shader代码手工优化和实现 ...
- Unity Shader学习记录(18) —— Shader动画
纹理动画 纹理动画在游戏中的应用非常广泛.尤其在各种资源都比较局限的移动平台上,我们往往会使用纹理动画来代替复杂的粒子系统等模拟各种动画效果. 11.2.1序列帧动画 _Time是float4类型, ...
最新文章
- FreeMark将long类型的时间格式化
- 基于ArcGIS JS API实现垂直滑动缩放条
- 邵阳学院学校云认证码_湖南所有五年制大专学校
- 《噬血代码》:一款轻度的魂Like游戏
- 计算机汇编语言运用哪个进制,运用汇编语言怎样以2进制、8进制、10进制、16进制方式输出10进制的数的计算结果。...
- 朱邦芬院士:我所熟悉的几位中国物理学大师的为人之本
- 为什么POJO中变量不能用is开头
- Kinect 开发 —— 近距离探测
- open读取文件操作
- CentOS英文环境下使用ibus输入法
- 第二阶段团队站立会议04
- 免费车型车系品牌api
- 指令(MISP技术的指令集)
- Android10手机OTG按钮,我又来了-荣耀10青春版手机OTG功能你会用吗?
- Activiti6.0.0及以上版本集成Activiti Modeler
- matlab z rc电路,基于MATLAB模拟RC电路的暂态过程.pdf
- 怎么获取淘宝商品详情
- Android降低屏幕白点吗,360手机桌面强化白点工具 降低安卓使用门槛
- matlab中的priniu,MATLAB中的plotyy命令
- 【C++笔记】 判断两个数互质(做大公约数为1)