New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: f97380ec7fe308f4fb5bb6658c9b2604 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 236e2b98d9a024546a3d5b0ee59c257e |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | |
|
| | |
|
| | | public class CharacterBase
|
| | | {
|
| | |
|
| | | |
| | |
|
| | |
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 446cfdee2e270e2459fa4dbb2c33b152 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 613ebae9f200e9d43b75a053fd050971 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using Spine.Unity;
|
| | | using Spine;
|
| | | using System;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | |
|
| | | // 动作控制
|
| | | public class MotionBase
|
| | | {
|
| | | protected SkeletonAnimation skeletonAnimation;
|
| | |
|
| | | public virtual void Init(SkeletonAnimation _skeletonAnimation)
|
| | | {
|
| | | skeletonAnimation = _skeletonAnimation;
|
| | | }
|
| | |
|
| | | public virtual void Play(string _motionName, bool _isLoop = false)
|
| | | {
|
| | | skeletonAnimation.AnimationState.SetAnimation(0, _motionName, _isLoop);
|
| | | }
|
| | |
|
| | | public virtual void Pause()
|
| | | {
|
| | | skeletonAnimation.AnimationState.TimeScale = 0;
|
| | | }
|
| | |
|
| | | public virtual void Resume()
|
| | | {
|
| | | skeletonAnimation.AnimationState.TimeScale = 1;
|
| | | }
|
| | |
|
| | | public virtual void MixBlend(string _motionName, float _duration)
|
| | | {
|
| | | // 获取当前轨道上的动画
|
| | | TrackEntry currentTrack = skeletonAnimation.AnimationState.GetCurrent(0);
|
| | | |
| | | if (currentTrack != null)
|
| | | {
|
| | | // 添加一个新的动画到轨道0,并设置混合时间
|
| | | TrackEntry newTrack = skeletonAnimation.AnimationState.SetAnimation(0, _motionName, true);
|
| | | |
| | | // 设置混合持续时间
|
| | | newTrack.MixDuration = _duration;
|
| | | |
| | | // 可选:设置混合类型
|
| | | // newTrack.MixBlend = MixBlend.Replace; // 默认值
|
| | | |
| | | // 可选:如果需要在混合完成后执行某些操作
|
| | | // newTrack.Complete += OnMixComplete;
|
| | | }
|
| | | else
|
| | | {
|
| | | // 如果当前没有动画在播放,直接播放新动画
|
| | | skeletonAnimation.AnimationState.SetAnimation(0, _motionName, true);
|
| | | }
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 7d0ffbc3831c9564481db79412785ff9 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: da9ffef894f7c304c8f0de2f85657112 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | |
|
| | | public class ConfigBase<U, T> where T : ConfigBase<U, T>, new()
|
| | | {
|
| | | public static Dictionary<U, T> dic = new Dictionary<U, T>();
|
| | |
|
| | | protected static bool isInit = false;
|
| | |
|
| | | public static T Get(U id)
|
| | | {
|
| | | if (!isInit)
|
| | | {
|
| | | Debug.LogError("ConfigBase 没有初始化");
|
| | | return null; // 或者抛出异常,视情况而定
|
| | | }
|
| | |
|
| | | if (dic.ContainsKey(id))
|
| | | {
|
| | | return dic[id];
|
| | | }
|
| | |
|
| | | return null;
|
| | | }
|
| | |
|
| | | public List<T> GetValues()
|
| | | {
|
| | | if (!isInit)
|
| | | {
|
| | | Debug.LogError(typeof(T).Name + " 没有初始化 GetValues");
|
| | | return null; // 或者抛出异常,视情况而定
|
| | | }
|
| | | List<T> result = new List<T>();
|
| | | result.AddRange(dic.Values);
|
| | | return result;
|
| | | }
|
| | |
|
| | | public static bool HasKey(U key)
|
| | | {
|
| | | if (!isInit)
|
| | | {
|
| | | Debug.LogError(typeof(T).Name + " 没有初始化 HasKey");
|
| | | return false; // 或者抛出异常,视情况而定
|
| | | }
|
| | |
|
| | | return dic.ContainsKey(key);
|
| | | }
|
| | |
|
| | | public static void Init(string[] lines)
|
| | | {
|
| | | Dictionary<string, string> rawDatas = new Dictionary<string, string>();
|
| | |
|
| | | for (int i = 3; i < lines.Length; i++)
|
| | | {
|
| | | string line = lines[i];
|
| | | var index = line.IndexOf("\t");
|
| | | if (index == -1)
|
| | | {
|
| | | continue;
|
| | | }
|
| | |
|
| | | string strKey = line.Substring(0, index);
|
| | | T config = new T();
|
| | | U key = config.LoadKey(strKey);
|
| | | config.LoadConfig(line);
|
| | | dic.Add(key, config);
|
| | | }
|
| | |
|
| | | isInit = true;
|
| | | }
|
| | |
|
| | | public virtual U LoadKey(string line)
|
| | | {
|
| | | return default(U);
|
| | | }
|
| | |
|
| | | public virtual void LoadConfig(string line)
|
| | | {
|
| | | |
| | | }
|
| | | |
| | | protected int ParseInt(string str)
|
| | | {
|
| | | int result = 0;
|
| | | int.TryParse(str, out result);
|
| | | return result;
|
| | | }
|
| | |
|
| | | protected float ParseFloat(string str)
|
| | | {
|
| | | float result = 0f;
|
| | | float.TryParse(str, out result);
|
| | | return result;
|
| | | }
|
| | |
|
| | | protected string[] Split(string str, char split)
|
| | | {
|
| | | return str.Split(split);
|
| | | }
|
| | |
|
| | | protected List<string> ParseStrList(string str, char split)
|
| | | {
|
| | | List<string> result = new List<string>();
|
| | | string[] strs = Split(str, split);
|
| | | for (int i = 0; i < strs.Length; i++)
|
| | | {
|
| | | result.Add(strs[i]);
|
| | | }
|
| | |
|
| | | return result;
|
| | | }
|
| | |
|
| | | protected List<int> ParseIntList(string str, char split)
|
| | | {
|
| | | List<int> result = new List<int>();
|
| | | string[] strs = Split(str, split);
|
| | | for (int i = 0; i < strs.Length; i++)
|
| | | {
|
| | | result.Add(ParseInt(strs[i]));
|
| | | }
|
| | | return result;
|
| | | }
|
| | |
|
| | | protected U GetKey(string key)
|
| | | {
|
| | | if (typeof(U) == typeof(string))
|
| | | {
|
| | | return (U)(object)key;
|
| | | }
|
| | | else if (typeof(U) == typeof(int))
|
| | | {
|
| | | return (U)(object)ParseInt(key);
|
| | | }
|
| | | else
|
| | | {
|
| | | Debug.LogError("GetKey 类型错误");
|
| | | return default(U);
|
| | | }
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: beeab167082007f42b3eedbb8a3c19e8 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using LitJson;
|
| | | using System;
|
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using System.Text.RegularExpressions;
|
| | | using UnityEngine;
|
| | |
|
| | | public class ConfigParse
|
| | | {
|
| | | public enum SegStrType
|
| | | {
|
| | | Multiple,
|
| | | KeyValue,
|
| | | }
|
| | |
|
| | | public static T? GetSegValue<T>(string msg, string key, SegStrType type) where T : struct
|
| | | {
|
| | | T? result = null;
|
| | | switch (type)
|
| | | {
|
| | | case SegStrType.Multiple:
|
| | | {
|
| | | uint index = 0;
|
| | | uint.TryParse(key, out index);
|
| | | result = (T)Convert.ChangeType(GetMultipleStr(msg, index), typeof(T));
|
| | | }
|
| | | break;
|
| | | case SegStrType.KeyValue:
|
| | | {
|
| | | result = (T)Convert.ChangeType(GetKeyValue(msg, key), typeof(T));
|
| | | }
|
| | | break;
|
| | | }
|
| | | return result;
|
| | | }
|
| | |
|
| | | public static string GetSegValue(string msg, string key, SegStrType type)
|
| | | {
|
| | | switch (type)
|
| | | {
|
| | | case SegStrType.Multiple:
|
| | | {
|
| | | uint index = 0;
|
| | | uint.TryParse(key, out index);
|
| | | return GetMultipleStr(msg, index);
|
| | | }
|
| | | case SegStrType.KeyValue:
|
| | | {
|
| | | return GetKeyValue(msg, key);
|
| | | }
|
| | | }
|
| | | return string.Empty;
|
| | | }
|
| | |
|
| | | private static string GetMultipleStr(string msg, uint index)
|
| | | {
|
| | | string[] segs = GetMultipleStr(msg);
|
| | | if (segs != null && index < segs.Length)
|
| | | {
|
| | | return segs[index];
|
| | | }
|
| | | return string.Empty;
|
| | | }
|
| | |
|
| | | public static T[] GetMultipleStr<T>(string msg) where T : struct
|
| | | {
|
| | | string[] segs = GetMultipleStr(msg);
|
| | | if (segs != null && segs.Length > 0)
|
| | | {
|
| | | T[] array = new T[segs.Length];
|
| | | for (int i = 0; i < segs.Length; i++)
|
| | | {
|
| | | array[i] = (T)Convert.ChangeType(segs[i], typeof(T));
|
| | | }
|
| | | return array;
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | public static string[] GetMultipleStr(string msg)
|
| | | {
|
| | | string[] segs = msg.Split('|');
|
| | | if (segs.Length == 1 && segs[0].Equals(string.Empty)) return null;
|
| | | return segs;
|
| | | }
|
| | |
|
| | | private static string GetKeyValue(string msg, string key)
|
| | | {
|
| | | string[] segs = GetMultipleStr(msg);
|
| | | for (int i = 0; i < segs.Length; i++)
|
| | | {
|
| | | string[] pair = GetKeyValue(segs[i]);
|
| | | if (pair.Length > 1)
|
| | | {
|
| | | if (!pair[0].Equals(key)) continue;
|
| | | else return pair[1];
|
| | | }
|
| | | else continue;
|
| | | }
|
| | | return string.Empty;
|
| | | }
|
| | |
|
| | | private static string[] GetKeyValue(string msg)
|
| | | {
|
| | | return msg.Split('_');
|
| | | }
|
| | |
|
| | | public static T[] GetKeyValueKeys<T>(string msg) where T : struct
|
| | | {
|
| | | string[] segs = GetMultipleStr(msg);
|
| | | if (segs != null && segs.Length > 0)
|
| | | {
|
| | | T[] array = new T[segs.Length];
|
| | | for (int i = 0; i < segs.Length; i++)
|
| | | {
|
| | | string[] pair = GetKeyValue(segs[i]);
|
| | | if (pair.Length > 1)
|
| | | {
|
| | | array[i] = (T)Convert.ChangeType(pair[0], typeof(T));
|
| | | }
|
| | | }
|
| | | return array;
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | public static T[] GetKeyValueValues<T>(string msg) where T : struct
|
| | | {
|
| | | string[] segs = GetMultipleStr(msg);
|
| | | if (segs != null && segs.Length > 0)
|
| | | {
|
| | | T[] array = new T[segs.Length];
|
| | | for (int i = 0; i < segs.Length; i++)
|
| | | {
|
| | | string[] pair = GetKeyValue(segs[i]);
|
| | | if (pair.Length > 1)
|
| | | {
|
| | | array[i] = (T)Convert.ChangeType(pair[1], typeof(T));
|
| | | }
|
| | | }
|
| | | return array;
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | public static Dictionary<T, P> GetDic<T, P>(string msg)
|
| | | {
|
| | | Dictionary<T, P> dic = null;
|
| | | string[] segs = GetMultipleStr(msg);
|
| | | if (segs != null && segs.Length > 0)
|
| | | {
|
| | | dic = new Dictionary<T, P>();
|
| | | for (int i = 0; i < segs.Length; i++)
|
| | | {
|
| | | string[] pair = GetKeyValue(segs[i]);
|
| | | if (pair.Length > 1)
|
| | | {
|
| | | dic.Add((T)Convert.ChangeType(pair[0], typeof(T)), (P)Convert.ChangeType(pair[1], typeof(P)));
|
| | | }
|
| | | }
|
| | | }
|
| | | return dic;
|
| | | }
|
| | |
|
| | | public static string ServerStringTrim(string str)
|
| | | {
|
| | | if (!string.IsNullOrEmpty(str))
|
| | | {
|
| | | str = str.Replace("\0", "");
|
| | | str = str.Replace("\x00", "");
|
| | | return str;
|
| | | }
|
| | | else
|
| | | {
|
| | | return string.Empty;
|
| | | }
|
| | | }
|
| | |
|
| | | //{'17':['63','6','27'],'65':['800'],'55':['139'],'19':['1000','2600','130']}
|
| | | public static Regex userDataRegex = new Regex(@"'([0-9]+)':\[(.*?)\]", RegexOptions.Singleline);
|
| | | public static Dictionary<int, List<int>> Analysis(string val)//正则表达式的字符串分割
|
| | | {
|
| | | string s = ServerStringTrim(val);
|
| | | if (string.IsNullOrEmpty(s))
|
| | | {
|
| | | return null;
|
| | | }
|
| | |
|
| | | s = s.Replace(" ", string.Empty);
|
| | | if (!userDataRegex.IsMatch(s))
|
| | | {
|
| | | return null;
|
| | | }
|
| | | else
|
| | | {
|
| | | Dictionary<int, List<int>> dics = new Dictionary<int, List<int>>();
|
| | | foreach (Match match in userDataRegex.Matches(s))
|
| | | {
|
| | | int id = int.Parse(match.Groups[1].Value);
|
| | | string str = match.Groups[2].Value;
|
| | | string[] vals = str.Split(',');
|
| | | List<int> list = new List<int>();
|
| | | for (int i = 0; i < vals.Length; i++)
|
| | | {
|
| | | int intval = int.Parse(vals[i].Replace('\'', ' '));
|
| | | list.Add(intval);
|
| | | }
|
| | | if (!dics.ContainsKey(id))
|
| | | {
|
| | | dics.Add(id, list);
|
| | | }
|
| | | }
|
| | | return dics;
|
| | | }
|
| | | }
|
| | |
|
| | | public static Dictionary<int, List<int>> ParseJsonDict(string jsonStr)
|
| | | {
|
| | | if (jsonStr == "{}" || string.IsNullOrEmpty(jsonStr))
|
| | | {
|
| | | return new Dictionary<int, List<int>>();
|
| | | }
|
| | | var dict = JsonMapper.ToObject<Dictionary<string, List<int>>>(jsonStr);
|
| | | Dictionary<int, List<int>> result = new Dictionary<int, List<int>>();
|
| | |
|
| | | foreach (var item in dict)
|
| | | {
|
| | | result[int.Parse(item.Key)] = item.Value;
|
| | | }
|
| | |
|
| | | return result;
|
| | | }
|
| | |
|
| | | public static Dictionary<int, int> ParseIntDict(string jsonStr)
|
| | | {
|
| | | if (jsonStr == "{}" || string.IsNullOrEmpty(jsonStr))
|
| | | {
|
| | | return new Dictionary<int, int>();
|
| | | }
|
| | | var dict = JsonMapper.ToObject<Dictionary<string, int>>(jsonStr);
|
| | | Dictionary<int, int> result = new Dictionary<int, int>();
|
| | |
|
| | | foreach (var item in dict)
|
| | | {
|
| | | result[int.Parse(item.Key)] = item.Value;
|
| | | }
|
| | |
|
| | | return result;
|
| | | }
|
| | |
|
| | | public static Dictionary<int, int[]> ParseIntArrayDict(string jsonStr)
|
| | | {
|
| | | if (jsonStr == "{}" || string.IsNullOrEmpty(jsonStr))
|
| | | {
|
| | | return new Dictionary<int, int[]>();
|
| | | }
|
| | | var dict = JsonMapper.ToObject<Dictionary<string, int[]>>(jsonStr);
|
| | | Dictionary<int, int[]> result = new Dictionary<int, int[]>();
|
| | |
|
| | | foreach (var item in dict)
|
| | | {
|
| | | result[int.Parse(item.Key)] = item.Value;
|
| | | }
|
| | |
|
| | | return result;
|
| | | }
|
| | |
|
| | | public static Dictionary<int, int[][]> ParseIntArray2Dict(string jsonStr)
|
| | | {
|
| | | if (jsonStr == "{}" || string.IsNullOrEmpty(jsonStr))
|
| | | {
|
| | | return new Dictionary<int, int[][]>();
|
| | | }
|
| | | var dict = JsonMapper.ToObject<Dictionary<string, int[][]>>(jsonStr);
|
| | | Dictionary<int, int[][]> result = new Dictionary<int, int[][]>();
|
| | |
|
| | | foreach (var item in dict)
|
| | | {
|
| | | result[int.Parse(item.Key)] = item.Value;
|
| | | }
|
| | |
|
| | | return result;
|
| | | }
|
| | |
|
| | |
|
| | | //万分率转为每个id对应的概率 [[万分概率,id1],[万分概率,id2]]
|
| | | public static Dictionary<int, int> GetRateDict(int[][] rateArray)
|
| | | {
|
| | | Dictionary<int, int> dic = new Dictionary<int, int>();
|
| | | //概率为 减去上一个概率的值即为当前ID概率
|
| | | for (int i = 0;i< rateArray.Length; i++)
|
| | | {
|
| | | if (i > 0)
|
| | | {
|
| | | dic[rateArray[i][1]] = rateArray[i][0] - rateArray[i - 1][0];
|
| | | }
|
| | | else
|
| | | {
|
| | | dic[rateArray[i][1]] = rateArray[i][0];
|
| | | }
|
| | | }
|
| | |
|
| | | return dic;
|
| | | }
|
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 6f9144568a1b6674da727f6a1a88aed9 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 776d1c99148d30f4799a606e5cd0f5de |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
| | |
| | | "references": [ |
| | | "GUID:3ffa07c58a98b0445a7a34376b165fd1", |
| | | "GUID:4129704b5a1a13841ba16f230bf24a57", |
| | | "GUID:f51ebe6a0ceec4240a699833d6309b23" |
| | | "GUID:f51ebe6a0ceec4240a699833d6309b23", |
| | | "GUID:e34a5702dd353724aa315fb8011f08c3", |
| | | "GUID:4d1926c9df5b052469a1c63448b7609a", |
| | | "GUID:68765d262e2128e4ab49c983f3411946", |
| | | "GUID:173464ddf4cdb6640a4dfa8a9281ad69", |
| | | "GUID:72d1fea872bd7a449bf3818f2b0a6708" |
| | | ], |
| | | "includePlatforms": [], |
| | | "excludePlatforms": [], |
| | |
| | | using UnityEngine;
|
| | | using Cysharp.Threading;
|
| | | using Cysharp.Threading.Tasks;
|
| | | using System.Threading.Tasks;
|
| | |
|
| | | /// <summary>
|
| | | /// Main类,作为热更新程序集的入口点
|
| | | /// </summary>
|
| | | public class Main
|
| | | {
|
| | | public static List<IGameSystemManager> managers = new List<IGameSystemManager>();
|
| | |
|
| | | /// <summary>
|
| | | /// 初始化函数,由Launch类调用
|
| | | /// </summary>
|
| | | public static void Init()
|
| | | public static async UniTask Init()
|
| | | {
|
| | | Debug.Log("Main.Init() 被调用");
|
| | | // 1. 初始化游戏系统
|
| | | InitializeGameSystems();
|
| | | await InitSystems();
|
| | |
|
| | | // 2. 加载配置
|
| | | LoadConfigurations();
|
| | | Debug.Log("关闭加载界面");
|
| | | LaunchLoadingWin.Instance.CloseWindow();
|
| | |
|
| | | // 3. 打开登录界面
|
| | | OpenLoginUI();
|
| | | SwitchToLoginScene();
|
| | | }
|
| | | |
| | |
|
| | | /// <summary>
|
| | | /// 初始化游戏系统
|
| | | /// </summary>
|
| | | private static void InitializeGameSystems()
|
| | | private static async UniTask InitSystems()
|
| | | {
|
| | | Debug.Log("初始化游戏系统");
|
| | | |
| | | // 这里可以初始化各种游戏系统,如资源管理、UI管理、音频管理等
|
| | | // 这里可以初始化大型系统 贯穿整个游戏的系统
|
| | | await ResManager.Instance.Init();
|
| | | UIManager.Instance.Init();
|
| | | StageManager.Instance.Init();
|
| | | LoginManager.Instance.Init();
|
| | |
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 加载配置
|
| | | /// </summary>
|
| | | private static void LoadConfigurations()
|
| | | private static void SwitchToLoginScene()
|
| | | {
|
| | | Debug.Log("加载游戏配置");
|
| | | // Debug.Log("打开登录界面");
|
| | | // UIManager.Instance.OpenWindow<LoginWin>();
|
| | | Debug.Log("切换到登录场景");
|
| | | ConfigManager.Instance.Init();
|
| | | StageManager.Instance.ToLoginScene();
|
| | | }
|
| | |
|
| | | // 这里可以加载游戏配置,如游戏参数、表格数据等
|
| | | public static void OnEnterGameScene()
|
| | | {
|
| | | // 初始化游戏场景
|
| | | Debug.Log("初始化游戏场景");
|
| | |
|
| | | // 初始化游戏系统
|
| | | managers.Add(PlaceManager.Instance);
|
| | | managers.Add(BattleManager.Instance);
|
| | | managers.Add(TeamManager.Instance);
|
| | |
|
| | | foreach (var manager in managers)
|
| | | {
|
| | | manager.Init();
|
| | | }
|
| | |
|
| | | foreach (var manager in managers)
|
| | | {
|
| | | manager.RequestNessaryData();
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | public static void OnSwitchToLoginScene()
|
| | | {
|
| | | foreach (var manager in managers)
|
| | | {
|
| | | manager.Release();
|
| | | }
|
| | |
|
| | | managers.Clear();
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | |
| | | /// </summary>
|
| | | private static void OpenLoginUI()
|
| | | {
|
| | | Debug.Log("关闭加载界面");
|
| | |
|
| | | LaunchLoadingWin.Instance.CloseWindow();
|
| | |
|
| | | Debug.Log("打开登录界面");
|
| | |
|
| | | // 获取Launch中的IsUseSDK标志
|
| | | bool isUseSDK = Launch.Instance.IsUseSDK;
|
| | | |
| | | // 根据IsUseSDK标志显示不同的登录界面
|
| | | if (isUseSDK)
|
| | | {
|
| | | Debug.Log("显示SDK登录界面");
|
| | | // 在这里实现SDK登录界面的显示逻辑
|
| | | // 例如:UIManager.Instance.OpenUI("SDKLoginUI");
|
| | | }
|
| | | else
|
| | | {
|
| | | Debug.Log("显示普通登录界面");
|
| | | // 在这里实现普通登录界面的显示逻辑
|
| | | // 例如:UIManager.Instance.OpenUI("NormalLoginUI");
|
| | | }
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: d17f7001c7a25da4b8f7c0051a479e37 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | | using Cysharp.Threading.Tasks;
|
| | | using System.Reflection;
|
| | |
|
| | |
|
| | | public class ConfigManager : ManagerBase<ConfigManager>
|
| | | {
|
| | | public bool isLoadFinished
|
| | | {
|
| | | get;
|
| | | private set;
|
| | | }
|
| | |
|
| | | public virtual async UniTask InitConfigs()
|
| | | {
|
| | | // 加载配置文件
|
| | | await LoadConfigs();
|
| | | }
|
| | |
|
| | | protected async UniTask LoadConfigs()
|
| | | {
|
| | | isLoadFinished = false;
|
| | |
|
| | | // 加载配置文件
|
| | |
|
| | | // 加载完成后设置isLoadFinished为true
|
| | | isLoadFinished = true;
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | | private async UniTask LoadConfig<T>() where T : class
|
| | | {
|
| | | string configName = typeof(T).Name;
|
| | |
|
| | | TextAsset textAsset = await ResManager.Instance.LoadAsset<TextAsset>("Config", configName);
|
| | | if (textAsset != null)
|
| | | {
|
| | | string[] lines = textAsset.text.Split('\n');
|
| | | var methodInfo = typeof(T).GetMethod("Init", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
| | | if (methodInfo != null)
|
| | | {
|
| | | methodInfo.Invoke(null, new object[] { lines });
|
| | | // 设置初始化标志
|
| | | var isInitField = typeof(T).GetField("isInit", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
|
| | | if (isInitField != null)
|
| | | {
|
| | | isInitField.SetValue(null, true);
|
| | | }
|
| | | Debug.Log($"加载配置: {typeof(T).Name} 成功");
|
| | | }
|
| | | else
|
| | | {
|
| | | Debug.LogError($"配置类 {typeof(T).Name} 没有静态Init方法");
|
| | | }
|
| | | }
|
| | | else
|
| | | {
|
| | | Debug.LogError($"找不到配置文件: {configName}");
|
| | | }
|
| | | }
|
| | |
|
| | | private void ClearConfigDictionary<T>() where T : class
|
| | | {
|
| | | // 重置 T 初始化状态
|
| | | var isInitField = typeof(T).GetField("isInit", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
|
| | | if (isInitField != null)
|
| | | {
|
| | | isInitField.SetValue(null, false);
|
| | | }
|
| | | }
|
| | |
|
| | | public override void Release()
|
| | | {
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | |
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 899d505772a98b44ba61e2e0d0a00072 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | // 游戏系统的管理基类
|
| | |
|
| | | // 添加一个非泛型的基类或接口
|
| | | public interface IGameSystemManager
|
| | | {
|
| | | public void Init();
|
| | | public void Release();
|
| | | public void RequestNessaryData();
|
| | | public bool IsNessaryDataReady();
|
| | | }
|
| | |
|
| | | // 让泛型类继承自非泛型基类
|
| | | public class GameSystemManager<T> : Singleton<T>, IGameSystemManager where T : GameSystemManager<T>, new()
|
| | | {
|
| | | public virtual void Init()
|
| | | {
|
| | | }
|
| | |
|
| | | public virtual void Release()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | public virtual void RequestNessaryData()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | public virtual bool IsNessaryDataReady()
|
| | | {
|
| | | return true;
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 05ef44209a69865458086694ce7d6f67 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 7b0931f43ab92084b8a1e5faa7fbfda2 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | public class BattleManager : GameSystemManager<BattleManager>
|
| | | {
|
| | | public override void Init()
|
| | | {
|
| | | base.Init();
|
| | | |
| | | }
|
| | |
|
| | | public override void Release()
|
| | | {
|
| | | base.Release();
|
| | | }
|
| | |
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: e2eea1200b9fe6644a6907b4e042f222 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | public class PlaceManager : GameSystemManager<PlaceManager>
|
| | | {
|
| | | public PlaceField placeField;
|
| | |
|
| | | public override void Init()
|
| | | {
|
| | | base.Init();
|
| | | |
| | | }
|
| | |
|
| | | public override void Release()
|
| | | {
|
| | | base.Release();
|
| | | }
|
| | |
|
| | | // 当队伍跟章节信息数据都有之后就可以创建场景了
|
| | | public void CreatePlaceField()
|
| | | { |
| | |
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: dc73049956fa1a241a3aeac4d7fdd7af |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | | /// <summary>
|
| | | /// 阵型类型
|
| | | /// </summary>
|
| | | public enum FormationType
|
| | | {
|
| | | None = 0,
|
| | | Type1 = 1,
|
| | | Type2 = 2,
|
| | | Type3 = 3,
|
| | | Type4 = 4,
|
| | | Type5 = 5
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 卡牌信息
|
| | | /// </summary>
|
| | | [Serializable]
|
| | | public class CardInfo
|
| | | {
|
| | | public int cardId; // 卡牌ID
|
| | | public int level; // 卡牌等级
|
| | | public int star; // 卡牌星级
|
| | | public int quality; // 卡牌品质
|
| | | |
| | | // 其他卡牌属性...
|
| | | |
| | | public CardInfo()
|
| | | {
|
| | | cardId = 0;
|
| | | level = 1;
|
| | | star = 1;
|
| | | quality = 1;
|
| | | }
|
| | | |
| | | public CardInfo(int _cardId, int _level = 1, int _star = 1, int _quality = 1)
|
| | | {
|
| | | cardId = _cardId;
|
| | | level = _level;
|
| | | star = _star;
|
| | | quality = _quality;
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 队伍卡牌信息
|
| | | /// </summary>
|
| | | [Serializable]
|
| | | public class SlotInfo
|
| | | {
|
| | | public CardInfo cardInfo; // 卡牌信息
|
| | | public int teamIndex; // 在队伍中的索引位置
|
| | | |
| | | public SlotInfo()
|
| | | {
|
| | | cardInfo = new CardInfo();
|
| | | teamIndex = -1;
|
| | | }
|
| | | |
| | | public SlotInfo(CardInfo _card, int _teamIndex)
|
| | | {
|
| | | cardInfo = _card;
|
| | | teamIndex = _teamIndex;
|
| | | }
|
| | |
|
| | | public bool IsEmptySlot()
|
| | | {
|
| | | return cardInfo == null || cardInfo.cardId == 0;
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 队伍信息
|
| | | /// </summary>
|
| | | [Serializable]
|
| | | public class TeamInfo
|
| | | {
|
| | | public int teamId; // 队伍ID
|
| | | public FormationType formation; // 阵型类型
|
| | | public List<SlotInfo> teamCards; // 队伍卡牌列表
|
| | | |
| | | public TeamInfo()
|
| | | {
|
| | | teamId = 0;
|
| | | formation = FormationType.Type1;
|
| | | teamCards = new List<SlotInfo>();
|
| | | }
|
| | | |
| | | public TeamInfo(int _teamId, string _teamName, FormationType _formation)
|
| | | {
|
| | | teamId = _teamId;
|
| | | formation = _formation;
|
| | | teamCards = new List<SlotInfo>();
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 添加卡牌到队伍
|
| | | /// </summary>
|
| | | public bool AddCard(CardInfo _card, int _teamIndex, bool _isLeader = false)
|
| | | {
|
| | | // 检查位置是否已被占用
|
| | | foreach (var teamCard in teamCards)
|
| | | {
|
| | | if (teamCard.teamIndex == _teamIndex)
|
| | | {
|
| | | Debug.LogWarning($"队伍位置 {_teamIndex} 已被占用");
|
| | | return false;
|
| | | }
|
| | | }
|
| | | |
| | | SlotInfo newTeamCard = new SlotInfo(_card, _teamIndex);
|
| | | teamCards.Add(newTeamCard);
|
| | | return true;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 移除队伍中的卡牌
|
| | | /// </summary>
|
| | | public bool RemoveCard(int _teamIndex)
|
| | | {
|
| | | for (int i = 0; i < teamCards.Count; i++)
|
| | | {
|
| | | if (teamCards[i].teamIndex == _teamIndex)
|
| | | {
|
| | | teamCards.RemoveAt(i);
|
| | | return true;
|
| | | }
|
| | | }
|
| | | |
| | | Debug.LogWarning($"未找到位置 {_teamIndex} 的卡牌");
|
| | | return false;
|
| | | }
|
| | | |
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 队伍管理器
|
| | | /// </summary>
|
| | | public class TeamManager : GameSystemManager<TeamManager>
|
| | | {
|
| | | // 所有队伍信息
|
| | | private List<TeamInfo> teamInfos = new List<TeamInfo>();
|
| | | |
| | | // 当前选中的队伍索引
|
| | | private int currentTeamIndex = 0;
|
| | | |
| | | // 最大队伍数量
|
| | | private const int MAX_TEAM_COUNT = 5;
|
| | | |
| | | // 每个队伍的最大卡牌数量
|
| | | private const int MAX_CARD_PER_TEAM = 6;
|
| | | |
| | | public override void Init()
|
| | | {
|
| | | base.Init();
|
| | | Debug.Log("TeamManager 初始化");
|
| | | |
| | | // 初始化默认队伍
|
| | | if (teamInfos.Count == 0)
|
| | | {
|
| | | CreateDefaultTeam();
|
| | | }
|
| | | }
|
| | | |
| | | public override void Release()
|
| | | {
|
| | | base.Release();
|
| | | Debug.Log("TeamManager 释放");
|
| | | |
| | | // 清理数据
|
| | | teamInfos.Clear();
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 创建默认队伍
|
| | | /// </summary>
|
| | | private void CreateDefaultTeam()
|
| | | {
|
| | | TeamInfo defaultTeam = new TeamInfo(1, "队伍1", FormationType.Type1);
|
| | | teamInfos.Add(defaultTeam);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取所有队伍信息
|
| | | /// </summary>
|
| | | public List<TeamInfo> GetAllTeams()
|
| | | {
|
| | | return teamInfos;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取指定ID的队伍
|
| | | /// </summary>
|
| | | public TeamInfo GetTeam(int _teamId)
|
| | | {
|
| | | return teamInfos.Find(team => team.teamId == _teamId);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取当前选中的队伍
|
| | | /// </summary>
|
| | | public TeamInfo GetCurrentTeam()
|
| | | {
|
| | | if (currentTeamIndex >= 0 && currentTeamIndex < teamInfos.Count)
|
| | | {
|
| | | return teamInfos[currentTeamIndex];
|
| | | }
|
| | | return null;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 设置当前选中的队伍
|
| | | /// </summary>
|
| | | public bool SetCurrentTeam(int _teamId)
|
| | | {
|
| | | for (int i = 0; i < teamInfos.Count; i++)
|
| | | {
|
| | | if (teamInfos[i].teamId == _teamId)
|
| | | {
|
| | | currentTeamIndex = i;
|
| | | return true;
|
| | | }
|
| | | }
|
| | | return false;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 创建新队伍
|
| | | /// </summary>
|
| | | public TeamInfo CreateTeam(string _teamName, FormationType _formation)
|
| | | {
|
| | | if (teamInfos.Count >= MAX_TEAM_COUNT)
|
| | | {
|
| | | Debug.LogWarning("已达到最大队伍数量限制");
|
| | | return null;
|
| | | }
|
| | | |
| | | // 生成新的队伍ID
|
| | | int newTeamId = 1;
|
| | | if (teamInfos.Count > 0)
|
| | | {
|
| | | newTeamId = teamInfos[teamInfos.Count - 1].teamId + 1;
|
| | | }
|
| | | |
| | | TeamInfo newTeam = new TeamInfo(newTeamId, _teamName, _formation);
|
| | | teamInfos.Add(newTeam);
|
| | | |
| | | return newTeam;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 删除队伍
|
| | | /// </summary>
|
| | | public bool DeleteTeam(int _teamId)
|
| | | {
|
| | | if (teamInfos.Count <= 1)
|
| | | {
|
| | | Debug.LogWarning("至少保留一个队伍");
|
| | | return false;
|
| | | }
|
| | | |
| | | for (int i = 0; i < teamInfos.Count; i++)
|
| | | {
|
| | | if (teamInfos[i].teamId == _teamId)
|
| | | {
|
| | | teamInfos.RemoveAt(i);
|
| | | |
| | | // 如果删除的是当前选中的队伍,则重新设置当前队伍
|
| | | if (currentTeamIndex >= teamInfos.Count)
|
| | | {
|
| | | currentTeamIndex = teamInfos.Count - 1;
|
| | | }
|
| | | |
| | | return true;
|
| | | }
|
| | | }
|
| | | |
| | | return false;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 修改队伍阵型
|
| | | /// </summary>
|
| | | public bool ChangeFormation(int _teamId, FormationType _newFormation)
|
| | | {
|
| | | TeamInfo team = GetTeam(_teamId);
|
| | | if (team != null)
|
| | | {
|
| | | team.formation = _newFormation;
|
| | | return true;
|
| | | }
|
| | | return false;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 向队伍添加卡牌
|
| | | /// </summary>
|
| | | public bool AddCardToTeam(int _teamId, CardInfo _card, int _teamIndex, bool _isLeader = false)
|
| | | {
|
| | | TeamInfo team = GetTeam(_teamId);
|
| | | if (team == null)
|
| | | {
|
| | | Debug.LogWarning($"未找到ID为 {_teamId} 的队伍");
|
| | | return false;
|
| | | }
|
| | | |
| | | if (team.teamCards.Count >= MAX_CARD_PER_TEAM)
|
| | | {
|
| | | Debug.LogWarning("队伍卡牌已达到最大数量");
|
| | | return false;
|
| | | }
|
| | | |
| | | return team.AddCard(_card, _teamIndex, _isLeader);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 从队伍移除卡牌
|
| | | /// </summary>
|
| | | public bool RemoveCardFromTeam(int _teamId, int _teamIndex)
|
| | | {
|
| | | TeamInfo team = GetTeam(_teamId);
|
| | | if (team == null)
|
| | | {
|
| | | Debug.LogWarning($"未找到ID为 {_teamId} 的队伍");
|
| | | return false;
|
| | | }
|
| | | |
| | | return team.RemoveCard(_teamIndex);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 交换队伍中两张卡牌的位置
|
| | | /// </summary>
|
| | | public bool SwapTeamCards(int _teamId, int _fromIndex, int _toIndex)
|
| | | {
|
| | | TeamInfo team = GetTeam(_teamId);
|
| | | if (team == null)
|
| | | {
|
| | | Debug.LogWarning($"未找到ID为 {_teamId} 的队伍");
|
| | | return false;
|
| | | }
|
| | | |
| | | SlotInfo fromCard = null;
|
| | | SlotInfo toCard = null;
|
| | | |
| | | foreach (var card in team.teamCards)
|
| | | {
|
| | | if (card.teamIndex == _fromIndex)
|
| | | {
|
| | | fromCard = card;
|
| | | }
|
| | | else if (card.teamIndex == _toIndex)
|
| | | {
|
| | | toCard = card;
|
| | | }
|
| | | }
|
| | | |
| | | if (fromCard == null)
|
| | | {
|
| | | Debug.LogWarning($"未找到位置 {_fromIndex} 的卡牌");
|
| | | return false;
|
| | | }
|
| | | |
| | | if (toCard == null)
|
| | | {
|
| | | // 如果目标位置没有卡牌,直接移动
|
| | | fromCard.teamIndex = _toIndex;
|
| | | }
|
| | | else
|
| | | {
|
| | | // 交换两张卡牌的位置
|
| | | fromCard.teamIndex = _toIndex;
|
| | | toCard.teamIndex = _fromIndex;
|
| | | }
|
| | | |
| | | return true;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 保存队伍数据
|
| | | /// </summary>
|
| | | public void SaveTeamData()
|
| | | {
|
| | | // 实现队伍数据的保存逻辑
|
| | | // 可以使用 PlayerPrefs、JSON 序列化或其他方式
|
| | | Debug.Log("保存队伍数据");
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 加载队伍数据
|
| | | /// </summary>
|
| | | public void LoadTeamData()
|
| | | {
|
| | | // 实现队伍数据的加载逻辑
|
| | | Debug.Log("加载队伍数据");
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 8ac01de78a793cf4fb759dddc21c0bbe |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | |
|
| | |
|
| | | public interface IManager
|
| | | {
|
| | | void Init();
|
| | | void Release();
|
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 15be84dd6a98de14cb553ac421b17fb9 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | | public class LoginManager : ManagerBase<LoginManager>
|
| | | {
|
| | | public override void Init()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | public override void Release()
|
| | | {
|
| | | |
| | | } |
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 344e28aa3edcfbd4f863a019c2cbaaac |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | |
|
| | | public class ManagerBase<T> : Singleton<T>, IManager where T : ManagerBase<T>, new()
|
| | | {
|
| | | public virtual void Init()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | public virtual void Release()
|
| | | {
|
| | |
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 8c651c6b070b83d48b0f07117ed43058 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System;
|
| | | using Cysharp.Threading.Tasks;
|
| | | using UnityEngine;
|
| | | using UnityEngine.SceneManagement;
|
| | |
|
| | | public enum StageName
|
| | | {
|
| | | Login,
|
| | | Game,
|
| | | }
|
| | |
|
| | | public class StageManager : Singleton<StageManager>, IManager
|
| | | {
|
| | | public StageName currentStage;
|
| | |
|
| | | public void Init()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | public void Release()
|
| | | {
|
| | |
|
| | | }
|
| | |
|
| | | public async UniTaskVoid ToLoginScene()
|
| | | {
|
| | | UIManager.Instance.DestroyAllUI();
|
| | |
|
| | | AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Login");
|
| | |
|
| | | await OnLoading(asyncOperation, () => 1f);
|
| | |
|
| | | Main.OnSwitchToLoginScene();
|
| | |
|
| | | currentStage = StageName.Login;
|
| | |
|
| | | UIManager.Instance.OpenWindow<LoginWin>();
|
| | | }
|
| | |
|
| | | protected float GetManagerRequestDataProgress()
|
| | | {
|
| | | if (Main.managers.Count == 0)
|
| | | {
|
| | | return 1f;
|
| | | }
|
| | |
|
| | | int count = 0;
|
| | |
|
| | | for (int i = 0; i < Main.managers.Count; i++)
|
| | | {
|
| | | var manager = Main.managers[i];
|
| | |
|
| | | if (manager.IsNessaryDataReady())
|
| | | {
|
| | | count++;
|
| | | }
|
| | | }
|
| | |
|
| | | return ((float)count) / ((float)Main.managers.Count);
|
| | | }
|
| | |
|
| | | public async UniTaskVoid ToGameScene()
|
| | | {
|
| | | UIManager.Instance.DestroyAllUI();
|
| | |
|
| | | ResManager.Instance.PrewarmResources();
|
| | |
|
| | | AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Game");
|
| | |
|
| | | await OnLoading(asyncOperation, GetManagerRequestDataProgress);
|
| | |
|
| | | // 加载初始化数据完成
|
| | | currentStage = StageName.Game;
|
| | |
|
| | | UIManager.Instance.OpenWindow<MainWin>();
|
| | | }
|
| | |
|
| | | protected async UniTask OnLoading(AsyncOperation asyncOperation, Func<float> getLoadingProgress, Func<UniTask> anthorTask = null)
|
| | | {
|
| | | asyncOperation.allowSceneActivation = false;
|
| | |
|
| | | LoadingWin loadingWin = UIManager.Instance.OpenWindow<LoadingWin>();
|
| | |
|
| | | while (!asyncOperation.isDone)
|
| | | {
|
| | | if (asyncOperation.progress >= 0.9f)
|
| | | {
|
| | | asyncOperation.allowSceneActivation = true;
|
| | | }
|
| | |
|
| | | loadingWin.SetProgress(asyncOperation.progress * 0.5f + getLoadingProgress() * 0.5f);
|
| | |
|
| | | await UniTask.Yield();
|
| | | }
|
| | |
|
| | | float managerProgress = getLoadingProgress();
|
| | |
|
| | | while (managerProgress < 1f)
|
| | | {
|
| | | loadingWin.SetProgress(asyncOperation.progress * 0.5f + managerProgress * 0.5f);
|
| | |
|
| | | await UniTask.Yield();
|
| | |
|
| | | managerProgress = getLoadingProgress();
|
| | | }
|
| | |
|
| | | if (anthorTask != null)
|
| | | {
|
| | | await anthorTask();
|
| | | }
|
| | |
|
| | | loadingWin.SetProgress(1f, true);
|
| | |
|
| | | await UniTask.Delay(TimeSpan.FromSeconds(0.5f));
|
| | |
|
| | | loadingWin.CloseWindow();
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: aac79594075c0524080fb21a459c7264 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 1244e95cb51b1cb42a8adaba3a5dff53 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | | /// <summary>
|
| | | /// 单位数据
|
| | | /// </summary>
|
| | | public class UnitData
|
| | | {
|
| | | public int ID { get; set; }
|
| | | public string Name { get; set; }
|
| | | public int HP { get; set; }
|
| | | public int Attack { get; set; }
|
| | | public float AttackSpeed { get; set; }
|
| | | public float MoveSpeed { get; set; }
|
| | | public string PrefabPath { get; set; }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 章节数据
|
| | | /// </summary>
|
| | | public class ChapterData
|
| | | {
|
| | | public int ID { get; set; }
|
| | | public string Name { get; set; }
|
| | | public int MapId { get; set; }
|
| | | public List<WaveData> Waves { get; set; }
|
| | | |
| | | /// <summary>
|
| | | /// 获取指定波次的敌人列表
|
| | | /// </summary>
|
| | | public List<int> GetEnemiesForWave(int wave)
|
| | | {
|
| | | if (wave <= 0 || wave > Waves.Count)
|
| | | return new List<int>();
|
| | | |
| | | return Waves[wave - 1].EnemyIds;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取指定波次的掉落物品
|
| | | /// </summary>
|
| | | public List<DropItemData> GetDropsForWave(int wave)
|
| | | {
|
| | | if (wave <= 0 || wave > Waves.Count)
|
| | | return new List<DropItemData>();
|
| | | |
| | | return Waves[wave - 1].DropItems;
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 波次数据
|
| | | /// </summary>
|
| | | public class WaveData
|
| | | {
|
| | | public int WaveIndex { get; set; }
|
| | | public List<int> EnemyIds { get; set; }
|
| | | public List<DropItemData> DropItems { get; set; }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 物品类型
|
| | | /// </summary>
|
| | | public enum ItemType
|
| | | {
|
| | | Gold,
|
| | | Diamond,
|
| | | Item
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 掉落物品数据
|
| | | /// </summary>
|
| | | public class DropItemData
|
| | | {
|
| | | public int ID { get; set; }
|
| | | public ItemType ItemType { get; set; }
|
| | | public int ItemId { get; set; }
|
| | | public int Amount { get; set; }
|
| | | public float DropRate { get; set; }
|
| | | public string IconPath { get; set; }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 4541140280fac3541b7ec64b9acd2f20 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | | /// <summary>
|
| | | /// 放置战斗掉落物品类
|
| | | /// </summary>
|
| | | public class PlaceDrop
|
| | | {
|
| | | // 掉落物品数据
|
| | | public DropItemData DropData { get; private set; }
|
| | | |
| | | // 位置
|
| | | public Vector2 Position { get; private set; }
|
| | | |
| | | // 状态
|
| | | private enum DropState
|
| | | {
|
| | | Dropping, // 掉落中
|
| | | Waiting, // 等待收集
|
| | | Flying // 飞向UI
|
| | | }
|
| | | |
| | | private DropState currentState = DropState.Dropping;
|
| | | |
| | | // 计时器
|
| | | private float waitTimer = 0f;
|
| | | private float waitDuration = 1.5f; // 等待1.5秒后自动收集
|
| | | |
| | | // 飞行相关
|
| | | private Vector2 targetPosition;
|
| | | private float flySpeed = 10f;
|
| | | |
| | | // 是否应该被收集
|
| | | public bool ShouldCollect { get; private set; } = false;
|
| | | |
| | | // 掉落动画计时器
|
| | | private float dropAnimTimer = 0f;
|
| | | private float dropAnimDuration = 0.5f;
|
| | | private Vector2 startPosition;
|
| | | private Vector2 endPosition;
|
| | | |
| | | /// <summary>
|
| | | /// 构造函数
|
| | | /// </summary>
|
| | | public PlaceDrop(DropItemData dropData)
|
| | | {
|
| | | DropData = dropData;
|
| | | |
| | | // 随机掉落位置(在场景中心附近)
|
| | | startPosition = new Vector2(Random.Range(-2f, 2f), 5f);
|
| | | endPosition = new Vector2(
|
| | | startPosition.x + Random.Range(-1f, 1f),
|
| | | Random.Range(-1f, 1f)
|
| | | );
|
| | | |
| | | Position = startPosition;
|
| | | |
| | | // 设置飞向的目标位置(UI上的货币栏位置)
|
| | | targetPosition = new Vector2(8f, 4f); // 示例位置,实际应该是UI中货币栏的世界坐标
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新掉落物品状态
|
| | | /// </summary>
|
| | | public void Update(float deltaTime)
|
| | | {
|
| | | switch (currentState)
|
| | | {
|
| | | case DropState.Dropping:
|
| | | UpdateDropping(deltaTime);
|
| | | break;
|
| | | |
| | | case DropState.Waiting:
|
| | | UpdateWaiting(deltaTime);
|
| | | break;
|
| | | |
| | | case DropState.Flying:
|
| | | UpdateFlying(deltaTime);
|
| | | break;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新掉落动画
|
| | | /// </summary>
|
| | | private void UpdateDropping(float deltaTime)
|
| | | {
|
| | | dropAnimTimer += deltaTime;
|
| | | float t = Mathf.Clamp01(dropAnimTimer / dropAnimDuration);
|
| | | |
| | | // 使用二次贝塞尔曲线模拟掉落效果
|
| | | Position = Vector2.Lerp(startPosition, endPosition, t);
|
| | | |
| | | // 掉落动画完成后切换到等待状态
|
| | | if (t >= 1.0f)
|
| | | {
|
| | | currentState = DropState.Waiting;
|
| | | waitTimer = 0f;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新等待状态
|
| | | /// </summary>
|
| | | private void UpdateWaiting(float deltaTime)
|
| | | {
|
| | | // 等待一段时间后自动收集
|
| | | waitTimer += deltaTime;
|
| | | if (waitTimer >= waitDuration)
|
| | | {
|
| | | currentState = DropState.Flying;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新飞行状态
|
| | | /// </summary>
|
| | | private void UpdateFlying(float deltaTime)
|
| | | {
|
| | | // 计算飞行方向
|
| | | Vector2 direction = (targetPosition - Position).normalized;
|
| | | |
| | | // 更新位置
|
| | | Position += direction * flySpeed * deltaTime;
|
| | | |
| | | // 检查是否到达目标
|
| | | float distanceToTarget = Vector2.Distance(Position, targetPosition);
|
| | | if (distanceToTarget < 0.1f)
|
| | | {
|
| | | // 到达目标,标记为应该被收集
|
| | | ShouldCollect = true;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 手动收集物品
|
| | | /// </summary>
|
| | | public void Collect()
|
| | | {
|
| | | currentState = DropState.Flying;
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 070f25c487448bb44ac2134e1290d5f0 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | | using System;
|
| | |
|
| | | /// <summary>
|
| | | /// 放置战斗场地类,管理战斗场景中的所有元素
|
| | | /// </summary>
|
| | | public class PlaceField
|
| | | {
|
| | |
|
| | | // 当前章节信息
|
| | | private ChapterData currentChapter;
|
| | | |
| | | // 场景中的所有单位
|
| | | private List<PlaceUnit> allUnits = new List<PlaceUnit>();
|
| | | |
| | | // 玩家单位列表
|
| | | private List<PlaceUnit> playerUnits = new List<PlaceUnit>();
|
| | | |
| | | // 敌人单位列表
|
| | | private List<PlaceUnit> enemyUnits = new List<PlaceUnit>();
|
| | | |
| | | // 场景中的掉落物品
|
| | | private List<PlaceDrop> dropItems = new List<PlaceDrop>();
|
| | | |
| | | // 战斗状态
|
| | | public enum BattleState
|
| | | {
|
| | | Preparing, // 准备中
|
| | | Fighting, // 战斗中
|
| | | Completed, // 战斗完成
|
| | | Waiting // 等待下一场
|
| | | }
|
| | | |
| | | public BattleState CurrentState { get; private set; } = BattleState.Preparing;
|
| | | |
| | | // 战斗完成事件
|
| | | public event Action OnBattleCompleted;
|
| | | |
| | | // 掉落物品收集事件
|
| | | public event Action<DropItemData> OnItemCollected;
|
| | | |
| | | // 等待计时器
|
| | | private float waitTimer = 0f;
|
| | | private const float WAIT_DURATION = 2f; // 战斗结束后等待2秒
|
| | | |
| | | /// <summary>
|
| | | /// 初始化战斗场景
|
| | | /// </summary>
|
| | | /// <param name="chapterId">章节ID</param>
|
| | | public void InitBattleField(int chapterId)
|
| | | {
|
| | | Debug.Log($"初始化战斗场地: 章节{chapterId}");
|
| | | |
| | | // 清空场景
|
| | | ClearField();
|
| | | |
| | | // 加载章节数据
|
| | | LoadChapterData(chapterId);
|
| | | |
| | | // 加载地图背景
|
| | | LoadMapBackground();
|
| | | |
| | | // 生成玩家阵容
|
| | | SpawnPlayerUnits();
|
| | | |
| | | // 生成敌方单位
|
| | | SpawnEnemyUnits();
|
| | | |
| | | // 设置战斗状态为准备中
|
| | | CurrentState = BattleState.Preparing;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 开始战斗
|
| | | /// </summary>
|
| | | public void StartBattle()
|
| | | {
|
| | | if (CurrentState != BattleState.Preparing && CurrentState != BattleState.Waiting)
|
| | | return;
|
| | | |
| | | Debug.Log("开始战斗");
|
| | | CurrentState = BattleState.Fighting;
|
| | | |
| | | // 通知所有单位开始战斗
|
| | | foreach (var unit in allUnits)
|
| | | {
|
| | | unit.StartBattle();
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新战场状态
|
| | | /// </summary>
|
| | | public void UpdateField(float deltaTime)
|
| | | {
|
| | | switch (CurrentState)
|
| | | {
|
| | | case BattleState.Fighting:
|
| | | UpdateFighting(deltaTime);
|
| | | break;
|
| | | |
| | | case BattleState.Completed:
|
| | | UpdateCompleted(deltaTime);
|
| | | break;
|
| | | |
| | | case BattleState.Waiting:
|
| | | UpdateWaiting(deltaTime);
|
| | | break;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新战斗状态
|
| | | /// </summary>
|
| | | private void UpdateFighting(float deltaTime)
|
| | | {
|
| | | // 更新所有单位
|
| | | for (int i = allUnits.Count - 1; i >= 0; i--)
|
| | | {
|
| | | if (i < allUnits.Count)
|
| | | {
|
| | | allUnits[i].UpdateUnit(deltaTime);
|
| | | }
|
| | | }
|
| | | |
| | | // 检查战斗是否结束
|
| | | CheckBattleEnd();
|
| | | |
| | | // 更新掉落物品
|
| | | UpdateDropItems(deltaTime);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新战斗完成状态
|
| | | /// </summary>
|
| | | private void UpdateCompleted(float deltaTime)
|
| | | {
|
| | | // 更新掉落物品
|
| | | UpdateDropItems(deltaTime);
|
| | | |
| | | // 检查是否所有掉落物品都已收集
|
| | | bool allItemsCollected = true;
|
| | | foreach (var item in dropItems)
|
| | | {
|
| | | if (!item.ShouldCollect)
|
| | | {
|
| | | allItemsCollected = false;
|
| | | break;
|
| | | }
|
| | | }
|
| | | |
| | | // 如果所有物品都已收集,进入等待状态
|
| | | if (allItemsCollected && dropItems.Count > 0)
|
| | | {
|
| | | CurrentState = BattleState.Waiting;
|
| | | waitTimer = 0f;
|
| | | }
|
| | | // 如果没有掉落物品,直接进入等待状态
|
| | | else if (dropItems.Count == 0)
|
| | | {
|
| | | CurrentState = BattleState.Waiting;
|
| | | waitTimer = 0f;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新等待状态
|
| | | /// </summary>
|
| | | private void UpdateWaiting(float deltaTime)
|
| | | {
|
| | | waitTimer += deltaTime;
|
| | | |
| | | // 等待时间结束后,开始下一场战斗
|
| | | if (waitTimer >= WAIT_DURATION)
|
| | | {
|
| | | // 清理战场
|
| | | ClearField();
|
| | | |
| | | // 重新初始化战场
|
| | | InitBattleField(currentChapter.ID);
|
| | | |
| | | // 开始新的战斗
|
| | | StartBattle();
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 加载章节数据
|
| | | /// </summary>
|
| | | private void LoadChapterData(int chapterId)
|
| | | {
|
| | | // 从配置管理器加载章节数据
|
| | | // currentChapter = ConfigManager.Instance.GetChapterData(chapterId);
|
| | | |
| | | // 临时代码,创建一个测试章节
|
| | | currentChapter = new ChapterData
|
| | | {
|
| | | ID = chapterId,
|
| | | Name = $"测试章节 {chapterId}",
|
| | | MapId = chapterId
|
| | | };
|
| | | |
| | | Debug.Log($"加载章节数据: {currentChapter.Name}");
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 加载地图背景
|
| | | /// </summary>
|
| | | private void LoadMapBackground()
|
| | | {
|
| | | // 根据章节数据加载对应的地图背景
|
| | | // MapManager.Instance.LoadMap(currentChapter.MapId);
|
| | | Debug.Log($"加载地图背景: MapID={currentChapter.MapId}");
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 生成玩家阵容
|
| | | /// </summary>
|
| | | private void SpawnPlayerUnits()
|
| | | {
|
| | | Debug.Log("生成玩家阵容");
|
| | | |
| | | // 从玩家数据中获取当前阵容
|
| | | // var formation = PlayerManager.Instance.CurrentFormation;
|
| | | |
| | | // 临时代码,创建测试玩家单位
|
| | | for (int i = 0; i < 3; i++)
|
| | | {
|
| | | UnitData unitData = new UnitData
|
| | | {
|
| | | ID = 1000 + i,
|
| | | Name = $"玩家角色 {i+1}",
|
| | | HP = 100,
|
| | | Attack = 10,
|
| | | AttackSpeed = 1.0f,
|
| | | MoveSpeed = 2.0f,
|
| | | PrefabPath = $"Characters/Player_{i+1}"
|
| | | };
|
| | | |
| | | PlaceUnit unit = new PlaceUnit(unitData, true);
|
| | | playerUnits.Add(unit);
|
| | | allUnits.Add(unit);
|
| | | |
| | | Debug.Log($"生成玩家单位: {unit.UnitData.Name}");
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 生成敌方单位
|
| | | /// </summary>
|
| | | private void SpawnEnemyUnits()
|
| | | {
|
| | | Debug.Log("生成敌方单位");
|
| | | |
| | | // 根据章节数据生成敌方单位
|
| | | // var enemyIds = currentChapter.GetEnemiesForWave(1);
|
| | | |
| | | // 临时代码,创建测试敌方单位
|
| | | for (int i = 0; i < 5; i++)
|
| | | {
|
| | | UnitData unitData = new UnitData
|
| | | {
|
| | | ID = 2000 + i,
|
| | | Name = $"敌方单位 {i+1}",
|
| | | HP = 50,
|
| | | Attack = 5,
|
| | | AttackSpeed = 0.8f,
|
| | | MoveSpeed = 1.5f,
|
| | | PrefabPath = $"Characters/Enemy_{i+1}"
|
| | | };
|
| | | |
| | | PlaceUnit unit = new PlaceUnit(unitData, false);
|
| | | enemyUnits.Add(unit);
|
| | | allUnits.Add(unit);
|
| | | |
| | | Debug.Log($"生成敌方单位: {unit.UnitData.Name}");
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 检查战斗是否结束
|
| | | /// </summary>
|
| | | private void CheckBattleEnd()
|
| | | {
|
| | | // 检查敌方单位是否全部阵亡
|
| | | bool allEnemyDead = true;
|
| | | foreach (var unit in enemyUnits)
|
| | | {
|
| | | if (!unit.IsDead)
|
| | | {
|
| | | allEnemyDead = false;
|
| | | break;
|
| | | }
|
| | | }
|
| | | |
| | | // 如果所有敌人都已阵亡,战斗结束
|
| | | if (allEnemyDead)
|
| | | {
|
| | | CompleteBattle();
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 完成战斗
|
| | | /// </summary>
|
| | | private void CompleteBattle()
|
| | | {
|
| | | Debug.Log("战斗完成");
|
| | | CurrentState = BattleState.Completed;
|
| | | |
| | | // 停止所有单位行动
|
| | | foreach (var unit in allUnits)
|
| | | {
|
| | | unit.StopBattle();
|
| | | }
|
| | | |
| | | // 生成掉落物品
|
| | | GenerateDropItems();
|
| | | |
| | | // 触发战斗完成事件
|
| | | OnBattleCompleted?.Invoke();
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 生成掉落物品
|
| | | /// </summary>
|
| | | private void GenerateDropItems()
|
| | | {
|
| | | Debug.Log("生成掉落物品");
|
| | | |
| | | // 根据章节掉落表生成掉落物品
|
| | | // var dropList = currentChapter.GetDropsForWave(1);
|
| | | |
| | | // 临时代码,创建测试掉落物品
|
| | | for (int i = 0; i < 5; i++)
|
| | | {
|
| | | DropItemData dropData = new DropItemData
|
| | | {
|
| | | ID = i,
|
| | | ItemType = (i % 3 == 0) ? ItemType.Gold : (i % 3 == 1) ? ItemType.Diamond : ItemType.Item,
|
| | | ItemId = i,
|
| | | Amount = UnityEngine.Random.Range(10, 100),
|
| | | DropRate = 1.0f,
|
| | | IconPath = $"Icons/Item_{i}"
|
| | | };
|
| | | |
| | | // 创建掉落物品
|
| | | PlaceDrop drop = new PlaceDrop(dropData);
|
| | | dropItems.Add(drop);
|
| | | |
| | | Debug.Log($"生成掉落物品: 类型={dropData.ItemType}, 数量={dropData.Amount}");
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新掉落物品
|
| | | /// </summary>
|
| | | private void UpdateDropItems(float deltaTime)
|
| | | {
|
| | | for (int i = dropItems.Count - 1; i >= 0; i--)
|
| | | {
|
| | | dropItems[i].Update(deltaTime);
|
| | | |
| | | // 检查是否需要收集物品
|
| | | if (dropItems[i].ShouldCollect)
|
| | | {
|
| | | // 触发物品收集事件
|
| | | OnItemCollected?.Invoke(dropItems[i].DropData);
|
| | | |
| | | // 移除物品
|
| | | dropItems.RemoveAt(i);
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 清空战场
|
| | | /// </summary>
|
| | | public void ClearField()
|
| | | {
|
| | | Debug.Log("清空战场");
|
| | | allUnits.Clear();
|
| | | playerUnits.Clear();
|
| | | enemyUnits.Clear();
|
| | | dropItems.Clear();
|
| | | CurrentState = BattleState.Preparing;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取玩家单位列表
|
| | | /// </summary>
|
| | | public List<PlaceUnit> GetPlayerUnits()
|
| | | {
|
| | | return new List<PlaceUnit>(playerUnits);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取敌方单位列表
|
| | | /// </summary>
|
| | | public List<PlaceUnit> GetEnemyUnits()
|
| | | {
|
| | | return new List<PlaceUnit>(enemyUnits);
|
| | | }
|
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: b82dee68a4dcad54780acf1dad335d8c |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | | /// <summary>
|
| | | /// 放置战斗单位类,代表战场上的一个角色
|
| | | /// </summary>
|
| | | public class PlaceUnit
|
| | | {
|
| | | // 单位数据
|
| | | public UnitData UnitData { get; private set; }
|
| | | |
| | | // 单位属性
|
| | | public int HP { get; private set; }
|
| | | public int MaxHP { get; private set; }
|
| | | public int Attack { get; private set; }
|
| | | public float AttackSpeed { get; private set; }
|
| | | public float MoveSpeed { get; private set; }
|
| | | |
| | | // 单位状态
|
| | | public bool IsPlayer { get; private set; }
|
| | | public bool IsDead { get; private set; }
|
| | | |
| | | // 位置和朝向
|
| | | public Vector2 Position { get; private set; }
|
| | | public Vector2 Direction { get; private set; }
|
| | | |
| | | // 战斗相关
|
| | | private PlaceUnit targetUnit;
|
| | | private float attackCooldown;
|
| | | |
| | | // 单位行为状态
|
| | | public enum UnitState
|
| | | {
|
| | | Idle, // 待机
|
| | | Moving, // 移动中
|
| | | Attacking, // 攻击中
|
| | | Dead // 死亡
|
| | | }
|
| | | |
| | | public UnitState CurrentState { get; private set; } = UnitState.Idle;
|
| | | |
| | | /// <summary>
|
| | | /// 构造函数
|
| | | /// </summary>
|
| | | /// <param name="data">单位数据</param>
|
| | | /// <param name="isPlayer">是否为玩家单位</param>
|
| | | public PlaceUnit(UnitData data, bool isPlayer)
|
| | | {
|
| | | UnitData = data;
|
| | | IsPlayer = isPlayer;
|
| | | |
| | | // 初始化属性
|
| | | MaxHP = data.HP;
|
| | | HP = MaxHP;
|
| | | Attack = data.Attack;
|
| | | AttackSpeed = data.AttackSpeed;
|
| | | MoveSpeed = data.MoveSpeed;
|
| | | |
| | | // 初始化攻击冷却
|
| | | attackCooldown = Random.Range(0f, 1f / AttackSpeed);
|
| | | |
| | | // 设置初始位置
|
| | | Position = isPlayer ? new Vector2(-5f + Random.Range(-1f, 1f), Random.Range(-2f, 2f)) : |
| | | new Vector2(5f + Random.Range(-1f, 1f), Random.Range(-2f, 2f));
|
| | | Direction = isPlayer ? Vector2.right : Vector2.left;
|
| | | |
| | | IsDead = false;
|
| | | CurrentState = UnitState.Idle;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 开始战斗
|
| | | /// </summary>
|
| | | public void StartBattle()
|
| | | {
|
| | | if (IsDead) return;
|
| | | |
| | | CurrentState = UnitState.Idle;
|
| | | FindTarget();
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 停止战斗
|
| | | /// </summary>
|
| | | public void StopBattle()
|
| | | {
|
| | | if (IsDead) return;
|
| | | |
| | | CurrentState = UnitState.Idle;
|
| | | targetUnit = null;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新单位状态
|
| | | /// </summary>
|
| | | public void UpdateUnit(float deltaTime)
|
| | | {
|
| | | if (IsDead) return;
|
| | | |
| | | // 如果没有目标,尝试寻找目标
|
| | | if (targetUnit == null || targetUnit.IsDead)
|
| | | {
|
| | | FindTarget();
|
| | | if (targetUnit == null)
|
| | | {
|
| | | CurrentState = UnitState.Idle;
|
| | | return;
|
| | | }
|
| | | }
|
| | | |
| | | // 根据与目标的距离决定行为
|
| | | float distanceToTarget = Vector2.Distance(Position, targetUnit.Position);
|
| | | float attackRange = 1.5f; // 攻击范围
|
| | | |
| | | if (distanceToTarget <= attackRange)
|
| | | {
|
| | | // 在攻击范围内,执行攻击
|
| | | AttackTarget(deltaTime);
|
| | | }
|
| | | else
|
| | | {
|
| | | // 不在攻击范围内,移动接近目标
|
| | | MoveToTarget(deltaTime);
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 寻找目标
|
| | | /// </summary>
|
| | | private void FindTarget()
|
| | | {
|
| | | // 从场景中寻找敌对单位作为目标
|
| | | List<PlaceUnit> potentialTargets = IsPlayer ? |
| | | PlaceManager.Instance.placeField.GetEnemyUnits() : |
| | | PlaceManager.Instance.placeField.GetPlayerUnits();
|
| | | |
| | | float minDistance = float.MaxValue;
|
| | | PlaceUnit nearestTarget = null;
|
| | | |
| | | foreach (var unit in potentialTargets)
|
| | | {
|
| | | if (!unit.IsDead)
|
| | | {
|
| | | float distance = Vector2.Distance(Position, unit.Position);
|
| | | if (distance < minDistance)
|
| | | {
|
| | | minDistance = distance;
|
| | | nearestTarget = unit;
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | targetUnit = nearestTarget;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 移动向目标
|
| | | /// </summary>
|
| | | private void MoveToTarget(float deltaTime)
|
| | | {
|
| | | CurrentState = UnitState.Moving;
|
| | | |
| | | // 计算移动方向
|
| | | Vector2 moveDirection = (targetUnit.Position - Position).normalized;
|
| | | |
| | | // 检查是否有障碍物,如果有则需要寻路
|
| | | if (HasObstacle(Position, targetUnit.Position))
|
| | | {
|
| | | // 简单的寻路逻辑
|
| | | moveDirection = FindPathDirection(targetUnit.Position);
|
| | | }
|
| | | |
| | | // 检查是否与其他单位重叠
|
| | | Vector2 avoidanceDirection = Vector2.zero;
|
| | | int avoidanceCount = 0;
|
| | | |
| | | // 获取所有单位
|
| | | List<PlaceUnit> allUnits = new List<PlaceUnit>();
|
| | | allUnits.AddRange(PlaceManager.Instance.placeField.GetPlayerUnits());
|
| | | allUnits.AddRange(PlaceManager.Instance.placeField.GetEnemyUnits());
|
| | | |
| | | // 检查附近的单位
|
| | | foreach (var unit in allUnits)
|
| | | {
|
| | | if (unit != this && !unit.IsDead)
|
| | | {
|
| | | float distance = Vector2.Distance(Position, unit.Position);
|
| | | if (distance < 1.0f) // 避让距离
|
| | | {
|
| | | // 计算避让方向
|
| | | Vector2 dir = (Position - unit.Position).normalized;
|
| | | avoidanceDirection += dir;
|
| | | avoidanceCount++;
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | // 如果有需要避让的单位,调整移动方向
|
| | | if (avoidanceCount > 0)
|
| | | {
|
| | | avoidanceDirection /= avoidanceCount;
|
| | | moveDirection = Vector2.Lerp(moveDirection, avoidanceDirection, 0.5f).normalized;
|
| | | }
|
| | | |
| | | // 更新位置
|
| | | Position += moveDirection * MoveSpeed * deltaTime;
|
| | | |
| | | // 更新朝向
|
| | | Direction = moveDirection;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 检查是否有障碍物
|
| | | /// </summary>
|
| | | private bool HasObstacle(Vector2 start, Vector2 end)
|
| | | {
|
| | | // 简单的障碍物检测,实际项目中可能需要更复杂的碰撞检测
|
| | | // 这里可以使用Physics2D.Raycast来检测
|
| | | |
| | | // 示例代码
|
| | | // RaycastHit2D hit = Physics2D.Raycast(start, end - start, Vector2.Distance(start, end), obstacleLayer);
|
| | | // return hit.collider != null;
|
| | | |
| | | // 临时代码,随机生成障碍物
|
| | | return Random.value < 0.1f;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 寻找路径方向
|
| | | /// </summary>
|
| | | private Vector2 FindPathDirection(Vector2 target)
|
| | | {
|
| | | // 使用A*寻路算法
|
| | | List<Node> path = AStar(Position, target);
|
| | | |
| | | if (path != null && path.Count > 0)
|
| | | {
|
| | | // 获取下一个节点的方向
|
| | | Vector2 nextNodePos = path[0].position;
|
| | | return (nextNodePos - Position).normalized;
|
| | | }
|
| | | |
| | | // 如果寻路失败,直接返回目标方向
|
| | | return (target - Position).normalized;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// A*寻路算法
|
| | | /// </summary>
|
| | | private List<Node> AStar(Vector2 start, Vector2 goal)
|
| | | {
|
| | | // 网格大小设置
|
| | | float gridSize = 0.5f;
|
| | | int gridWidth = 20;
|
| | | int gridHeight = 10;
|
| | | |
| | | // 创建开放列表和关闭列表
|
| | | List<Node> openList = new List<Node>();
|
| | | List<Node> closedList = new List<Node>();
|
| | | |
| | | // 创建起点和终点节点
|
| | | Node startNode = new Node(start, null);
|
| | | Node goalNode = new Node(goal, null);
|
| | | |
| | | // 计算起点的f、g、h值
|
| | | startNode.g = 0;
|
| | | startNode.h = CalculateHeuristic(startNode, goalNode);
|
| | | startNode.f = startNode.g + startNode.h;
|
| | | |
| | | // 将起点加入开放列表
|
| | | openList.Add(startNode);
|
| | | |
| | | // 开始A*算法主循环
|
| | | while (openList.Count > 0)
|
| | | {
|
| | | // 找到开放列表中f值最小的节点
|
| | | Node currentNode = FindNodeWithLowestF(openList);
|
| | | |
| | | // 如果当前节点是目标节点,则构建路径并返回
|
| | | if (Vector2.Distance(currentNode.position, goalNode.position) < gridSize)
|
| | | {
|
| | | return BuildPath(currentNode);
|
| | | }
|
| | | |
| | | // 将当前节点从开放列表移除,加入关闭列表
|
| | | openList.Remove(currentNode);
|
| | | closedList.Add(currentNode);
|
| | | |
| | | // 获取当前节点的相邻节点
|
| | | List<Node> neighbors = GetNeighbors(currentNode, gridSize, gridWidth, gridHeight);
|
| | | |
| | | foreach (Node neighbor in neighbors)
|
| | | {
|
| | | // 如果相邻节点在关闭列表中,则跳过
|
| | | if (IsNodeInList(neighbor, closedList))
|
| | | {
|
| | | continue;
|
| | | }
|
| | | |
| | | // 如果相邻节点位置有障碍物,则跳过
|
| | | if (HasObstacle(currentNode.position, neighbor.position))
|
| | | {
|
| | | continue;
|
| | | }
|
| | | |
| | | // 计算从起点经过当前节点到相邻节点的代价
|
| | | float tentativeG = currentNode.g + Vector2.Distance(currentNode.position, neighbor.position);
|
| | | |
| | | // 如果相邻节点不在开放列表中,或者新路径更优,则更新相邻节点
|
| | | if (!IsNodeInList(neighbor, openList) || tentativeG < neighbor.g)
|
| | | {
|
| | | neighbor.parent = currentNode;
|
| | | neighbor.g = tentativeG;
|
| | | neighbor.h = CalculateHeuristic(neighbor, goalNode);
|
| | | neighbor.f = neighbor.g + neighbor.h;
|
| | | |
| | | // 如果相邻节点不在开放列表中,则加入开放列表
|
| | | if (!IsNodeInList(neighbor, openList))
|
| | | {
|
| | | openList.Add(neighbor);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | // 如果开放列表为空,则寻路失败,返回null
|
| | | return null;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 计算启发式函数值(曼哈顿距离)
|
| | | /// </summary>
|
| | | private float CalculateHeuristic(Node node, Node goal)
|
| | | {
|
| | | // 使用曼哈顿距离作为启发式函数
|
| | | return Mathf.Abs(node.position.x - goal.position.x) + Mathf.Abs(node.position.y - goal.position.y);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 查找开放列表中f值最小的节点
|
| | | /// </summary>
|
| | | private Node FindNodeWithLowestF(List<Node> list)
|
| | | {
|
| | | Node lowestNode = list[0];
|
| | | |
| | | for (int i = 1; i < list.Count; i++)
|
| | | {
|
| | | if (list[i].f < lowestNode.f)
|
| | | {
|
| | | lowestNode = list[i];
|
| | | }
|
| | | }
|
| | | |
| | | return lowestNode;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 获取节点的相邻节点
|
| | | /// </summary>
|
| | | private List<Node> GetNeighbors(Node node, float gridSize, int gridWidth, int gridHeight)
|
| | | {
|
| | | List<Node> neighbors = new List<Node>();
|
| | | |
| | | // 8个方向的相邻节点
|
| | | Vector2[] directions = new Vector2[]
|
| | | {
|
| | | new Vector2(1, 0), // 右
|
| | | new Vector2(-1, 0), // 左
|
| | | new Vector2(0, 1), // 上
|
| | | new Vector2(0, -1), // 下
|
| | | new Vector2(1, 1), // 右上
|
| | | new Vector2(1, -1), // 右下
|
| | | new Vector2(-1, 1), // 左上
|
| | | new Vector2(-1, -1) // 左下
|
| | | };
|
| | | |
| | | foreach (Vector2 dir in directions)
|
| | | {
|
| | | Vector2 neighborPos = node.position + dir * gridSize;
|
| | | |
| | | // 检查是否在网格范围内
|
| | | if (neighborPos.x >= -gridWidth/2 && neighborPos.x <= gridWidth/2 &&
|
| | | neighborPos.y >= -gridHeight/2 && neighborPos.y <= gridHeight/2)
|
| | | {
|
| | | Node neighbor = new Node(neighborPos, node);
|
| | | neighbors.Add(neighbor);
|
| | | }
|
| | | }
|
| | | |
| | | return neighbors;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 检查节点是否在列表中
|
| | | /// </summary>
|
| | | private bool IsNodeInList(Node node, List<Node> list)
|
| | | {
|
| | | foreach (Node n in list)
|
| | | {
|
| | | if (Vector2.Distance(n.position, node.position) < 0.1f)
|
| | | {
|
| | | return true;
|
| | | }
|
| | | }
|
| | | |
| | | return false;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 构建从起点到当前节点的路径
|
| | | /// </summary>
|
| | | private List<Node> BuildPath(Node node)
|
| | | {
|
| | | List<Node> path = new List<Node>();
|
| | | Node currentNode = node;
|
| | | |
| | | // 从目标节点回溯到起点
|
| | | while (currentNode.parent != null)
|
| | | {
|
| | | path.Insert(0, currentNode);
|
| | | currentNode = currentNode.parent;
|
| | | }
|
| | | |
| | | return path;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// A*寻路的节点类
|
| | | /// </summary>
|
| | | private class Node
|
| | | {
|
| | | public Vector2 position; // 节点位置
|
| | | public Node parent; // 父节点
|
| | | public float g; // 从起点到当前节点的代价
|
| | | public float h; // 从当前节点到目标节点的估计代价
|
| | | public float f; // f = g + h,总代价
|
| | | |
| | | public Node(Vector2 pos, Node parent)
|
| | | {
|
| | | this.position = pos;
|
| | | this.parent = parent;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 攻击目标
|
| | | /// </summary>
|
| | | private void AttackTarget(float deltaTime)
|
| | | {
|
| | | CurrentState = UnitState.Attacking;
|
| | | |
| | | // 攻击冷却
|
| | | attackCooldown -= deltaTime;
|
| | | if (attackCooldown <= 0)
|
| | | {
|
| | | // 执行攻击
|
| | | PerformAttack();
|
| | | |
| | | // 重置冷却
|
| | | attackCooldown = 1f / AttackSpeed;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 执行攻击
|
| | | /// </summary>
|
| | | private void PerformAttack()
|
| | | {
|
| | | if (targetUnit != null && !targetUnit.IsDead)
|
| | | {
|
| | | // 造成伤害
|
| | | targetUnit.TakeDamage(Attack);
|
| | | |
| | | // 播放攻击动画/特效
|
| | | Debug.Log($"{UnitData.Name} 攻击 {targetUnit.UnitData.Name}, 造成 {Attack} 点伤害");
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 受到伤害
|
| | | /// </summary>
|
| | | public void TakeDamage(int damage)
|
| | | {
|
| | | if (IsDead) return;
|
| | | |
| | | // 计算实际伤害(考虑防御等因素)
|
| | | int defense = Mathf.Max(0, MaxHP / 20); // 简单防御计算,基于最大生命值
|
| | | int actualDamage = Mathf.Max(1, damage - defense); // 确保至少造成1点伤害
|
| | | |
| | | // 扣除生命值
|
| | | HP -= actualDamage;
|
| | | |
| | | // 检查是否死亡
|
| | | if (HP <= 0)
|
| | | {
|
| | | HP = 0;
|
| | | Die();
|
| | | }
|
| | | |
| | | // 显示伤害数字
|
| | | Debug.Log($"{UnitData.Name} 受到 {actualDamage} 点伤害, 剩余HP: {HP}/{MaxHP}");
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 死亡处理
|
| | | /// </summary>
|
| | | private void Die()
|
| | | {
|
| | | IsDead = true;
|
| | | CurrentState = UnitState.Dead;
|
| | | |
| | | // 播放死亡动画
|
| | | Debug.Log($"{UnitData.Name} 死亡");
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 84bf5729662617b4582cbe05bad8d53c |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System;
|
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | | using UnityEngine.UI;
|
| | |
|
| | | public class LoadingWin : UIBase
|
| | | {
|
| | | protected int currentProgress = 0;
|
| | | protected int targetProgress = 0;
|
| | |
|
| | | protected Text titleText;
|
| | | protected Text tipsText;
|
| | | protected Image progressBar;
|
| | | protected Text progressText;
|
| | |
|
| | | protected override void InitComponent()
|
| | | {
|
| | | base.InitComponent();
|
| | | titleText = transform.Find("Text_Loading").GetComponent<Text>();
|
| | | tipsText = transform.Find("Text_Tips").GetComponent<Text>();
|
| | | progressBar = transform.Find("Img_Progress/Img_Foreground").GetComponent<Image>();
|
| | | progressText = transform.Find("Text_Progress").GetComponent<Text>();
|
| | | }
|
| | |
|
| | | public override void HandleOpen()
|
| | | {
|
| | | base.HandleOpen();
|
| | | currentProgress = targetProgress = 0;
|
| | | Refresh();
|
| | | }
|
| | |
|
| | | public override void HandleClose()
|
| | | {
|
| | | base.HandleClose();
|
| | | }
|
| | |
|
| | | public override void Refresh()
|
| | | {
|
| | | base.Refresh();
|
| | | UpdateProgress();
|
| | | }
|
| | |
|
| | | public void SetProgress(float value, bool directly = false)
|
| | | {
|
| | | if (directly)
|
| | | {
|
| | | currentProgress = targetProgress = (int)(value * 100);
|
| | | UpdateProgress();
|
| | | }
|
| | | else
|
| | | {
|
| | | currentProgress = (int)(value * 100);
|
| | | }
|
| | |
|
| | | |
| | | }
|
| | |
|
| | | protected void UpdateProgress()
|
| | | {
|
| | | progressText.text = currentProgress + "%";
|
| | | progressBar.fillAmount = currentProgress / 100f;
|
| | | }
|
| | |
|
| | | protected void Update()
|
| | | {
|
| | | if (currentProgress < targetProgress)
|
| | | {
|
| | | currentProgress = (int)Mathf.Lerp(currentProgress, targetProgress, 0.1f);
|
| | | UpdateProgress();
|
| | | }
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: e85e62037b34d9944a44a4c93764c656 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: bef9e971d62416147ae8006de5cbff6a |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System;
|
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using System.Diagnostics.Tracing;
|
| | | using UnityEngine;
|
| | | using UnityEngine.UI;
|
| | |
|
| | | public class LoginWin : UIBase
|
| | | {
|
| | | private InputField username;
|
| | | private InputField password;
|
| | | private Button loginBtn;
|
| | | private Button registerBtn;
|
| | |
|
| | | protected override void InitComponent()
|
| | | {
|
| | | base.InitComponent();
|
| | | Debug.Log("初始化登录窗口");
|
| | | username = transform.Find("InputUserName").GetComponent<InputField>();
|
| | | password = transform.Find("InputPassword").GetComponent<InputField>();
|
| | | loginBtn = transform.Find("Buttons/ButtonLogin").GetComponent<Button>();
|
| | | registerBtn = transform.Find("Buttons/ButtonRegister").GetComponent<Button>();
|
| | |
|
| | | loginBtn.onClick.AddListener(OnLoginBtnClick);
|
| | | registerBtn.onClick.AddListener(OnRegisterBtnClick);
|
| | | }
|
| | |
|
| | | public override void HandleOpen()
|
| | | {
|
| | | base.HandleOpen();
|
| | | Debug.Log("打开登录窗口");
|
| | | ResManager.Instance.PrewarmResources();
|
| | | Refresh();
|
| | | }
|
| | |
|
| | | public override void HandleClose()
|
| | | {
|
| | | base.HandleClose();
|
| | | Debug.Log("关闭登录窗口");
|
| | | }
|
| | |
|
| | | public override void Refresh()
|
| | | {
|
| | | base.Refresh();
|
| | | Debug.Log("刷新登录窗口");
|
| | | }
|
| | |
|
| | | private void OnRegisterBtnClick()
|
| | | {
|
| | | // TODO 注册
|
| | | Debug.Log("注册");
|
| | | }
|
| | |
|
| | | private void OnLoginBtnClick()
|
| | | {
|
| | | // TODO 登录
|
| | | Debug.Log("登录" + username.text + " / " + password.text);
|
| | | UIManager.Instance.CloseWindow(this);
|
| | |
|
| | | StageManager.Instance.ToGameScene();
|
| | | }
|
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 1d9e1ce1eab28d84188a1c2db2c1c472 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 35cec4a6bce278e4b9c8efc66988e0e2 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | | using UnityEngine.UI;
|
| | |
|
| | | /// <summary>
|
| | | /// 游戏主界面
|
| | | /// </summary>
|
| | | public class MainWin : UIBase
|
| | | {
|
| | | private GameObject windowBackground;
|
| | |
|
| | | // 底部按钮组
|
| | | private Button[] bottomTabButtons;
|
| | | |
| | | // 当前选中的底部标签索引
|
| | | private int currentTabIndex = 0;
|
| | | |
| | | // 当前打开的子界面
|
| | | private UIBase currentSubUI;
|
| | | |
| | | /// <summary>
|
| | | /// 初始化组件
|
| | | /// </summary>
|
| | | protected override void InitComponent()
|
| | | {
|
| | | base.InitComponent();
|
| | |
|
| | | windowBackground = transform.Find("RawImgBackground").gameObject;
|
| | |
|
| | | bottomTabButtons = new Button[5];
|
| | |
|
| | | for (int i = 1; i <= 5; i++)
|
| | | {
|
| | | string buttonName = "Buttons/Button" + i;
|
| | | bottomTabButtons[i-1] = transform.Find(buttonName).GetComponent<Button>();
|
| | | }
|
| | |
|
| | | // 初始化UI组件事件
|
| | | InitButtonEvents();
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 初始化UI组件事件
|
| | | /// </summary>
|
| | | private void InitButtonEvents()
|
| | | {
|
| | | // 初始化底部按钮
|
| | | for (int i = 0; i < bottomTabButtons.Length; i++)
|
| | | {
|
| | | int index = i; // 捕获索引
|
| | | bottomTabButtons[i].onClick.AddListener(() => {
|
| | | OnBottomTabButtonClicked(index);
|
| | | });
|
| | | }
|
| | | }
|
| | | |
| | | protected override void OnOpen()
|
| | | {
|
| | | base.OnOpen();
|
| | | |
| | | // 默认选中第一个标签
|
| | | SelectBottomTab(0);
|
| | |
|
| | | // 刷新UI
|
| | | Refresh();
|
| | | }
|
| | | |
| | | public override void Refresh()
|
| | | {
|
| | | UpdatePlayerInfo();
|
| | | UpdateCurrency();
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新玩家信息
|
| | | /// </summary>
|
| | | private void UpdatePlayerInfo()
|
| | | {
|
| | | // 从玩家数据中获取信息并更新UI
|
| | | // 例如:
|
| | | // playerNameText.text = PlayerData.Instance.Name;
|
| | | // playerLevelText.text = "Lv." + PlayerData.Instance.Level;
|
| | | // powerText.text = PlayerData.Instance.Power.ToString();
|
| | | // expSlider.value = PlayerData.Instance.ExpRatio;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新货币信息
|
| | | /// </summary>
|
| | | private void UpdateCurrency()
|
| | | {
|
| | | // 从玩家数据中获取货币信息并更新UI
|
| | | // 例如:
|
| | | // goldText.text = PlayerData.Instance.Gold.ToString();
|
| | | // diamondText.text = PlayerData.Instance.Diamond.ToString();
|
| | | // energyText.text = PlayerData.Instance.Energy + "/" + PlayerData.Instance.MaxEnergy;
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 底部标签按钮点击
|
| | | /// </summary>
|
| | | private void OnBottomTabButtonClicked(int index)
|
| | | {
|
| | | SelectBottomTab(index);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 选择底部标签
|
| | | /// </summary>
|
| | | private void SelectBottomTab(int index)
|
| | | {
|
| | | // 如果点击当前已选中的标签,不做处理
|
| | | if (currentTabIndex == index && currentSubUI != null)
|
| | | {
|
| | | return;
|
| | | }
|
| | | |
| | | // 更新当前选中的标签索引
|
| | | currentTabIndex = index;
|
| | | |
| | | // 更新按钮状态
|
| | | UpdateButtonsState();
|
| | | |
| | | // 关闭当前打开的子界面
|
| | | CloseCurrentSubUI();
|
| | | |
| | | // 根据选中的标签打开对应的界面
|
| | | OpenSubUIByTabIndex(index);
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 更新按钮状态
|
| | | /// </summary>
|
| | | private void UpdateButtonsState()
|
| | | {
|
| | | // 遍历所有按钮,设置选中状态
|
| | | for (int i = 0; i < bottomTabButtons.Length; i++)
|
| | | {
|
| | | // 这里可以根据是否选中设置按钮的视觉效果
|
| | | // 例如:改变图片、颜色等
|
| | | // bottomTabButtons[i].GetComponent<Image>().color = (i == currentTabIndex) ? Color.blue : Color.white;
|
| | |
|
| | | // 或者激活/禁用选中图标
|
| | | bottomTabButtons[i].image.color = (i == currentTabIndex) ? Color.white : Color.gray;
|
| | | }
|
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 关闭当前打开的子界面
|
| | | /// </summary>
|
| | | private void CloseCurrentSubUI()
|
| | | {
|
| | | if (currentSubUI != null)
|
| | | {
|
| | | // 关闭当前界面
|
| | | UIManager.Instance.CloseWindow(currentSubUI);
|
| | | currentSubUI = null;
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 根据标签索引打开对应的子界面
|
| | | /// </summary>
|
| | | private void OpenSubUIByTabIndex(int index)
|
| | | {
|
| | | Debug.Log("打开子界面 : " + index);
|
| | |
|
| | | // 主城 阵容 同盟 福利 冒险
|
| | |
|
| | | //根据索引打开不同的界面
|
| | | switch (index)
|
| | | {
|
| | | case 0:
|
| | | // 例如:打开主页界面
|
| | | // currentSubUI = UIManager.Instance.OpenUI<HomeUI>();
|
| | | Debug.Log("打开主城界面");
|
| | | break;
|
| | | case 1:
|
| | | // 例如:打开角色界面
|
| | | // currentSubUI = UIManager.Instance.OpenUI<CharacterUI>();
|
| | | Debug.Log("打开阵容界面");
|
| | | break;
|
| | | case 2:
|
| | | // 例如:打开背包界面
|
| | | // currentSubUI = UIManager.Instance.OpenUI<BagUI>();
|
| | | Debug.Log("打开同盟界面");
|
| | | break;
|
| | | case 3:
|
| | | // 例如:打开任务界面
|
| | | // currentSubUI = UIManager.Instance.OpenUI<QuestUI>();
|
| | | Debug.Log("打开福利界面");
|
| | | break;
|
| | | case 4:
|
| | | // 例如:打开设置界面
|
| | | currentSubUI = UIManager.Instance.OpenWindow<PlaceWin>();
|
| | | Debug.Log("打开冒险界面");
|
| | |
|
| | | windowBackground.SetActive(false);
|
| | | break;
|
| | | default:
|
| | | Debug.LogWarning("未知的标签索引: " + index);
|
| | | break;
|
| | | }
|
| | | }
|
| | | } |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 0b14b415a3ac64548a78d163d6cb7e33 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 2a75dbf92ff839445b4bf6be823add40 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | | using UnityEngine.UI;
|
| | |
|
| | | /// <summary>
|
| | | /// 场景界面
|
| | | /// </summary>
|
| | | public class PlaceWin : UIBase
|
| | | {
|
| | | protected Button btnExplore;
|
| | |
|
| | | // protected |
| | |
|
| | | /// <summary>
|
| | | /// 初始化组件
|
| | | /// </summary>
|
| | | protected override void InitComponent()
|
| | | {
|
| | | base.InitComponent();
|
| | | |
| | | // 在这里初始化组件
|
| | | btnExplore = transform.Find("BtnExplore").GetComponent<Button>();
|
| | | btnExplore.onClick.AddListener(OnExploreClick);
|
| | | }
|
| | | |
| | | |
| | | /// <summary>
|
| | | /// 窗口打开时调用
|
| | | /// </summary>
|
| | | protected override void OnOpen()
|
| | | {
|
| | | base.OnOpen();
|
| | | |
| | | // 窗口打开时的逻辑
|
| | | |
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 窗口关闭时调用
|
| | | /// </summary>
|
| | | protected override void OnClose()
|
| | | {
|
| | | base.OnClose();
|
| | | |
| | | // 窗口关闭时的逻辑
|
| | | |
| | | }
|
| | | |
| | | /// <summary>
|
| | | /// 刷新界面
|
| | | /// </summary>
|
| | | public override void Refresh()
|
| | | {
|
| | | // 刷新界面的逻辑
|
| | | }
|
| | |
|
| | | private void OnExploreClick()
|
| | | {
|
| | | // UIManager.Instance.OpenUI<ExploreWin>();
|
| | | }
|
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 846b941e24d55594fac435ba7031cfa9 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | | using DG.Tweening; // DOTween 插件引用
|
| | | using DG.Tweening;
|
| | | using UnityEngine.UI; // DOTween 插件引用
|
| | |
|
| | | public enum UILayer
|
| | | {
|
| | |
| | | SlideFromRight // 从右侧滑入
|
| | | }
|
| | |
|
| | | [RequireComponent(typeof(Canvas))]
|
| | | [RequireComponent(typeof(CanvasGroup))]
|
| | | [RequireComponent(typeof(CanvasScaler))]
|
| | | public class UIBase : MonoBehaviour
|
| | | {
|
| | | #region 属性和变量
|
| | |
|
| | | // UI基本属性
|
| | | [SerializeField] public UILayer uiLayer = UILayer.Mid;
|
| | | [SerializeField] public string uiName;
|
| | | [SerializeField][HideInInspector] public string uiName;
|
| | | [SerializeField] public bool isMainUI = false;
|
| | |
|
| | | // 持久化相关
|
| | | [SerializeField] public bool isPersistent = false;
|
| | | [SerializeField] public int maxIdleRounds = 20;
|
| | | [SerializeField][HideInInspector] public int maxIdleRounds = 20;
|
| | |
|
| | | // 动画相关
|
| | | [SerializeField] public UIAnimationType openAnimationType = UIAnimationType.FadeInOut;
|
| | | [SerializeField] public UIAnimationType closeAnimationType = UIAnimationType.FadeInOut;
|
| | | [SerializeField] public float animationDuration = 0.3f;
|
| | | [SerializeField] public Ease animationEase = Ease.OutQuad; // 确保使用 DG.Tweening.Ease
|
| | | [SerializeField] public UIAnimationType openAnimationType = UIAnimationType.None;
|
| | | [SerializeField] public UIAnimationType closeAnimationType = UIAnimationType.None;
|
| | | [SerializeField][HideInInspector] public float animationDuration = 0.3f;
|
| | | [SerializeField][HideInInspector] public Ease animationEase = Ease.OutQuad; // 确保使用 DG.Tweening.Ease
|
| | |
|
| | | // 运行时状态
|
| | | [HideInInspector] public int lastUsedRound = 0;
|
| | |
| | | rectTransform = GetComponent<RectTransform>();
|
| | | }
|
| | |
|
| | | // 初始化UI
|
| | | public virtual void Init()
|
| | | {
|
| | | // 确保组件已初始化
|
| | | InitComponent();
|
| | | }
|
| | |
|
| | | #endregion
|
| | |
|
| | | #region UI操作方法
|
| | |
| | | }
|
| | |
|
| | | // 打开UI
|
| | | public virtual void Open()
|
| | | public virtual void HandleOpen()
|
| | | {
|
| | | // 如果正在播放动画,先停止
|
| | | StopCurrentAnimation();
|
| | |
|
| | | gameObject.SetActive(true);
|
| | | isActive = true;
|
| | |
|
| | | // 根据动画类型播放打开动画
|
| | | PlayOpenAnimation();
|
| | |
|
| | | isActive = true;
|
| | | OnOpen();
|
| | |
|
| | | }
|
| | |
|
| | | // 关闭UI
|
| | | public virtual void Close()
|
| | | public virtual void HandleClose()
|
| | | {
|
| | | // 如果正在播放动画,先停止
|
| | | StopCurrentAnimation();
|
| | |
| | | // 根据动画类型播放关闭动画
|
| | | PlayCloseAnimation();
|
| | |
|
| | | isActive = false;
|
| | | OnClose();
|
| | | gameObject.SetActive(false);
|
| | | isActive = false;
|
| | | }
|
| | |
|
| | | // 关闭所有子UI
|
| | | for (int i = childrenUI.Count - 1; i >= 0; i--)
|
| | | public void CloseWindow()
|
| | | {
|
| | | if (childrenUI[i] != null && childrenUI[i].isActive)
|
| | | {
|
| | | childrenUI[i].Close();
|
| | | }
|
| | | }
|
| | | UIManager.Instance.CloseWindow(this);
|
| | | }
|
| | |
|
| | | // 刷新UI
|
| | |
| | | }
|
| | |
|
| | | // 动画完成后的回调
|
| | | currentAnimation.OnComplete(() => {
|
| | | currentAnimation.OnComplete(() =>
|
| | | {
|
| | | isAnimating = false;
|
| | |
|
| | | // 启用交互
|
| | |
| | | }
|
| | |
|
| | | // 动画完成后的回调
|
| | | currentAnimation.OnComplete(() => {
|
| | | currentAnimation.OnComplete(() =>
|
| | | {
|
| | | isAnimating = false;
|
| | |
|
| | | // 确保UI不可见且不可交互
|
| | |
| | | #region 初始化方法
|
| | |
|
| | | // 初始化
|
| | | private void Init()
|
| | | public void Init()
|
| | | {
|
| | | InitUIRoot();
|
| | | }
|
| | |
| | | // 创建UI根节点
|
| | | private void InitUIRoot()
|
| | | {
|
| | | GameObject root = GameObject.Instantiate(Resources.Load<GameObject>("UIRoot"));
|
| | | GameObject root = GameObject.Find("UIRoot");
|
| | | if (root == null)
|
| | | {
|
| | | root = GameObject.Instantiate(Resources.Load<GameObject>("UI/UIRoot"));
|
| | |
|
| | | if (root == null)
|
| | | {
|
| | | Debug.LogError("无法找到UI根节点");
|
| | | return;
|
| | | }
|
| | | }
|
| | |
|
| | | uiRoot = root.transform;
|
| | | uiRoot.position = Vector3.zero;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | // 获取UI实例,如果不存在则返回null
|
| | | private UIBase GetUI(string uiName)
|
| | | public T GetUI<T>() where T : UIBase
|
| | | {
|
| | | string uiName = typeof(T).Name;
|
| | | if (string.IsNullOrEmpty(uiName))
|
| | | {
|
| | | Debug.LogError("UI名称为空");
|
| | |
| | | UIBase ui;
|
| | | if (uiDict.TryGetValue(uiName, out ui))
|
| | | {
|
| | | return ui;
|
| | | return ui as T;
|
| | | }
|
| | |
|
| | | return null;
|
| | |
| | | #region UI资源管理
|
| | |
|
| | | // 加载UI预制体
|
| | | private UIBase LoadUIResource(string uiName)
|
| | | private T LoadUIResource<T>(string uiName) where T : UIBase
|
| | |
|
| | | {
|
| | | // 这里是资源加载部分,根据项目实际情况实现
|
| | | // 可以使用Resources.Load或者其他资源管理系统
|
| | |
|
| | | // 示例代码,实际项目中需要替换为真实的资源加载逻辑
|
| | | GameObject prefab = null;
|
| | |
|
| | | // TODO: 在这里实现资源加载逻辑
|
| | | // prefab = Resources.Load<GameObject>("UI/" + uiName);
|
| | | GameObject prefab = ResManager.Instance.LoadUI(uiName);
|
| | |
|
| | | if (prefab == null)
|
| | | {
|
| | |
| | | }
|
| | |
|
| | | GameObject uiObject = GameObject.Instantiate(prefab);
|
| | | UIBase uiBase = uiObject.GetComponent<UIBase>();
|
| | | uiObject.name = uiName;
|
| | | T uiBase = uiObject.GetComponent<T>();
|
| | |
|
| | | if (uiBase == null)
|
| | | {
|
| | |
| | | // 设置父节点为UI根节点
|
| | | uiObject.transform.SetParent(GetTransForLayer(uiBase.uiLayer), false);
|
| | |
|
| | | // 初始化UI
|
| | | uiBase.Init();
|
| | |
|
| | | // 设置排序顺序
|
| | | int baseSortingOrder = GetBaseSortingOrderForLayer(uiBase.uiLayer);
|
| | |
| | | #region 公共接口方法
|
| | |
|
| | | // 打开单个UI窗口
|
| | | public UIBase OpenWindow(string uiName)
|
| | | public T OpenWindow<T>() where T : UIBase
|
| | | {
|
| | | string uiName = typeof(T).Name;
|
| | | if (string.IsNullOrEmpty(uiName))
|
| | | {
|
| | | Debug.LogError("尝试打开空名称的UI窗口");
|
| | |
| | | currentRound++;
|
| | |
|
| | | // 先尝试获取已加载的UI
|
| | | UIBase ui = GetUI(uiName);
|
| | | T ui = GetUI<T>();
|
| | |
|
| | | // 如果UI不存在,则加载
|
| | | if (ui == null)
|
| | | {
|
| | | ui = LoadUIResource(uiName);
|
| | | ui = LoadUIResource<T>(uiName);
|
| | | if (ui == null)
|
| | | return null;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | // 关闭当前UI链上的非System层UI
|
| | | topUI.Close();
|
| | | topUI.HandleClose();
|
| | |
|
| | | // 清理父子关系
|
| | | if (topUI.parentUI != null)
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | ui.Open();
|
| | | ui.HandleOpen();
|
| | |
|
| | | // 如果栈中有其他UI,则将栈顶UI设为父UI
|
| | | if (!ui.isMainUI && ui.uiLayer != UILayer.System && uiStack.Count > 0)
|
| | |
| | | return;
|
| | |
|
| | | // 创建一个列表来存储需要关闭的UI
|
| | | List<UIBase> uisToClose = new List<UIBase>();
|
| | | uisToClose.Add(ui);
|
| | | List<UIBase> uisToClose = new List<UIBase>
|
| | | {
|
| | | ui
|
| | | };
|
| | |
|
| | | // 递归收集所有子UI
|
| | | CollectChildrenUI(ui, uisToClose);
|
| | |
| | | foreach (var uiToClose in uisToClose)
|
| | | {
|
| | | // 关闭UI
|
| | | uiToClose.Close();
|
| | | uiToClose.HandleClose();
|
| | |
|
| | | // 清理父子关系
|
| | | if (uiToClose.parentUI != null)
|
| | |
| | | RemoveFromUIStack(uisToClose);
|
| | | }
|
| | |
|
| | | // 关闭所有UI窗口
|
| | | public void CloseAllWindows()
|
| | | {
|
| | | foreach (var ui in uiDict.Values)
|
| | | {
|
| | | if (ui != null)
|
| | | {
|
| | | ui.Close();
|
| | | }
|
| | | }
|
| | | |
| | | uiStack.Clear();
|
| | | }
|
| | |
|
| | | // 返回上一级UI
|
| | | public void GoBack()
|
| | |
| | |
|
| | | // 关闭当前UI
|
| | | UIBase currentUI = uiStack.Pop();
|
| | | currentUI.Close();
|
| | |
|
| | | CloseWindow(currentUI);
|
| | |
|
| | | // 更新排序顺序
|
| | | UpdateUISortingOrder();
|
| | |
| | | // 销毁所有UI
|
| | | public void DestroyAllUI()
|
| | | {
|
| | | foreach (var ui in uiDict.Values)
|
| | | List<string> uiNames = new List<string>(uiDict.Keys);
|
| | |
|
| | | foreach (var ui in uiNames)
|
| | | {
|
| | | if (ui != null)
|
| | | {
|
New file |
| | |
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using UnityEngine;
|
| | |
|
| | | public class DontDestroyOnLoad : MonoBehaviour
|
| | | {
|
| | | void Awake()
|
| | | {
|
| | | DontDestroyOnLoad(gameObject);
|
| | | }
|
| | | }
|
New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: ebddc3e48e1baa844a56615981c5c152 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | | defaultReferences: [] |
| | | executionOrder: 0 |
| | | icon: {instanceID: 0} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |