使用反射保存Trigger状态变量

This commit is contained in:
liuyu 2024-09-07 17:17:12 +08:00
parent a105033700
commit 5e26973e4e
16 changed files with 355 additions and 187 deletions

View File

@ -11,6 +11,7 @@ public class Device_Seal : Device_Base
/// <summary>
/// 是否被剪开
/// </summary>
[ReconnetAtrribute]
public bool isCut;
/// <summary>
/// 被剪的位置
@ -39,19 +40,4 @@ public class Device_Seal : Device_Base
isCut = false;
gameObject.SetActive(true);
}
/// <summary>
/// ¶ÏÏßÖØÁ¬
/// </summary>
/// <param name="triggerInfo"></param>
/// <exception cref="NotImplementedException"></exception>
public override void LoadCurrentTriggerStat(string triggerInfo)
{
if (triggerInfo != "")
isCut = bool.Parse(triggerInfo);
}
public override string SaveCurrentTriggerStat()
{
return isCut.ToString();
}
}

View File

@ -10,6 +10,7 @@ public class Check_JieXian : PermanentTriggerBase
/// <summary>
/// 是否已检查接线完好
/// </summary>
[ReconnetAtrribute]
public bool isChecked;
/// <summary>
/// 接线
@ -75,22 +76,4 @@ public class Check_JieXian : PermanentTriggerBase
base.CallScoreAction(true);
}
}
/// <summary>
/// ¶ÏÏßÖØÁ¬
/// </summary>
/// <returns></returns>
/// <exception cref="System.NotImplementedException"></exception>
public override string SaveCurrentTriggerStat()
{
return isChecked.ToString();
//throw new System.NotImplementedException();
}
public override void LoadCurrentTriggerStat(string triggerInfo)
{
if (triggerInfo != "")
isChecked = bool.Parse(triggerInfo);
//throw new System.NotImplementedException();
}
}

View File

@ -10,6 +10,7 @@ public class Device_NamePlate : Device_Base
/// <summary>
/// 是否检查
/// </summary>
[ReconnetAtrribute]
public bool isChecked;
/// <summary>
@ -54,21 +55,4 @@ public class Device_NamePlate : Device_Base
}
}
}
/// <summary>
/// ¶ÏÏßÖØÁ¬
/// </summary>
/// <param name="triggerInfo"></param>
/// <exception cref="System.NotImplementedException"></exception>
public override void LoadCurrentTriggerStat(string triggerInfo)
{
if (triggerInfo != "")
isChecked = bool.Parse(triggerInfo);
//throw new System.NotImplementedException();
}
public override string SaveCurrentTriggerStat()
{
return isChecked.ToString();
//throw new System.NotImplementedException();
}
}

View File

@ -5,6 +5,7 @@ using UnityEngine;
public class Device_Switch : Device_Base
{
[ReconnetAtrribute]
public bool isOpen;
/// <summary>
@ -63,30 +64,4 @@ public class Device_Switch : Device_Base
transform.localEulerAngles = new Vector3(0, 45, 0);
}
/// <summary>
/// ¶ÏÏßÖØÁ¬
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public override string SaveCurrentTriggerStat()
{
return isOpen.ToString();
//throw new NotImplementedException();
}
public override void LoadCurrentTriggerStat(string triggerInfo)
{
if (triggerInfo != "")
{
if (bool.Parse(triggerInfo))
{
OpenState();
}
else
{
CloseState();
}
}
//throw new NotImplementedException();
}
}

View File

@ -17,10 +17,12 @@ public class Device_CabinetDoor : Device_Base
/// <summary>
/// 是否打开
/// </summary>
[ReconnetAtrribute]
public bool isOpen;
/// <summary>
/// 是否带点
/// </summary>
[ReconnetAtrribute]
public bool hasElectricity;
public void Open()
{
@ -90,36 +92,4 @@ public class Device_CabinetDoor : Device_Base
transform.localEulerAngles = Vector3.zero;
transform.Find("计量柜锁2/计量柜锁3").localEulerAngles = Vector3.zero;
}
/// <summary>
/// ¶ÏÏßÖØÁ¬
/// </summary>
/// <returns></returns>
/// <exception cref="System.NotImplementedException"></exception>
class tempCabin {
public bool isOpen;
public bool hasElectricity;
}
public override string SaveCurrentTriggerStat()
{
tempCabin tmp = new tempCabin();
tmp.hasElectricity = hasElectricity;
tmp.isOpen = isOpen;
return JsonConvert.SerializeObject(tmp);
//throw new System.NotImplementedException();
}
public override void LoadCurrentTriggerStat(string triggerInfo)
{
tempCabin tmp = JsonMapper.ToObject<tempCabin>(triggerInfo);
tmp.hasElectricity= hasElectricity;
if (tmp.isOpen)
{
OpenState();
}else
{
CloseState();
}
//throw new System.NotImplementedException();
}
}

