框架说明上传
This commit is contained in:
parent
d72dbca0a6
commit
fa059e8d5b
|
|
@ -0,0 +1,796 @@
|
|||
|
||||
|
||||
文档说明
|
||||
|
||||
|
||||
文档编写目的
|
||||
|
||||
此文档编写目的为讲解unity开发框架的使用。
|
||||
|
||||
2. 更新版本记录
|
||||
|
||||
本文档的更新版本信息如下表所示:
|
||||
|版本号 |更新日期 |更新内容摘要 |更新人 |
|
||||
|V1.0 |2026/01/28 |初始版本,对初 |司忠占 |
|
||||
| | |始版本框架做了 | |
|
||||
| | |基本解释 | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
框架内容讲解-UI框架
|
||||
|
||||
1.本UI框架是一个基础的UI框架,包括UI加载、卸载、显示、隐藏等外部方法,还包括
|
||||
一些子类的重写方法,包括OnInit、OnShow、OnUnload三种,使用者可根据项目功能自
|
||||
行调用,具体的使用方法为,创建一个名为xxxView(建议写法)的物体,再创建一个同
|
||||
名的脚本,脚本继承UIView后,在脚本中实现逻辑,然后把物体制作成预制体存放于Re
|
||||
sources文件夹下或者脚本所在的同级resources文件夹下,通过UIView.Load<XXXXView
|
||||
>(ViewLevel.TOP)加载预制体(显示隐藏卸载同理,无需传入层级);ViewLevel为物体加
|
||||
载的层级,具体层级可见代码注释。详情可见图1:
|
||||
|
||||
[pic]
|
||||
图1
|
||||
|
||||
脚本示例:using SK.Framework;(命名空间)
|
||||
|
||||
public class HomeView : UIView
|
||||
{
|
||||
protected override void OnInit(IViewData data)
|
||||
{
|
||||
base.OnInit(data);
|
||||
}
|
||||
}
|
||||
UI框架的核心属性:
|
||||
UI画布:Canvas uiCanvas = UI.Canvas;
|
||||
UI相机:Camera uiCamera = UI.Camera;
|
||||
UI Resolution 分辨率:Vector2 uiResolution = UI.Resolution;
|
||||
获取UI视图
|
||||
当UI视图被加载时,可以通过UIView.Get<HomeView>();来获取一个存在的UI视图,进而
|
||||
对UI进行相关的逻辑操作。
|
||||
4.此类UI操作中,其他操作同理:
|
||||
UIView.Show<HomeView>();
|
||||
UIView.Hide<HomeView>();
|
||||
UIView.Unload<HomeView>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ActionChain事件链
|
||||
|
||||
框架内置了八种类型的事件,分别是Simple普通事件、Delay延迟事件、Timer定时事件
|
||||
、Until条件事件、While条件事件、Tween动画事件、Animate动画事件、Timeline时间
|
||||
轴事件。也可以通过继承AbstractAction抽象事件类,重写OnInvoke和OnReset函数来自
|
||||
定义事件。下面是内置的八种事件的介绍:
|
||||
1.Simple 普通事件
|
||||
普通事件是最简单的,可以理解为一个简单的Action回调函数。
|
||||
|
||||
2.Delay 延迟事件
|
||||
延迟事件需要指定一个时长,在经过该时长后执行指定的回调函数。
|
||||
|
||||
3.Timer 定时事件
|
||||
定时事件可以理解为定时器,分为正计时和倒计时,通过参数isReverse指定,事件为A
|
||||
ction<float>类型,通过已经计时的时长(正计时)或剩余的时长(倒计时)调用执行
|
||||
。
|
||||
|
||||
4.Until 条件事件
|
||||
Until条件事件需要指定一个Func<bool>条件,表示直到该条件成立时,调用回调函数,
|
||||
事件结束。
|
||||
|
||||
5.While 条件事件
|
||||
While条件事件同样需要指定一个Func<bool>条件,与Until条件事件不同的是,While条
|
||||
件事件中设置的回调函数在条件成立时一直被调用,当条件不再成立时,事件结束。
|
||||
|
||||
6.Tween 动画事件
|
||||
框架中集成了DoTween插件,Tween事件表示的是播放一个DoTween动画,动画播放完后,
|
||||
事件结束。
|
||||
|
||||
7.Animate 动画事件
|
||||
Animate动画事件指的是通过Animator播放动画,需要指定Animator组件和Animator
|
||||
Controller中动画状态State的名称,动画播放完后,事件结束。
|
||||
|
||||
8.Timeline 时间轴事件
|
||||
时间轴事件需要指定事件开始的时间节点,和事件执行的时长,需要配合Timeline
|
||||
ActionChain时间轴事件链使用。
|
||||
|
||||
ActionChain详解
|
||||
事件链包含三种类型,分别是Timeline时间轴事件链、Sequence序列事件链和Concurre
|
||||
nt并发事件链,均继承自IActionChain接口,包含Begin启动、Pause暂停、Resume恢复
|
||||
、Stop终止函数。
|
||||
Timeline时间轴事件链示例代码:
|
||||
[SerializeField] private GameObject cube;
|
||||
[SerializeField] private GameObject sphere;
|
||||
|
||||
private TimelineActionChain timeline;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
timeline = this.Timeline()
|
||||
//通过Append添加时间轴事件
|
||||
//第一个参数表示该事件开始的时间节点
|
||||
//第二个参数表示该事件的时长
|
||||
.Append(0f, 5f, s => cube.transform.position =
|
||||
Vector3.Lerp(Vector3.zero, new Vector3(0, 0, 5f), s))
|
||||
.Append(2f, 4f, s => sphere.transform.position =
|
||||
Vector3.Lerp(Vector3.zero, Vector3.up * 2f, s))
|
||||
.Begin() as TimelineActionChain;
|
||||
|
||||
//2倍速
|
||||
timeline.Speed = 2f;
|
||||
}
|
||||
用法:可做情景演绎,此事件链可以获取当前timeline.CurrentTime,可读可写,可
|
||||
以理解成一个可编程的视频播放器。
|
||||
Sequence 序列事件链
|
||||
序列事件链中的事件是依次执行的,即只有上一个事件执行结束后,才会开始执行下一
|
||||
个事件,适用于固定操作的业务流程编写。举例如下:
|
||||
this.Sequence()
|
||||
//普通事件
|
||||
.Event(() => Debug.Log("Begin"))
|
||||
//延迟2秒
|
||||
.Delay(2f)
|
||||
//普通事件
|
||||
.Event(() => Debug.Log("2f"))
|
||||
//直到按下键盘A键
|
||||
.Until(() => Input.GetKeyDown(KeyCode.A))
|
||||
//普通事件
|
||||
.Event(() => Debug.Log("A Pressed."))
|
||||
//DoTween动画事件
|
||||
.Tween(() => transform.DOMove(new Vector3(0f, 0f, 1f), 2f))
|
||||
//定时事件
|
||||
.Timer(3f, false, s => Debug.Log(s))
|
||||
.Begin()
|
||||
.OnStop(() => Debug.Log("Completed"));
|
||||
也可使用private IActionChain ac; ac= this.Sequence();
|
||||
ac.Pause();使当前事件链暂停(停止,开始等同理,详见代码)
|
||||
|
||||
|
||||
Concurrent 并发事件链
|
||||
并发事件链中的事件是并发执行的,在事件链启动时同时开启执行,在所有的事件都执
|
||||
行完成后,事件链终止,适用于一些同时进行的逻辑处理。示例如下:
|
||||
this.Concurrent()
|
||||
.Event(() => Debug.Log("Begin"))
|
||||
.Delay(1f, () => Debug.Log("1f"))
|
||||
.Delay(2f, () => Debug.Log("2f"))
|
||||
.Delay(3f, () => Debug.Log("3f"))
|
||||
.Until(() => Input.GetKeyDown(KeyCode.A))
|
||||
.OnStop(() => Debug.Log("Completed"));
|
||||
.Begin()
|
||||
|
||||
|
||||
事件链嵌套
|
||||
事件链之间支持互相嵌套,示例代码:
|
||||
this.Sequence()
|
||||
.Event(() => Debug.Log("Begin"))
|
||||
//嵌套一个并发事件链
|
||||
.Append(new ConcurrentActionChain()
|
||||
.Delay(1f, () => Debug.Log("1f"))
|
||||
.Delay(2f, () => Debug.Log("2f"))
|
||||
.Delay(3f, () => Debug.Log("3f"))
|
||||
as IAction)
|
||||
//并发事件链执行完成后 继续执行序列事件链
|
||||
.Until(() => Input.GetKeyDown(KeyCode.A))
|
||||
.Event(() => Debug.Log("A Pressed."))
|
||||
.Timer(3f, false, s => Debug.Log(s))
|
||||
.Begin()
|
||||
.OnStop(() => Debug.Log("Completed."));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Timer时间工具类
|
||||
|
||||
Timer模块实现了一系列计时工具,包括定时器(倒计时)、计时器、秒表、闹钟等,它
|
||||
们均继承自接口ITimer,支持启动、暂停、恢复、停止计时等行为。
|
||||
Countdown 定时器(倒计时)
|
||||
获取一个定时器可以通过如下方式,计时类工具的运行依赖于携程,通过this获取定时
|
||||
器表示使用当前的MonoBehaviour开启携程,使用Timer获取定时器表示使用计时模块管
|
||||
理器的MonoBehaviour开启携程。
|
||||
Countdown countdown1 = this.Countdown(5f);
|
||||
Countdown countdown2 = Timer.Countdown(10f, true);
|
||||
第一个参数为float类型,表示定时的时长,第二个参数为bool类型,表示计时是否忽略
|
||||
时间的缩放,默认为false。通过如下方式设置定时器的启动、执行、暂停、恢复、停止
|
||||
事件:
|
||||
//定时器
|
||||
private Countdown countdown;
|
||||
countdown = Timer.Countdown(5f)
|
||||
.OnLaunch(() => Debug.Log("定时器启动"))
|
||||
.OnExecute(s => Debug.Log(string.Format("剩余时间{0}", s)))
|
||||
.OnPause(() => Debug.Log("定时器暂停"))
|
||||
.OnResume(() => Debug.Log("定时器恢复"))
|
||||
.OnStop(() => Debug.Log("定时器停止"));
|
||||
可以通过Launch、Pause、Resume、Stop方法来控制countdown。
|
||||
|
||||
Clock 计时器(正计时)
|
||||
计时器与定时器具有相同的事件,不同的是,定时器为倒计时,例如定时5秒,其值将会
|
||||
从5逐渐到0,到0后自动停止,计时器为正向计时,需要调用Stop手动终止,可以通过S
|
||||
topWhen为其设置停止的条件,当条件满足时,计时器将自动停止。脚本示例:
|
||||
private Clock clock;
|
||||
clock=Timer.Clock()
|
||||
.OnExecute(s => Debug.Log(string.Format("已经计时{0}", s)))
|
||||
//设置停止条件 当键盘A按下时 计时器停止
|
||||
.StopWhen(() => Input.GetKeyDown(KeyCode.A))
|
||||
.Launch();
|
||||
可以通过clock.ElapsedTime来获取已经计时的时间
|
||||
|
||||
|
||||
TimeUtility 功用(时间格式化工具)
|
||||
[pic]
|
||||
|
||||
|
||||
Messenger 消息中心.
|
||||
|
||||
Messenger消息中心包含两部分内容,一部分是消息的发布、订阅系统,另一部分是消息
|
||||
的打包、拆包系统。它们是用于脚本之间解耦的利器。
|
||||
private void Start()
|
||||
{
|
||||
//订阅消息主题为Example的消息
|
||||
//订阅后,当该主题的消息发布时,订阅事件将会被执行
|
||||
Messenger.Subscribe<int>("Example", SubscribeEvent);
|
||||
|
||||
//发布消息主题为Example的消息
|
||||
//消息内容为一个int类型的数值50
|
||||
Messenger.Publish("Example", 50);
|
||||
}
|
||||
private void SubscribeEvent(int num)
|
||||
{
|
||||
Debug.Log(num);
|
||||
}
|
||||
注意:Publish的执行应该晚于消息订阅Subscribe
|
||||
取消订阅消息主题为Example的消息
|
||||
取消后,消息主题为Example的消息被发布时,订阅事件SubscribeEvent不再会执行
|
||||
Messenger.Unsubscribe<int>("Example", SubscribeEvent);
|
||||
|
||||
SceneLoader 场景加载器
|
||||
|
||||
加载器支持通过场景名称和场景指针加载场景:
|
||||
/// <summary>
|
||||
/// 异步加载场景
|
||||
/// </summary>
|
||||
/// <param name="sceneName">场景名称</param>
|
||||
/// <param name="sceneActivationDelay">激活延迟时长</param>
|
||||
/// <param name="loadSceneMode">场景加载方式</param>
|
||||
/// <returns></returns>
|
||||
public static SceneLoader LoadAsync(string sceneName, float
|
||||
sceneActivationDelay = 3f, LoadSceneMode loadSceneMode =
|
||||
LoadSceneMode.Single)
|
||||
其中sceneActivationDelay参数表示当场景在内存中加载完成时,需要延迟该时长才允
|
||||
许场景激活,原理是首先将异步操作AsyncOperation中的allowSceneActivation设为fa
|
||||
lse,在场景加载完成并延迟后再将其设为true,该参数默认值为3。
|
||||
|
||||
|
||||
代码示例如下:
|
||||
//加载名为Example的场景
|
||||
SceneLoader.LoadAsync("Example", 5f)
|
||||
.OnBegan(() => Debug.Log("开始加载"))
|
||||
.OnLoading(progress => Debug.Log(string.Format("加载进度 {0}",
|
||||
progress)))
|
||||
.OnCompleted(() => Debug.Log("加载完成"));
|
||||
|
||||
AimableObject 物体交互系统
|
||||
|
||||
使用功能前,需要将脚本Aim System挂载在场景物体上
|
||||
再把AimableObject脚本挂在需要被操作的物体上或者是继承此脚本重写,需要挂载碰撞
|
||||
体
|
||||
Description属性表示该物体的描述信息,AimableDistance属性表示该物体可被瞄准检
|
||||
测到的距离,通过OnEnter、OnExit、OnStay,OnClick分别为该交互物体设置瞄准进入
|
||||
事件、瞄准退出事件、瞄准停留,点击事件,也可以通过继承AimableObject类,来重写
|
||||
这些事件,如下所示
|
||||
public class Example : AimableObject
|
||||
{
|
||||
protected override void OnEnter()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
protected override void OnStay()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
protected override void OnExit()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
[pic]
|
||||
Aim System
|
||||
[pic]
|
||||
Toggle表示整个系统的开关,将其设为false后,系统将不再进行瞄准检测,MainCamer
|
||||
a是用于瞄准检测的相机,AimLayer表示检测的层级,AimMaxDistance表示检测的最大距
|
||||
离,AimMode表示瞄准的方式,包含两种,一种是Mouse,使用鼠标的位置发出射线进行
|
||||
瞄准检测,当我们的相机是自由视角、上帝视角时,通常使用这种方式;另一种则是Vi
|
||||
ew
|
||||
Centre,通过屏幕的中心点发出射线进行瞄准检测,当我们的相机是第一人称或第三人
|
||||
称视角时,通常使用这种方式。需要注意,当AimMode为ViewCentre模式时,AimMaxDis
|
||||
tance属性才起作用,AimableObject的OnClick事件只有为鼠标输入的时候才会生效,V
|
||||
iewCentre模式需自行实现类似效果。
|
||||
|
||||
除此之外,AimSystem中的核心属性还包括CurrentAimableObject,它记录了当前所瞄准
|
||||
的物体
|
||||
|
||||
|
||||
|
||||
Question 问题模块
|
||||
|
||||
创建问题配置文件,在文件夹右键鼠标,选择创建问题配置文件
|
||||
[pic]
|
||||
模块中内置了五种题型,可以在配置文件中进行配置,分别是判断题、单选题、多选题
|
||||
、填空题、论述题,它们均继承自Question Base基类。
|
||||
|
||||
使用方法1:依托QuestionsHandler进行问题管理,需先实现QuestionsHandler的初始化
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="profile">问题配置文件</param>
|
||||
public QuestionsHandler(QuestionsProfile profile)
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="resourcesPath">配置文件的路径</param>
|
||||
public QuestionsHandler(string resourcesPath)
|
||||
初始化操作:
|
||||
public QuestionsProfile questionsProfile;
|
||||
public QuestionsHandler questionsHandler;
|
||||
private QuestionBase currectQuestion;
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
//初始化操作
|
||||
questionsHandler = new QuestionsHandler(questionsProfile);
|
||||
//获取选择内容
|
||||
currectQuestion = questionsHandler.Switch(1);
|
||||
|
||||
//获取问题
|
||||
Debug.Log(currectQuestion.Question);
|
||||
|
||||
|
||||
}
|
||||
初始化完成后,可以通过questionsHandler进行问题管理:
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.A))
|
||||
{
|
||||
//上一题
|
||||
currectQuestion = questionsHandler.Last();
|
||||
Debug.Log(currectQuestion.Question);
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.D))
|
||||
{
|
||||
//下一题
|
||||
currectQuestion = questionsHandler.Next();
|
||||
Debug.Log(currectQuestion.Question);
|
||||
}
|
||||
if (Input.GetKeyDown(KeyCode.S))
|
||||
{
|
||||
//根据题目ID跳转到指定题目
|
||||
currectQuestion = questionsHandler.Switch(5);
|
||||
Debug.Log(currectQuestion.Question);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
使用方法2:获取配置文件的问题列表自行管理
|
||||
public QuestionsProfile questionsProfile;
|
||||
void Start()
|
||||
{
|
||||
List<SingleChoiceQuestion> mySingles = questionsProfile.SingleChoices;
|
||||
SingleChoiceQuestion single = mySingles[0];
|
||||
//获取问题,同理获取题解,选项,是否正确
|
||||
string que = single.Question;
|
||||
bool isRight = single.IsCorrect(0);
|
||||
}
|
||||
|
||||
判定当前问题的对错:currectQuestion.IsCorrect(0);其中IsCorrect方法传递的参数
|
||||
一般为当前选项的序号,例如ABCD四个选项,选则A则为0,选择B则为1,如多选的情况
|
||||
下,选择AB则为0,1
|
||||
|
||||
因为选项内容不一致,所以在方法1中无法获取每个题型的选项内容,如在UI中自行搭建
|
||||
了答题界面且编辑好问题内容,则方法1更为便捷,如需动态生成问题内容,则方法2更
|
||||
便捷。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Score 计分模块
|
||||
|
||||
通过右键/Create/Score
|
||||
Profile创建一个分数配置文件,首先在ScoreIDConstant脚本中编写代表分数项ID的in
|
||||
t常量
|
||||
[pic]
|
||||
然后进行分数的编辑
|
||||
[pic]
|
||||
ID为分数项ID,Description为分数项描述信息,Value为分数项分值,模块内默认的配
|
||||
置文件加载路径为Resources/Score Profile,也可以在代码中进行更改。
|
||||
|
||||
创建单项分数项操作:
|
||||
Score.Create(ScoreIDConstant.QUESTION_1);Create方法在调用的时候会生成并返回
|
||||
一个唯一值,此值是后续进行一系列操作的唯一凭证,包括赋分,删除,取消得分等操
|
||||
作。
|
||||
[pic]
|
||||
|
||||
创建一个得分组合:
|
||||
有些场景的一个步骤会包含多个得分点,此时我们就需要多个得分点组成一个得分组,
|
||||
方法如下:
|
||||
string[] flags = Score.CreateGroup("选择题", ValueMode.Additive,
|
||||
ScoreIDConstant.QUESTION_1,
|
||||
ScoreIDConstant.QUESTION_2
|
||||
);
|
||||
|
||||
|
||||
赋分操作:
|
||||
单项得分: string score1= Score.Create(ScoreIDConstant.QUESTION_1);
|
||||
Score.Obtain(score1);
|
||||
|
||||
|
||||
分数组合得分: Score.Obtain("选择题",
|
||||
flags[0]);此时第一个得分点得分,取消同理
|
||||
获取分值:
|
||||
获取总分:
|
||||
Score.GetSum();
|
||||
获取分数组合的分值:
|
||||
Score.GetGroupSum("选择题");
|
||||
通过Score.GetSum(); 获取的总分值为所有得分点的得分,包括组合中的分数。
|
||||
|
||||
Task任务系统
|
||||
|
||||
TaskManager:负责任务调度与模式管理
|
||||
TaskData:负责一个任务的流程推进
|
||||
TaskStep:仅负责记录单步状态,不控制流程
|
||||
TaskManager有三种模式:
|
||||
Teach, // 教学模式(强提示)
|
||||
Practice, // 练习模式(弱提示)
|
||||
Exam // 考试模式(无提示)
|
||||
任务由多个step组成,需按顺序完成步骤,支持完成,失败,跳步的操作。每个步骤最
|
||||
终只会产生一种结果:
|
||||
public enum StepResult
|
||||
{
|
||||
None, //初始
|
||||
Correct,//正确
|
||||
Error,//错误
|
||||
Skipped// 跳过
|
||||
}
|
||||
|
||||
|
||||
使用流程:
|
||||
步骤 1:创建 TaskData 并配置基本信息
|
||||
private TaskData _task;
|
||||
void Start()
|
||||
{
|
||||
|
||||
_task = new TaskData
|
||||
{
|
||||
TaskId = "Task_01",
|
||||
TaskName = "状态驱动示例任务",
|
||||
TaskDescription = "按下数字键1-5依次完成五个操作步骤"
|
||||
};
|
||||
|
||||
AddStep(1, "步骤1 down");
|
||||
AddStep(2, "步骤2 down");
|
||||
AddStep(3, "步骤3 down");
|
||||
AddStep(4, "步骤4 down");
|
||||
AddStep(5, "步骤5 down");
|
||||
//设置任务开始事件内容
|
||||
_task.OnTaskStarted += OnTaskStarted;
|
||||
}
|
||||
/// <summary>
|
||||
/// 任务开始时重置示例状态
|
||||
/// </summary>
|
||||
private void OnTaskStarted(TaskData task)
|
||||
{
|
||||
Debug.Log("任务开始,等待操作输入");
|
||||
|
||||
}
|
||||
步骤 2:创建并添加 TaskStep,注:step生命周期中OnStepHint
|
||||
事件只有当任务不为考核时才执行
|
||||
/// <summary>
|
||||
/// 添加 Step
|
||||
/// </summary>
|
||||
private void AddStep(int stepId, string desc)
|
||||
{
|
||||
var step = new TaskStep
|
||||
{
|
||||
StepId = stepId,
|
||||
Description = desc
|
||||
};
|
||||
|
||||
step.OnStepStarted += s =>
|
||||
{
|
||||
Debug.Log($"【Step 开始】{s.Description}");
|
||||
};
|
||||
|
||||
step.OnStepHint += s =>
|
||||
{
|
||||
Debug.Log($"【提示】{s.Description}");
|
||||
};
|
||||
|
||||
step.OnStepCompleted += s =>
|
||||
{
|
||||
Debug.Log($"【Step 正确完成】{s.Description}");
|
||||
};
|
||||
|
||||
step.OnStepError += s =>
|
||||
{
|
||||
Debug.LogWarning($"【Step 错误完成】{s.Description}");
|
||||
};
|
||||
|
||||
step.OnStepSkipped += s =>
|
||||
{
|
||||
Debug.LogWarning($"【Step 跳过】{s.Description}");
|
||||
};
|
||||
//添加步骤
|
||||
_task.Steps.Add(step);
|
||||
}
|
||||
步骤3:设置任务模式并启动
|
||||
// 设置任务模式
|
||||
TaskManager.Instance.SetMode(TaskMode.Exam);
|
||||
//添加taskdata
|
||||
TaskManager.Instance.AddTask(_task);
|
||||
//启动任务
|
||||
TaskManager.Instance.Start();
|
||||
所有的任务步骤只调用一个推进接口:
|
||||
//发送当前 Step 结果(并自动进入下一个)
|
||||
TaskManager.Instance.ReportCurrentStepResult(isError);
|
||||
若当前步骤正确完成,则
|
||||
TaskManager.Instance.ReportCurrentStepResult(false);
|
||||
若当前步骤错误完成,则
|
||||
TaskManager.Instance.ReportCurrentStepResult(true);
|
||||
→→→→→→设计原则错误为true,正确为false,请勿混淆!!!←←←←←←←
|
||||
跳步操作通过指定step的id来跳转向指定步骤,代码如下:
|
||||
TaskManager.Instance.JumpToStepById(1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
单例管理器
|
||||
|
||||
普通单例类示例:
|
||||
using SK.Framework;
|
||||
public class TestA : ISingleton
|
||||
{
|
||||
public string myStr;
|
||||
|
||||
public void OnInit()
|
||||
{
|
||||
myStr = "Test";
|
||||
}
|
||||
public void Func()
|
||||
{
|
||||
Debug.Log("Singleton Example.");
|
||||
}
|
||||
}
|
||||
使用示例: TestA a = Singleton<TestA>.Instance;
|
||||
a. myStr = string.Empty;
|
||||
//单例释放
|
||||
Singleton<TestA>.Dispose();
|
||||
|
||||
Mono单例类示例:
|
||||
Mono类型的单例通过继承IMonoSingleton接口来实现,IsDontDestroyOnLoad属性用于指
|
||||
定该单例物体是否作不销毁处理。
|
||||
public class A : MonoBehaviour, IMonoSingleton
|
||||
{
|
||||
public string myStr { get; private set; }
|
||||
|
||||
public bool IsDontDestroyOnLoad { get { return true; } }
|
||||
|
||||
public void OnInit()
|
||||
{
|
||||
myStr = "Test";
|
||||
}
|
||||
|
||||
public void Func()
|
||||
{
|
||||
Debug.Log("Singleton Example.");
|
||||
}
|
||||
}
|
||||
使用示例:MonoSingleton<A>.Instance.Func();
|
||||
单例释放:MonoSingleton<A>.Dispose();
|
||||
|
||||
|
||||
场景相机管理器
|
||||
|
||||
场景相机管理器位置如下图:
|
||||
[pic]
|
||||
FreeCameraController实现了与Unity编辑器Scene视图中同样的相机操作,包括WASD移
|
||||
动,QE上升下降,鼠标控制方向。界面如图:
|
||||
[pic]
|
||||
RoamCameraController为一个物体观察相机,可以基于参数围绕物体运动:
|
||||
[pic]
|
||||
调用该脚本中SetTarget方法,可动态切换观察对象,上述组件可针对具体项目进行修改
|
||||
。
|
||||
|
||||
Extension扩展函数
|
||||
|
||||
此类扩展函数内容较多,大多数都是项目中实用的快速方法,此处只列举几个示例,需
|
||||
自行阅读代码:
|
||||
private GameObject test;
|
||||
test.Activate();//开启物体
|
||||
test.Deactivate();关闭物体
|
||||
test.transform.SetEulerAngles(0, 0, 0);基于Transform的设置欧拉角
|
||||
|
||||
//Array合并
|
||||
string[] exampleArray = new string[] { "AAA", "BBB" };
|
||||
string[] target = new string[] { "CCC", "DDD" };
|
||||
string[] merge = exampleArray.Merge(target);
|
||||
|
||||
//字典操作
|
||||
Dictionary<int, string> dic = new Dictionary<int, string>() { { 5, "AAA"
|
||||
}, { 10, "BBB" } };
|
||||
|
||||
//拷贝字典
|
||||
Dictionary<int, string> copy = dic.Copy();
|
||||
//遍历字典
|
||||
dic.ForEach(m => Debug.Log(string.Format("Key{0} Value{1}", m.Key,
|
||||
m.Value)));
|
||||
|
||||
Dictionary<int, string> target = new Dictionary<int, string>() { {
|
||||
11, "CCC" }, { 20, "DDD" } };
|
||||
//合并字典
|
||||
dic.AddRange(target);
|
||||
|
||||
//将字典的所有值放入到一个列表中
|
||||
List<string> list = dic.Value2List();
|
||||
//将字典的所有值放入到一个Array中
|
||||
string[] array = dic.Value2Array();
|
||||
|
||||
//尝试添加
|
||||
if (dic.TryAdd(20, "DDD")) Debug.Log("添加成功");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
WebRequester网络请求器
|
||||
|
||||
创建WebInterface Profile 网络接口配置文件:
|
||||
[pic]
|
||||
配置一个获取时间的免费接口:
|
||||
[pic]
|
||||
Name表示该接口的命名,Url为接口的地址,Method表示该接口的请求方式,该接口以G
|
||||
ET方式调用,Args为string类型数组,表示接口的参数名称,该接口不包含任何参数,
|
||||
所以不需要添加。
|
||||
接口的注册与回调:
|
||||
//注册接口
|
||||
WebRequester.RegisterInterface<TextResponseWebInterface>("北京时间", out
|
||||
var hourStatistics);
|
||||
//设置回调函数
|
||||
hourStatistics.OnCompleted(response => Debug.Log(response));
|
||||
hourStatistics.SendWebRequest();
|
||||
//注销接口
|
||||
WebRequester.UnregisterInterface("北京时间");
|
||||
|
||||
更多用法说明:
|
||||
1.GET
|
||||
|
||||
上例中我们以GET的方式发起网络请求调用一个接口,并且没有任何参数,假如接口包含
|
||||
参数arg1和arg2,我们需要在配置文件中进行设置:
|
||||
[pic]
|
||||
代码中: hourStatistics.SendWebRequest("value1","value2");
|
||||
此时系统会自动将Url进行参数拼接,最终结果为:
|
||||
https://apps.game.qq.com/CommArticle/app/reg/gdate.php?arg1=value1&arg2=valu
|
||||
e2
|
||||
|
||||
2.Post
|
||||
倘若以POST方式发起网络请求调用接口,传入的第一个参数是POST的数据,后面的参数
|
||||
表示请求头,为可选参数,假如以"Content-Type"
|
||||
"application/json"为请求头,则代码为:
|
||||
//注册接口
|
||||
WebRequester.RegisterInterface<TextResponseWebInterface>("北京时间", out
|
||||
var hourStatistics);
|
||||
|
||||
string s = this.ToJson();
|
||||
//设置回调函数
|
||||
hourStatistics.OnCompleted(response => Debug.Log(response));
|
||||
hourStatistics.SendWebRequest(s, "Content-Type=application/json");
|
||||
|
||||
为了更灵活的进行网络请求,可以自行定义请求内容,代码如下:
|
||||
[pic]
|
||||
[pic]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
本地文件加载器
|
||||
|
||||
[pic]
|
||||
本地文件加载器提供三种本地文件加载:
|
||||
1.文本加载
|
||||
[pic]
|
||||
图片加载,图片加载有两种方式,一种加载固定路径的单张图片,单张图片的路径需以
|
||||
文件格式结束(完整路径)一种传入文件夹路径,将加载文件夹下的所有图片并返回一
|
||||
个list,支持png,jpg,jpeg三种图片格式,返回Texture2D
|
||||
[pic]
|
||||
音频加载
|
||||
音频加载与图片加载类似,同样支持两种方式,当使用单个文件加载的时候,需以完整
|
||||
路径结束,音频加载支持mp3,ogg,wav三种格式,调用onComplete回调使用音频,方法调
|
||||
用以协程的方式调用:
|
||||
[pic]
|
||||
|
||||
|
||||
实用工具
|
||||
|
||||
Variables资源管理类
|
||||
资源管理类实现了一个方便资源进行分类管理的脚本,使用方法如下图:
|
||||
public Variables variables;
|
||||
[pic]
|
||||
|
||||
|
||||
第一个参数为资源名称,第二个参数为类型,如下所示,第三个参数为需要指定的物体
|
||||
,其中component可以是该物体身上的任意可获取的组件:
|
||||
[pic]
|
||||
获取方法: public Button enterBtn; enterBtn =
|
||||
variables.Get<Button>("enterBtn");
|
||||
Get填入的需要是对应的类型,例如上述资源中绑定了一个名为enterBtn,类型为Butto
|
||||
n的EnterBtn的物体,则获取的时候需要传入对应的类型与名称。
|
||||
|
||||
同理,可以动态的将已经设置好的物体进行变更,注意:变更只能是同类型物体进行变
|
||||
更,不同类型无法进行:
|
||||
[pic]
|
||||
public Variables Variables;
|
||||
public Transform obj1;
|
||||
private void Awake()
|
||||
{
|
||||
Variables.Set<Transform>("Obj2", obj1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
运行时则变成
|
||||
[pic]
|
||||
|
||||
此工具可将资源集中存放,集中管理,方便使用和阅读。
|
||||
|
||||
HighlightOutline物体高亮类
|
||||
此物体高亮效果比较简单且只支持标准渲染器,后续考虑融合高亮专用插件,在此不做
|
||||
其他讲解:
|
||||
[pic]
|
||||
Loading…
Reference in New Issue