Main/Component/UI/Common/ClickScreenOtherSpace.cs
@@ -26,6 +26,7 @@ public void AddListener(Action _callBack) { m_ClickOtherEvent = null; m_ClickOtherEvent += _callBack; } @@ -34,22 +35,31 @@ m_ClickOtherEvent = null; } private void LateUpdate() { if (Input.GetMouseButtonDown(0)) { if (Input.GetMouseButtonDown(0)) { var sp = Input.mousePosition; switch (m_RespondType) { switch (m_RespondType) { case RespondType.In: if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) { if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) { m_ClickOtherEvent?.Invoke(); this.SetActive(!m_DeActiveSelf); } break; case RespondType.Out: if (!RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) { if (!RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) { m_ClickOtherEvent?.Invoke(); this.SetActive(!m_DeActiveSelf); } break; case RespondType.InOut: m_ClickOtherEvent?.Invoke(); this.SetActive(!m_DeActiveSelf); break; } } @@ -59,5 +69,7 @@ { In, Out, InOut } } Main/Component/UI/Decorate/Graph/CircleHollowImage.cs
@@ -22,7 +22,7 @@ [SerializeField] Vector2 m_HollowArea=new Vector2(50,50); public Vector2 hollowArea { public Vector2 cell { get { return m_HollowArea; } set { m_HollowArea = value; @@ -40,8 +40,8 @@ private Image m_Image; public Image image { get { return m_Image ?? (m_Image = this.AddMissingComponent<Image>()); } } private List<Vector3> innerVertices; private List<Vector3> outterVertices; protected List<Vector3> innerVertices; protected List<Vector3> outterVertices; protected override void Awake() { innerVertices = new List<Vector3>(); @@ -60,8 +60,8 @@ var height = image.rectTransform.rect.height; var outerArea = new Vector2(0.5f * width,0.5f * height); var realCenter = new Vector2(Mathf.Clamp(center.x,-width * 0.5f + hollowArea.x,width * 0.5f - hollowArea.x), Mathf.Clamp(center.y,-height * 0.5f + hollowArea.y,height * 0.5f - hollowArea.y)); var realCenter = new Vector2(Mathf.Clamp(center.x,-width * 0.5f + cell.x,width * 0.5f - cell.x), Mathf.Clamp(center.y,-height * 0.5f + cell.y,height * 0.5f - cell.y)); var uv = image.overrideSprite != null ? DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero; @@ -84,7 +84,7 @@ var sinA = Mathf.Sin(degree); degree = degree - degreeDelta; position = new Vector3(realCenter.x + cosA * hollowArea.x,realCenter.y + sinA * hollowArea.y); position = new Vector3(realCenter.x + cosA * cell.x,realCenter.y + sinA * cell.y); uv0 = new Vector2(position.x * uvScaleX + uvCenterX,position.y * uvScaleY + uvCenterY); uiVertex = UIUtility.PackageUIVertex(position,uv0,image.color); vh.AddVert(uiVertex); @@ -118,7 +118,7 @@ return Contains(local,outterVertices,innerVertices); } private bool Contains(Vector2 p,List<Vector3> outterVertices,List<Vector3> innerVertices) { protected bool Contains(Vector2 p,List<Vector3> outterVertices,List<Vector3> innerVertices) { var crossNumber = 0; crossNumber += UIUtility.RayCrossingCount(p,innerVertices); crossNumber += UIUtility.RayCrossingCount(p,outterVertices); Main/Component/UI/Effect/EffectPlayer.cs
@@ -61,7 +61,11 @@ protected EffectPenetrationBlocker blocker = null; protected bool isInit = false; protected bool isPlaying = false; public bool isPlaying { get; protected set; } protected List<ParticleSystem> particleList = new List<ParticleSystem>(); Main/Component/UI/Effect/ImageMask.cs
New file @@ -0,0 +1,51 @@ using UnityEngine; [ExecuteAlways] public class ImageMask : PostEffectsBaseEx { static readonly string shaderName = "lcl/screenEffect/MaskEffect"; // 遮罩大小 [Range(0.01f, 10f), Tooltip("遮罩大小")] public float size = 5.0f; // 边缘模糊程度 [Range(0.0001f, 0.1f), Tooltip("边缘模糊程度")] public float edgeBlurLength = 0.05f; // 遮罩中心位置 private Vector2 pos = new Vector4(0.5f, 0.5f); void OnEnable() { shader = Shader.Find(shaderName); } // 渲染屏幕 void OnRenderImage(RenderTexture source, RenderTexture destination) { if (material) { // 把鼠标坐标传递给shader material.SetVector("_Pos", pos); // 遮罩大小 material.SetFloat("_Size", size); // 模糊程度 material.SetFloat("_EdgeBlurLength", edgeBlurLength); // 渲染 Graphics.Blit(source, destination, material); } else { Graphics.Blit(source, destination); } } // void Update() // { // if (Input.GetMouseButton(0)) // { // Vector2 mousePos = Input.mousePosition; // //将mousePos转化为(0,1)区间 // pos = new Vector2(mousePos.x / Screen.width, mousePos.y / Screen.height); // } // } } Main/Component/UI/Effect/ImageMask.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: ee09ec995c4136c479e4006f2569871d MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Component/UI/Effect/PostEffectsBaseEx.cs
New file @@ -0,0 +1,52 @@ using UnityEngine; using System.Collections; [ExecuteAlways] [RequireComponent(typeof(Camera))] //提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质 public class PostEffectsBaseEx : MonoBehaviour { //Inspector面板上直接拖入 public Shader shader = null; private Material _material = null; public Material material { get { if (_material == null) _material = GenerateMaterial(shader); return _material; } } //根据shader创建用于屏幕特效的材质 protected Material GenerateMaterial(Shader shader) { if (shader == null) return null; //需要判断shader是否支持 if (shader.isSupported == false) return null; Material material = new Material(shader); material.hideFlags = HideFlags.DontSave; if (material) return material; return null; } private void OnDisable() { // remove material if (_material) { #if UNITY_EDITOR DestroyImmediate(_material); #else Destroy(_material); #endif _material = null; } } } Main/Component/UI/Effect/PostEffectsBaseEx.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: b5298cad543792440b5dfa70feb00939 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Component/UI/Effect/UIEffectPlayer.cs
@@ -24,7 +24,7 @@ public void PlayByArrIndex(int index, bool showLog = true, bool closePMA = false) { var config = EffectConfig.Get(effectId); playSpineAnimIndex = config.animIndex[index]; playSpineAnimIndex = index < config.animIndex.Length ? config.animIndex[index] : 0; PlayAsync(showLog, closePMA).Forget(); } Main/Config/Configs/GuideConfig.cs
@@ -1,6 +1,6 @@ //-------------------------------------------------------- // [Author]: YYL // [ Date ]: 2025年8月5日 // [ Date ]: 2025年10月9日 //-------------------------------------------------------- using System.Collections.Generic; @@ -17,17 +17,12 @@ } public int ID; public int Type; public int TriggerType; public int Condition; public int SupplementCondition; public string WinName; public int PreGuideId; public int[] Steps; public int CanSkip; public int RemoveWhenOtherGuide; public int CannotCompleteByClick; public int[] UnfoldAreas; public int AutoCompleteTime; public override int LoadKey(string _key) { @@ -41,13 +36,13 @@ string[] tables = input.Split('\t'); int.TryParse(tables[0],out ID); int.TryParse(tables[1],out Type); int.TryParse(tables[1],out TriggerType); int.TryParse(tables[2],out TriggerType); int.TryParse(tables[2],out Condition); int.TryParse(tables[3],out Condition); int.TryParse(tables[3],out SupplementCondition); int.TryParse(tables[4],out SupplementCondition); WinName = tables[4]; int.TryParse(tables[5],out PreGuideId); @@ -64,28 +59,6 @@ int.TryParse(StepsStringArray[i],out Steps[i]); } } int.TryParse(tables[7],out CanSkip); int.TryParse(tables[8],out RemoveWhenOtherGuide); int.TryParse(tables[9],out CannotCompleteByClick); if (tables[10].Contains("[")) { UnfoldAreas = JsonMapper.ToObject<int[]>(tables[10]); } else { string[] UnfoldAreasStringArray = tables[10].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries); UnfoldAreas = new int[UnfoldAreasStringArray.Length]; for (int i=0;i<UnfoldAreasStringArray.Length;i++) { int.TryParse(UnfoldAreasStringArray[i],out UnfoldAreas[i]); } } int.TryParse(tables[11],out AutoCompleteTime); } catch (Exception exception) { Main/Config/PartialConfigs/GuideConfig.cs
New file @@ -0,0 +1,51 @@ using System.Collections.Generic; using UnityEngine; public partial class GuideConfig : ConfigBase<int, GuideConfig> { public static Dictionary<string, List<int>> winToGuidesDic = new Dictionary<string, List<int>>(); public static Dictionary<int, List<int>> typeToGuidesDic = new Dictionary<int, List<int>>(); protected override void OnConfigParseCompleted() { base.OnConfigParseCompleted(); List<int> list = null; if (!winToGuidesDic.TryGetValue(WinName, out list)) { list = new List<int>(); winToGuidesDic.Add(WinName, list); } list.Add(ID); List<int> list2 = null; if (!typeToGuidesDic.TryGetValue(TriggerType, out list2)) { list2 = new List<int>(); typeToGuidesDic.Add(TriggerType, list2); } list2.Add(ID); } public static List<int> GetGuideListByWinName(string winName) { List<int> list = null; if (winToGuidesDic.TryGetValue(winName, out list)) { return list; } return null; } public static List<int> GetGuideListByType(int type) { List<int> list = null; if (typeToGuidesDic.TryGetValue(type, out list)) { return list; } return null; } } Main/Config/PartialConfigs/GuideConfig.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: 732dbddf9b05def43a171ec3ea9b4f9d MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Core/NetworkPackage/DTCFile/ServerPack/HA7_Interaction/DTCA710_tagMCGuideState.cs
@@ -7,6 +7,6 @@ public override void Done(GameNetPackBasic vNetPack) { base.Done(vNetPack); HA710_tagMCGuideState vNetData = vNetPack as HA710_tagMCGuideState; //NewBieCenter.Instance.ResetGuideRecords(vNetData.GuideState); NewBieCenter.Instance.ResetGuideRecords(vNetData.GuideState); } } Main/Core/ResModule/ScriptableObjectLoader.cs
New file @@ -0,0 +1,48 @@ using UnityEngine; using System; #if UNITY_EDITOR using UnityEditor; #endif public class ScriptableObjectLoader { public const string bundleName = "scriptableobjects"; public const string SoNewBieGuide_Suffix = "NewBieGuideStep_"; public static NewBieGuideScriptableObject LoadSoNewBieGuideStep(int _id) { NewBieGuideScriptableObject config = null; if (!AssetSource.isUseAssetBundle) { #if UNITY_EDITOR var resourcePath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, "ScriptableObject/NewBieGuide/", SoNewBieGuide_Suffix, _id, ".asset"); config = AssetDatabase.LoadAssetAtPath<NewBieGuideScriptableObject>(resourcePath); #endif } else { var assetName = StringUtility.Contact(SoNewBieGuide_Suffix, _id); var assetInfo = new AssetInfo(bundleName, assetName); config = AssetBundleUtility.Instance.Sync_LoadAsset(assetInfo) as NewBieGuideScriptableObject; } if (config == null) { Debug.LogErrorFormat("ScriptableObjectLoader.LoadSoNewBieGuideStep() => 加载不到资源: {0}.", _id); } return config; } } Main/Core/ResModule/ScriptableObjectLoader.cs.meta
New file @@ -0,0 +1,12 @@ fileFormatVersion: 2 guid: a931a089f7045294f91a15bc047d72e2 timeCreated: 1504164167 licenseType: Free MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Main.cs
@@ -83,6 +83,7 @@ managers.Add(GoldRushManager.Instance); managers.Add(MailManager.Instance); managers.Add(FirstChargeManager.Instance); managers.Add(NewBieCenter.Instance); foreach (var manager in managers) { Main/Manager/UIManager.cs
@@ -177,7 +177,7 @@ } // 获取层级对应的Transform private Transform GetTransForLayer(UILayer layer) public Transform GetTransForLayer(UILayer layer) { // 尝试从缓存中获取Transform if (layerTransformCache.TryGetValue(layer, out Transform trans)) @@ -314,6 +314,18 @@ return false; } public bool IsOpened(string uiName) { UIBase ui = GetUI(uiName); if (null != ui) { return ui.IsActive(); } return false; } // 获取指定类型的所有UI实例 public List<T> GetAllUI<T>() where T : UIBase { Main/System/Main/HomeWin.cs
@@ -286,10 +286,8 @@ getReward.DataEx = (uint)TaskManager.Instance.mainTask.TaskID; GameNetSystem.Instance.SendInfo(getReward); } else { //根据任务类型引导 } TaskManager.Instance.ClickTask(); } void DisplayCard(TeamType teamType) Main/System/NewBieGuidance.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: bcb9714d50603ba4b8983bc75d173197 folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Main/System/NewBieGuidance/GuideCircleHollowImage.cs
New file @@ -0,0 +1,25 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.Sprites; using UnityEngine.UI; //引导用的圆形镂空图 public class GuideCircleHollowImage : CircleHollowImage { public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) { return true; } //是否在镂空圈内 public bool IsInCirleArea(Vector2 screenPoint, Camera eventCamera) { Vector2 local; RectTransformUtility.ScreenPointToLocalPointInRectangle(image.rectTransform, screenPoint, eventCamera, out local); return !Contains(local, outterVertices, innerVertices); } } Main/System/NewBieGuidance/GuideCircleHollowImage.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: 692dc2485f4fcda48a20cb270bf673f4 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/NewBieGuidance/NewBieCenter.cs
New file @@ -0,0 +1,414 @@ using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using LitJson; public class NewBieCenter : GameSystemManager<NewBieCenter> { int m_CurrentGuide = 0; public int currentGuide { get { return m_CurrentGuide; } set { m_CurrentGuide = value; } } int m_GuideStep = 0; public int guideStep { get { return m_GuideStep; } private set { m_GuideStep = value; } } public bool inGuiding { get { return currentGuide != 0; } } List<int> allGuides = new List<int>(); public List<int> completeGuidesBuf = new List<int>(); bool inited = false; public event Action guideStepChangeEvent; public event Action guideBeginEvent; public event Action<int> guideCompletedEvent; public override void Init() { TaskManager.Instance.OnTaskUpdate += OnTaskUpdateEvent; TaskManager.Instance.OnTaskClick += OnTaskClickEvent; FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent; PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh; UIManager.Instance.OnOpenWindow += OnOpenWindow; } public override void Release() { TaskManager.Instance.OnTaskUpdate -= OnTaskUpdateEvent; TaskManager.Instance.OnTaskClick -= OnTaskClickEvent; FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent; PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh; UIManager.Instance.OnOpenWindow -= OnOpenWindow; } void OnOpenWindow(UIBase _ui) { var guides = GuideConfig.GetGuideListByWinName(_ui.name); if (guides != null) { TryStartNewBieGuides(guides); } } void OnTaskUpdateEvent() { var guides = GuideConfig.GetGuideListByType((int)GuideTriggerType.MainLineQuestCanDo); if (guides != null) { TryStartNewBieGuides(guides); } } void OnTaskClickEvent() { var guides = GuideConfig.GetGuideListByType((int)GuideTriggerType.MissionClick); if (guides != null) { TryStartNewBieGuides(guides); } } void OnFuncStateChangeEvent(int _funcId) { var guides = GuideConfig.GetGuideListByType((int)GuideTriggerType.FunctionOpen); if (guides != null) { TryStartNewBieGuides(guides); } } void PlayerDataRefresh(PlayerDataType type) { if (type == PlayerDataType.LV) { var guides = GuideConfig.GetGuideListByType((int)GuideTriggerType.Level); if (guides != null) { TryStartNewBieGuides(guides); } } else if (type == PlayerDataType.ExAttr1) { var guides = GuideConfig.GetGuideListByType((int)GuideTriggerType.Map); if (guides != null) { TryStartNewBieGuides(guides); } } } public bool IsGuideCompleted(int guideId) { return completeGuidesBuf.Contains(guideId); } // 服务器记录的引导进度 public void ResetGuideRecords(uint[] _guideRecords) { completeGuidesBuf.Clear(); if (_guideRecords == null || _guideRecords.Length == 0) { return; } for (int i = 0; i < _guideRecords.Length; i++) { var guideRecord = _guideRecords[i]; for (ushort j = 0; j < 31; j++) { if (MathUtility.GetBitValue(guideRecord, j)) { completeGuidesBuf.Add(i * 31 + j); } } } } //找出可进行的引导 public void TryStartNewBieGuides(List<int> _guides) { if (!inited) { var allGuideConfigs = GuideConfig.GetValues(); foreach (var config in allGuideConfigs) { allGuides.Add(config.ID); } inited = true; } if (_guides == null) { return; } if (currentGuide != 0) { return; } var ok = false; for (int i = 0; i < _guides.Count; i++) { var guideId = _guides[i]; if (completeGuidesBuf.Contains(guideId)) { continue; } var config = GuideConfig.Get(guideId); if (config.PreGuideId != 0 && !completeGuidesBuf.Contains(config.PreGuideId)) { // 如果前置引导没有完成,则跳过 continue; } ok = CheckGuideCondition(guideId); if (ok && currentGuide != guideId) { StartNewBieGuide(guideId); break; } } } public void StartNewBieGuide(int _id) { if (_id == 0) { Debug.LogError("请检查引导id = 0 的情况"); return; } var config = GuideConfig.Get(_id); if (config == null) { Debug.LogError($"没有该引导ID,请检查引导id = {_id} 的情况"); return; } AutoFightModel.Instance.isPause = true; currentGuide = _id; guideStep = config.Steps.Length > 0 ? config.Steps[0] : 0; if (guideBeginEvent != null) { guideBeginEvent(); } if (!UIManager.Instance.IsOpened<NewBieWin>()) { UIManager.Instance.OpenWindow<NewBieWin>(); } else { guideStepChangeEvent?.Invoke(); } UIManager.Instance.CloseWindow<ChatWin>(); } public void FinishNewBieGuide(int _id) { var guideRecord = currentGuide; currentGuide = 0; UIManager.Instance.CloseWindow<NewBieWin>(); if (!completeGuidesBuf.Contains(guideRecord)) { completeGuidesBuf.Add(guideRecord); } var send = new CA222_tagCMSetGuideOK(); send.GuideIndex = (byte)_id; send.IsOK = 1; GameNetSystem.Instance.SendInfo(send); if (guideCompletedEvent != null) { guideCompletedEvent(guideRecord); } AutoFightModel.Instance.isPause = false; } public void RemoveNewBieGuide(int _id) { if (!completeGuidesBuf.Contains(_id)) { completeGuidesBuf.Add(_id); } var send = new CA222_tagCMSetGuideOK(); send.GuideIndex = (byte)_id; send.IsOK = 1; GameNetSystem.Instance.SendInfo(send); } public void FinishCurrentGuideWithoutCloseWin() { var guideRecord = currentGuide; currentGuide = 0; completeGuidesBuf.Add(guideRecord); var send = new CA222_tagCMSetGuideOK(); send.GuideIndex = (byte)guideRecord; send.IsOK = 1; GameNetSystem.Instance.SendInfo(send); if (guideCompletedEvent != null) { guideCompletedEvent(guideRecord); } AutoFightModel.Instance.isPause = false; } public void ReportGuideStepComplete(int _step) { if (_step == guideStep) { var config = GuideConfig.Get(currentGuide); if (config == null) { guideStep = 0; Debug.Log("1 FinishNewBieGuide " + _step); FinishNewBieGuide(currentGuide); return; } var stepIndex = Array.IndexOf(config.Steps, _step); if (stepIndex < config.Steps.Length - 1) { guideStep = config.Steps[stepIndex + 1]; Debug.Log("3 FinishNewBieGuide " + _step); if (guideStepChangeEvent != null) { guideStepChangeEvent(); } } else { guideStep = 0; Debug.Log("2 FinishNewBieGuide " + _step); FinishNewBieGuide(currentGuide); } } } public bool CheckGuideCondition(int _guideId) { var config = GuideConfig.Get(_guideId); if (config == null) { return false; } if (!UIManager.Instance.IsOpened(config.WinName)) { return false; } switch ((GuideTriggerType)config.TriggerType) { case GuideTriggerType.None: return true; case GuideTriggerType.FunctionOpen: return FuncOpen.Instance.IsFuncOpen(config.Condition); case GuideTriggerType.Level: return PlayerDatas.Instance.baseData.LV >= config.Condition; case GuideTriggerType.OpenWindow: return UIManager.Instance.IsOpened(config.WinName); case GuideTriggerType.MainLineQuestCanDo: if (config.SupplementCondition == 2) { return TaskManager.Instance.mainTask.TaskID == config.Condition && TaskManager.Instance.GetMainTaskState() == 2; } return TaskManager.Instance.mainTask.TaskID == config.Condition; case GuideTriggerType.Map: return PlayerDatas.Instance.baseData.ExAttr1 >= config.Condition; case GuideTriggerType.MissionClick: return TaskManager.Instance.GetMainTaskType() == config.Condition; default: return false; } } public void CompleteAllGuides() { var send = new CA222_tagCMSetGuideOK(); send.GuideIndex = 255; send.IsOK = 1; GameNetSystem.Instance.SendInfo(send); currentGuide = 0; UIManager.Instance.CloseWindow<NewBieWin>(); var allGuideKeys = GuideConfig.GetKeys(); for (int i = 0; i < allGuideKeys.Count; i++) { completeGuidesBuf.Add(allGuideKeys[i]); } } public void ResetAllGuides() { var send = new CA222_tagCMSetGuideOK(); send.GuideIndex = 255; send.IsOK = 0; GameNetSystem.Instance.SendInfo(send); currentGuide = 0; UIManager.Instance.CloseWindow<NewBieWin>(); completeGuidesBuf.Clear(); } public void ResetGuide(int _guide) { var send = new CA222_tagCMSetGuideOK(); send.GuideIndex = (byte)_guide; send.IsOK = 0; GameNetSystem.Instance.SendInfo(send); completeGuidesBuf.Remove(_guide); } } public enum GuideTriggerType { None = 999, //无限制 效果同5 MainLineQuestCanDo = 1, //主线任务 (如首次进入游戏按任务接取引导) FunctionOpen = 2, //功能开放 Map = 3, //地图(关卡副本) 玩家数据ExAttr1 20103代表当前已经过了第2章第1关第3波 MissionClick = 4, //点击任务按任务类型引导 OpenWindow = 5, //打开界面的时机 如装备替换界面 Level = 6, //等级满足条件 } Main/System/NewBieGuidance/NewBieCenter.cs.meta
New file @@ -0,0 +1,12 @@ fileFormatVersion: 2 guid: db99a7a80292e504b989a2e4d29fa3e6 timeCreated: 1501222672 licenseType: Free MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/NewBieGuidance/NewBieGuideScriptableObject.cs
New file @@ -0,0 +1,63 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(menuName = "Config/NewbieGuideStep")] public class NewBieGuideScriptableObject : ScriptableObject { public int stepId; public GuideType guideType; public Vector2 clickPosition; //点击目标的偏移量 public Vector2 clickSize; public Vector2 tipPosition; public ArrowPosition arrowPosition; public string UIElementPath; public int effect; public int voice; public Vector2 usherPosition; public UsherOrientation usherOrientation; public int usherAction; public bool clickAnyWhereComplete = false; public bool clickCompleteNoMask = false; //任意点击关闭 勾选此项会隐藏蒙版 // 引导的文本的箭头位置 public enum ArrowPosition { None, Left, Right, Top, Bottom, } // 引导人物(带文字 类似对话流程) public enum UsherOrientation { Normal = 0, //默认 Reversal = 1 // 反向 } public const string GuidesPrefixNewBie = "guide_new_"; public string GetTipContent() { return Language.Get(GuidesPrefixNewBie + stepId); } public bool HasTipContent() { return LanguageConfig.HasKey(GuidesPrefixNewBie + stepId); } } public enum GuideType { NewBie, Function, NpcTalk, } Main/System/NewBieGuidance/NewBieGuideScriptableObject.cs.meta
New file @@ -0,0 +1,12 @@ fileFormatVersion: 2 guid: 3d16610a4022c8f4eaec9f99c29cbf01 timeCreated: 1511793683 licenseType: Pro MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/NewBieGuidance/NewBieMask.cs
New file @@ -0,0 +1,24 @@ using UnityEngine; using System.Collections; using UnityEngine.UI; using UnityEngine.Events; public class NewBieMask : MonoBehaviour { [SerializeField] GuideCircleHollowImage m_Mask; public GuideCircleHollowImage mask { get { return m_Mask; } } public void Display(int _guideStep, Transform _target) { var config = ScriptableObjectLoader.LoadSoNewBieGuideStep(_guideStep); m_Mask.center = (Vector2)this.transform.InverseTransformPoint(_target.position) + config.clickPosition; m_Mask.cell = config.clickSize; } } Main/System/NewBieGuidance/NewBieMask.cs.meta
New file @@ -0,0 +1,12 @@ fileFormatVersion: 2 guid: 02c283f062dcc2640a944a87af02705e timeCreated: 1501222721 licenseType: Free MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/NewBieGuidance/NewBieWin.cs
New file @@ -0,0 +1,324 @@ using System; using System.Collections; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using DG.Tweening; //引导功能包含 // 1.功能开启 // 2.引导NPC对话 // 3.点击引导 public class NewBieWin : UIBase { [SerializeField] NewBieMask m_NewBieMask; //遮罩,可镂空 //新功能开放 [SerializeField] Transform m_NewFunction; [SerializeField] Transform m_ContainerFunctionBg; //附加说明特效为显示时播放 不需要代码控制 [SerializeField] Text m_FunctionName; [SerializeField] Image m_FuncIcon; //功能图片飞入对应位置 [SerializeField] UIEffectPlayer unlockEffect; //飞到对应功能后爆开特效 //引导npc对话 [SerializeField] Transform m_GuideTalkRect; [SerializeField] UIEffectPlayer m_newBieGuideNPC; [SerializeField] Button m_ClickTalk; [SerializeField] RichText m_TalkText; //点击引导 [SerializeField] Transform m_NewBieGuide; [SerializeField] Transform m_ContainerDialogue; [SerializeField] RichText m_Dialogue; [SerializeField] Image m_ArrowUP; [SerializeField] Image m_ArrowDown; [SerializeField] Image m_ArrowLeft; [SerializeField] Image m_ArrowRight; [SerializeField] UIEffectPlayer m_ClickEffect; [SerializeField] ClickScreenOtherSpace m_ClickScreenOtherSpace; Transform m_ClickTarget; GuideConfig config; NewBieGuideScriptableObject stepConfig; //引导步骤 #region Built-in protected override void InitComponent() { m_ClickTalk.AddListener(()=> { ReportStepOver(); }); } protected override void OnPreOpen() { m_ClickTarget = null; //关闭其他可能在主界面显示的窗口等 UIManager.Instance.CloseWindow<ChatWin>(); NewBieCenter.Instance.guideStepChangeEvent += OnStepChange; } protected override void OnPreClose() { NewBieCenter.Instance.guideStepChangeEvent -= OnStepChange; if (NewBieCenter.Instance.currentGuide != 0) { NewBieCenter.Instance.FinishCurrentGuideWithoutCloseWin(); } m_ClickTarget = null; stepConfig = null; } protected override void NextFrameAfterOpen() { Display(); } #endregion void Display() { config = GuideConfig.Get(NewBieCenter.Instance.currentGuide); if (config == null) { CloseWindow(); return; } var step = NewBieCenter.Instance.guideStep; stepConfig = ScriptableObjectLoader.LoadSoNewBieGuideStep(step); if (stepConfig == null) { CloseWindow(); return; } try { m_ClickTarget = FindTransform(stepConfig.UIElementPath); if (m_ClickTarget != null) { m_lastTargetPosition = m_ClickTarget.position; } } catch (Exception ex) { Debug.LogError(ex); NewBieCenter.Instance.FinishNewBieGuide(NewBieCenter.Instance.currentGuide); } var type = stepConfig.guideType; if (type == GuideType.NewBie && stepConfig.clickCompleteNoMask) { m_NewBieMask.SetActive(false); } else { m_NewBieMask.SetActive(true); m_NewBieMask.Display(step, m_ClickTarget); } if (type == GuideType.Function) { m_NewFunction.SetActive(true); m_NewBieGuide.SetActive(false); m_GuideTalkRect.SetActive(false); DisplayFunctionUnLock(config.Condition); } else if (type == GuideType.NpcTalk) { m_NewFunction.SetActive(false); m_NewBieGuide.SetActive(false); m_GuideTalkRect.SetActive(true); DisplayNPCTalk(); } else { m_NewFunction.SetActive(false); m_NewBieGuide.SetActive(true); m_GuideTalkRect.SetActive(false); DisplayGuide(); } } private void DisplayFunctionUnLock(int _functionId) { var config = FuncOpenLVConfig.Get(_functionId); m_FunctionName.text = config.Name; m_FuncIcon.SetSprite(config.Icon); m_ContainerFunctionBg.SetActive(true); m_FuncIcon.SetActive(true); m_FuncIcon.transform.localPosition = Vector3.zero; unlockEffect.Stop(); Co_FunctionUnLockDelay().Forget(); } void DisplayNPCTalk() { m_newBieGuideNPC.effectId = stepConfig.effect; m_newBieGuideNPC.PlayByArrIndex(stepConfig.usherAction); m_newBieGuideNPC.transform.localPosition = stepConfig.usherPosition; m_newBieGuideNPC.transform.localScale = new Vector3(stepConfig.usherOrientation == NewBieGuideScriptableObject.UsherOrientation.Normal ? 1 : -1, 1, 1); m_TalkText.text = stepConfig.GetTipContent(); } private void DisplayGuide() { Co_DisplayGuide(); } //完成当前引导步骤 private void ReportStepOver() { m_ClickTarget = null; NewBieCenter.Instance.ReportGuideStepComplete(NewBieCenter.Instance.guideStep); } private void OnStepChange() { Display(); } async UniTask Co_FunctionUnLockDelay() { await UniTask.Delay(2000); m_ContainerFunctionBg.SetActive(false); unlockEffect.transform.position = m_ClickTarget.position; m_FuncIcon.transform.DOMove(m_ClickTarget.position, 0.5f).SetEase(Ease.OutQuad).OnComplete(() => { m_FuncIcon.SetActive(false); unlockEffect.onComplete = ReportStepOver; unlockEffect.Play(); }); } void Co_DisplayGuide() { if (stepConfig.HasTipContent()) { m_ContainerDialogue.SetActive(true); m_Dialogue.text = stepConfig.GetTipContent(); m_ArrowUP.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Top); m_ArrowDown.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Bottom); m_ArrowLeft.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Left); m_ArrowRight.SetActive(stepConfig.arrowPosition == NewBieGuideScriptableObject.ArrowPosition.Right); m_ContainerDialogue.transform.position = m_ClickTarget.position; m_ContainerDialogue.transform.localPosition = m_ContainerDialogue.transform.localPosition + (Vector3)stepConfig.tipPosition; } else { m_ContainerDialogue.SetActive(false); } m_ClickEffect.effectId = stepConfig.effect; //如果需要点击特效也增加偏移量 m_ClickEffect.SetActive(true); m_ClickEffect.Play(); m_ClickEffect.transform.position = m_ClickTarget.position; m_ClickEffect.transform.localPosition = m_ClickEffect.transform.localPosition + (Vector3)stepConfig.usherPosition; if (stepConfig.clickCompleteNoMask) { m_ClickScreenOtherSpace.enabled = true; m_ClickScreenOtherSpace.AddListener(() => { ReportStepOver(); }); } else { m_ClickScreenOtherSpace.enabled = false; m_ClickScreenOtherSpace.RemoveAllListeners(); } } void Update() { if (Input.GetMouseButtonDown(0)) { if (stepConfig.clickAnyWhereComplete || m_NewBieMask.mask.IsInCirleArea(Input.mousePosition, CameraManager.uiCamera)) { if (m_ClickTarget == null) { Debug.LogError("引导 m_ClickTarget == null; step = " + NewBieCenter.Instance.guideStep); } var btn = m_ClickTarget.GetComponent<Button>(); ReportStepOver(); if (btn != null) { btn.onClick.Invoke(); } } } CheckTarget(); } Vector3 m_lastTargetPosition; //引导的目标发生位置变化的情况 void CheckTarget() { if (m_ClickTarget == null) return; if (m_lastTargetPosition != m_ClickTarget.position) { Display(); } } //BaseCanvas/MainInterfaceWin/Widget_RightBottom/Container_Function/Function_Grid/Grid_6/Content/Btn_@* //分割成BaseCanvas/MainInterfaceWin/Widget_RightBottom/Container_Function/Function_Grid/Grid_6/Content 和 Btn_ //在WindowCenter.Instance.uiRoot的 BaseCanvas/MainInterfaceWin/Widget_RightBottom/Container_Function/Function_Grid/Grid_6/Content下查找以Btn_开头的第一个子物体 //支持路径末尾加@*做模糊查找 private Transform FindTransform(string path) { if (!path.EndsWith("@*")) { return UIManager.Instance.GetUIRoot().transform.Find(path); } var paths = path.Split('/'); var newPath = string.Join("/", paths, 0, paths.Length - 1); string findName = paths[paths.Length - 1].Replace("@*", ""); var parent = UIManager.Instance.GetUIRoot().transform.Find(newPath); if (parent == null) { return null; } var comps = parent.GetComponentsInChildren<Transform>(); for (int i = 0; i < comps.Length; i++) { if (comps[i].name.StartsWith(findName)) { return comps[i]; } } return UIManager.Instance.GetUIRoot().transform.Find(path); } } Main/System/NewBieGuidance/NewBieWin.cs.meta
New file @@ -0,0 +1,12 @@ fileFormatVersion: 2 guid: fc299fd4d447c8246bffc13b3c03966d timeCreated: 1511253322 licenseType: Pro MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/Task/TaskManager.cs
@@ -31,7 +31,7 @@ //主线任务,暂且只处理主线任务 public TaskDetailDates mainTask = new TaskDetailDates(); public event Action OnTaskUpdate; public event Action OnTaskClick; public override void Init() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize; @@ -67,6 +67,11 @@ } public void ClickTask() { OnTaskClick?.Invoke(); } // 任务状态 1-进行中 2-可领取 public int GetMainTaskState() { @@ -80,4 +85,11 @@ return taskConfig.Index - TaskConfig.Get(mainTask.TaskID).Index + 1; } public int GetMainTaskType() { if (mainTask.TaskID == 0) return 0; var taskConfig = TaskConfig.Get(mainTask.TaskID); return taskConfig.TaskType; } } Main/Utility/EnumHelper.cs
@@ -1142,17 +1142,7 @@ } public enum FunctionUnlockType { NoneType = 0, Treasure = 1, Normal = 2, TreasureSkill = 3, Skill = 4, TreasureFunc = 5, TreasureChapter = 6, } public enum RedPointState @@ -1319,49 +1309,8 @@ } public enum GuideType { NewBie = 1, Functional = 2, } public enum GuideTriggerType { None = 998,//无限制 FunctionOpen = 1,//功能开放 ManualFunctionOpen = 51,//手动功能开放 Level = 2, //等级满足条件 Treasure = 3,//法宝 EquipQuality = 4,//装备品质 Item = 5,//指定物品 TreasureDungeon = 6,//法宝副本 Map = 11,//地图 RuneInlay = 12,//符印镶嵌 RealmSitDown = 13,//境界打坐 ItemCompound = 14,//物品合成 HangUpResult = 15,//挂机结算 TreasureCollectSoul = 16,//法宝集魂 TreasureAwaken = 17,//法宝觉醒 Pray = 18,//祈愿 VIPExperience = 19,//vip体验 FairyLandBuyTimes = 20,//仙界秘境购买次数 TeamAutoAccept = 21,//自动接受组队邀请 TrialExchange = 22,//宗门试炼兑换材料 QuestCanAccept = 100,//任务可接 MainLineQuestCanDo = 101,//任务进行中 MainLineQuestCanAward = 102,//任务可领奖 MainLineQuestLimit = 106,//任务被限制 MainLineQuestContinue = 110,//任务可继续 BranchQuestCando = 201,//支线任务可做 BranchQuestCanAward = 202,//支线任务可领奖 BranchQuestLimit = 206,//支线任务被限制 BranchQuestContinue = 210,//支线任务可继续 } public enum FuncPowerType Main/Utility/UIUtility.cs
@@ -310,24 +310,6 @@ vertexHelper.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2); } // public static string GetUIElementRelativePath(UIRoot _root, Transform _transform) // { // List<Transform> parents = new List<Transform>() { _transform }; // GetParents(_transform, ref parents); // if (parents.Contains(_root.transform)) // { // parents.Remove(_root.transform); // } // var names = new string[parents.Count]; // for (int i = 0; i < names.Length; i++) // { // names[i] = parents[i].gameObject.name; // } // return string.Join("/", names); // } public static void GetParents(Transform _transform, ref List<Transform> _parents) { @@ -344,4 +326,22 @@ } } public static string GetUIElementRelativePath(Transform _root, Transform _transform) { List<Transform> parents = new List<Transform>() { _transform }; GetParents(_transform, ref parents); if (parents.Contains(_root)) { parents.Remove(_root); } var names = new string[parents.Count]; for (int i = 0; i < names.Length; i++) { names[i] = parents[i].gameObject.name; } return string.Join("/", names); } }