zhouqijie

新手指引实现

指引信息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)