View File

@ -10,26 +10,11 @@ public class Device_Socket : Device_Base
/// <summary>
/// 验电位置
/// </summary>
[ReconnetAtrribute]
public Transform testPosAndRot;
/// <summary>
/// 是否带电
/// </summary>
[ReconnetAtrribute]
public bool hasElectricity;
/// <summary>
/// ¶ÏÏßÖØÁ¬±£´æ
/// </summary>
/// <param name="triggerInfo"></param>
/// <exception cref="System.NotImplementedException"></exception>
public override void LoadCurrentTriggerStat(string triggerInfo)
{
if (triggerInfo != "")
hasElectricity = bool.Parse(triggerInfo);
}
public override string SaveCurrentTriggerStat()
{
return hasElectricity.ToString();
}
}

8
Assets/Scripts/HQB.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ec21e9d11e37de04fba96037a6515a29
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property, AllowMultiple =false)]
public class ReconnetAtrribute : Attribute
{
public string Description { get; }
public ReconnetAtrribute()
{
Description = "";
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01e2c8f14904bb44c8ebfe71e3089711
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class ReflectionTest : MonoBehaviour
{
public PermanentTriggerBase ptb;
public MobileController mc;
// Start is called before the first frame update
void Start()
{
FieldInfo[] fieldInfo = ptb.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fieldInfo)
{
if (field.GetCustomAttribute<ReconnetAtrribute>() != null)
{
ReconnetAtrribute attribute = field.GetCustomAttribute<ReconnetAtrribute>();
object value = field.GetValue(ptb);
Debug.Log($"Field: {field.Name}, Value: {value}, Description: {attribute.Description}");
if (attribute.Description == "downIndex")
{
field.SetValue(ptb, 1);
}
Debug.Log($"=>Field: {field.Name}, Value: {value}, Description: {attribute.Description}");
}
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.V))
{
Debug.Log("X");
Debug.Log("===>" + mc.downIndex);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 10fa826c5945ca84ca64dee6f1d99354
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -7,6 +7,10 @@ using System.IO;
using LitJson;
using System;
using Unity.Burst.CompilerServices;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
/// <summary>
/// 断线重连管理
@ -14,21 +18,21 @@ using Unity.Burst.CompilerServices;
public class ReconnectMgr : SingletonMono<ReconnectMgr>
{
[HideInInspector]
public string localStatFileName = "realtimeStat.json";//保存文件的文件名
public string localStatFileName = "realtimeStat.json";//保存文件的文件名
[HideInInspector]
public int countDown_AutoSave = 600;//自动保存的时间间隔
private TB_UserExamStat UserExamStat = new TB_UserExamStat();
private string localStatPath = "";
private Coroutine coroutine;//自动保存倒计时
public int countDown_AutoSave = 600;//自动保存的时间间隔
private TB_UserExamStat UserExamStat = new TB_UserExamStat();
private string localStatPath = "";
private Coroutine coroutine;//自动保存倒计时
//[HideInInspector]
//public List<string> experiencedScene = new List<string>();//用户经历过的场景
/// <summary>
/// 初始化函数,记录时间间隔
/// </summary>
public void Init( )
public void Init()
{
localStatPath = Application.streamingAssetsPath + "/" + localStatFileName;
localStatPath = Application.streamingAssetsPath + "/" + localStatFileName;
//UserExamStat.experiencedScene.Clear();//清空用户经历过的场景
//experiencedScene.Clear();
}
@ -48,7 +52,7 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
ReconnectMgr()//构造函数
{
Init( );
Init();
}
/// <summary>
@ -57,21 +61,21 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
public void RealtimeStatWriter()
{
//记录步骤相关各项信息
UserExamStat.schemeID = ProcessManager.Instance.schemeID;
UserExamStat.schemeID = ProcessManager.Instance.schemeID;
//记录得分情况
ScoreBase scoreBase = FindFirstObjectByType<ScoreBase>();
UserExamStat.systemID = scoreBase.systemId;
ScoreBase scoreBase = FindFirstObjectByType<ScoreBase>();
UserExamStat.systemID = scoreBase.systemId;
UserExamStat.allSubScore.Clear();
if ( scoreBase != null )
if (scoreBase != null)
{
foreach (var item in scoreBase.GetStepScore())
{
ReconnectSubScoreInfo sub = new ReconnectSubScoreInfo();
sub.index = item.Key;
sub.subProcessId = item.Value.subProcessId;
sub.currentScore = item.Value.currentScore;
sub.isDone = item.Value.isDone;
UserExamStat.allSubScore.Add( sub );
sub.index = item.Key;
sub.subProcessId = item.Value.subProcessId;
sub.currentScore = item.Value.currentScore;
sub.isDone = item.Value.isDone;
UserExamStat.allSubScore.Add(sub);
};
//保存场景内独有信息
UserExamStat.currentSceneOtherInfo = scoreBase.SaveSceneBufferList();
@ -85,12 +89,12 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
foreach (var itemInfo in item.Value)
{
UserExamStat.allToolAndMaterial.Add(((ItemInfo)itemInfo).toolName);
ReconnectItemInfo rec = new ReconnectItemInfo();//获取场景内(工具间)所有可以装备材料的物品
rec.toolId = itemInfo.toolId;
rec.toolName = itemInfo.toolName;
rec.triggerID = itemInfo.triggerID;
ReconnectItemInfo rec = new ReconnectItemInfo();//获取场景内(工具间)所有可以装备材料的物品
rec.toolId = itemInfo.toolId;
rec.toolName = itemInfo.toolName;
rec.triggerID = itemInfo.triggerID;
//rec.toolOrDeviceOrMaterial = item.itemInfo.toolOrDeviceOrMaterial;
rec.selfPosInToolRoom = itemInfo.selfPosInToolRoom;
rec.selfPosInToolRoom = itemInfo.selfPosInToolRoom;
UserExamStat.currentSceneTools.Add(rec);
}
}
@ -111,12 +115,12 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
PermanentTriggerBase[] allPermanentTriggers = FindObjectsOfType<PermanentTriggerBase>();
foreach (PermanentTriggerBase item in allPermanentTriggers)
{
ReconnectTriggerInfo ret = new ReconnectTriggerInfo();
ret.triggerName = item.triggerName;
ret.triggerID = item.triggerID;
ret.selfPosInScene = item.transform.localPosition;
ret.selfRotInScene = item.transform.localEulerAngles;
ret.triggerInfo = item.SaveCurrentTriggerStat();
ReconnectTriggerInfo ret = new ReconnectTriggerInfo();
ret.triggerName = item.triggerName;
ret.triggerID = item.triggerID;
ret.selfPosInScene = item.transform.localPosition;
ret.selfRotInScene = item.transform.localEulerAngles;
ret.triggerInfo = GetTriggerAttribute(item);//item.SaveCurrentTriggerStat();
UserExamStat.currentSceneTriggers.Add(ret);
}
@ -126,6 +130,42 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
File.WriteAllText(localStatPath, UserJson);
}
/// <summary>
/// 获取常驻交互的属性
/// </summary>
/// <param name="permanentTriggerBase"></param>
public string GetTriggerAttribute(PermanentTriggerBase permanentTriggerBase)
{
JsonData ptbData = new JsonData();
FieldInfo[] fieldInfo = permanentTriggerBase.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fieldInfo)
{
if (field.GetCustomAttribute<ReconnetAtrribute>() != null)
{
ReconnetAtrribute attribute = field.GetCustomAttribute<ReconnetAtrribute>();
object value = field.GetValue(permanentTriggerBase);
ptbData[field.Name] = value.ToString();
}
}
//return Regex.Unescape(ptbData.ToJson());
return ptbData.ToJson();
}
public void SetTriggerAttribute(string triggerJson, PermanentTriggerBase permanentTriggerBase)
{
JsonData ptbData = JsonMapper.ToObject<JsonData>(triggerJson);
FieldInfo[] fieldInfo = permanentTriggerBase.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fieldInfo)
{
if (field.GetCustomAttribute<ReconnetAtrribute>() != null)
{
ReconnetAtrribute attribute = field.GetCustomAttribute<ReconnetAtrribute>();
Type type = field.GetValue(permanentTriggerBase).GetType();
string tmp = ptbData[field.Name].ToString();
field.SetValue(permanentTriggerBase, Convert.ChangeType(tmp, type));
}
}
}
/// <summary>
/// 读取用户状态(先使用同步,后用异步)
/// </summary>
@ -135,19 +175,20 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
{
try
{
StreamReader sr = new StreamReader(localStatPath);
string user_last_stat = sr.ReadToEnd();
StreamReader sr = new StreamReader(localStatPath);
string user_last_stat = sr.ReadToEnd();
sr.Close();
UserExamStat = JsonMapper.ToObject<TB_UserExamStat>(user_last_stat);
UserExamStat = JsonMapper.ToObject<TB_UserExamStat>(user_last_stat);
return true;
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
return false;
return false;
}
}
else {
else
{
return false;
}
}
@ -158,7 +199,8 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
public void RecoverScene()
{
//先恢复场景
ScenesManager.Instance.LoadSceneAsyn(UserExamStat.sceneName, () => {
ScenesManager.Instance.LoadSceneAsyn(UserExamStat.sceneName, () =>
{
//右侧工具栏切换
if (!GameManager.UIMgr.GetPanel<UI_MenuBar>())//office场景下,右侧工具栏可能会隐藏
{
@ -172,8 +214,8 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
GameManager.EventMgr.EventTrigger(Enum_EventType.SwitchScene, GameManager.RunModelMgr.SceneType);
//恢复背包中的装备
TooRoomMannger tooRoomMannger = FindAnyObjectByType<TooRoomMannger>();
List<ItemInfo> itemInPack = ToolAndmaterialMgr.Instance.CreateItemInfoByName(UserExamStat.allToolAndMaterial);
TooRoomMannger tooRoomMannger = FindAnyObjectByType<TooRoomMannger>();
List<ItemInfo> itemInPack = ToolAndmaterialMgr.Instance.CreateItemInfoByName(UserExamStat.allToolAndMaterial);
foreach (ItemInfo item in itemInPack)
{
for (int j = 0; j < UserExamStat.currentSceneTools.Count; j++)
@ -187,10 +229,10 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
}
PacksackBagMgr.Instance.AddOneToolOrMater(item);
}
if ( tooRoomMannger != null )tooRoomMannger.RemoveRepeat();
if (tooRoomMannger != null) tooRoomMannger.RemoveRepeat();
//恢复已穿戴的装备
List<ItemInfo> itemWear = ToolAndmaterialMgr.Instance.CreateItemInfoByName(UserExamStat.allWear);
List<ItemInfo> itemWear = ToolAndmaterialMgr.Instance.CreateItemInfoByName(UserExamStat.allWear);
foreach (ItemInfo item in itemWear)
{
PacksackBagMgr.Instance.WearItemState(item, true);
@ -201,8 +243,8 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
}
//恢复场景内各个触发器状态
PermanentTriggerBase[] allPermanentTriggers = FindObjectsOfType<PermanentTriggerBase>();
List<ReconnectTriggerInfo> allReconTrigs = UserExamStat.currentSceneTriggers;
PermanentTriggerBase[] allPermanentTriggers = FindObjectsOfType<PermanentTriggerBase>();
List<ReconnectTriggerInfo> allReconTrigs = UserExamStat.currentSceneTriggers;
foreach (PermanentTriggerBase item in allPermanentTriggers)
{
item.gameObject.SetActive(false);
@ -215,7 +257,8 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
{
item.transform.localPosition = ret.selfPosInScene;
item.transform.localEulerAngles = ret.selfRotInScene;
item.LoadCurrentTriggerStat(ret.triggerInfo);
SetTriggerAttribute(ret.triggerInfo, item);
//item.LoadCurrentTriggerStat(ret.triggerInfo);
}
break;
}
@ -280,10 +323,11 @@ public class ReconnectMgr : SingletonMono<ReconnectMgr>
RealtimeStatWriter();
Debug.Log("当前场景:" + UserExamStat.sceneName);
}
else if(Input.GetKeyDown(KeyCode.Y))
else if (Input.GetKeyDown(KeyCode.Y))
{
RealtimeStatReader();
RecoverScene();
}
}
}

View File

@ -5,9 +5,12 @@ using UnityEngine;
using UnityEngine.EventSystems;
using LitJson;
using Newtonsoft.Json;
using Unity.VisualScripting;
using System.Reflection;
public class MobileController : PermanentTriggerBase
{
[ReconnetAtrribute]
public int downIndex = 0;
protected override void OnMEnter()
{
@ -69,17 +72,17 @@ public class MobileController : PermanentTriggerBase
/// 断线重连的状态保存与读取
/// </summary>
/// <param name="triggerInfo"></param>
public override void LoadCurrentTriggerStat(string triggerInfo)
{
if (triggerInfo != "")
{
this.downIndex = int.Parse(triggerInfo);
}
}
//public override void LoadCurrentTriggerStat(string triggerInfo)
//{
// if (triggerInfo != "")
// {
// this.downIndex = int.Parse(triggerInfo);
// }
//}
public override string SaveCurrentTriggerStat()
{
return downIndex.ToString();
//throw new NotImplementedException();
}
//public override string SaveCurrentTriggerStat()
//{
// return downIndex.ToString();
// //throw new NotImplementedException();
//}
}

View File

@ -5,13 +5,16 @@ using HighlightPlus;
using UnityEngine.EventSystems;
using System;
using Unity.VisualScripting;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// 常驻交互
/// </summary>
public class PermanentTriggerBase : MonoBehaviour
{
[ReconnetAtrribute]
public int triggerID;
[ReconnetAtrribute]
public string triggerName;
public HighlightEffect _highlight;
@ -138,9 +141,9 @@ public class PermanentTriggerBase : MonoBehaviour
/// <summary>
/// 保存Trigger的自身具体信息,参考scoreBase
/// </summary>
public virtual string SaveCurrentTriggerStat() { return ""; }
//public virtual string SaveCurrentTriggerStat() { return ""; }
/// <summary>
/// 加载Trigger的自身具体信息,参考scoreBase
/// </summary>
public virtual void LoadCurrentTriggerStat(string triggerInfo) { }
//public virtual void LoadCurrentTriggerStat(string triggerInfo) { }
}

View File

@ -0,0 +1,142 @@
{
"systemID": 10002,
"schemeID": 1002,
"currentScore": 0.0,
"allSubScore": [
{
"index": 1,
"subProcessId": 1,
"currentScore": 0.0,
"isDone": true
},
{
"index": 2,
"subProcessId": 2,
"currentScore": 0.0,
"isDone": true
},
{
"index": 3,
"subProcessId": 3,
"currentScore": 0.0,
"isDone": false
},
{
"index": 4,
"subProcessId": 4,
"currentScore": 0.0,
"isDone": false
},
{
"index": 5,
"subProcessId": 5,
"currentScore": 0.0,
"isDone": false
},
{
"index": 6,
"subProcessId": 6,
"currentScore": 0.0,
"isDone": false
},
{
"index": 7,
"subProcessId": 7,
"currentScore": 0.0,
"isDone": false
},
{
"index": 8,
"subProcessId": 8,
"currentScore": 0.0,
"isDone": false
},
{
"index": 9,
"subProcessId": 9,
"currentScore": 0.0,
"isDone": false
},
{
"index": 10,
"subProcessId": 10,
"currentScore": 0.0,
"isDone": false
},
{
"index": 11,
"subProcessId": 11,
"currentScore": 0.0,
"isDone": false
},
{
"index": 12,
"subProcessId": 12,
"currentScore": 0.0,
"isDone": false
},
{
"index": 13,
"subProcessId": 13,
"currentScore": 0.0,
"isDone": false
},
{
"index": 14,
"subProcessId": 14,
"currentScore": 0.0,
"isDone": false
},
{
"index": 15,
"subProcessId": 15,
"currentScore": 0.0,
"isDone": false
},
{
"index": 16,
"subProcessId": 16,
"currentScore": 0.0,
"isDone": false
},
{
"index": 17,
"subProcessId": 17,
"currentScore": 0.0,
"isDone": false
},
{
"index": 18,
"subProcessId": 18,
"currentScore": 0.0,
"isDone": false
}
],
"experiencedScene": [
"02_MenuScene",
"03_OfficeScene"
],
"allToolAndMaterial": [],
"allWear": [],
"sceneName": "03_OfficeScene",
"currentSceneTools": [],
"currentSceneTriggers": [
{
"triggerID": 5005,
"triggerName": "手机",
"selfPosInScene": {
"x": 0.0244421959,
"y": 0.885706842,
"z": -1.00569367
},
"selfRotInScene": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"triggerInfo": "{\"downIndex\":\"2\",\"triggerID\":\"5005\",\"triggerName\":\"\\u624B\\u673A\"}"
}
],
"currentSceneOtherInfo": "{\r\n \"TestPen3list\": [],\r\n \"InSwitchCloseYDList\": [],\r\n \"InSwitchOpenYDList\": [],\r\n \"currentunInstallJieXian\": [],\r\n \"currentInstallJieXian\": [],\r\n \"installCover\": [],\r\n \"currentInstallTestJieXian\": []\r\n}",
"experiencedScenes": []
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 61f30bf5680ef6b4590e9fca4c15f30e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: