主要学习内容
TypeEventSystem
ActionKit
Timer类
1、TypeEventSystem-适用于一个条件触发,多个组件响应的情况
例如:动物园系统中,点击肉食动物按钮,动物园中有肉食属性的动物都进行显示。
步骤:
1、动物自身脚本上进行判断是否有肉食属性,有则注册事件
2、事件发送方:按钮点击,发送通知事件
3、事件接收方:动物,执行处理事件的操作
①单事件触发
代码学习
using System;
using System.Collections;
using System.Collections.Generic;
using QFramework;
using UnityEngine;
// namespace QFramework.Example//在类的外面嵌套上命名空间
// {
public class TypeEventSystemController : MonoBehaviour
{
//用结构体定义一个事件,适合一对多的情况,一触发,多响应
public struct EventA
{
//参数
public int Count;
}
//在start中监听事件
void Start()
{
//注册并回调,简单写法
TypeEventSystem.Global.Register<EventA>(e => //输入e点击Tab
{
Debug.Log(e.Count);
}).UnRegisterWhenGameObjectDestroyed(gameObject);//注销,与当前的gameobject进行关联
//传统事件机制的用法①②③
//①TypeEventSystem.Global.Register<EventA>(onEventA);
}
//②
//void onEventA(Event e)
//{
//}
//③销毁
//private void OnDestroy()
//{
// TypeEventSystem.Global.UnRegister<EventA>(onEventA);
// }
// Update is called once per frame
void Update()
{
//发送事件
if (Input.GetMouseButtonDown(0))
{
//第一种写法:自动new一个A,但是无法传参
//TypeEventSystem.Global.Send<EventA>();
//第二种写法
TypeEventSystem.Global.Send(new EventA()
{
Count = 10
});
}
}
}
// }
②多事件触发
using System.Collections;
using System.Collections.Generic;
using QFramework;
using SnakeGame;
using Unity.VisualScripting;
using UnityEngine;
public class MutiEvent : MonoBehaviour
//添加
// IOnEvent<MutiEvent.IEventA>,
// IOnEvent<MutiEvent.EventB>//报错可进行点击自动生成代码
{
public interface IEventA//接口形式
{
public abstract void Function();
}
public struct EventB: IEventA
{
public void Function()
{
print("从管道B中流出");
}
}
public struct EventC: IEventA
{
public void Function()
{
print("从管道C中流出");
}
}
void Start()
{
TypeEventSystem.Global.Register<IEventA>(a =>
{
Debug.Log(a.GetType().Name);
}).UnRegisterWhenGameObjectDestroyed(gameObject); //输出名字
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
TypeEventSystem.Global.Send<IEventA>(new EventB());
}
if (Input.GetMouseButtonDown(1))
{
TypeEventSystem.Global.Send<IEventA>(new EventC());
}
}
}
2、ActionKit
①单独使用时
1)延时功能
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using QFramework;
public class ActionKitExample : MonoBehaviour
{
void Start()
{
//调用延时功能
DelayTime();
}
/// <summary>
/// 实现延时功能
/// </summary>
void DelayTime()
{
print("开始时间 "+Time.time);
ActionKit.Delay(1.0f, () =>
{
print("延迟时间:" + Time.time);
}).Start(this);//底层使用的是MonoBehaviour中的东西,所以需要关联一下gameObject
}
}
运行结果:大约延迟1s
/// <summary>
/// 序列和完成回调
/// </summary>
void SequenceAndCallBack()
{
print("序列开始:"+Time.time);
ActionKit.Sequence()
.Callback(() => print("DelayStart延时开始:"+Time.time))//回调函数
.Delay(1.0f)//延时一秒
.Callback(()=>Debug.Log("Delay Finish延时结束:"+Time.time))
.Start(this,_=>{print("Sequence Finish序列结束:"+Time.time);});
}
运行结果:sequence从上到下执行
/// <summary>
/// 帧延时
/// </summary>
void DelayFrameExample()
{
//延时一帧后回调
print("帧延时开始帧率数"+Time.frameCount);
ActionKit.DelayFrame(1, () =>
{
print("帧延时结束帧率数" + Time.frameCount);
}).Start(this);
//序列延时10帧后回调
ActionKit.Sequence()
.DelayFrame(10)
.Callback(() => print("序列延时帧率数" + Time.frameCount))
.Start(this);
//下一帧做什么
ActionKit.NextFrame(() => { }).Start(this);
}
运行结果
/// <summary>
/// 支持协程的方式
/// </summary>
void CoroutineExample()
{
//第一种:普通
//ActionKit.Coroutine(() => SomeCoroutine()).Start(this);
//ActionKit.Coroutine(SomeCoroutine).Start(this);
//第二种:将协程转换为动作
//SomeCoroutine().ToAction().Start(this);
//第三种:序列的方式执行
ActionKit.Sequence()
.Coroutine(()=>SomeCoroutine())
.Callback(()=>print("结束"))//如果是多个:使用delegte
.Start(this);
}
IEnumerator SomeCoroutine()
{
yield return new WaitForSeconds(1.0f);
print("你好"+Time.time);
}
运行结果:我感觉跟上面序列完成回调的Delay(1.0f)方法是一样的,且不如上面的简单,这个方法可以弃用了
2)条件执行
/// <summary>
/// 条件执行(仅执行一次)
/// </summary>
void ConditionExample()
{
ActionKit.Sequence()
.Callback(() => print("条件发生之前"))
.Condition(() => Input.GetMouseButtonDown(0))//每帧调用后面的委托,直到委托返回为true,执行下一步
.Callback(() => print("鼠标点击"))
.Start(this);
}
运行结果:一直在等待条件的执行
/// <summary>
/// 重复执行
/// </summary>
void RepeatExample()
{
print("点击五次鼠标右键,输出信息");
ActionKit.Repeat(5)//改为关键字repeat
.Condition(() => Input.GetMouseButtonDown(1))//每帧调用后面的委托,直到委托返回为true,执行下一步
.Callback(() => print("鼠标点击"))
.Start(this, () =>
{
print("5次右键点击完成");
});
}
运行结果:条件重复5次后输出
/// <summary>
/// 并行执行,同时执行动作,动作全部完成执行最后finish函数
/// </summary>
void ParallelExample()
{
print("并行开始");
ActionKit.Parallel()
.Delay(1.0f, () => { print(Time.time); })
.Delay(2.0f, () => { print(Time.time); })
.Delay(3.0f, () => { print(Time.time); })
.Start(this, () =>
{
print("并行结束" + Time.time);
});
}
运行结果
3)自定义动作执行
/// <summary>
///自定义动作
/// </summary>
void CutomExample()
{
ActionKit.Custom(a =>
{
a
.OnStart(() => { print("OnStart"); })
.OnExecute(dt =>
{
print("OnExecute");
if (Time.frameCount > 5)
{
a.Finish();//注意这里是Finish
}
})
.OnFinish(() => { print("OnFinish"); });
}).Start(this);
}
运行结果:事件开始,执行,结束
//传数据的自定义事件
public class ActionData
{
public int FrameCount;//公有,其他函数可以访问
}
/// <summary>
///自定义动作,含参数
/// </summary>
void CutomExampleWithParameter()
{
ActionKit.Custom<ActionData>(a =>//传一个自定义的数据类型
{
a.OnStart(() =>
{
a.Data = new ActionData()
{
FrameCount=0
};
print("OnStart");
})
.OnExecute(dt =>
{
print("OnExecute");
a.Data.FrameCount++;
if (a.Data.FrameCount > 5)
{
a.Finish();//注意这里是Finish
}
})
.OnFinish(() => { print("OnFinish"); });
}).Start(this);
}
运行结果:开始的时候定义参数值,执行时进行判断,符合条件结束
②与DoTween插件集成
集成步骤:
查找-双击-导入
代码
/// <summary>
/// DoTween的集成,Dotween和ActionKit组合使用
/// </summary>
void DotweenExample()
{
ActionKit.Sequence()
.DOTween(() => transform.DOMoveX(5, 1))
.Start(this);
}
运行结果:挂在脚本的物体在一秒钟,x变为5
3、Timer计时器
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using QFramework;
using QFramework.TimeExtend;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using Timer = QFramework.TimeExtend.Timer;
public class Test : MonoBehaviour
{
private Timer timer1;
private Timer timer2;
public Text timeText;
void Start()
{
ActionKit.Sequence()
.Callback(() => print("按下F1新建一个计时器"))
.Condition(() => Input.GetKey(KeyCode.F1))
.Callback(() => timer1 = Timer.AddTimer(10, "Timer1", false, true)
.OnUpdated(a =>
{
timeText.text = ((1 - a) * 10).ToString();
})
.OnCompleted(() => //十秒完成后
{
print("Timer1计时10秒结束");
}))
.Condition(()=> Input.GetKey(KeyCode.D))
.Callback(delegate
{
Timer.DelTimer("Timer1");
print("删除-计时器1");
}
)
.Condition(()=> Input.GetKey(KeyCode.A))
.Callback(delegate
{
if (!Timer.Exist(timer2))
{
timer2 = Timer.AddTimer(10, "Timer2", false, true)
.OnUpdated(a =>
{
timeText.text = (a*10).ToString();
})
.OnCompleted(()=>//十秒完成后
{
print("Timer2计时10秒结束");
});
print("新建-计时器2");
}
}
)
.Condition(() => Input.GetKey(KeyCode.S))
.Callback(delegate
{
if (Timer.Exist(timer2))
{
Timer.Pause(timer2);
print("暂停-计时器2");
}
}
)
.Condition(() => Input.GetKey(KeyCode.F))
.Callback(delegate
{
if (Timer.Exist(timer2))
{
Timer.Resum(timer2);
print("计时器恢复");
}
}
)
.Start(this);
}
}
}