新手指引实现
指引信息JSON示例
CRE:使用数据驱动的新手指引,而不是硬编码新手指引,可以方便策划修改。
{
"guides": [
{
"id": "guideButtonEquipment",
"conditions": [
"lvl:10"
],
"steps": [
{
"text": "装备物品",
"focus": "MainMenuCanvas/Windows/PanelMenu/ButtonEquipment",
"scroll": true,
"cloneButton": false,
"tapAnyPosition": false
},
{
"text": "装备物品",
"focus": "MainMenuCanvas/Windows/WindowCharacter/ScrollItems/Viewport/Content/ITEM0",
"scroll": true,
"cloneButton": false,
"tapAnyPosition": false
}
]
},
//...
]
}
反序列化代码示例
从JSON反序列化新手指引,condition(触发条件)可以反序列化为
Func<bool>
格式。
public class GuideDeserializer
{
public static GuideInfo[] Deserialize()
{
string json = Resources.Load<TextAsset>("Json/Guides").text;
JsonData jGuides = JsonMapper.ToObject(json)["guides"];
GuideInfo[] infos = new GuideInfo[jGuides.Count];
for (int i = 0; i < jGuides.Count; ++i)
{
infos[i] = new GuideInfo();
infos[i].id = (string)jGuides[i]["id"];
//CONDITIONS
var conditionStrArr = UtilsLitJson.GetArray<string>(jGuides[i]["conditions"]);
infos[i].conditions = new System.Func<bool>[conditionStrArr.Length + 1];
for (int j = 0; j < conditionStrArr.Length; ++j)
{
infos[i].conditions[j] = GuideDeserializer.ConvertCondition(conditionStrArr[j]);
}
infos[i].conditions[infos[i].conditions.Length - 1] = () =>
{
var mainMenu = GameObject.FindObjectOfType<MainMenuCanvas>();
return mainMenu == null || (mainMenu.UnimportantWindowClear());
};
//STEPS
JsonData jSteps = jGuides[i]["steps"];
infos[i].steps = new SoftGuideStep[jSteps.Count];
for (int j = 0; j < jSteps.Count; ++j)
{
infos[i].steps[j] = new SoftGuideStep();
infos[i].steps[j].text = (string)jSteps[j]["text"];
infos[i].steps[j].focus = (string)jSteps[j]["focus"];
infos[i].steps[j].scroll = (bool)jSteps[j]["scroll"];
infos[i].steps[j].cloneButton = (bool)jSteps[j]["cloneButton"];
infos[i].steps[j].tapAnyPosition = (bool)jSteps[j]["tapAnyPosition"];
}
}
return infos;
}
public static System.Func<bool> ConvertCondition(string conditionStr)
{
string[] arr = conditionStr.Split(':');
switch (arr[0])
{
case "lvl":
{
int lvlNeed = int.Parse(arr[1]); //Debug.LogAssertion("Needlvl " + arr[1]);
return () => Infomanager.Instance.userdata.accountLvl >= lvlNeed;
}
case "mainline":
{
int mainlineNeed = int.Parse(arr[1]); //Debug.LogAssertion("Need Mainline " + arr[1]);
return () => Infomanager.Instance.userdata.unlockedLevels.Contains(mainlineNeed);
}
case "active":
{
string path = arr[1]; //Debug.LogAssertion("Need Active " + arr[1]);
return () =>
{
var node = UtilsScene.Find(path);
if (node != null)
{
if(node.GetComponent<UnlockableFunctionBase>() != null)
{
return (node.GetComponent<UnlockableFunctionBase>().IsFunctionActive());
}
else
{
return (node.gameObject.activeSelf);
}
}
return false;
};
}
}
return () => false;
}
}
UI路径系统示例
用于在场景中查找某个UI元素。
public static Transform Find(string path)
{
string[] segments = path.Split('/');
var roots = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
Transform currentNode = null;
for (int i = 0; i < segments.Length; ++i)
{
if (i == 0)
{
currentNode = roots.FirstOrDefault(obj => obj.name == segments[0]).transform;
}
else
{
currentNode = currentNode.Find(segments[i]);
}
if (currentNode == null) break;
}
//找到节点
return currentNode;
}
(END)