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学习基于JSON的UI回放系统(倍速)

Unity学习基于JSON的UI回放系统(倍速)

Unity学习完全基于Ultimate Replay 2.0的UI回放系统

Unity学习完全基于Ultimate Replay 2.0的UI回放系统

Unity 动画系列十一 Animator Record 录制与回放

Unity学习之路:《游戏编程模式》-命令模式