Unity学习基于JSON的UI回放系统
Posted 努力码代码走上人生巅峰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity学习基于JSON的UI回放系统相关的知识,希望对你有一定的参考价值。
【Unity学习】基于JSON的UI回放系统(一)
前言
鉴于Unity商城中的游戏回放插件(EZ Replay Manager,Ultimate Replay 2.0)都都不太好实现UI的回放操作,本人基于JSON文件的格式将UI文本信息储存下来,利用ScriptableObject加载UI数据,进行UI的回放,对于工业和军工仿真来说足够实现其要求了,若还有其他实现方式,务必请万能的网友告诉我,在此只记录下我实现的方式。
演示视频
Unity UI回放系统
具体实现
1、创建ScriptableObject脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "ReplayUI", menuName = "MyScriptObject/ReplayUI_SO")]
public class ReplayUI_SO : ScriptableObject
public List<ReplayTask> replayTaskTexts = new List<ReplayTask>();
[System.Serializable]
public class ReplayTask
public string taskName;
public List<ReplayRealtimeText> replayRealtimeTexts = new List<ReplayRealtimeText>();
public ReplayTask(string taskName, List<ReplayRealtimeText> replayRealtimeTexts)
this.taskName = taskName;
this.replayRealtimeTexts = replayRealtimeTexts;
[System.Serializable]
public class ReplayRealtimeText
public float time;
public string contentText;
public ReplayRealtimeText(float time, string contentText)
this.time = time;
this.contentText = contentText;
2、将每一个需要回放的UI内容绑定一个脚本,脚本属性绑定其中需要回放的组件内容。(以下脚本参考本人上一篇博客)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TaskRealTimeInfo : MonoBehaviour
public Text textPrefab;
public RectTransform contentRoot;
public MScrollRect scrollRect;
public InputField taskName;
public List<ReplayRealtimeText> replayRealtimeTexts;
private float interval = 1.5f;
private float time = 0, recordTime;
private string testText;
private void Update()
if (ReplayUIManager.Instance.isRecord)
time += Time.deltaTime;
if (time >= interval)
testText = Time.timeSinceLevelLoad.ToString();
AddText(testText);
time = 0;
else if (!ReplayUIManager.Instance.isRecord)
recordTime = Time.timeSinceLevelLoad;
public void AddText(string str)
UIHelper.AddScrollText(textPrefab, contentRoot, str, scrollRect);
if (ReplayUIManager.Instance.isRecord)
replayRealtimeTexts.Add(new ReplayRealtimeText(Time.timeSinceLevelLoad-recordTime, str));
3、创建UI回放管理类:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
public class ReplayUIManager : Singleton<ReplayUIManager>
public TaskRealTimeInfo taskRealTimeInfo;
public Dropdown replayTaskNameDrop;
public string replayTaskName;
public bool isRecord = false;
public bool isReplay = false;
private List<ReplayRealtimeText> replayRealtimeTexts;
private ReplayUI_SO replayUI_SO;
private ReplayRealtimeText tempReplayRealtimeText;
private ReplayTask replayTask;
private float dataTime, sceneTime;
private float replayStartTime = 0f;
private bool isGetReplayData = false;
public int dataCount = 0;
private Dropdown.OptionData optionData;
protected override void Awake()
base.Awake();
replayUI_SO = Resources.Load<ReplayUI_SO>("Replay/ReplayUI");
LoadTaskUIData();
replayTaskNameDrop.ClearOptions();
foreach (var data in replayUI_SO.replayTaskTexts)
optionData = new Dropdown.OptionData(data.taskName);
replayTaskNameDrop.options.Add(optionData);
private void Update()
if (isReplay)
//开始回放UI
if (isGetReplayData)
ReplayRealtimeText();
//回放结束
if (dataCount <= 0)
replayRealtimeTexts = null;
isReplay = false;
isGetReplayData = false;
Debug.Log("回放结束!");
private void ClearHistoryData()
//清除原有数据
GameObject obj;
for (int i = 0; i < taskRealTimeInfo.contentRoot.childCount; i++)
obj = taskRealTimeInfo.contentRoot.GetChild(i).gameObject;
Destroy(obj);
replayTask = null;
taskRealTimeInfo.replayRealtimeTexts=new List<ReplayRealtimeText>();
public void RecordStart()
ClearHistoryData();
foreach (var data in replayUI_SO.replayTaskTexts)
if (data.taskName.Equals(taskRealTimeInfo.taskName.text))
Debug.LogError("任务名称重复,不能重复录制同一任务!");
return;
if (!string.IsNullOrEmpty(taskRealTimeInfo.taskName.text))
isRecord = true;
Debug.Log("开始录制!");
else
Debug.LogWarning("未命名任务名称!");
public void RecordEnd()
foreach (var data in replayUI_SO.replayTaskTexts)
if (data.taskName.Equals(taskRealTimeInfo.taskName.text))
Debug.LogError("任务名称重复,不能重复录制同一任务!");
return;
if (!string.IsNullOrEmpty(taskRealTimeInfo.taskName.text))
isRecord = false;
if (isRecord)
return;
replayTask = new ReplayTask(taskRealTimeInfo.taskName.text, taskRealTimeInfo.replayRealtimeTexts);
replayUI_SO.replayTaskTexts.Add(replayTask);
SaveTaskUIData();
replayTaskNameDrop.ClearOptions();
foreach (var data in replayUI_SO.replayTaskTexts)
optionData = new Dropdown.OptionData(data.taskName);
replayTaskNameDrop.options.Add(optionData);
Debug.Log("录制结束!");
else
Debug.LogWarning("未命名任务名称!");
public void ReplayStart()
StartCoroutine(Replay());
IEnumerator Replay()
ClearHistoryData();
if (replayTaskNameDrop.options.Count == 0)
yield break;
replayTaskName = replayTaskNameDrop.options[replayTaskNameDrop.value].text;
yield return new WaitForSeconds(0.1f);
isReplay = true;
//根据任务名称获取回放数据
foreach (var data in replayUI_SO.replayTaskTexts)
if (data.taskName.Equals(replayTaskName))
replayRealtimeTexts = data.replayRealtimeTexts;
dataCount = replayRealtimeTexts.Count;
isGetReplayData = true;
//初始化回放起始时间
replayStartTime = Time.timeSinceLevelLoad;
break;
Debug.Log("开始回放!");
private void ReplayRealtimeText()
foreach (var data in replayRealtimeTexts)
if (data.Equals(tempReplayRealtimeText))
continue;
dataTime = (int)(data.time * 100) * 0.01f;
sceneTime = (int)((Time.timeSinceLevelLoad - replayStartTime) * 100) * 0.01f;
if (dataTime == sceneTime)
taskRealTimeInfo.AddText(data.contentText);
tempReplayRealtimeText = data;
dataCount--;
break;
private void SaveTaskUIData()
Save(replayUI_SO, @Application.streamingAssetsPath + "/Replay/ReplayUIData.json");
private void Save(object data, string url)
var jsonData = JsonUtility.ToJson(data, true);
StreamWriter streamWriter = null;
try
if (!File.Exists(url))
File.Create(url).Dispose();
if (File.Exists(url))
streamWriter = new StreamWriter(url);
streamWriter.WriteLine(jsonData);
streamWriter.Close();
streamWriter.Dispose();
catch (System.Exception e)
Debug.LogError(e);
public async void LoadTaskUIData()
await Load(replayUI_SO, @Application.streamingAssetsPath + "/Replay/ReplayUIData.json");
public async Task Load(Object data, string url)
if (!File.Exists(url))
File.Create(url).Dispose();
Encoding encoding = Encoding.GetEncoding("utf-8");
StreamReader streamReader = new StreamReader(url, encoding);
string str = await streamReader.ReadToEndAsync();
JsonUtility.FromJsonOverwrite(str, data);
streamReader.Close();
streamReader.Dispose();
4、上一步用到单例父类如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T:Singleton<T>
private static T instance;
public static T Instance
get return instance;
protected virtual void Awake()
if (instance != null)
Destroy(gameObject);
else
instance = (T)this;
public static bool IsInitialized
get return instance != null;
protected virtual void OnDestroy()
if (instance == this)
instance = null;
工程下载
Unity UI回放系统Demo
下一篇基于JSON的UI回放系统(倍速)(二)将结合我使用的Ultimate Replay 2.0插件介绍如何进行倍速回放。
以上是关于Unity学习基于JSON的UI回放系统的主要内容,如果未能解决你的问题,请参考以下文章
Unity学习完全基于Ultimate Replay 2.0的UI回放系统
Unity学习完全基于Ultimate Replay 2.0的UI回放系统