yyl
2025-05-13 6208ed5ed833142a459d0dc8ad8622ca8047a80e
update
4 文件已重命名
4个文件已修改
5个文件已删除
24 文件已复制
49个文件已添加
5321 ■■■■ 已修改文件
Main/Battle/BattleField.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/BattleObject.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/BattleObject/BattleObject.cs 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/BattleObject/BattleObject.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/Motion.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/Motion/MotionBase.cs 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/Motion/MotionBase.cs.meta 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/Motion/MotionName.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/Motion/MotionName.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardInfo.Properties.cs 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardInfo.Properties.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardInfo.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardInfo.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardSkillMgr.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardSkillMgr.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardType.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/CardType.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Card/Motion.meta 补丁 | 查看 | 原始文档 | blame | 历史
Main/Character/CharacterBase.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Character/Motion/MotionBase.cs 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Common/FieldPrint.cs 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Common/FieldPrint.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FamilyConfig.cs 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FamilyConfig.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Formula.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Main.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/ConfigManager.cs 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/GameSystemManager/TeamManager.cs 400 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/GameSystemManager/TeamManager.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/Clock.cs 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/Clock.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/AccountLoginState.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/AccountLoginState.cs.meta 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/ConnectedState.cs 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/ConnectedState.cs.meta 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/CreateOrSelectRoleState.cs 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/CreateOrSelectRoleState.cs.meta 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/DTCs.meta 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/DTCs/DtcBasic.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/DTCs/DtcBasic.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/DisconnectState.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/DisconnectState.cs.meta 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/NetState.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/NetState.cs.meta 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/NetUpdateBehaviour.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/NetUpdateBehaviour.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/NeverConnectState.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/NeverConnectState.cs.meta 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/PackageRegedit.cs 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/PackageRegedit.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/RoleLoginState.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DataToCtl/RoleLoginState.cs.meta 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DebugPkgCache.cs 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DebugPkgCache.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/GameNetEncode.cs 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/GameNetEncode.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/GameNetPackBasic.cs 1133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/GameNetPackBasic.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/GameNetSystem.cs 445 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/GameNetSystem.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/NetPkgCtl.cs 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/NetPkgCtl.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/Socket.meta 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/Socket/ClientSocket.cs 451 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/Socket/ClientSocket.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/readme.txt 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/readme.txt.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamBase.Properties.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamBase.Properties.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamBase.cs 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamBase.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamCard.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamCard.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamConst.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Team/TeamConst.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Tools.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Tools/UI.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Tools/UI/EffectPenetrationBlocker.cs 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Tools/UI/EffectPenetrationBlocker.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/UI/UIBase.cs 236 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/UI/UIManager.cs 84 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Utility/StringUtility.cs 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Battle/BattleField.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4c003e768bc58494b9225ef57ba628ea
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Battle/BattleObject.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dc0938f1b84b1c54c8205f7fae9d531c
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Battle/BattleObject/BattleObject.cs
New file
@@ -0,0 +1,244 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 战斗对象阵营枚举
/// </summary>
public enum BattleCamp
{
    Friendly,   // 友方
    Enemy       // 敌方
}
/// <summary>
/// 战斗状态枚举
/// </summary>
[Flags]
public enum BattleState
{
    None = 0,
    Stunned = 1 << 0,     // 眩晕
    Poisoned = 1 << 1,    // 中毒
    Bleeding = 1 << 2,    // 流血
    Silenced = 1 << 3,    // 沉默
    Frozen = 1 << 4,      // 冰冻
    Burned = 1 << 5       // 灼烧
}
/// <summary>
/// 战斗对象基类
/// </summary>
public class BattleObject
{
    /// <summary>
    /// 战斗对象ID
    /// </summary>
    public string BattleObjectId { get; protected set; }
    /// <summary>
    /// 战斗对象阵营
    /// </summary>
    public BattleCamp Camp { get; protected set; } = BattleCamp.Friendly;
    // Buff系统
    // List<BuffInfo> buffList;         // 所有buff列表
    // List<BuffInfo> gainBuffList;     // 增益buff列表
    // List<BuffInfo> debuffList;       // 减益buff列表
    /// <summary>
    /// 初始化战斗对象
    /// </summary>
    /// <param name="id">战斗对象ID</param>
    /// <param name="camp">战斗对象阵营</param>
    public virtual void Initialize(string id, BattleCamp camp)
    {
        BattleObjectId = id;
        Camp = camp;
        // 初始化Buff列表
        // buffList = new List<BuffInfo>();
        // gainBuffList = new List<BuffInfo>();
        // debuffList = new List<BuffInfo>();
    }
    #region Buff系统(待实现)
    // /// <summary>
    // /// 添加Buff
    // /// </summary>
    // /// <param name="buff">Buff信息</param>
    // public virtual void AddBuff(BuffInfo buff)
    // {
    //     // 添加Buff到列表
    //     // 根据Buff类型添加到对应列表
    //     // 应用Buff效果
    // }
    //
    // /// <summary>
    // /// 移除Buff
    // /// </summary>
    // /// <param name="buffId">Buff ID</param>
    // public virtual void RemoveBuff(string buffId)
    // {
    //     // 从列表中移除Buff
    //     // 移除Buff效果
    // }
    //
    // /// <summary>
    // /// 更新所有Buff
    // /// </summary>
    // public virtual void UpdateBuffs()
    // {
    //     // 更新所有Buff的持续时间
    //     // 移除已过期的Buff
    //     // 应用Buff的持续效果
    // }
    //
    // /// <summary>
    // /// 获取所有Buff
    // /// </summary>
    // /// <returns>Buff列表</returns>
    // public virtual List<BuffInfo> GetAllBuffs()
    // {
    //     return buffList;
    // }
    //
    // /// <summary>
    // /// 获取所有增益Buff
    // /// </summary>
    // /// <returns>增益Buff列表</returns>
    // public virtual List<BuffInfo> GetGainBuffs()
    // {
    //     return gainBuffList;
    // }
    //
    // /// <summary>
    // /// 获取所有减益Buff
    // /// </summary>
    // /// <returns>减益Buff列表</returns>
    // public virtual List<BuffInfo> GetDebuffs()
    // {
    //     return debuffList;
    // }
    #endregion
    #region 战斗相关函数
    /// <summary>
    /// 攻击目标
    /// </summary>
    /// <param name="target">攻击目标</param>
    /// <param name="damage">伤害值</param>
    /// <param name="isCritical">是否暴击</param>
    /// <returns>实际造成的伤害</returns>
    public virtual float AttackTarget(BattleObject target)
    {
        // 子类实现具体逻辑
        return 0;
    }
    /// <summary>
    /// 被攻击
    /// </summary>
    /// <param name="attacker">攻击者</param>
    /// <param name="damage">伤害值</param>
    /// <param name="isCritical">是否暴击</param>
    /// <returns>实际受到的伤害</returns>
    public virtual float UnderAttack(BattleObject attacker)
    {
        // 子类实现具体逻辑
        return 0;
    }
    /// <summary>
    /// 治疗目标
    /// </summary>
    /// <param name="target">治疗目标</param>
    /// <param name="healAmount">治疗量</param>
    /// <param name="isCritical">是否暴击</param>
    /// <returns>实际治疗量</returns>
    public virtual float HealTargets(List<BattleObject> targets)
    {
        // 子类实现具体逻辑
        return 0;
    }
    /// <summary>
    /// 被治疗
    /// </summary>
    /// <param name="healer">治疗者</param>
    /// <param name="healAmount">治疗量</param>
    /// <param name="isCritical">是否暴击</param>
    /// <returns>实际被治疗量</returns>
    public virtual float BeHealed(BattleObject healer, float healAmount)
    {
        // 子类实现具体逻辑
        return 0;
    }
    /// <summary>
    /// 复活目标
    /// </summary>
    /// <param name="target">复活目标</param>
    /// <param name="healthPercent">复活后的生命值百分比</param>
    /// <returns>是否复活成功</returns>
    public virtual bool Revive(BattleObject target)
    {
        // 子类实现具体逻辑
        return false;
    }
    /// <summary>
    /// 被复活
    /// </summary>
    /// <param name="reviver">复活者</param>
    /// <param name="healthPercent">复活后的生命值百分比</param>
    /// <returns>是否被复活成功</returns>
    public virtual bool BeRevived(BattleObject reviver, float healthPercent = 0.5f)
    {
        // 子类实现具体逻辑
        return false;
    }
    #endregion
    #region 辅助函数
    /// <summary>
    /// 判断是否为敌对关系
    /// </summary>
    /// <param name="other">其他战斗对象</param>
    /// <returns>是否为敌对关系</returns>
    public virtual bool IsEnemy(BattleObject other)
    {
        if (other == null) return false;
        // 不同阵营为敌对关系
        return Camp != other.Camp;
    }
    /// <summary>
    /// 判断是否为友好关系
    /// </summary>
    /// <param name="other">其他战斗对象</param>
    /// <returns>是否为友好关系</returns>
    public virtual bool IsFriendly(BattleObject other)
    {
        if (other == null) return false;
        // 相同阵营为友好关系
        return Camp == other.Camp;
    }
    public virtual void Run()
    {
        // 子类实现具体逻辑
    }
    #endregion
}
Main/Battle/BattleObject/BattleObject.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Battle/BattleObject/BattleObject.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 585da1d11cf0f484faa41cf4708eaf26
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Battle/Motion.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ca986d7b9ba51db4f84c00f18ba896b4
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Battle/Motion/MotionBase.cs
New file
@@ -0,0 +1,247 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity;
using Cysharp.Threading.Tasks;
/// <summary>
/// 角色动画基类,处理所有与动画相关的功能
/// </summary>
public class MotionBase
{
    public class WaitingTask
    {
        public List<int> triggerFrame;
        public MotionName motionName;
        public int currentFrame;
        public Action<MotionName, int> callback;
        public WaitingTask(List<int> triggerFrame, MotionName motionName, Action<MotionName, int> _callback)
        {
            this.triggerFrame = triggerFrame;
            this.motionName = motionName;
            this.currentFrame = 0;
            this.callback = _callback;
        }
        public bool IsFinished()
        {
            return triggerFrame.Count <= 0;
        }
        public void Run()
        {
            if (triggerFrame.Count > 0)
            {
                currentFrame ++;
                if (currentFrame >= triggerFrame[0])
                {
                    triggerFrame.RemoveAt(0);
                    callback?.Invoke(motionName, currentFrame);
                }
            }
        }
    }
    // 动画事件
    public Action OnAttackAnimationComplete;
    public Action OnHitAnimationComplete;
    public Action<int> OnAttackHitEvent; //trigger index
    #region 组件引用
    protected SkeletonGraphic skeletonGraphic;
    protected Spine.AnimationState spineAnimationState;
    protected Spine.Skeleton skeleton;
    #endregion
    #region 动画设置
    // 动画混合时间
    protected float defaultMixDuration = 0.2f;
    #endregion
    protected List<WaitingTask> waitingTaskList = new List<WaitingTask>();
    protected List<WaitingTask> removeList = new List<WaitingTask>();
    #region 初始化方法
    /// <summary>
    /// 初始化动画组件
    /// </summary>
    /// <param name="skeletonGraphic">骨骼动画组件</param>
    public virtual void Initialize(SkeletonGraphic skeletonGraphic)
    {
        this.skeletonGraphic = skeletonGraphic;
        if (skeletonGraphic != null)
        {
            spineAnimationState = skeletonGraphic.AnimationState;
            skeleton = skeletonGraphic.Skeleton;
            // 设置动画混合时间
            if (spineAnimationState != null)
            {
                spineAnimationState.Data.DefaultMix = defaultMixDuration;
            }
            // 播放默认动画
            PlayAnimation(MotionName.idle, true);
            // 设置动画事件监听
            SetupAnimationHandlers();
        }
        else
        {
            Debug.LogError("缺少SkeletonGraphic组件!");
        }
    }
    #endregion
    #region 动画控制
    /// <summary>
    /// 播放指定动画
    /// </summary>
    /// <param name="motionName">动画枚举</param>
    /// <param name="loop">是否循环</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry PlayAnimation(MotionName motionName, bool loop)
    {
        if (spineAnimationState == null) return null;
        // 直接使用 ToString() 而不是调用 GetAnimationName
        return spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
    }
    /// <summary>
    /// 播放指定动画(使用字符串名称)
    /// </summary>
    /// <param name="animationName">动画名称</param>
    /// <param name="loop">是否循环</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry PlayAnimation(string animationName, bool loop)
    {
        if (spineAnimationState == null) return null;
        return spineAnimationState.SetAnimation(0, animationName, loop);
    }
    /// <summary>
    /// 添加动画到队列
    /// </summary>
    /// <param name="motionName">动画枚举</param>
    /// <param name="loop">是否循环</param>
    /// <param name="delay">延迟时间</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry AddAnimation(MotionName motionName, bool loop, float delay)
    {
        if (spineAnimationState == null) return null;
        // 直接使用 ToString() 而不是调用 GetAnimationName
        return spineAnimationState.AddAnimation(0, motionName.ToString(), loop, delay);
    }
    /// <summary>
    /// 添加动画到队列(使用字符串名称)
    /// </summary>
    /// <param name="animationName">动画名称</param>
    /// <param name="loop">是否循环</param>
    /// <param name="delay">延迟时间</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry AddAnimation(string animationName, bool loop, float delay)
    {
        if (spineAnimationState == null) return null;
        return spineAnimationState.AddAnimation(0, animationName, loop, delay);
    }
    /// <summary>
    /// 设置动画事件监听
    /// </summary>
    protected virtual void SetupAnimationHandlers()
    {
        if (spineAnimationState == null) return;
        // 监听动画完成事件
        spineAnimationState.Complete += OnAnimationComplete;
    }
    /// <summary>
    /// 动画完成事件处理
    /// </summary>
    protected virtual void OnAnimationComplete(Spine.TrackEntry trackEntry)
    {
        string animation = trackEntry.Animation.Name;
        // 攻击动画完成后恢复到待机状态
        if (animation == MotionName.atk1.ToString() ||
            animation == MotionName.atk2.ToString())
        {
            OnAttackAnimationComplete?.Invoke();
            PlayAnimation(MotionName.idle, true);
        }
        // 受伤动画完成后恢复到待机状态
        else if (animation == MotionName.hit.ToString())
        {
            OnHitAnimationComplete?.Invoke();
            PlayAnimation(MotionName.idle, true);
        }
    }
    /// <summary>
    /// 动画事件处理
    /// </summary>
    protected virtual void OnTriggerHitEvent(MotionName motionName, int hitIndex)
    {
        OnAttackHitEvent?.Invoke(hitIndex);
    }
    //  拓展了播放动画方法,添加了触发帧的功能,在攻击动画中多段攻击的触发帧
    //  例如:攻击动画有三段,第一段攻击在第1帧触发,第二段攻击在第10帧触发,第三段攻击在第20帧触发
    //  那么triggerFrame就应该是[1, 10, 20]
    public virtual void PlayAnimationEx(MotionName motionName, bool loop, List<int> triggerFrame = null)
    {
        PlayAnimation(motionName, loop);
        if (triggerFrame != null && triggerFrame.Count >= 0)
        {
            AddWaitingTask(triggerFrame, motionName);
        }
    }
    protected void AddWaitingTask(List<int> triggerFrame, MotionName motionName)
    {
        if (triggerFrame != null && triggerFrame.Count > 0)
        {
            WaitingTask waitingTask = new WaitingTask(triggerFrame, motionName, OnTriggerHitEvent);
            waitingTaskList.Add(waitingTask);
        }
    }
    public virtual void Run()
    {
        foreach (WaitingTask waitingTask in waitingTaskList)
        {
            waitingTask.Run();
            if (waitingTask.IsFinished())
            {
                removeList.Add(waitingTask);
            }
        }
        foreach (WaitingTask waitingTask in removeList)
        {
            waitingTaskList.Remove(waitingTask);
        }
        removeList.Clear();
    }
    #endregion
}
Main/Battle/Motion/MotionBase.cs.meta
Main/Battle/Motion/MotionName.cs
New file
@@ -0,0 +1,10 @@
public enum MotionName
{
    atk1,
    atk2,
    hit,
    idle,
    run,
}
Main/Battle/Motion/MotionName.cs.meta
File was renamed from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 88b8611ab751dba40a16159f3d2fcbcb
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Card.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ec4bdc5ff35cf96419554a0e46696eb6
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Card/CardInfo.Properties.cs
New file
@@ -0,0 +1,51 @@
public partial class CardInfo
{
    // 战斗属性的触发几率计算是1对1的,可同时触发多个属性且多次触发,触发几率不会随着目标数量多少而改变,只会根据同一目标的触发次数增多而降低。
    // 即在一回合内,同一个目标反击、连击、击晕、暴击、闪避可以同时并多次触发,触发几率随机触发次数的增加而降低,每个属性开公式来(参数:触发几率、抵抗几率、已触发次数)
    // 优先判断是否命中,必中后同时判断此次攻击是否连击、击晕、暴击生效
    // 反击时必命中目标
    // 武将属性需时时计算,根据技能、BUFF、装备等属性来源改变而改变
    //战斗属性
    //闪避概率
    public float dodge = 0f;
    //暴击概率
    public float crit = 0f;
    //连击概率
    public float comboRate = 0f;
    //眩晕概率
    public float stunRate = 0f;
    //反击概率
    public float counterAttack = 0f;
    //攻击目标时,造成伤害转化成生命的百分比数值提升
    public float recoverRate = 0f;
    //战斗抵抗属性
    //闪避抵抗
    public float dodgeResist = 0f;
    //暴击抵抗
    public float critResist = 0f;
    //连击抵抗
    public float comboResist = 0f;
    //眩晕抵抗
    public float stunResist = 0f;
    //反击抵抗
    public float counterAttackResist = 0f;
    //减少攻击时吸血转化成生命的百分比数值
    public float recoverResist = 0f;
    //计算个人/职业/种族养成属性加成
    public void CalculateProperties()
    {
        //todo
    }
    public int CalculatePower()
    {
        //todo
        return 0;
    }
}
Main/Card/CardInfo.Properties.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Card/CardInfo.Properties.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 8b30e11e231880d45a28598cef7b63f5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Card/CardInfo.cs
New file
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using UnityEngine;
public partial class CardInfo
{
    public long sid;
    public int cardId;
    public int cardLevel;
    public int cardStar;
    public int breakLevel;
    // public List<int> cardEquipList;
    // public List<int> cardRuneList;
    // public List<int> cardMedalList;
    // public CardConfig cardConfig;
    public CardSkillMgr cardSkillMgr;
    public CardInfo(/*TODO 等待服务器数据*/)
    {
        cardSkillMgr = new CardSkillMgr(this);
    }
}
Main/Card/CardInfo.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Card/CardInfo.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 1a586a3dd13cc774fadc7b2129a8c885
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Card/CardSkillMgr.cs
New file
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
/// <summary>
/// 角色技能管理器,处理所有与技能相关的功能
/// </summary>
public class CardSkillMgr
{
    public CardInfo cardInfo;
    public CardSkillMgr(CardInfo _cardInfo)
    {
        this.cardInfo = _cardInfo;
        Init();
    }
    public void Init()
    {
    }
}
Main/Card/CardSkillMgr.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Card/CardSkillMgr.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 97462d62c358e0a41a1ba6d83d821ad4
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Card/CardType.cs
New file
@@ -0,0 +1,17 @@
public enum CardType
{
    Wei,        // 魏
    Shu,        // 蜀
    Wu,         // 吴
    Shen,       // 神
    Mo,         // 魔
}
// 上阵4名指定国武将可激活 生命+10% 攻击+10%,激活后相应词条亮起与对应图标修改。
// 上阵5名指定国武将可激活 生命+15% 攻击+15%,激活后相应词条亮起与对应图标修改。
// 上阵6名指定国武将可激活 生命+20% 攻击+20%,激活后相应词条亮起与对应图标修改。
// 属性数值需要支持配置
// 阵营颜色:魏国:蓝、吴国:红色、蜀国:绿色、神:黄色、魔:暗紫
// 当满足多条词条时,只有最高属性词条生效并修改成对应图标显示
// 根据上阵武将情况时时修改阵营光环图标并激活对应词条
Main/Card/CardType.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Card/CardType.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 52648f1b5c66b3b41b7654ff65f1b2b0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Card/Motion.meta
Main/Character/CharacterBase.cs
File was deleted
Main/Character/Motion/MotionBase.cs
File was deleted
Main/Common/FieldPrint.cs
New file
@@ -0,0 +1,100 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class FieldPrint
{
    public static string PrintFields(object _object)
    {
        if (_object == null)
        {
            return string.Empty;
        }
        var fields = _object.GetType().GetFields();
        var contents = new string[fields.Length];
        for (int i = 0; i < fields.Length; i++)
        {
            var field = fields[i];
            var fieldContent = field.GetValue(_object);
            contents[i] = string.Format("\"{0}\":{1}", field.Name, fieldContent);
        }
        return string.Join(";  ", contents);
    }
    public static List<string> PrintFieldsExpand(object _object, bool _includeArray)
    {
        if (_object == null)
        {
            return null;
        }
        var fields = _object.GetType().GetFields();
        var contents = new List<string>();
        for (int i = 0; i < fields.Length; i++)
        {
            var field = fields[i];
            var fieldContent = field.GetValue(_object);
            if (fieldContent is Array)
            {
                contents.AddRange(PrintArray(field.Name, fieldContent));
            }
            else
            {
                contents.Add(string.Format("\"{0}\":{1}", field.Name, fieldContent));
            }
        }
        return contents;
    }
    private static string[] PrintArray(string _name, object _object)
    {
        var objects = _object as Array;
        var contents = new string[objects.Length];
        for (int i = 0; i < objects.Length; i++)
        {
            var o = objects.GetValue(i);
            var type = o.GetType();
            if (type.Name == "String")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (String)o);
            }
            else if (type.Name == "UInt32")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (UInt32)o);
            }
            else if (type.Name == "Byte")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (Byte)o);
            }
            else if (type.Name == "UInt16")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (UInt16)o);
            }
            else if (type.Name == "Single")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (float)o);
            }
            else if (type.Name == "Boolean")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (bool)o);
            }
            else if (type.Name == "Int32")
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->({2}){3}", _name, i, type.Name, (int)o);
            }
            else
            {
                contents[i] = string.Format("\"{0}\"[{1}]-->{2}", _name, i, PrintFields(o));
            }
        }
        return contents;
    }
}
Main/Common/FieldPrint.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Common/FieldPrint.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: e8426254dd294aa428e2078f8e48cd5e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Config/Configs/FamilyConfig.cs
New file
@@ -0,0 +1,50 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月13日
//--------------------------------------------------------
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System;
using UnityEngine;
using LitJson;
public partial class FamilyConfig : ConfigBase<int, FamilyConfig>
{
    public int familyLV;
    public int memberCnt;
    public int deputyLeaderCnt;
    public int eliteCnt;
    public int needMoney;
    public int weekMissionMoneyMax;
    public int bossFBCnt;
    public int ZhenbaogeWeights;
    public override int LoadKey(string _key)
    {
        int key = GetKey(_key);
        return key;
    }
    public override void LoadConfig(string input)
    {
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out familyLV);
            int.TryParse(tables[1],out memberCnt);
            int.TryParse(tables[2],out deputyLeaderCnt);
            int.TryParse(tables[3],out eliteCnt);
            int.TryParse(tables[4],out needMoney);
            int.TryParse(tables[5],out weekMissionMoneyMax);
            int.TryParse(tables[6],out bossFBCnt);
            int.TryParse(tables[7],out ZhenbaogeWeights);
    }
}
Main/Config/Configs/FamilyConfig.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Config/Configs/FamilyConfig.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 3aa8bbc93ccbf0348ae003e053029d7f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Formula.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8d0fec473a0754742863776bae15b005
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Main.cs
@@ -57,7 +57,6 @@
        // 初始化游戏系统
        managers.Add(PlaceManager.Instance);
        managers.Add(BattleManager.Instance);
        managers.Add(TeamManager.Instance);
        foreach (var manager in managers)
        {
Main/Manager/ConfigManager.cs
@@ -33,6 +33,17 @@
        isLoadFinished = false;
        // 加载配置文件
        int totalConfigs = 1;
        Type[] configTypes = new Type[] {
            typeof(FamilyConfig)
        };
        // 逐个加载配置并更新进度
        for (int i = 0; i < configTypes.Length; i++)
        {
            await LoadConfigByType(configTypes[i]);
            loadingProgress = (float)(i + 1) / totalConfigs;
        }
        // 加载完成后设置isLoadFinished为true
        loadingProgress = 1f;
@@ -68,11 +79,6 @@
            Debug.LogError($"找不到配置文件: {configName}");
        }
    }
    private async UniTask LoadConfig<T>() where T : class
    {
@@ -122,11 +128,7 @@
    public override void Release()
    {
        // 没有找到配置类
        // 清空 FamilyConfig 字典
        ClearConfigDictionary<FamilyConfig>();
    }
}
}
Main/Manager/GameSystemManager/TeamManager.cs
File was deleted
Main/Manager/GameSystemManager/TeamManager.cs.meta
File was deleted
Main/NetworkPackage.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5e5b6f2644a590642aa1697217e1cdf4
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/NetworkPackage/Clock.cs
New file
@@ -0,0 +1,90 @@
using System;
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.Events;
using StartAot;
public class Clock
{
    public bool stopped { get; set; }
    DateTime alarmTime;
    UnityAction alarmCallBack;
    public Clock(DateTime alarmTime, UnityAction callBack)
    {
        this.alarmTime = alarmTime;
        this.alarmCallBack = callBack;
    }
    public bool CanAlarm()
    {
        return DateTime.Now >= alarmTime;
    }
    public void Execute()
    {
        if (alarmCallBack != null)
        {
            alarmCallBack();
            alarmCallBack = null;
        }
    }
    static List<Clock> clocks = new List<Clock>();
    public static void Init()
    {
        new LogicUpdate().Start(OnUpdate);
    }
    public static Clock AlarmAt(DateTime alarmTime, UnityAction callBack)
    {
        var clock = new Clock(alarmTime, callBack);
        clocks.Add(clock);
        return clock;
    }
    public static Clock AlarmAfter(double seconds, UnityAction callBack)
    {
        var clock = new Clock(DateTime.Now.AddSeconds(seconds), callBack);
        clocks.Add(clock);
        return clock;
    }
    public static void Stop(Clock clock)
    {
        if (clocks.Contains(clock))
        {
            clock.stopped = true;
        }
    }
    static void OnUpdate()
    {
        for (var i = clocks.Count - 1; i >= 0; i--)
        {
            var clock = clocks[i];
            if (clock.stopped)
            {
                clocks.RemoveAt(i);
                continue;
            }
            if (clock.CanAlarm())
            {
                try
                {
                    clock.Execute();
                    clocks.RemoveAt(i);
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }
        }
    }
}
Main/NetworkPackage/Clock.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/NetworkPackage/Clock.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 7122809994ef46c4a876e823b99c2473
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/NetworkPackage/DataToCtl.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d31cd6caeeca0034bac8394eb2571a2a
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/NetworkPackage/DataToCtl/AccountLoginState.cs
New file
@@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AccountLoginState : NetState
{
    const int OVERTIME_THRESHOLD = 15;
    float overTime = 0f;
    public override void OnEnter()
    {
        base.OnEnter();
        overTime = Time.time + OVERTIME_THRESHOLD;
    }
    protected override void Update()
    {
        if (GameNetSystem.Instance.netState != GameNetSystem.NetState.AccountLogin)
        {
            return;
        }
        if (Time.time > overTime)
        {
            GameNetSystem.Instance.LoginOut();
            // ServerForceExitHintWin.reason = 111;
        }
    }
    public override void OnExit()
    {
        base.OnExit();
    }
}
Main/NetworkPackage/DataToCtl/AccountLoginState.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/DataToCtl/AccountLoginState.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
licenseType: Free
guid: f5abaa5b8abbec948a68390b75c55a90
timeCreated: 1519302320
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
Main/NetworkPackage/DataToCtl/ConnectedState.cs
New file
@@ -0,0 +1,149 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class ConnectedState : NetState
{
    const int OVERTIME_THRESHOLD = 20;
    bool connectedDetecting = false;
    NetworkReachability m_NetWorkReachability = NetworkReachability.ReachableViaCarrierDataNetwork;
    NetworkReachability netWorkReachability {
        get { return m_NetWorkReachability; }
        set {
            if (m_NetWorkReachability != value)
            {
                m_NetWorkReachability = value;
                DetectConnected(3);
            }
        }
    }
    public override void OnEnter()
    {
        base.OnEnter();
        m_NetWorkReachability = Application.internetReachability;
        // NetLinkWin.Hide();
    }
    protected override void Update()
    {
        if (GameNetSystem.Instance.netState != GameNetSystem.NetState.Connected)
        {
            return;
        }
        if (connectedDetecting)
        {
            return;
        }
        if (GameNetSystem.Instance.timeSinceMainSocketLastProtocol > OVERTIME_THRESHOLD
            || (GameNetSystem.Instance.crossServerConnected_Loigc && GameNetSystem.Instance.timeSinceCrossServerSocketLastProtocol > OVERTIME_THRESHOLD))
        {
            DetectConnected(3);
        }
        else if (!GameNetSystem.Instance.mainSocketConnected
            || (GameNetSystem.Instance.crossServerConnected_Loigc && !GameNetSystem.Instance.crossServerSocketConnected))
        {
            DetectConnected(3);
        }
        else
        {
#if UNITY_IOS && !UNITY_EDITOR
            netWorkReachability = Application.internetReachability;
#endif
        }
    }
    Clock clock;
    public override void OnExit()
    {
        if (clock != null)
        {
            Clock.Stop(clock);
        }
        clock = null;
        base.OnExit();
    }
    private void DetectConnected(int _seconds)
    {
        connectedDetecting = true;
        // var sendInfo1 = new C0104_tagCOnlineReturn();
        // sendInfo1.Type = 0;
        // GameNetSystem.Instance.SendInfo(sendInfo1);// 在线回应
        // if (GameNetSystem.Instance.crossServerConnected_Loigc)
        // {
        //     var sendInfo2 = new C0104_tagCOnlineReturn();
        //     sendInfo2.Type = 0;
        //     GameNetSystem.Instance.SendToCrossServer(sendInfo2);// 在线回应
        // }
        // if (clock != null)
        // {
        //     Clock.Stop(clock);
        // }
        // clock = Clock.AlarmAt(DateTime.Now + new TimeSpan(_seconds * TimeSpan.TicksPerSecond), OnDetectEnd);
    }
    private void OnDetectEnd()
    {
        connectedDetecting = false;
        var isDisconnected = false;
#if UNITY_IOS && !UNITY_EDITOR
        isDisconnected = GameNetSystem.Instance.timeSinceMainSocketLastProtocol > 3f;
#else
        isDisconnected = !GameNetSystem.Instance.mainSocketConnected
            || GameNetSystem.Instance.timeSinceMainSocketLastProtocol > OVERTIME_THRESHOLD;
#endif
        if (GameNetSystem.Instance.crossServerConnected_Loigc)
        {
#if UNITY_IOS && !UNITY_EDITOR
            isDisconnected = isDisconnected || GameNetSystem.Instance.timeSinceCrossServerSocketLastProtocol > 3f;
#else
            isDisconnected = isDisconnected || !GameNetSystem.Instance.crossServerSocketConnected
                || GameNetSystem.Instance.timeSinceCrossServerSocketLastProtocol > OVERTIME_THRESHOLD;
#endif
        }
        if (isDisconnected)
        {
            switch (Application.internetReachability)
            {
                case NetworkReachability.NotReachable:
                    GameNetSystem.Instance.Disconnect();
                    // WindowCenter.Instance.Open<DisconnectHintWin>();
                    break;
                case NetworkReachability.ReachableViaCarrierDataNetwork:
                case NetworkReachability.ReachableViaLocalAreaNetwork:
                    GameNetSystem.Instance.Reconnect();
                    break;
            }
        }
    }
    private void OnApplicationPause(bool pause)
    {
        if (GameNetSystem.Instance.netState != GameNetSystem.NetState.Connected)
        {
            return;
        }
        if (!pause)
        {
            DetectConnected(3);
        }
    }
}
Main/NetworkPackage/DataToCtl/ConnectedState.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/NetworkPackage/DataToCtl/ConnectedState.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,7 +1,8 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 0c7c606c8fec2ad4b8463a33d2673213
timeCreated: 1519302351
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
Main/NetworkPackage/DataToCtl/CreateOrSelectRoleState.cs
New file
@@ -0,0 +1,125 @@
// using System.Collections;
// using System.Collections.Generic;
// using UnityEngine;
// using System;
// public class CreateOrSelectRoleState : NetState
// {
//     const int OVERTIME_THRESHOLD = 12;
//     bool connectedDetecting = false;
//     NetworkReachability m_NetWorkReachability = NetworkReachability.ReachableViaCarrierDataNetwork;
//     NetworkReachability netWorkReachability {
//         get { return m_NetWorkReachability; }
//         set {
//             if (m_NetWorkReachability != value)
//             {
//                 m_NetWorkReachability = value;
//                 DetectConnected(3);
//             }
//         }
//     }
//     public override void OnEnter()
//     {
//         m_NetWorkReachability = Application.internetReachability;
//         // NetLinkWin.Hide();
//         base.OnEnter();
//     }
//     protected override void Update()
//     {
//         if (GameNetSystem.Instance.netState != GameNetSystem.NetState.CreateOrSelectRole)
//         {
//             return;
//         }
//         if (connectedDetecting)
//         {
//             return;
//         }
//         if (GameNetSystem.Instance.timeSinceMainSocketLastProtocol > OVERTIME_THRESHOLD)
//         {
//             DetectConnected(3);
//         }
//         else if (!GameNetSystem.Instance.mainSocketConnected)
//         {
//             DetectConnected(3);
//         }
//         else
//         {
// #if UNITY_IOS && !UNITY_EDITOR
//             netWorkReachability = Application.internetReachability;
// #endif
//         }
//     }
//     public override void OnExit()
//     {
//         if (clock != null)
//         {
//             Clock.Stop(clock);
//         }
//         clock = null;
//         base.OnExit();
//     }
//     Clock clock;
//     private void DetectConnected(int _seconds)
//     {
//         connectedDetecting = true;
//         var sendInfo = new C0104_tagCOnlineReturn();
//         sendInfo.Type = 0;
//         GameNetSystem.Instance.SendInfo(sendInfo);// 在线回应
//         if (clock != null)
//         {
//             Clock.Stop(clock);
//         }
//         clock = Clock.AlarmAt(DateTime.Now + new TimeSpan(_seconds * TimeSpan.TicksPerSecond), OnDetectEnd);
//     }
//     private void OnDetectEnd()
//     {
//         connectedDetecting = false;
//         var isDisconnected = false;
// #if UNITY_IOS && !UNITY_EDITOR
//         isDisconnected = GameNetSystem.Instance.timeSinceMainSocketLastProtocol > 3f;
// #else
//         isDisconnected = !GameNetSystem.Instance.mainSocketConnected
//             || GameNetSystem.Instance.timeSinceMainSocketLastProtocol > OVERTIME_THRESHOLD;
// #endif
//         if (isDisconnected)
//         {
//             switch (Application.internetReachability)
//             {
//                 case NetworkReachability.NotReachable:
//                     GameNetSystem.Instance.Disconnect();
//                     WindowCenter.Instance.Open<DisconnectHintWin>();
//                     break;
//                 case NetworkReachability.ReachableViaCarrierDataNetwork:
//                 case NetworkReachability.ReachableViaLocalAreaNetwork:
//                     GameNetSystem.Instance.Reconnect();
//                     break;
//             }
//         }
//     }
//     private void OnApplicationPause(bool pause)
//     {
//         if (GameNetSystem.Instance.netState != GameNetSystem.NetState.CreateOrSelectRole)
//         {
//             return;
//         }
//         if (!pause)
//         {
//             DetectConnected(3);
//         }
//     }
// }
Main/NetworkPackage/DataToCtl/CreateOrSelectRoleState.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/DataToCtl/CreateOrSelectRoleState.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
licenseType: Free
guid: 903872d42f3a20149883eac95f2b5c80
timeCreated: 1519307260
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
Main/NetworkPackage/DataToCtl/DTCs.meta
New file
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 679cd6ab06f24164bbd2bfd2060ee0bb
folderAsset: yes
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
Main/NetworkPackage/DataToCtl/DTCs/DtcBasic.cs
New file
@@ -0,0 +1,15 @@
using UnityEngine;
using System.Collections;
/** 数据转逻辑处理的基类 */
public class DtcBasic {
    /** 最近一次触发数据包处理的时刻 */
    //    protected float _lastDoneTime = 0;
    /** 继承类需要重写的方法,一般仅改变数据层,但也充许直接操作对象,如有必要 */
    public virtual void Done(GameNetPackBasic vNetPack) {
        //        _lastDoneTime = Time.time; // 由于是非主线程,所以不能使用 Time
    }
}
Main/NetworkPackage/DataToCtl/DTCs/DtcBasic.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 02cde0a61d95dc34fa677099daf7d232
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Main/NetworkPackage/DataToCtl/DisconnectState.cs
New file
@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DisconnectState : NetState
{
    public override void OnEnter()
    {
        base.OnEnter();
        // NetLinkWin.Hide();
    }
    protected override void Update()
    {
        if (GameNetSystem.Instance.netState != GameNetSystem.NetState.DisConnected)
        {
            return;
        }
    }
    public override void OnExit()
    {
        base.OnExit();
    }
}
Main/NetworkPackage/DataToCtl/DisconnectState.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/NetworkPackage/DataToCtl/DisconnectState.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,7 +1,8 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 441d0f42949286a47af2e4046c225f9b
timeCreated: 1519302373
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
Main/NetworkPackage/DataToCtl/NetState.cs
New file
@@ -0,0 +1,27 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NetState : MonoBehaviour
{
    private void Awake()
    {
        enabled = false;
    }
    public virtual void OnEnter()
    {
        enabled = true;
    }
    protected virtual void Update()
    {
    }
    public virtual void OnExit()
    {
        enabled = false;
    }
}
Main/NetworkPackage/DataToCtl/NetState.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/NetworkPackage/DataToCtl/NetState.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,7 +1,8 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 0626c2db7c48f1646821d77eb3d8f3e6
timeCreated: 1519302437
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
Main/NetworkPackage/DataToCtl/NetUpdateBehaviour.cs
New file
@@ -0,0 +1,34 @@
using UnityEngine;
using System.Collections;
using System;
public class NetUpdateBehaviour : MonoBehaviour
{
    Action onUpdate;
    public void RegisterUpdateCallBack(Action _onUpdate)
    {
        onUpdate += _onUpdate;
    }
    void Update()
    {
#if UNITY_EDITOR
        if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Escape))
        {
            GameNetSystem.Instance.LoginOut();
        }
#endif
        if (onUpdate!=null)
        {
            onUpdate();
        }
    }
    private void OnApplicationQuit()
    {
        GameNetSystem.Instance.Disconnect();
    }
}
Main/NetworkPackage/DataToCtl/NetUpdateBehaviour.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d9f19d1b8cac52440a9b08b5b3a131d8
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Main/NetworkPackage/DataToCtl/NeverConnectState.cs
New file
@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NeverConnectState : NetState
{
    public override void OnEnter()
    {
        base.OnEnter();
        // NetLinkWin.Hide();
    }
    protected override void Update()
    {
        if (GameNetSystem.Instance.netState != GameNetSystem.NetState.NerverConnect)
        {
            return;
        }
    }
    public override void OnExit()
    {
        base.OnExit();
    }
}
Main/NetworkPackage/DataToCtl/NeverConnectState.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/DataToCtl/NeverConnectState.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
licenseType: Free
guid: 6cc286e08ca8714449e69d7573918a06
timeCreated: 1519301439
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
Main/NetworkPackage/DataToCtl/PackageRegedit.cs
New file
@@ -0,0 +1,147 @@
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
//using ILCrossBinding;
public class PackageRegedit
{
    #region 主工程原生的封包
    static object lockojb1 = new object();
    static Dictionary<ushort, Type> m_PackageTable = new Dictionary<ushort, Type>();
    static Dictionary<ushort, Type> packageTable
    {
        get
        {
            lock (lockojb1) { return m_PackageTable; }
        }
    }
    static object lockojb2 = new object();
    static Dictionary<ushort, DtcBasic> m_PackToBusinessTable = new Dictionary<ushort, DtcBasic>();
    static Dictionary<ushort, DtcBasic> packToBusinessTable
    {
        get
        {
            lock (lockojb2) { return m_PackToBusinessTable; }
        }
    }
    #endregion
    public static void Init()
    {
        // 登记相应的数据体及对应的数据转逻辑类
        // Register(typeof(HA328_tagMCHistoryReChargeAwardRecord), typeof(DTCA328_tagMCHistoryReChargeAwardRecord));
    }
    //主工程注册封包
    public static void Register(Type _pack, Type _business)
    {
        var packInstance = _pack.Assembly.CreateInstance(_pack.Name) as GameNetPackBasic;
        var businessInstance = _business.Assembly.CreateInstance(_business.Name) as DtcBasic;
        if (packToBusinessTable.ContainsKey(packInstance.cmd))
        {
            Debug.LogErrorFormat("重复封包登记: {0}!", _pack.Name);
        }
        else
        {
            packToBusinessTable[packInstance.cmd] = businessInstance;
            packageTable[packInstance.cmd] = _pack;
        }
    }
    public static bool Contain(ushort _cmd)
    {
        return packToBusinessTable.ContainsKey(_cmd);
    }
    public static void Distribute(GameNetPackBasic _package)
    {
        try
        {
            //执行主工程的封包
            if (packToBusinessTable.ContainsKey(_package.cmd))
                packToBusinessTable[_package.cmd].Done(_package);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.Message + "\r\n" + ex.StackTrace);
            Debug.LogErrorFormat("封包是否为Null:{0};", _package == null);
            if (_package != null)
            {
                Debug.LogErrorFormat("封包编号是:{0};", _package.cmd);
            }
        }
    }
    /// <summary>
    /// 转换一个协议包
    /// </summary>
    /// <param name="vBytes"></param>
    /// <returns></returns>
    public static GameNetPackBasic TransPack(ServerType socketType, ushort cmd, byte[] vBytes)
    {
#if UNITY_EDITOR
        int length = vBytes.Length;
        string vStr = "";
        for (int i = 0; i < length; i++)
        {
            vStr += vBytes[i].ToString("x2").ToUpper() + ",";
        }
#endif
        // 主工程有登记
        if (packageTable.ContainsKey(cmd))
        {
            var packageType = packageTable[cmd];
            // 实例化并强转为协议包基类
            var packageInstance = packageType.Assembly.CreateInstance(packageType.Name) as GameNetPackBasic;
            packageInstance.ReadFromBytes(vBytes);// 解析内容
            if (packageInstance.cmd == (ushort)0x03F0 || packageInstance.cmd == (ushort)0x1801)
            {
                byte[] vPyBody = new byte[vBytes.Length - 4];
                Array.Copy(vBytes, 4, vPyBody, 0, vPyBody.Length);
                packageInstance = TransForPyPack(vPyBody);
            }
            packageInstance.socketType = socketType;
#if UNITY_EDITOR
            NetPkgCtl.RecordPackage(socketType, vStr, NetPackagetType.Server, packageInstance.ToString(), FieldPrint.PrintFields(packageInstance), FieldPrint.PrintFieldsExpand(packageInstance, true));
#endif
            return packageInstance;
        }
        else //未注册
        {
#if UNITY_EDITOR
            NetPkgCtl.RecordPackage(socketType, vStr, NetPackagetType.Server, string.Empty, string.Empty, null);
#endif
        }
        return null;
    }
    /// <summary>
    /// 解析PY的模拟包
    /// </summary>
    /// <param name="vBytes"></param>
    /// <returns></returns>
    private static GameNetPackBasic TransForPyPack(byte[] vBytes)
    {
        GameNetPackBasic vNetPackInst = null;
        ushort vPackCmd = (ushort)((ushort)(vBytes[0] << 8) + vBytes[1]);
        // 主工程封包
        if (packageTable.ContainsKey(vPackCmd))
        {
            Type vNetPackType = packageTable[vPackCmd];
            vNetPackInst = vNetPackType.Assembly.CreateInstance(vNetPackType.Name) as GameNetPackBasic;
            vNetPackInst.ReadFromBytes(vBytes);// 解析内容
        }
        else
        {
            Debug.Log("收到未定义的解包协议:" + vBytes[0].ToString("x2").ToUpper() + "," + vBytes[1].ToString("x2").ToUpper());
        }
        return vNetPackInst;
    }
}
Main/NetworkPackage/DataToCtl/PackageRegedit.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b019a6de742f30a45899664d4938287f
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Main/NetworkPackage/DataToCtl/RoleLoginState.cs
New file
@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RoleLoginState : NetState
{
    const int OVERTIME_THRESHOLD_1 = 20;
    const int OVERTIME_THRESHOLD_2 = 10;
    float timer1 = 0f;
    float timer2 = 0f;
    public override void OnEnter()
    {
        base.OnEnter();
        timer1 = 0f;
        timer2 = 0f;
    }
    protected override void Update()
    {
        if (GameNetSystem.Instance.netState != GameNetSystem.NetState.RoleLogin)
        {
            return;
        }
        timer1 += Time.deltaTime;
        if (timer1 > OVERTIME_THRESHOLD_1)
        {
            GameNetSystem.Instance.Disconnect();
            // WindowCenter.Instance.Open<DisconnectHintWin>();
        }
        timer2 += Time.deltaTime;
        if (timer2 > OVERTIME_THRESHOLD_2)
        {
            GameNetSystem.Instance.Disconnect();
            // WindowCenter.Instance.Open<DisconnectHintWin>();
        }
    }
    public override void OnExit()
    {
        base.OnExit();
    }
}
Main/NetworkPackage/DataToCtl/RoleLoginState.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/NetworkPackage/DataToCtl/RoleLoginState.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,7 +1,8 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: c0696575305fead4f96cf7726264e959
timeCreated: 1519302335
licenseType: Pro
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
Main/NetworkPackage/DebugPkgCache.cs
New file
@@ -0,0 +1,46 @@
using System.Collections.Generic;
public class DebugPkgCache
{
    private string dataTime;
    private int code;
    private static List<DebugPkgCache> m_List = new List<DebugPkgCache>();
    public static void Push(GameNetPackBasic package)
    {
        if (m_List.Count != 0)
        {
            if (m_List[m_List.Count - 1].code == 258)
            {
                return;
            }
        }
        DebugPkgCache _p = new DebugPkgCache();
        _p.dataTime = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
        _p.code = package.cmd;
        m_List.Add(_p);
    }
    public static void UpLoad()
    {
        var _contents = new System.Text.StringBuilder();
        foreach (var _content in m_List)
        {
            _contents.Append("[");
            _contents.Append(_content.dataTime);
            _contents.Append("]");
            _contents.Append(_content.code);
            _contents.Append("\r\n");
        }
#if UNITY_EDITOR
        UnityEngine.Debug.Log("登陆异常: " + _contents.ToString());
#endif
        _contents = null;
        m_List.Clear();
    }
}
Main/NetworkPackage/DebugPkgCache.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/DebugPkgCache.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
guid: 90b1b61b46516f047a22f3e5920983cd
timeCreated: 1538230240
licenseType: Free
MonoImporter:
  serializedVersion: 2
Main/NetworkPackage/GameNetEncode.cs
New file
@@ -0,0 +1,248 @@
using UnityEngine;
using System;
using System.Collections;
using System.Text;
/** 字节流的加解密 */
public class GameNetEncode
{
    int[] gSendKeyDict = new int[1024] //发送加密用密钥
   {
    0x3bc46229, 0x71463c13, 0x4df97c63, 0x20a6b7b6, 0x5cb0c110, 0x780d5397, 0x161f22f9, 0x71f1eda0,
    0x4c4797a4, 0x7b3d7177, 0x2679595a, 0x54c92286, 0x2af45923, 0x2e5cd5f4, 0x5bc860c7, 0x14929ca9,
    0x1fef64cf, 0x30a25d4c, 0x5daf8680, 0x4553de47, 0x787d45e5, 0x5631bfc0, 0x6de263c5, 0x3493e5a1,
    0x6559f3a9, 0x3833d191, 0x799e1dd6, 0x55b96cf7, 0x71901158, 0x740ac2fc, 0x66aea5f4, 0x58252a89,
    0x59fc2e33, 0x7de26045, 0x513ff95d, 0x71481097, 0x38bc057b, 0x66dc51a9, 0x6bbb6152, 0x60f58d62,
    0x63c9be6e, 0x13185b6a, 0x4df0b314, 0x7231cb28, 0x4a032c4d, 0x67d89dc5, 0x3ccb8fe1, 0x16bbf02b,
    0x35dd0e58, 0x2601d4fe, 0x7fd4a4fa, 0x57945ea8, 0x59024fcf, 0x31379952, 0x35beeba0, 0x40bef4e3,
    0x601f47f3, 0x6fd49f02, 0x4540e911, 0x4a814d19, 0x4a18fa02, 0x5bfef64f, 0x4379ee8e, 0x7e5cfd8b,
    0x49f0553d, 0x7a184b77, 0x45235957, 0x7205d879, 0x369174e5, 0x44ca26bb, 0x4bcdd2ad, 0x6e942c24,
    0x77cee037, 0x7aee2c5b, 0x2c6a8fce, 0x263302ca, 0x5bc8ca77, 0x57925c98, 0x486091fb, 0x368a62ad,
    0x5c0052e2, 0x785953b0, 0x7e6de674, 0x72258e0a, 0x1556c4ba, 0x727689e4, 0x1494e67a, 0x67154325,
    0x7238d73c, 0x52869374, 0x2855774b, 0x450dfc3b, 0x4235edac, 0x7f8360a0, 0x3e724a28, 0x61422f8d,
    0x56435747, 0x45147da9, 0x57821c51, 0x52388f5c, 0x54eb8f4e, 0x357b52cd, 0x5a8cf707, 0x79de49e5,
    0x45a97d02, 0x1f5b644e, 0x22f56f88, 0x3015496c, 0x1eafb3a1, 0x2f9e926a, 0x1aede716, 0x6bfe742e,
    0x5c5bb26c, 0x43b55962, 0x37b9caef, 0x163fec6d, 0x359524a4, 0x6c731176, 0x18fad454, 0x3a875067,
    0x2c592187, 0x7dc62ee6, 0x184a4885, 0x3a87fa5d, 0x15b16c57, 0x238c81f3, 0x225e38c3, 0x70b5408f,
    0x7057b451, 0x2fc376db, 0x4efac24b, 0x6cf8b53d, 0x1d44d4b9, 0x425455df, 0x48ef4e61, 0x71a466a8,
    0x496c14cc, 0x46bc8340, 0x635fd242, 0x62e11f0e, 0x63e267cb, 0x3fd1bf3c, 0x559a0f2f, 0x16d8a4b1,
    0x17b1acf7, 0x65e26614, 0x72b6d268, 0x40dbf9cf, 0x5c97ef8d, 0x3771b008, 0x3e47352e, 0x3dc59ca9,
    0x4df2a6d1, 0x78cff158, 0x4b4ddcbf, 0x13d7c780, 0x2315f600, 0x6aceda44, 0x4ec43a5c, 0x1456b092,
    0x304fec5c, 0x1cd1b70d, 0x6aebcb45, 0x691eca1f, 0x63d7c522, 0x5a79aff1, 0x24ab58bb, 0x5477026a,
    0x6de92795, 0x412e0932, 0x103837fc, 0x155f03b1, 0x6f4b66f5, 0x15c0630e, 0x6e4b8a49, 0x2e997433,
    0x6584c280, 0x6e6cf9c6, 0x3f237ce3, 0x5ab23630, 0x27f9a578, 0x4176e59a, 0x6c908907, 0x2340a7eb,
    0x2537e71b, 0x74a05aca, 0x584eb3f9, 0x1da5e3a2, 0x1bae0aaa, 0x65bee996, 0x67eacef6, 0x4b86ff93,
    0x250e7f66, 0x60abbe3f, 0x1373b740, 0x19434e02, 0x379ee08d, 0x52cfe103, 0x58379615, 0x30a69d2c,
    0x7cb3355f, 0x788c7623, 0x4ccd20b6, 0x52177752, 0x2795311f, 0x3cbefde0, 0x6fa8d863, 0x328162b5,
    0x7417730a, 0x5ea19478, 0x757e4a5c, 0x683b2192, 0x1014c662, 0x6e47322c, 0x78ad4fe1, 0x1d28f22d,
    0x2f1b6265, 0x6bf3eb3c, 0x16fb4e33, 0x285acec3, 0x53842a54, 0x22912fe9, 0x36d87690, 0x2d66ad96,
    0x1435ed70, 0x717e0c71, 0x79710639, 0x5bbec0e3, 0x6254a6f6, 0x55fb6915, 0x5aca866f, 0x2443b6ee,
    0x1e1cbe2a, 0x40744a16, 0x4d2d0c70, 0x5752f9f4, 0x162a464a, 0x7de20fb1, 0x1918797e, 0x5990f036,
    0x686c3e94, 0x398cb62a, 0x3705bad7, 0x29af3bf5, 0x1803d24c, 0x176715bf, 0x243409bc, 0x6d6efb6f,
    0x574f98af, 0x234722af, 0x7fc22b6c, 0x681f08e5, 0x7162d4fe, 0x3d3a2d3b, 0x1953b12b, 0x68d63a97,
    0x4a28b679, 0x373521a3, 0x36823834, 0x7aa9a2c5, 0x58739860, 0x7460c827, 0x705aa9c8, 0x5d1ecfb0,
    0x293841f4, 0x76420507, 0x66267b2a, 0x371a0b96, 0x17352673, 0x4ffe1884, 0x2ec0ed97, 0x42889cb8,
    0x7e45a51e, 0x73fadedc, 0x6db84e50, 0x6b070556, 0x3da14936, 0x3c1b1050, 0x6d7b3695, 0x15c343b1,
    0x684709f9, 0x78d68120, 0x2bd1cba7, 0x24db1207, 0x4ed48aa8, 0x1f6e618d, 0x21e2fec5, 0x3476269a,
    0x4a095a83, 0x7b7d7dd5, 0x1d05cd2e, 0x5bdc73a7, 0x693634ca, 0x34247e39, 0x599e8023, 0x38c86772,
    0x73d840bd, 0x711226f9, 0x4d47ece4, 0x67352c38, 0x39a0519d, 0x27a79856, 0x4988b4b1, 0x43e8e83a,
    0x282626a9, 0x34788e8e, 0x4c5484ca, 0x63fafdb8, 0x7987ab1f, 0x7167a1e2, 0x7f99566f, 0x57964af3,
    0x7b343642, 0x549e8692, 0x2518aee1, 0x5a376a29, 0x6823cb52, 0x30a24cdf, 0x17ccdf5f, 0x5ea6f19b,
    0x1dba598e, 0x49c3a107, 0x281a4528, 0x10efb38a, 0x6e96fc34, 0x512b0b4b, 0x340c897d, 0x7490fe33,
    0x428f3a88, 0x31c12fec, 0x68dfe19e, 0x712cdbda, 0x4f1647c7, 0x27330f28, 0x27164ecb, 0x1bf252bd,
    0x3f504332, 0x63524540, 0x5e58de44, 0x5803a51a, 0x4f117809, 0x32114a74, 0x5264e94a, 0x54189135,
    0x18099d8d, 0x285bb305, 0x6645551b, 0x379c914b, 0x1c5b16fc, 0x160a6f31, 0x5717d2f8, 0x3d891b9d,
    0x55de3397, 0x6f340b39, 0x5b9e2021, 0x473be26c, 0x3d506e9f, 0x1d18ef5e, 0x79db45d6, 0x1d8913f6,
    0x78afaf51, 0x62eb9fdd, 0x7ffcd957, 0x42499a7c, 0x5c0188f1, 0x1eb4fcfa, 0x19d03be6, 0x40a55c3e,
    0x63c67abc, 0x2a9482f2, 0x5803dabe, 0x46597b7d, 0x1c592ff4, 0x2e9c8a06, 0x3a746f24, 0x1c3a9677,
    0x6579bfd7, 0x2f8a8677, 0x4ac63e55, 0x3033076d, 0x4d44eda6, 0x729b4882, 0x108a5993, 0x4efd249f,
    0x49d768a1, 0x6abb3c6b, 0x542fde1b, 0x17d9804e, 0x14dd0c09, 0x1f52aa70, 0x42013531, 0x108128b8,
    0x184c1f1c, 0x28edf6d0, 0x2a6d5412, 0x2b93e81e, 0x278c951b, 0x6c01e1cb, 0x28dcfbff, 0x1fc284c1,
    0x4c4b4d46, 0x760bc7a4, 0x6653fa38, 0x59f500de, 0x3a3952de, 0x1d4de099, 0x791e67fd, 0x40acdab9,
    0x38f71d21, 0x6f6780e8, 0x4ec9ea8f, 0x3ae34c8f, 0x4f6bcf50, 0x470958d5, 0x59aaf32c, 0x78a38ca1,
    0x47c878ab, 0x2d05b49d, 0x272dff16, 0x17a10d30, 0x2f775473, 0x54fcbc81, 0x5034d78b, 0x5a09bc7a,
    0x323709e6, 0x31e4b4c2, 0x20bfd1cc, 0x71d444c0, 0x1ba1ec45, 0x3aae3d9e, 0x10230f1a, 0x4eca4c42,
    0x36613ad0, 0x73449356, 0x4f07bcb2, 0x798eb540, 0x1c4c60c8, 0x7a29ce2a, 0x5c7953d8, 0x11dfddfb,
    0x76b4356a, 0x46ef225b, 0x4f3ed9c9, 0x4255e0b1, 0x1a1a3bfa, 0x71c92026, 0x3cc01fc6, 0x77dcd3a3,
    0x4493e3b5, 0x187ff3cf, 0x62b7030f, 0x272b0912, 0x5219c7dc, 0x30fba593, 0x74ecace4, 0x36734f3c,
    0x6602efb0, 0x15ac59b4, 0x7c42d285, 0x6d933062, 0x64ec0e6f, 0x240e9070, 0x2048f534, 0x5afd32c4,
    0x764ac35a, 0x318b6608, 0x509da22c, 0x479f18a3, 0x10ecd9b2, 0x56f4d2bc, 0x6f5bb2b1, 0x4004203d,
    0x21a388b5, 0x2eddeacd, 0x69d38c03, 0x24f343d3, 0x475ab3a4, 0x2f0f1e79, 0x38d05f60, 0x51c979a5,
    0x4bdc29bf, 0x21567a01, 0x4da96a09, 0x52cff3f4, 0x3c7ee647, 0x5bf3e5a5, 0x6d5f353e, 0x41ce60fe,
    0x3202507a, 0x15e165a6, 0x4704d640, 0x4b192b04, 0x12d57b9a, 0x6f375a41, 0x5eb52e4d, 0x195bb847,
    0x270a66e5, 0x31ecbfba, 0x42542aa6, 0x725eab04, 0x61353d9b, 0x6b336e4e, 0x495c048c, 0x3b0a217f,
    0x4b7796ff, 0x69b05a3e, 0x1cf6813d, 0x24e3f5f5, 0x53f7b64e, 0x28cfd3cb, 0x11a231fb, 0x5349fea7,
    0x1003caca, 0x3d75c733, 0x17a3b404, 0x62a84dd5, 0x19212fb1, 0x1449fcb8, 0x5382f099, 0x47eb71c0,
    0x4347ac44, 0x3de05898, 0x1bd45cfa, 0x2a6eb4a6, 0x2788b3c3, 0x30fd1b14, 0x158e3a68, 0x16a65cc9,
    0x3a62a56e, 0x1735206c, 0x7429d620, 0x13c5ec67, 0x71000c85, 0x742a20e0, 0x4ed0c966, 0x62a261c1,
    0x24a2e049, 0x23a2f0b1, 0x77d63977, 0x78107717, 0x5f7bc3f8, 0x46bfc01d, 0x1fbc1795, 0x30fee2aa,
    0x3a2d46d3, 0x648a5b65, 0x690460fd, 0x4a8c96b8, 0x7d3b241a, 0x3e226ac9, 0x2e0e5ef3, 0x245b0182,
    0x45a5830e, 0x62c5b289, 0x663fe6b4, 0x1f5c4d48, 0x17f036ed, 0x5bf452e6, 0x73ba9981, 0x475da04a,
    0x68d5fef8, 0x65f1081e, 0x5edd249a, 0x318d5cc9, 0x7ee7c66f, 0x14dd6a73, 0x60d0813f, 0x463d6103,
    0x7c57e492, 0x12b22e23, 0x2a6134b1, 0x68214739, 0x4c315ca2, 0x1e53636f, 0x7064902e, 0x5748a5ab,
    0x3a3b1ddd, 0x2000b697, 0x32e9f0f8, 0x2a154e9a, 0x38c74385, 0x5361afdb, 0x6078004c, 0x326d9044,
    0x33ae54d8, 0x236df37c, 0x1295f36e, 0x316a74ea, 0x6bb68517, 0x407181b8, 0x2ce0cb9b, 0x77c202cc,
    0x11a6f383, 0x546cf6d0, 0x63ec9614, 0x3d2d7c2b, 0x5446eb59, 0x2611cb05, 0x4d31ac1a, 0x650b9f45,
    0x408923dd, 0x469a9295, 0x5545f2eb, 0x127ee65c, 0x2f23004c, 0x42bf3dc1, 0x55a21bc8, 0x2a47c7ae,
    0x76cfcfe7, 0x4b0558c9, 0x2f32e3f2, 0x4c9af57c, 0x46800def, 0x23ac4bee, 0x5af654a7, 0x6d339e06,
    0x56b4a1a2, 0x38759b6e, 0x7de50327, 0x5be1ab8c, 0x1d461e41, 0x2c89278a, 0x496750b5, 0x4bd4044e,
    0x6ad8030c, 0x6ab56c82, 0x7d96aa8e, 0x43deca8d, 0x2537fb44, 0x164bc297, 0x3e8ac9f4, 0x6dfd9c87,
    0x6de91e26, 0x28d89e07, 0x29f2f425, 0x6851d47d, 0x501b2ef6, 0x14f7cf13, 0x263b3a62, 0x35dcc8b0,
    0x1d4ddcf2, 0x7284c1fb, 0x407db9ec, 0x49360b5e, 0x4be00359, 0x4466beff, 0x5a7fdc01, 0x6f7daac8,
    0x66cae96c, 0x44392a60, 0x35fb95e2, 0x1dca712f, 0x19c9826b, 0x1c0fc45c, 0x3674a8cf, 0x1f5424d1,
    0x212bad97, 0x5296e934, 0x3ed9e209, 0x7e99c7ee, 0x2095762e, 0x19cfd129, 0x4c325ace, 0x1fc3d8c9,
    0x1fea5371, 0x3ca8d079, 0x6a96b85f, 0x1e82919f, 0x49a468a0, 0x63b19765, 0x5db66bfc, 0x6da828b1,
    0x31d7c4fc, 0x252b722d, 0x5228f2e5, 0x52bf1040, 0x5921a3c2, 0x50b58911, 0x18cb165b, 0x53dc368a,
    0x6ac3ac36, 0x22d52052, 0x39682b9c, 0x39ed45d0, 0x312b3195, 0x2899d82e, 0x65ef53e9, 0x25c2e453,
    0x28247321, 0x279dece6, 0x2374bc83, 0x7216f450, 0x6ff9dc17, 0x4aa276ba, 0x7a3edea7, 0x28ced40b,
    0x10bf43bb, 0x5f07a9ea, 0x5a1fbf99, 0x7db99dc1, 0x59092d4a, 0x5b6116b7, 0x4c5a3096, 0x2d0a67b4,
    0x7f500805, 0x4365e95f, 0x58530edf, 0x57ce8421, 0x793f6f2c, 0x397d2a23, 0x1c4e83b5, 0x449fc14c,
    0x48316a00, 0x5a25fd43, 0x77794456, 0x16d2a973, 0x6615abbf, 0x197be300, 0x1e7dd204, 0x6a60c2d4,
    0x3a04d3aa, 0x7716f798, 0x3fe5b9fd, 0x3ececfb3, 0x57bfad01, 0x3888334c, 0x4986d582, 0x674f0e4d,
    0x695a6f05, 0x36b1aa5d, 0x5c3c89d3, 0x225f78e3, 0x7e53fcf4, 0x263acd09, 0x472d0830, 0x672405b5,
    0x7759260f, 0x5f60a791, 0x4fda8dd9, 0x72bce703, 0x41f3e597, 0x45622235, 0x6840a40e, 0x7bd8cb0d,
    0x3366a2ca, 0x59c84135, 0x403d6010, 0x5ec31c14, 0x7df370e9, 0x43ca64d2, 0x1b86a31e, 0x602e4056,
    0x27cf4f35, 0x100e894a, 0x416b5a76, 0x30f9da15, 0x670168eb, 0x390586de, 0x77a0bf5b, 0x5935078f,
    0x516e554f, 0x142351cf, 0x355b970d, 0x3c9ca305, 0x7c4f579e, 0x7c333a5a, 0x57f572ca, 0x26d582b8,
    0x12559f1a, 0x7d082cc3, 0x3e5defd4, 0x79a2b8e5, 0x23b98701, 0x30c8f147, 0x7c97f768, 0x6357d3d0,
    0x3f75d694, 0x3b186c28, 0x7482feca, 0x5fc71db6, 0x70ef0113, 0x3a59dda4, 0x5d304737, 0x31ebdcd9,
    0x494665be, 0x635121fc, 0x4e041df0, 0x50909377, 0x47998fd6, 0x175ef171, 0x5ee31c35, 0x6c313fd1,
    0x1f6d7699, 0x11992041, 0x5aab6747, 0x30599c27, 0x4885bd48, 0x72fedeac, 0x3d39f064, 0x7ebf5eb9,
    0x3f67f323, 0x3208f8f5, 0x323bb4ce, 0x6e5879c7, 0x19cad36b, 0x7dd61759, 0x360afdc3, 0x54ad5b92,
    0x5e31855e, 0x5132fe19, 0x75d8a084, 0x3ba72e58, 0x69f2dc3d, 0x1dbecd76, 0x28613e51, 0x521a185a,
    0x2cec9749, 0x436b41ae, 0x246e846b, 0x614b7bd8, 0x7e22a1bf, 0x6498f302, 0x26646c10, 0x3db43713,
    0x788a52e2, 0x130f95b3, 0x321a7a81, 0x353ee449, 0x7b41adf2, 0x1e1239ff, 0x4a4100fe, 0x294219bc,
    0x4472a22d, 0x65cf8c27, 0x42925cc7, 0x7e76a9a9, 0x1a224ad5, 0x446e146b, 0x3e10371d, 0x4929e254,
    0x602c2f28, 0x48f4770b, 0x568cc53e, 0x77ebcdfa, 0x56a98267, 0x2c4db448, 0x36c0086b, 0x2af972dd,
    0x580463d2, 0x44a96860, 0x6c290de4, 0x52a3133b, 0x39f71eaa, 0x47780b94, 0x51fb2eea, 0x5aee6d55,
    0x20b76a2d, 0x36433225, 0x425750bb, 0x76b4fb6b, 0x1f8da99c, 0x1ea1cc51, 0x17112499, 0x587e33bd,
    0x5e182c37, 0x41886659, 0x1f4067c2, 0x2355c88c, 0x157a6d3f, 0x4235687d, 0x4ade2377, 0x49dde816,
    0x64b853f2, 0x78f956fd, 0x69adecf8, 0x3ddd7c9c, 0x577d7391, 0x521b121a, 0x16b32586, 0x4e8a6c5e,
    0x16904b5d, 0x1d181612, 0x15723a5f, 0x3fcfd99d, 0x65318693, 0x1c80bb27, 0x723de4c3, 0x10d06297,
    0x5aa73c77, 0x62b07596, 0x72d069f5, 0x33e4618d, 0x33343046, 0x53a215a3, 0x4070db32, 0x56542cbf,
    0x6fbb1141, 0x4020078b, 0x60e455bb, 0x520e566e, 0x674dbaa8, 0x3a90938f, 0x6f6b42d0, 0x6f99ecd8,
    0x69e873bc, 0x219e1df0, 0x630a97b2, 0x6a84ba3e, 0x4f992fbb, 0x28fb66ec, 0x5b61159f, 0x468d84e0,
    0x1b52cde7, 0x6483cac4, 0x494889d8, 0x6fca4efe, 0x24ac597e, 0x25f781b9, 0x74830d9d, 0x7c0a96d8,
    0x17cc49c1, 0x4993e008, 0x7bb4462e, 0x5fb596af, 0x26bfc1f0, 0x49c795f5, 0x37e6a4cc, 0x246484c2,
    0x737dd14b, 0x6e42efbd, 0x58dca6b5, 0x6b78d34f, 0x15d6b313, 0x46a415a1, 0x3b6e152b, 0x72ee7099,
    0x4c8f0e86, 0x7cff4be1, 0x3731456c, 0x7eaa06e0, 0x54e736e5, 0x488332be, 0x6cb058b9, 0x54833c62,
    0x4fce6b70, 0x64790676, 0x796a7c52, 0x754af360, 0x58021767, 0x1be0df4b, 0x32e12978, 0x290d8a1b,
    0x5859120b, 0x45e9f17b, 0x55f16569, 0x20d11ad1, 0x7d7ade9a, 0x1b86cd47, 0x73b90166, 0x7c0fbbc3,
    0x7a42ec55, 0x6a5d9eef, 0x4147daaf, 0x6c2dbf31, 0x520fd67c, 0x65546eb3, 0x7b5d1a84, 0x1c2bf35c,
    0x383ea450, 0x5ef960d3, 0x1b707626, 0x5ed5e282, 0x4012090f, 0x1606f590, 0x47476ed3, 0x21ac12e5,
    0x4445a3fa, 0x48444928, 0x205691cd, 0x7eca46c2, 0x198d4052, 0x7c0153dc, 0x542eb852, 0x5409bc5d,
    0x3b401555, 0x7c6f29ec, 0x3b3647a3, 0x519f6df3, 0x2d700644, 0x71143b98, 0x3eee7100, 0x2e7651c6,
    0x3bace25f, 0x449c9521, 0x5d0471a9, 0x7c859a13, 0x17b3a4e7, 0x7b461ec5, 0x286ed2df, 0x2362f51e,
    0x3749b51a, 0x2528dcc6, 0x15d6a9e0, 0x5350cd24, 0x1c842639, 0x649b2f61, 0x7c8cd7ed, 0x7f088866,
    0x7fbaf784, 0x3cf212da, 0x114b4a47, 0x7680c924, 0x3e68543c, 0x59dd5f6e, 0x1c023a2c, 0x18efad9f,
    0x7e33d39e, 0x6ba0095e, 0x35f16cdd, 0x70491015, 0x1f69b8ee, 0x506460eb, 0x594d739a, 0x1478c6c8
   };
    byte[] gSendKeyBytes;//加工后的加密钥
    int m_KeyEncodeIndex = 250;
    public int KeyEncodeIndex {
        get { return m_KeyEncodeIndex; }
        set { m_KeyEncodeIndex = value; }
    }
    /** 解密用字串 */
    byte[] gKeyBytes = new byte[] { 184, 187, 199, 191, 32, 195, 241, 214, 247, 32, 206, 196, 195, 247, 32, 186, 205, 208, 179, 32, 215, 212, 211, 201, 32, 198, 189, 181, 200, 32, 185, 171, 213, 253, 32, 183, 168, 214, 206, 32, 176, 174, 185, 250, 32, 190, 180, 210, 181, 32, 179, 207, 208, 197, 32, 211, 209, 201, 198 };
    /// <summary>
    /// 加密
    /// </summary>
    /// <param name="vBuffer"></param>
    /// <returns></returns>
    public byte[] BaseXorAdd(byte[] vBuffer)
    {
        ConfigEncodeKey();
        return BaseXorAdd(vBuffer, gSendKeyBytes);
    }
    /// <summary>
    /// 加密
    /// </summary>
    /// <param name="vBuffer"></param>
    /// <param name="vPassword"></param>
    /// <returns></returns>
    byte[] BaseXorAdd(byte[] vBuffer, byte[] vPassword)
    {
        int i;
        int l = vBuffer.Length;
        byte vSubBuffer;
        byte vSingleRst;
        byte ucByte = 0;
        int vKeyLeng = vPassword.Length;
        int vKeyIndex;
        for (i = 0; i < l; i++)
        {
            vKeyIndex = i % vKeyLeng;
            vSubBuffer = vBuffer[i];
            vSingleRst = (byte)(vSubBuffer ^ vPassword[vKeyIndex]);
            vSingleRst ^= ucByte;
            ucByte += vSubBuffer;
            vSingleRst ^= (byte)i;
            vSingleRst ^= 0x78;
            vSingleRst ^= 0x05;
            vSingleRst ^= 0x27;
            vBuffer[i] = vSingleRst;
        }
        return vBuffer;
    }
    /// <summary>
    /// 解密
    /// </summary>
    /// <param name="vBuffer"></param>
    /// <returns></returns>
    public byte[] BaseXorSub(byte[] vBuffer)
    {
        return BaseXorSub(vBuffer, gKeyBytes);
    }
    /// <summary>
    /// 解密
    /// </summary>
    /// <param name="vBuffer"></param>
    /// <param name="vPassword"></param>
    /// <returns></returns>
    byte[] BaseXorSub(byte[] vBuffer, byte[] vPassword)
    {
        int i;
        byte ucByte = 0;
        byte ucTemp = 0;
        int l = vBuffer.Length;
        byte vSubBuffer;
        byte vSingleRst;
        int vKeyLeng = vPassword.Length;
        int vKeyIndex;
        for (i = 0; i < l; i++)
        {
            vKeyIndex = i % vKeyLeng;
            vSubBuffer = vBuffer[i];
            vSingleRst = (byte)(vSubBuffer ^ 0x78);
            vSingleRst ^= 0x05;
            vSingleRst ^= 0x27;
            vSingleRst ^= (byte)i;
            ucByte += ucTemp;
            vSingleRst ^= ucByte;
            vSingleRst ^= vPassword[vKeyIndex];
            ucTemp = vSingleRst;
            vBuffer[i] = vSingleRst;
        }
        return vBuffer;
    }
    /// <summary>
    /// 配置加密密钥
    /// </summary>
    void ConfigEncodeKey()
    {
        int vIndex = KeyEncodeIndex % gSendKeyDict.Length;
        gSendKeyBytes = BitConverter.GetBytes((int)(gSendKeyDict[vIndex] ^ 153518004u));
        KeyEncodeIndex++;
    }
}
Main/NetworkPackage/GameNetEncode.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/GameNetEncode.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
guid: 60ade13afb439874889e483f8d22d3c1
timeCreated: 1490778989
licenseType: Free
MonoImporter:
  serializedVersion: 2
Main/NetworkPackage/GameNetPackBasic.cs
New file
@@ -0,0 +1,1133 @@
using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Collections.Generic;
/** 通迅包基类,处理字节流转换 */
public class GameNetPackBasic
{
    public ServerType socketType = ServerType.Main;
    /** 协议号 */
    protected ushort _cmd = 0;
    /** 协议号引用 */
    public ushort cmd { get { return _cmd; } }
    /** 信息转换后的字节包 */
    protected byte[] _writedBytes;
    /** 用于发送的组合帧 */
    protected byte[] _combineBytes;
    /** 信息转换后的字节包的引用 */
    public byte[] dataBytes { get { return _writedBytes; } }
    /** 用于发送的组合帧的引用 */
    public byte[] combineBytes { get { return _combineBytes; } }
    /** 字节写入位置索引 */
    protected int _writeIndex = 0;
    /** 解析位置索引 */
    protected int _readIndex = 2;
    /** 最终合并采用的协议,为0表示不调整 */
    protected ushort combineCmd = 0;
    /** 字符编码机 */
    public static Encoding StrEncoding = Encoding.UTF8;
    //自定义字段,用于后续更新用
    private Dictionary<string, object> fields;
    public void SetField(string key, object o)
    {
        if (fields == null)
            fields = new Dictionary<string, object>();
        fields[key] = o;
    }
    //获取自定义字段
    public T GetField<T>(string key)
    {
        if (fields == null)
        {
            Debug.LogErrorFormat("未设置自定义字段:{0}", key);
            return default(T);
        }
        if (fields.TryGetValue(key, out object o))
        {
            if (o is T)
                return (T)o;
            else
            {
                Debug.LogErrorFormat("自定义字段:{0},不是类型:{1}", key, typeof(T));
                return default(T);
            }
        }
        Debug.LogErrorFormat("不存在自定义字段:{0}", key);
        return default(T);
    }
    /** 子信息类型 */
    public enum NetDataType
    {
        BYTE,
        WORD,
        DWORD,
        Chars,
        Int,
        Double
    }
    /** 字符串长度写入的方式 */
    public enum StrWriteLen
    {
        BYTE,
        WORD,
        DWORD
    }
    /** 字节占用字节量 */
    public static short ByteLeng = 1;
    /** 布尔值占用字节量 */
    public static short BoolLeng = 1;
    /** 短整型占用字节量 */
    public static short ShortLeng = 2;
    /** 整型占用字节量 */
    public static short IntLeng = 4;
    /** 长整型占用字节量 */
    public static short LongLeng = 8;
    /** 双浮点型占用字节量 */
    public static short DoubleLeng = 8;
    /** 从字节包中解析信息 */
    public virtual void ReadFromBytes(byte[] vBytes)
    {
    }
    /** 将信息写成字节包 */
    public virtual void WriteToBytes()
    {
    }
    private string _vInfoCont = "";
    public string vInfoCont {
        get {
            return _vInfoCont;
        }
    }
    /** 组合帧信息 */
    public void CombineDatas(GameNetEncode encoder)
    {
        try
        {
            if (_writedBytes == null)
            {
                _writedBytes = new byte[0];
            }
            byte[] vCmdAndSubCmd = new byte[2];
            vCmdAndSubCmd[0] = (byte)((_cmd & 0xFF00) >> 8);
            vCmdAndSubCmd[1] = (byte)(_cmd & 0xFF);
            byte[] vCmdAndBody = new byte[_writedBytes.Length + vCmdAndSubCmd.Length]; // 协议与内容
            //DesignDebug.NetLog("GameNetPackBasic vCmdAndBody:" + vCmdAndBody.Length);
            Array.Copy(vCmdAndSubCmd, 0, vCmdAndBody, 0, vCmdAndSubCmd.Length);
            if (_writedBytes.Length > 0)
                Array.Copy(_writedBytes, 0, vCmdAndBody, vCmdAndSubCmd.Length, _writedBytes.Length);
            if (combineCmd != 0) // 采用另外的协议号
            {
                byte[] vExCmdAndBody = new byte[vCmdAndBody.Length + 4];
                vExCmdAndBody[0] = (byte)((combineCmd & 0xFF00) >> 8);
                vExCmdAndBody[1] = (byte)(combineCmd & 0xFF);
                var _lengthBytes = BitConverter.GetBytes((ushort)vCmdAndBody.Length);
                vExCmdAndBody[2] = _lengthBytes[0];
                vExCmdAndBody[3] = _lengthBytes[1];
                Array.Copy(vCmdAndBody, 0, vExCmdAndBody, 4, vCmdAndBody.Length);
                vCmdAndBody = vExCmdAndBody;
            }
            vCmdAndBody = encoder.BaseXorAdd(vCmdAndBody); // 加密
            _combineBytes = new byte[vCmdAndBody.Length + 6]; // 合并体
            byte[] vFrameHead = new byte[] { 255, 204 };
            byte[] vMsgBodyLength = BitConverter.GetBytes(vCmdAndBody.Length);
            Array.Copy(vFrameHead, 0, _combineBytes, 0, vFrameHead.Length);
            Array.Copy(vMsgBodyLength, 0, _combineBytes, 2, vMsgBodyLength.Length);
            Array.Copy(vCmdAndBody, 0, _combineBytes, 6, vCmdAndBody.Length);
        }
        catch (Exception ex)
        {
            Debug.LogFormat("封包信息组合异常 :{0}", ex);
        }
    }
    /** 转换字节段为布尔值 */
    protected void TransBytes(out bool vTof, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vTof = false;
            if (vNetDataType == NetDataType.BYTE)
            {
                if ((_readIndex + BoolLeng) <= vBytes.Length)
                {
                    vTof = BitConverter.ToBoolean(vBytes, _readIndex);
                    _readIndex += BoolLeng;
                }
                else
                {
                    Debug.LogError("(line:130) 字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为布尔值异常:{0}", ex);
            vTof = false;
        }
    }
    /** 转换字节段为字节 */
    protected void TransBytes(out byte vbyte, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vbyte = 0;
            if (vNetDataType == NetDataType.BYTE)
            {
                if ((_readIndex + ByteLeng) <= vBytes.Length)
                {
                    vbyte = vBytes[_readIndex];
                    _readIndex += ByteLeng;
                }
                else
                {
                    Debug.LogError("(line:189) 字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为字节异常:{0}", ex);
            vbyte = 0;
        }
    }
    /** 转换字节段为短整型 */
    protected void TransBytes(out short vShort, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vShort = 0;
            if (vNetDataType == NetDataType.WORD)
            {
                if ((_readIndex + ShortLeng) <= vBytes.Length)
                {
                    vShort = BitConverter.ToInt16(vBytes, _readIndex);
                    _readIndex += ShortLeng;
                }
                else
                {
                    Debug.LogError(" 字节包数据量不足");
                }
            }
            else if (vNetDataType == NetDataType.BYTE)
            {
                if ((_readIndex + ByteLeng) <= vBytes.Length)
                {
                    byte vTheByte = vBytes[_readIndex];
                    byte[] vTempBytes = new byte[2];
                    vTempBytes[0] = vTheByte;
                    if (vTheByte > 127)
                        vTempBytes[1] = 0xFF;
                    vShort = BitConverter.ToInt16(vTempBytes, 0);
                    // DesignDebug.NetLog("vShort:" + vShort);
                    _readIndex += ByteLeng;
                }
                else
                {
                    Debug.LogError(" 字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为短整型异常:{0}", ex);
            vShort = 0;
        }
    }
    /** 转换字节段为短整型 */
    protected void TransBytes(out ushort vShort, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vShort = 0;
            if (vNetDataType == NetDataType.WORD)
            {
                if ((_readIndex + ShortLeng) <= vBytes.Length)
                {
                    vShort = BitConverter.ToUInt16(vBytes, _readIndex);
                    _readIndex += ShortLeng;
                }
                else
                {
                    Debug.LogError("字节包数据量不足");
                }
            }
            else if (vNetDataType == NetDataType.BYTE)
            {
                if ((_readIndex + ByteLeng) <= vBytes.Length)
                {
                    vShort = (ushort)vBytes[_readIndex];
                    _readIndex += ByteLeng;
                }
                else
                {
                    Debug.LogError("字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为短整型异常:{0}", ex);
            vShort = 0;
        }
    }
    /** 转换字节段为整型 */
    protected void TransBytes(out int vInt, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vInt = 0;
            if (vNetDataType == NetDataType.DWORD || vNetDataType == NetDataType.Int)
            {
                if ((_readIndex + IntLeng) <= vBytes.Length)
                {
                    vInt = BitConverter.ToInt32(vBytes, _readIndex);
                    _readIndex += IntLeng;
                }
                else
                {
                    Debug.LogError("字节包数据量不足");
                }
            }
            else if (vNetDataType == NetDataType.BYTE)
            {
                vInt = (int)vBytes[_readIndex];
                _readIndex += 1;
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为整型异常:{0}", ex);
            vInt = 0;
        }
    }
    /** 转换字节段为整型 */
    protected void TransBytes(out uint vInt, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vInt = 0;
            if (vNetDataType == NetDataType.DWORD || vNetDataType == NetDataType.Int)
            {
                if ((_readIndex + IntLeng) <= vBytes.Length)
                {
                    vInt = BitConverter.ToUInt32(vBytes, _readIndex);
                    _readIndex += IntLeng;
                }
                else
                {
                    Debug.LogError("(line:228) 字节包数据量不足");
                }
            }
            else if (vNetDataType == NetDataType.WORD)
            {
                if ((_readIndex + ShortLeng) <= vBytes.Length)
                {
                    vInt = (uint)BitConverter.ToUInt16(vBytes, _readIndex);
                    _readIndex += ShortLeng;
                }
                else
                {
                    Debug.LogError("(line:238) 字节包数据量不足");
                }
            }
            else if (vNetDataType == NetDataType.BYTE)
            {
                vInt = (uint)vBytes[_readIndex];
                _readIndex += 1;
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为整型异常:{0}", ex);
            vInt = 0;
        }
    }
    protected void TransBytes(out byte[] bytes, byte[] vBytes, NetDataType vNetDataType, byte vLeng)
    {
        TransBytes(out bytes, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out byte[] bytes, byte[] vBytes, NetDataType vNetDataType, ushort vLeng)
    {
        TransBytes(out bytes, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out byte[] bytes, byte[] vBytes, NetDataType vNetDataType, short vLeng)
    {
        TransBytes(out bytes, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out byte[] bytes, byte[] vBytes, NetDataType vNetDataType, uint vLeng)
    {
        TransBytes(out bytes, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out byte[] bytes, byte[] vBytes, NetDataType vNetDataType, int vLeng)
    {
        try
        {
            bytes = new byte[vLeng];
            if (vNetDataType == NetDataType.BYTE)
            {
                if ((_readIndex + ByteLeng) <= vBytes.Length)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        bytes[i] = vBytes[_readIndex];
                        _readIndex += ByteLeng;
                    }
                }
                else
                {
                    Debug.LogError("字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为字节数组异常:{0}", ex);
            bytes = null;
        }
    }
    protected void TransBytes(out ushort[] uShorts, byte[] vBytes, NetDataType vNetDataType, byte vLeng)
    {
        TransBytes(out uShorts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out ushort[] uShorts, byte[] vBytes, NetDataType vNetDataType, short vLeng)
    {
        TransBytes(out uShorts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out ushort[] uShorts, byte[] vBytes, NetDataType vNetDataType, ushort vLeng)
    {
        TransBytes(out uShorts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out ushort[] uShorts, byte[] vBytes, NetDataType vNetDataType, uint vLeng)
    {
        TransBytes(out uShorts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out ushort[] uShorts, byte[] vBytes, NetDataType vNetDataType, int vLeng)
    {
        try
        {
            uShorts = new ushort[vLeng];
            if (vNetDataType == NetDataType.WORD)
            {
                if ((_readIndex + ShortLeng) <= vBytes.Length)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        uShorts[i] = BitConverter.ToUInt16(vBytes, _readIndex);
                        _readIndex += ShortLeng;
                    }
                }
                else
                {
                    Debug.LogError("(line:179) 字节包数据量不足");
                }
            }
            else if (vNetDataType == NetDataType.BYTE)
            {
                if ((_readIndex + ByteLeng) <= vBytes.Length)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        uShorts[i] = (ushort)vBytes[_readIndex];
                        _readIndex += ByteLeng;
                    }
                }
                else
                {
                    Debug.LogError("(line:189) 字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为短整型数组异常:{0}", ex);
            uShorts = null;
        }
    }
    /** 转换字节段为短整型数组 */
    protected void TransBytes(out short[] vShorts, byte[] vBytes, NetDataType vNetDataType, byte vLeng)
    {
        TransBytes(out vShorts, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为短整型数组 */
    protected void TransBytes(out short[] vShorts, byte[] vBytes, NetDataType vNetDataType, short vLeng)
    {
        TransBytes(out vShorts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out short[] vShorts, byte[] vBytes, NetDataType vNetDataType, ushort vLeng)
    {
        TransBytes(out vShorts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out short[] vShorts, byte[] vBytes, NetDataType vNetDataType, uint vLeng)
    {
        TransBytes(out vShorts, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为短整型数组 */
    protected void TransBytes(out short[] vShorts, byte[] vBytes, NetDataType vNetDataType, int vLeng)
    {
        try
        {
            vShorts = new short[vLeng];
            if (vLeng > 0)
            {
                if (vNetDataType == NetDataType.WORD)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        vShorts[i] = (short)BitConverter.ToInt16(vBytes, _readIndex);
                        _readIndex += ShortLeng;
                    }
                }
                else if (vNetDataType == NetDataType.BYTE)
                {
                    byte vTheByte;
                    byte[] vTempBytes;
                    for (int i = 0; i < vLeng; i++)
                    {
                        vTheByte = vBytes[i];
                        vTempBytes = new byte[2];
                        vTempBytes[0] = vTheByte;
                        if (vTheByte > 127)
                            vTempBytes[1] = 0xFF;
                        vShorts[i] = BitConverter.ToInt16(vTempBytes, 0);
                        _readIndex += ByteLeng;
                    }
                }
                else
                {
                    Debug.LogError("请指定正确的数据源类型");
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为短整型数组异常:{0}", ex);
            vShorts = null;
        }
    }
    /** 转换字节段为整型数组 */
    protected void TransBytes(out int[] vInts, byte[] vBytes, NetDataType vNetDataType, byte vLeng)
    {
        TransBytes(out vInts, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为整型数组 */
    protected void TransBytes(out int[] vInts, byte[] vBytes, NetDataType vNetDataType, short vLeng)
    {
        TransBytes(out vInts, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为整型数组 */
    protected void TransBytes(out int[] vInts, byte[] vBytes, NetDataType vNetDataType, ushort vLeng)
    {
        TransBytes(out vInts, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为整型数组 */
    protected void TransBytes(out int[] vInts, byte[] vBytes, NetDataType vNetDataType, uint vLeng)
    {
        TransBytes(out vInts, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为整型数组 */
    protected void TransBytes(out int[] vInts, byte[] vBytes, NetDataType vNetDataType, int vLeng)
    {
        try
        {
            vInts = new int[vLeng];
            if (vLeng > 0)
            {
                if (vNetDataType == NetDataType.DWORD || vNetDataType == NetDataType.Int)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        vInts[i] = (int)BitConverter.ToInt32(vBytes, _readIndex);
                        _readIndex += IntLeng;
                    }
                }
                else if (vNetDataType == NetDataType.WORD)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        vInts[i] = (int)BitConverter.ToInt16(vBytes, _readIndex);
                        _readIndex += ShortLeng;
                    }
                }
                else if (vNetDataType == NetDataType.BYTE)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        vInts[i] = (int)vBytes[i];
                        _readIndex += ByteLeng;
                    }
                }
                else
                {
                    Debug.LogError("请指定正确的数据源类型");
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为整型数组异常:{0}", ex);
            vInts = null;
        }
    }
    protected void TransBytes(out uint[] uInts, byte[] vBytes, NetDataType vNetDataType, byte vLeng)
    {
        TransBytes(out uInts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out uint[] uInts, byte[] vBytes, NetDataType vNetDataType, short vLeng)
    {
        TransBytes(out uInts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out uint[] uInts, byte[] vBytes, NetDataType vNetDataType, ushort vLeng)
    {
        TransBytes(out uInts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out uint[] uInts, byte[] vBytes, NetDataType vNetDataType, uint vLeng)
    {
        TransBytes(out uInts, vBytes, vNetDataType, (int)vLeng);
    }
    protected void TransBytes(out uint[] uInts, byte[] vBytes, NetDataType vNetDataType, int vLeng)
    {
        try
        {
            uInts = new uint[vLeng];
            if (vLeng > 0)
            {
                if (vNetDataType == NetDataType.DWORD || vNetDataType == NetDataType.Int)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        uInts[i] = (uint)BitConverter.ToUInt32(vBytes, _readIndex);
                        _readIndex += IntLeng;
                    }
                }
                else if (vNetDataType == NetDataType.WORD)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        uInts[i] = (uint)BitConverter.ToUInt16(vBytes, _readIndex);
                        _readIndex += ShortLeng;
                    }
                }
                else if (vNetDataType == NetDataType.BYTE)
                {
                    for (int i = 0; i < vLeng; i++)
                    {
                        uInts[i] = (uint)vBytes[i];
                        _readIndex += ByteLeng;
                    }
                }
                else
                {
                    Debug.LogError("请指定正确的数据源类型");
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为无符号整型数组异常:{0}", ex);
            uInts = null;
        }
    }
    /** 转换字节段为Double型数据 */
    protected void TransBytes(out double vDouble, byte[] vBytes, NetDataType vNetDataType)
    {
        try
        {
            vDouble = 0;
            if (vNetDataType == NetDataType.Double)
            {
                if ((_readIndex + DoubleLeng) <= vBytes.Length)
                {
                    vDouble = BitConverter.ToDouble(vBytes, _readIndex);
                    _readIndex += DoubleLeng;
                }
                else
                {
                    Debug.LogError("(line:341) 字节包数据量不足");
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为Double型数据异常:{0}", ex);
            vDouble = 0;
        }
    }
    protected void TransBytes(out string vStr, byte[] vBytes, NetDataType vNetDataType, byte vLeng)
    {
        TransBytes(out vStr, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为字符串 */
    protected void TransBytes(out string vStr, byte[] vBytes, NetDataType vNetDataType, ushort vLeng)
    {
        TransBytes(out vStr, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为字符串 */
    protected void TransBytes(out string vStr, byte[] vBytes, NetDataType vNetDataType, uint vLeng)
    {
        TransBytes(out vStr, vBytes, vNetDataType, (int)vLeng);
    }
    /** 转换字节段为字符串 */
    protected void TransBytes(out string vStr, byte[] vBytes, NetDataType vNetDataType, int vLeng)
    {
        try
        {
            vStr = "";
            if (vLeng == 0)
                return;
            if (vNetDataType == NetDataType.Chars)
            {
                if ((_readIndex + vLeng) <= vBytes.Length)
                {
                    vStr = StrEncoding.GetString(vBytes, _readIndex, vLeng);
                    _readIndex += vLeng;
                }
                else
                {
                    Debug.LogErrorFormat("(line:365) 字节包数据量不足: _readIndex {0}, vLeng {1}, vBytes.Length {2}", _readIndex, vLeng, vBytes.Length);
                }
            }
            else
            {
                Debug.LogError("请指定正确的数据源类型");
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("转换字节段为字符串异常:{0}", ex);
            vStr = string.Empty;
        }
    }
    /** 转换布尔值为字节 */
    protected void WriteBytes(bool vTof, NetDataType vType)
    {
        this.WriteBytes(BitConverter.GetBytes(vTof));
    }
    /** 转换短整型为字节 */
    protected void WriteBytes(short vShort, NetDataType vType)
    {
        this.WriteBytes((int)vShort, vType);
    }
    /** 以固定的字节长度转短整型数值数组为字节 */
    protected void WriteBytes(short[] vShorts, NetDataType vType, int vLockLeng)
    {
        this.WriteBytes(ShortsToInts(vShorts), vType, vLockLeng);
    }
    /** 以固定的字节长度转短整型数值数组为字节 */
    protected void WriteBytes(ushort[] uShorts, NetDataType vType, int vLockLeng)
    {
        this.WriteBytes(UShortsToInts(uShorts), vType, vLockLeng);
    }
    /** 以固定的字节长度转字节数组为字节 */
    protected void WriteBytes(byte[] bytes, NetDataType vType, int vLockLeng)
    {
        this.WriteBytes(BytesToInts(bytes), vType, vLockLeng);
    }
    /** 转短整型数值数组为字节 */
    protected void WriteBytes(short[] vShorts, NetDataType vType, StrWriteLen vWriteLen)
    {
        this.WriteBytes(ShortsToInts(vShorts), vType, vWriteLen);
    }
    /** 无符号短整数组转整型数组 */
    private int[] UShortsToInts(ushort[] uShorts)
    {
        try
        {
            int l = uShorts.Length;
            int[] vInts = new int[l];
            int i;
            for (i = 0; i < l; i++)
                vInts[i] = (int)uShorts[i];
            return vInts;
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
            return null;
        }
    }
    /** 短整数组转整型数组 */
    private int[] ShortsToInts(short[] vShorts)
    {
        try
        {
            int l = vShorts.Length;
            int[] vInts = new int[l];
            int i;
            for (i = 0; i < l; i++)
                vInts[i] = (int)vShorts[i];
            return vInts;
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
            return null;
        }
    }
    /** 字节数组转整型数组 */
    private int[] BytesToInts(byte[] bytes)
    {
        try
        {
            if (bytes != null)
            {
                int l = bytes.Length;
                int[] vInts = new int[l];
                int i;
                for (i = 0; i < l; i++)
                    vInts[i] = (int)bytes[i];
                return vInts;
            }
            else
            {
                int[] vInts = new int[0];
                return vInts;
            }
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
            return null;
        }
    }
    /** 转换整型为字节 */
    protected void WriteBytes(int vInt, NetDataType vType)
    {
        try
        {
            byte[] vRst;
            if (vType == NetDataType.WORD)
                vRst = BitConverter.GetBytes((short)vInt);
            else if (vType == NetDataType.BYTE)
            {
                vRst = new byte[1];
                vRst[0] = (byte)(vInt & 0xFF); // BitConverter.GetBytes ((byte)vInt);
            }
            else
                vRst = BitConverter.GetBytes((int)vInt);
            this.WriteBytes(vRst);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    protected void WriteBytes(uint[] vInts, NetDataType vType, int vLockLeng)
    {
        try
        {
            if (vInts.Length != vLockLeng)
                Array.Resize(ref vInts, vLockLeng);
            this.WriteBytes(vInts, vType);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 约束数组长度并转为字节段,不写入长度 */
    protected void WriteBytes(int[] vInts, NetDataType vType, int vLockLeng)
    {
        try
        {
            if (vInts.Length != vLockLeng)
                Array.Resize(ref vInts, vLockLeng);
            this.WriteBytes(vInts, vType);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 整型数组转为字节段,以指定的数据类型写入长度 */
    protected void WriteBytes(int[] vInts, NetDataType vType, StrWriteLen vWriteLen)
    {
        try
        {
            if (vWriteLen == StrWriteLen.BYTE)
                this.WriteBytes(new Byte[] { (byte)vInts.Length });
            else if (vWriteLen == StrWriteLen.WORD)
                this.WriteBytes(BitConverter.GetBytes((short)vInts.Length));
            else
                this.WriteBytes(BitConverter.GetBytes((int)vInts.Length));
            this.WriteBytes(vInts, vType);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 转整型数值数组为字节 */
    private void WriteBytes(uint[] vInts, NetDataType vType)
    {
        try
        {
            int l = vInts.Length;
            byte[] vRst;
            int i;
            int vBytesLen;
            if (vType == NetDataType.BYTE)
            {
                vBytesLen = l;
                vRst = new byte[vBytesLen];
                for (i = 0; i < l; i++)
                    Array.Copy(BitConverter.GetBytes((byte)vInts[i]), 0, vRst, i, 1);
            }
            else if (vType == NetDataType.WORD)
            {
                vBytesLen = l * 2;
                vRst = new byte[vBytesLen];
                for (i = 0; i < l; i++)
                    Array.Copy(BitConverter.GetBytes((short)vInts[i]), 0, vRst, i * 2, 2);
            }
            else
            {
                vBytesLen = l * 4;
                vRst = new byte[vBytesLen];
                for (i = 0; i < l; i++)
                    Array.Copy(BitConverter.GetBytes((int)vInts[i]), 0, vRst, i * 4, 4);
            }
            this.WriteBytes(vRst);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 转整型数值数组为字节 */
    private void WriteBytes(int[] vInts, NetDataType vType)
    {
        try
        {
            int l = vInts.Length;
            byte[] vRst;
            int i;
            int vBytesLen;
            if (vType == NetDataType.BYTE)
            {
                vBytesLen = l;
                vRst = new byte[vBytesLen];
                for (i = 0; i < l; i++)
                    Array.Copy(BitConverter.GetBytes((byte)vInts[i]), 0, vRst, i, 1);
            }
            else if (vType == NetDataType.WORD)
            {
                vBytesLen = l * 2;
                vRst = new byte[vBytesLen];
                for (i = 0; i < l; i++)
                    Array.Copy(BitConverter.GetBytes((short)vInts[i]), 0, vRst, i * 2, 2);
            }
            else
            {
                vBytesLen = l * 4;
                vRst = new byte[vBytesLen];
                for (i = 0; i < l; i++)
                    Array.Copy(BitConverter.GetBytes((int)vInts[i]), 0, vRst, i * 4, 4);
            }
            this.WriteBytes(vRst);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 转换双精度数值为字节段 */
    protected void WriteBytes(uint vuint, NetDataType vType)
    {
        try
        {
            byte[] vRst;
            vRst = BitConverter.GetBytes(vuint);
            this.WriteBytes(vRst);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 转换字符串为字节段,byte量定长型,不写入长度 */
    protected void WriteBytes(string vStr, NetDataType vType, int vShortLen)
    {
        if (vStr == null)
        {
            vStr = string.Empty;
        }
        try
        {
            byte[] vRst = StrEncoding.GetBytes(vStr);
            if (vRst.Length != vShortLen)
                Array.Resize(ref vRst, vShortLen);
            this.WriteBytes(vRst);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 转换字符串为字节段,动长型,前置写入长度 */
    protected void WriteBytes(string vStr, NetDataType vType, StrWriteLen vWriteLen)
    {
        try
        {
            byte[] vRst = StrEncoding.GetBytes(vStr);
            if (vWriteLen == StrWriteLen.BYTE)
                this.WriteBytes(new Byte[] { (byte)vRst.Length });
            else if (vWriteLen == StrWriteLen.WORD)
                this.WriteBytes(BitConverter.GetBytes((short)vRst.Length));
            else
                this.WriteBytes(BitConverter.GetBytes((int)vRst.Length));
            this.WriteBytes(vRst);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
    /** 写入一段字节数据 */
    private void WriteBytes(byte[] vBytes)
    {
        try
        {
            Array.Resize(ref _writedBytes, _writeIndex + vBytes.Length);
            vBytes.CopyTo(_writedBytes, _writeIndex);
            _writeIndex = _writedBytes.Length;
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
}
Main/NetworkPackage/GameNetPackBasic.cs.meta
File was renamed from Utility/StringUtility.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
guid: d2428e8224ba4d247a3aab84b19aaa9b
timeCreated: 1490779004
licenseType: Free
MonoImporter:
  serializedVersion: 2
Main/NetworkPackage/GameNetSystem.cs
New file
@@ -0,0 +1,445 @@
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
public class GameNetSystem : Singleton<GameNetSystem>
{
    // NetUpdateBehaviour m_NetUpdateBehaviour;
    NeverConnectState neverConnectState;
    AccountLoginState accountLoginState;
    // CreateOrSelectRoleState createOrSelectRoleState;
    RoleLoginState roleLoginState;
    ConnectedState connectedState;
    DisconnectState disconnectState;
    NetState m_NetState;
    public NetState netState
    {
        get { return this.m_NetState; }
        set
        {
            if (this.m_NetState != value)
            {
                switch (m_NetState)
                {
                    case NetState.NerverConnect:
                        neverConnectState.OnExit();
                        break;
                    case NetState.AccountLogin:
                        accountLoginState.OnExit();
                        break;
                    case NetState.CreateOrSelectRole:
                        // createOrSelectRoleState.OnExit();
                        break;
                    case NetState.RoleLogin:
                        roleLoginState.OnExit();
                        break;
                    case NetState.Connected:
                        connectedState.OnExit();
                        break;
                    case NetState.DisConnected:
                        disconnectState.OnExit();
                        break;
                }
                this.m_NetState = value;
                switch (m_NetState)
                {
                    case NetState.NerverConnect:
                        neverConnectState.OnEnter();
                        break;
                    case NetState.AccountLogin:
                        accountLoginState.OnEnter();
                        break;
                    case NetState.CreateOrSelectRole:
                        // createOrSelectRoleState.OnEnter();
                        break;
                    case NetState.RoleLogin:
                        roleLoginState.OnEnter();
                        break;
                    case NetState.Connected:
                        connectedState.OnEnter();
                        break;
                    case NetState.DisConnected:
                        disconnectState.OnEnter();
                        break;
                }
            }
        }
    }
    private ClientSocket mainSocket;
    public bool mainSocketConnected { get { return mainSocket == null ? false : mainSocket.connected; } }
    public float timeSinceMainSocketLastProtocol
    {
        get { return mainSocket == null ? Time.time : (float)(DateTime.Now - mainSocket.lastPackageTime).TotalSeconds; }
    }
    public bool crossServerConnected_Loigc { get; set; }
    private ClientSocket crossServerSocket;
    public bool crossServerSocketConnected { get { return crossServerConnected_Loigc && (crossServerSocket == null ? false : crossServerSocket.connected); } }
    public float timeSinceCrossServerSocketLastProtocol
    {
        get { return crossServerSocket == null ? Time.time : (float)(DateTime.Now - crossServerSocket.lastPackageTime).TotalSeconds; }
    }
    Queue<GameNetPackBasic> mainProtocolQueue = new Queue<GameNetPackBasic>();
    Queue<GameNetPackBasic> crossSeverProtocolQueue = new Queue<GameNetPackBasic>();
    public CrossServerData crossServerData { get; private set; }
    public GameNetSystem()
    {
        var gameObject = new GameObject("NetUpdateBehaviour");
        GameObject.DontDestroyOnLoad(gameObject);
        // m_NetUpdateBehaviour = gameObject.AddComponent<NetUpdateBehaviour>();
        // m_NetUpdateBehaviour.RegisterUpdateCallBack(OnUpdate);
        neverConnectState = gameObject.AddComponent<NeverConnectState>();
        accountLoginState = gameObject.AddComponent<AccountLoginState>();
        // createOrSelectRoleState = gameObject.AddComponent<CreateOrSelectRoleState>();
        roleLoginState = gameObject.AddComponent<RoleLoginState>();
        connectedState = gameObject.AddComponent<ConnectedState>();
        disconnectState = gameObject.AddComponent<DisconnectState>();
        netState = NetState.NerverConnect;
    }
    public void BeginConnectGameServer(string ip, int port, Action<bool> onConnected)
    {
        try
        {
            if (mainSocketConnected)
            {
                mainSocket.CloseConnect();
            }
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex);
        }
        mainSocket = new ClientSocket(ServerType.Main);
        mainProtocolQueue.Clear();
        mainSocket.Connect(ip, port, (bool ok) =>
        {
            if (onConnected != null)
            {
                onConnected(ok);
            }
        });
    }
    public void BeginConnectCrossServer(string ip, int port, Action<bool> onConnected)
    {
        try
        {
            crossServerConnected_Loigc = false;
            if (crossServerSocketConnected)
            {
                crossServerSocket.CloseConnect();
            }
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex);
        }
        crossServerSocket = new ClientSocket(ServerType.CrossSever);
        crossSeverProtocolQueue.Clear();
        this.crossServerSocket.Connect(ip, port, (bool ok) =>
        {
            if (onConnected != null)
            {
                onConnected(ok);
            }
        });
    }
    public void UpdateCrossServerData(string ip, int port, byte state)
    {
        this.crossServerData = new CrossServerData(ip, port, state);
        if (this.crossServerData.crossState == 0)
        {
            crossServerConnected_Loigc = false;
        }
    }
    public void SendInfo(GameNetPackBasic protocol)
    {
        if (mainSocket != null)
        {
            mainSocket.SendInfo(protocol);
            DebugPkgCache.Push(protocol);
        }
    }
    public void SendInfo(byte[] vBytes)
    {
        if (mainSocket != null)
        {
            mainSocket.SendInfo(vBytes);
        }
    }
    public void SendToCrossServer(GameNetPackBasic protocol)
    {
        if (crossServerSocket != null)
        {
            protocol.socketType = ServerType.CrossSever;
            crossServerSocket.SendInfo(protocol);
            DebugPkgCache.Push(protocol);
        }
    }
    public void PushPackage(GameNetPackBasic protocol, ServerType type)
    {
        lock (this)
        {
            if (protocol == null)
            {
                return;
            }
            if (PackageRegedit.Contain(protocol.cmd))
            {
                switch (type)
                {
                    case ServerType.Main:
                        mainProtocolQueue.Enqueue(protocol);
                        break;
                    case ServerType.CrossSever:
                        crossSeverProtocolQueue.Enqueue(protocol);
                        break;
                    default:
                        break;
                }
                DebugPkgCache.Push(protocol);
            }
            else
            {
                Debug.LogErrorFormat("数据包(cmd:{0})未登记!", protocol.cmd);
            }
        }
    }
    public void Disconnect()
    {
        try
        {
            if (mainSocket != null)
            {
                mainSocket.CloseConnect();
            }
            if (crossServerSocket != null)
            {
                crossServerSocket.CloseConnect();
            }
            mainProtocolQueue.Clear();
            crossSeverProtocolQueue.Clear();
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
        finally
        {
            netState = NetState.DisConnected;
            // var loginModel = ModelCenter.Instance.GetModel<LoginModel>();
            // loginModel.busy = false;
            // CrossServerLogin.Instance.busy = false;
        }
    }
    public void DisconnectCrossServer()
    {
        try
        {
            if (crossServerSocket != null)
            {
                crossServerSocket.CloseConnect();
            }
            crossSeverProtocolQueue.Clear();
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
        finally
        {
            // CrossServerLogin.Instance.busy = false;
        }
    }
    public void Reconnect()
    {
        try
        {
            if (mainSocket != null)
            {
                mainSocket.CloseConnect();
            }
            if (crossServerSocket != null)
            {
                crossServerSocket.CloseConnect();
            }
            mainProtocolQueue.Clear();
            crossSeverProtocolQueue.Clear();
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
        finally
        {
            netState = NetState.AccountLogin;
            // CrossServerLogin.Instance.busy = false;
            // var loginModel = ModelCenter.Instance.GetModel<LoginModel>();
            // loginModel.busy = false;
            // loginModel.ReAccountLogin();
        }
    }
    public void LoginOut()
    {
        // if (CameraController.Instance != null)
        //     CameraController.Instance.SetInGame(false);
        // DTC0102_tagCDBPlayer.isAfterPlayerDataInitialize = false;
        try
        {
            // ynmbxxjUtil.Instance.RoleLoginOut();
            crossServerConnected_Loigc = false;
            if (mainSocket != null)
            {
                mainSocket.CloseConnect();
            }
            if (crossServerSocket != null)
            {
                crossServerSocket.CloseConnect();
            }
            mainProtocolQueue.Clear();
            crossSeverProtocolQueue.Clear();
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
        finally
        {
            netState = NetState.NerverConnect;
            // CrossServerLogin.Instance.busy = false;
            // //ArenaManager.isArenaClient = false;
            // var loginModel = ModelCenter.Instance.GetModel<LoginModel>();
            // loginModel.busy = false;
            // WindowJumpMgr.Instance.ClearJumpData();
            // StageLoad.Instance.PushSceneLoadCommand(new StageLoad.StageLoadCommand()
            // {
            //     toMapId = 1,
            //     toLineId = 0,
            //     needEmpty = false,
            //     needLoadResource = true,
            //     serverType = ServerType.Main,
            //     isClientLoadMap = true
            // });
            // //CameraManager.uiCamera.clearFlags = CameraClearFlags.SolidColor;
            // //GameObject obj = GameObject.Find("NormalCanvas");
            // //int count = obj.transform.childCount;
            // //for (int i = count - 1; i >= 0; --i)
            // //{
            // //    //Debug.LogError(obj.transform.GetChild(i).name);
            // //    GameObject.Destroy(obj.transform.GetChild(i).gameObject);
            // //}
            // //SceneManager.LoadScene("Empty");
            // NetLinkWin.Hide();
            // DTC0403_tagPlayerLoginLoadOK.neverLoginOk = true;
        }
    }
    public void OnAccountLogin()
    {
        netState = NetState.AccountLogin;
    }
    public void OnEnterWorld()
    {
        netState = NetState.RoleLogin;
    }
    void OnUpdate()
    {
        lock (this)
        {
            while (mainProtocolQueue.Count > 0)
            {
                var package = mainProtocolQueue.Dequeue();
                if (package != null)
                {
                    PackageRegedit.Distribute(package);
                }
            }
            while (crossSeverProtocolQueue.Count > 0)
            {
                var package = crossSeverProtocolQueue.Dequeue();
                if (package != null)
                {
                    PackageRegedit.Distribute(package);
                }
            }
        }
    }
    public enum NetState
    {
        NerverConnect = 1,
        AccountLogin = 2,
        CreateOrSelectRole = 3,
        RoleLogin = 4,
        Connected = 5,
        DisConnected = 6,
    }
    public struct CrossServerData
    {
        public string ip;
        public int port;
        public CrossServerState crossState;
        public CrossServerData(string ip, int port, byte state)
        {
            this.ip = ip;
            this.port = port;
            this.crossState = (CrossServerState)state;
        }
    }
    public enum CrossServerState
    {
        No = 0,
        Yes = 1,
        Error = 2,
    }
}
public enum ServerType
{
    Main = 1,
    CrossSever = 2,
}
Main/NetworkPackage/GameNetSystem.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/GameNetSystem.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
guid: d15eb6a75fd16904c90f2b94e4b6a3b9
timeCreated: 1490779004
licenseType: Free
MonoImporter:
  serializedVersion: 2
Main/NetworkPackage/NetPkgCtl.cs
New file
@@ -0,0 +1,113 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
using System.IO;
public class NetPkgCtl
{
    private static List<NetPackage> packages = new List<NetPackage>(); //发送接收封包存储列表
    private static List<NetPackage> tempPackages = new List<NetPackage>();//暂停时缓存的封包列表
    public static bool stopRecieve = false;
    public static void RecordPackage(ServerType socketType, string bytes, NetPackagetType packType, string packageName, string fields, List<string> fieldDetails)
    {
#if UNITY_EDITOR
        var package = new NetPackage();
        package.socketType = socketType;
        package.time = DateTime.Now.ToString("HH:mm:ss:fff");
        package.type = packType;
        if (string.IsNullOrEmpty(packageName))
        {
            package.content = bytes.Replace(",", " ");
            var byteStr = package.content.Split(' ');
            if (byteStr.Length > 1)
            {
                package.name = StringUtility.Contact("H", byteStr[0], byteStr[1], "(未注册)");
            }
        }
        else
        {
            package.content = bytes.Replace(",", " ");
            package.name = packageName;
            package.fields = fields;
            package.fieldDetails = fieldDetails;
        }
        if (!stopRecieve)
        {
            packages.Add(package);
        }
        else
        {
            tempPackages.Add(package);
        }
#endif
    }
    public static List<NetPackage> GetPackages()
    {
        return packages;
    }
    public static List<NetPackage> GetTempPackages()
    {
        return tempPackages;
    }
    public static void WriteAllNetLog(bool @details)
    {
        if (packages != null)
        {
            var count = 0;
            var lines = new List<string>();
            for (int i = packages.Count - 1; i >= 0; i--)
            {
                if (count > 20000)
                {
                    break;
                }
                var package = packages[i];
                var line = string.Empty;
                line = StringUtility.Contact(package.type == NetPackagetType.Client ? "【发送】\t" : "【接收】\t", package.time, ":", package.name, @details ? "\r\n" : "-->" + package.fields);
                if (@details && package.fieldDetails != null)
                {
                    for (int j = 0; j < package.fieldDetails.Count; j++)
                    {
                        line = StringUtility.Contact(line, "\t\t\t", package.fieldDetails[j], "\r\n");
                    }
                }
                lines.Add(line);
                count++;
            }
            File.WriteAllLines(Application.dataPath + "/PackageLogs_" + (@details ? "details" : "abstract") + "_" + DateTime.Now.ToString("HH_mm_ss") + ".txt", lines.ToArray());
        }
    }
}
public class NetPackage
{
    public ServerType socketType;
    public bool show = false;
    public string time;
    public string serverTime;
    public string content;
    public string name;
    public NetPackagetType type;
    public string fields;
    public List<string> fieldDetails;
}
public enum NetPackagetType
{
    Client = 1,
    Server = 2,
    All = 3,
}
Main/NetworkPackage/NetPkgCtl.cs.meta
copy from Utility/StringUtility.cs.meta copy to Main/NetworkPackage/NetPkgCtl.cs.meta
File was copied from Utility/StringUtility.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: c0960ed66238bdd49b70860dfee23488
timeCreated: 1475005527
guid: e81970dd36cd37a4e99bb147804eee19
timeCreated: 1505721949
licenseType: Free
MonoImporter:
  serializedVersion: 2
Main/NetworkPackage/Socket.meta
New file
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2838f73e758458447bee2d084e64ae9d
folderAsset: yes
timeCreated: 1490778980
licenseType: Free
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
Main/NetworkPackage/Socket/ClientSocket.cs
New file
@@ -0,0 +1,451 @@
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class ClientSocket
{
    GameNetEncode encoder = new GameNetEncode();
    Socket m_Socket;
    public Socket socket { get { return m_Socket; } }
    private Thread m_packageThread;
    private byte[] bufferBytes = new byte[4096];                       // 4K,单包字节数组缓存
    private byte[] fragmentBytes;                                               //留包后的内容
    private long getBytesTotal = 0;                                            //发送的数据总量
    private long sendBytesTotal = 0;                                         //发送的数据总量
    public bool connected { get { return m_Socket == null ? false : m_Socket.Connected; } }
    ServerType socketType = ServerType.Main;
    DateTime m_LastPackageTime;
    public DateTime lastPackageTime { get { return m_LastPackageTime; } }
    bool isStopTreading = false;
    string ip;
    int port;
    Action<bool> onConnected = null;
    public ClientSocket(ServerType type)
    {
        this.socketType = type;
    }
    public void Connect(string _ip, int _port, Action<bool> _onConnected)
    {
        try
        {
            ip = _ip;
            port = _port;
            onConnected = _onConnected;
            //目前测试到异步两个问题
            // 1. BeginGetHostAddresses 不明情况下会很久才回调,导致触发超时
            // 2. 超时的情况下多次尝试登录后,会触发多次OnGetHostAddresses,导致登录异常
            //Dns.BeginGetHostAddresses(_ip, OnGetHostAddresses, null);
            IPAddress ipAddress;
#if UNITY_IPHONE
            IPHostEntry ipAddresses = Dns.GetHostEntry(_ip);
            ipAddress = ipAddresses.AddressList[0];
#else
            IPAddress[] ipAddresses = Dns.GetHostAddresses(_ip);
            ipAddress = ipAddresses[0];
#endif
            if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
            {
                Debug.Log("当前使用的网络: IPV6");
                m_Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
            }
            else
            {
                Debug.Log("当前使用的网络: IPV4");
                m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            }
            var ipEndPoint = new IPEndPoint(ipAddress, port);
            if (ipEndPoint == null)
            {
                Debug.Log("IpEndPoint is null");
            }
            m_Socket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallBack), null);
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
        }
    }
    private void OnGetHostAddresses(IAsyncResult _result)
    {
        var ipAddresses = Dns.EndGetHostAddresses(_result);
        if (ipAddresses[0].AddressFamily == AddressFamily.InterNetworkV6)
        {
            Debug.Log("当前使用的网络: IPV6");
            m_Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
        }
        else
        {
            Debug.Log("当前使用的网络: IPV4");
            m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        var ipEndPoint = new IPEndPoint(ipAddresses[0], port);
        if (ipEndPoint == null)
        {
            Debug.Log("IpEndPoint is null");
        }
        m_Socket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallBack), null);
    }
    /// <summary>
    /// 链接成功时的回调
    /// </summary>
    /// <param name="_result"></param>
    private void ConnectCallBack(IAsyncResult _result)
    {
        if (!_result.IsCompleted)
        {
            Debug.Log("链接超时!");
            CloseConnect();
            if (onConnected != null)
            {
                onConnected(false);
                onConnected = null;
            }
        }
        else
        {
            try
            {
                if (m_Socket != null && m_Socket.Connected)
                {
                    Debug.Log("确认的链接实现");
                    OnConnectSuccess();
                }
                else
                {
                    if (m_Socket != null)
                    {
                        m_Socket.Disconnect(true);
                    }
                }
            }
            catch (System.Exception ex)
            {
                Debug.Log(ex);
            }
            finally
            {
                if (onConnected != null)
                {
                    onConnected(m_Socket != null && m_Socket.Connected);
                    onConnected = null;
                }
            }
        }
        onConnected = null;
    }
    /// <summary>
    /// 关闭链接
    /// </summary>
    public void CloseConnect()
    {
        Debug.Log("==== CloseConnect");
        try
        {
            isStopTreading = true;
            if (m_packageThread != null)
            {
                m_packageThread.Abort();
            }
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex);
        }
        try
        {
            if (m_Socket != null && m_Socket.Connected)
            {
                m_Socket.Shutdown(SocketShutdown.Both);
                m_Socket.Close();
            }
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex);
        }
        sendQueue.Clear();
        m_Socket = null;
    }
    /// <summary>
    /// 链接成功
    /// </summary>
    private void OnConnectSuccess()
    {
        if (m_packageThread != null)
        {
            m_packageThread.Abort();
            m_packageThread = null;
        }
        m_LastPackageTime = DateTime.Now;
        m_packageThread = new Thread(new ThreadStart(ReceiveInfo)); // 启动线程接收信息
        m_packageThread.IsBackground = true;
        m_packageThread.Start();
        isStopTreading = false;
    }
    /// <summary>
    /// 接收信息
    /// </summary>
    private void ReceiveInfo()
    {
        while (!isStopTreading)
        {
            try
            {
                var shutdown = false;
                if (!m_Socket.Connected)
                {
                    shutdown = true;
                }
                if (!shutdown)
                {
                    var dataLength = m_Socket.Receive(bufferBytes);
                    if (dataLength <= 0)
                    {
                        shutdown = true;
                    }
                    else
                    {
                        getBytesTotal += dataLength;
                        var bytes = new byte[dataLength];
                        Array.Copy(bufferBytes, 0, bytes, 0, dataLength);
                        ReadInfo(bytes);
                    }
                }
                if (shutdown)
                {
                    isStopTreading = true;
                    m_Socket.Shutdown(SocketShutdown.Both);
                    m_Socket.Close();
                }
            }
            catch (Exception e)
            {
                Debug.Log(e);
            }
        }
    }
    static byte[] vCmdBytes = new byte[2];
    /// <summary>
    /// 阅读信息
    /// </summary>
    /// <param name="vBytes"></param>
    private void ReadInfo(byte[] vBytes)
    {
        try
        {
            byte[] fixBytes = vBytes;
            // 如果存在留包,则并包
            if (fragmentBytes != null && fragmentBytes.Length > 0)
            {
                Array.Resize(ref fixBytes, vBytes.Length + fragmentBytes.Length);
                Array.Copy(fragmentBytes, 0, fixBytes, 0, fragmentBytes.Length);
                Array.Copy(vBytes, 0, fixBytes, fragmentBytes.Length, vBytes.Length);
            }
            fragmentBytes = null; // 清理掉留包
            int vReadIndex = 0; // 初始指针
            byte[] vPackBytes;
            int vLeavingLeng = 0;
            int vBodyLeng = 0;
            int vTotalLeng = fixBytes.Length;
            GameNetPackBasic vNetpack;
            while (vReadIndex < vTotalLeng)
            {
                vLeavingLeng = vTotalLeng - vReadIndex;
                if (vLeavingLeng < 6) // 未符合包的最低限度字节量, 留包
                {
                    fragmentBytes = new byte[vLeavingLeng];
                    Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
                    break;
                }
                vBodyLeng = BitConverter.ToInt32(fixBytes, vReadIndex + 2);
                if (vBodyLeng > vLeavingLeng - 6)// 未完整的包则留包
                {
                    fragmentBytes = new byte[vLeavingLeng];
                    Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
                    break;
                }
                vPackBytes = new byte[vBodyLeng];
                Array.Copy(fixBytes, vReadIndex + 6, vPackBytes, 0, vBodyLeng); // 提取包的字节内容
                                                                                // 完整的包则读包
                vPackBytes = encoder.BaseXorSub(vPackBytes);
                Array.Copy(vPackBytes, 0, vCmdBytes, 0, 2);
                var cmd = (ushort)((ushort)(vCmdBytes[0] << 8) + vCmdBytes[1]);
                bool isRegist = false;  // 未注册封包处理
                // 处理主工程的封包
                if (PackageRegedit.Contain(cmd))
                {
                    vNetpack = PackageRegedit.TransPack(socketType, cmd, vPackBytes);
                    if (vNetpack != null)
                    {
                        if (Launch.Instance.EnableNetLog)
                        {
                            Debug.LogFormat("收包:{0}", vNetpack.GetType().Name);
                        }
                        m_LastPackageTime = DateTime.Now;
                        GameNetSystem.Instance.PushPackage(vNetpack, this.socketType);
                        isRegist = true;
                    }
                }
                vReadIndex += 6 + vBodyLeng;
                // 未注册封包处理
                if (!isRegist)
                {
#if UNITY_EDITOR
                    PackageRegedit.TransPack(socketType, cmd, vPackBytes);
#endif
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogErrorFormat("收包异常:{0}", ex);
        }
    }
    /// <summary>
    /// 发送信息
    /// </summary>
    public void SendInfo(GameNetPackBasic protocol)
    {
        if (!connected)
        {
            return;
        }
        if (protocol == null)
        {
            Debug.LogError("要发的信息对象为空");
            return;
        }
        if (Launch.Instance.EnableNetLog)
        {
            Debug.LogFormat("发包:{0}", protocol.GetType().Name);
        }
        if (protocol.combineBytes == null)
        {
            protocol.WriteToBytes();
        }
        protocol.CombineDatas(encoder);
#if UNITY_EDITOR
        NetPkgCtl.RecordPackage(socketType, protocol.vInfoCont, NetPackagetType.Client, protocol.ToString(), FieldPrint.PrintFields(protocol), FieldPrint.PrintFieldsExpand(protocol, true));
#endif
        sendBytesTotal += protocol.combineBytes.Length;
        SendBytes(protocol.combineBytes);
    }
    /// <summary>
    /// 发送信息
    /// </summary>
    /// <param name="vBytes"></param>
    public void SendInfo(byte[] vBytes)
    {
        if (!connected)
        {
            Debug.LogError("尚未与该后端链接!无法发送信息");
            return;
        }
        if (vBytes == null || vBytes.Length < 2)
        {
            Debug.LogError("要发的信息数据为空或数据不足");
            return;
        }
        vBytes = encoder.BaseXorAdd(vBytes);
        byte[] vFrameHead = new byte[] { 255, 204 };
        byte[] vMsgBodyLength = BitConverter.GetBytes(vBytes.Length);
        byte[] vTotal = new byte[vBytes.Length + 6];
        Array.Copy(vFrameHead, 0, vTotal, 0, vFrameHead.Length);
        Array.Copy(vMsgBodyLength, 0, vTotal, 2, vMsgBodyLength.Length);
        Array.Copy(vBytes, 0, vTotal, 6, vBytes.Length);
        SendBytes(vTotal);
    }
    Queue<byte[]> sendQueue = new Queue<byte[]>();
    private void SendBytes(byte[] bytes)
    {
        try
        {
            if (sendQueue.Count > 0)
            {
                sendQueue.Enqueue(bytes);
            }
            else
            {
                m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
            }
        }
        catch
        {
            Debug.LogError("网络数据包发送异常");
        }
    }
    /// <summary>
    /// 发送完成的回调
    /// </summary>
    /// <param name="vAsyncSend"></param>
    private void SendInfoCallBack(IAsyncResult vAsyncSend)
    {
        try
        {
            if (sendQueue.Count > 0)
            {
                var bytes = sendQueue.Dequeue();
                m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
            }
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }
    }
}
Main/NetworkPackage/Socket/ClientSocket.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a21face58faa9ff48aaab18157a3a6d1
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Main/NetworkPackage/readme.txt
New file
@@ -0,0 +1,14 @@
脚本目录归类:
ClientPack
前端发给后端的协议包定义
ServerPack
后端发给前端的协议包定义
Socket
Socket通迅逻辑
模块使用说明:
请使用 GameNetSystem.Inst 引用通迅系统
Main/NetworkPackage/readme.txt.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7d7ba81527e4e8b47aa40a31f36e028d
timeCreated: 1490779014
licenseType: Free
TextScriptImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Team.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da718520b160d8e42811e4591ee08143
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Team/TeamBase.Properties.cs
New file
@@ -0,0 +1,18 @@
public partial class TeamBase
{
    //  各种组队的养成系统等级
    //  阵型内卡牌的羁绊增益
    public void CalculateProperties(CardInfo cardInfo)
    {
    }
    public void CalculatePower()
    {
    }
}
Main/Team/TeamBase.Properties.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Team/TeamBase.Properties.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 7987ea50714808f4cb68eb80db70ab6b
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Team/TeamBase.cs
New file
@@ -0,0 +1,78 @@
//  阵型基础
public partial class TeamBase
{
    public TeamCard[] teamCards = new TeamCard[TeamConst.MaxTeamCardCount];
    public int GetTeamCardCount()
    {
        int count = 0;
        for (int i = 0; i < teamCards.Length; i++)
        {
            if (teamCards[i] != null)
            {
                count++;
            }
        }
        return count;
    }
    public bool SwapTeamCard(int index1, int index2)
    {
        if (index1 < 0 || index1 >= teamCards.Length || index2 < 0 || index2 >= teamCards.Length)
        {
            return false;
        }
        TeamCard temp = teamCards[index1];
        teamCards[index1] = teamCards[index2];
        teamCards[index2] = temp;
        temp.cardIndex = index2;
        teamCards[index1].cardIndex = index1;
        return true;
    }
    public bool AddTeamCard(CardInfo cardInfo)
    {
        if (cardInfo == null)
        {
            return false;
        }
        for (int i = 0; i < teamCards.Length; i++)
        {
            if (teamCards[i] == null)
            {
                teamCards[i] = new TeamCard();
                teamCards[i].cardInfo = cardInfo;
                teamCards[i].cardIndex = i;
                return true;
            }
        }
        return false;
    }
    public bool RemoveTeamCard(int index)
    {
        if (index < 0 || index >= teamCards.Length)
        {
            return false;
        }
        teamCards[index] = null;
        return true;
    }
    public bool IsFull()
    {
        return GetTeamCardCount() >= teamCards.Length;
    }
    public bool IsEmpty()
    {
        return GetTeamCardCount() == 0;
    }
}
Main/Team/TeamBase.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Team/TeamBase.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 201a5c1db01d2284f93b3099dc05bfe6
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Team/TeamCard.cs
New file
@@ -0,0 +1,17 @@
public class TeamCard
{
    public CardInfo cardInfo;
    public TeamBase teamBase;
    public int cardIndex;
    public void MergeProperties()
    {
        if (cardInfo == null)
        {
            return;
        }
    }
}
Main/Team/TeamCard.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Team/TeamCard.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 87558c063506d4345a5d8b2e4496f85c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Team/TeamConst.cs
New file
@@ -0,0 +1,6 @@
public class TeamConst
{
    public const int MaxTeamCardCount = 6;
}
Main/Team/TeamConst.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Team/TeamConst.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 9333c652da8f9af4cb78b99ae93a4a8c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/Tools.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed19de39701d6f34ca1ccc9485b759bd
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Tools/UI.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e68e1dc0a519c794a9e1f8203e8f6b2a
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Tools/UI/EffectPenetrationBlocker.cs
New file
@@ -0,0 +1,156 @@
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 特效穿透阻挡器
/// 将此脚本挂在特效游戏对象上,可以防止特效穿透UI界面
/// </summary>
public class EffectPenetrationBlocker : MonoBehaviour
{
    [Tooltip("是否在UI层级下自动调整排序顺序")]
    public bool autoAdjustSorting = true;
    [Tooltip("特效渲染器,如果为空则自动获取")]
    public Renderer[] effectRenderers;
    [Tooltip("特效粒子系统,如果为空则自动获取")]
    public ParticleSystem[] particleSystems;
    [Tooltip("自定义排序顺序,仅在不自动调整时有效")]
    public int customSortingOrder = 0;
    [Tooltip("自定义排序层,为空则使用默认UI层")]
    public string customSortingLayer = "UI";
    [Tooltip("特效所属的Canvas,如果为空则查找父级Canvas")]
    public Canvas parentCanvas;
    [Tooltip("特效在Canvas中的排序偏移量")]
    public int sortingOrderOffset = 1;
    private int canvasSortingOrder = 0;
    private void Awake()
    {
        // 如果没有指定渲染器,则自动获取
        if (effectRenderers == null || effectRenderers.Length == 0)
        {
            effectRenderers = GetComponentsInChildren<Renderer>(true);
        }
        // 如果没有指定粒子系统,则自动获取
        if (particleSystems == null || particleSystems.Length == 0)
        {
            particleSystems = GetComponentsInChildren<ParticleSystem>(true);
        }
        // 查找父级Canvas
        if (parentCanvas == null)
        {
            parentCanvas = GetComponentInParent<Canvas>();
        }
        if (autoAdjustSorting)
        {
            UpdateSortingOrder();
        }
        else
        {
            // 使用自定义排序
            ApplySortingSettings(customSortingOrder, customSortingLayer);
        }
    }
    private void OnEnable()
    {
        if (autoAdjustSorting)
        {
            UpdateSortingOrder();
        }
    }
    /// <summary>
    /// 更新排序顺序,确保特效显示在当前UI界面上方
    /// </summary>
    public void UpdateSortingOrder()
    {
        if (!autoAdjustSorting) return;
        // 获取父级Canvas的排序顺序
        if (parentCanvas != null)
        {
            canvasSortingOrder = parentCanvas.sortingOrder;
        }
        else
        {
            // 如果没有找到父级Canvas,则使用默认值
            canvasSortingOrder = 0;
        }
        // 将特效的排序顺序设置为Canvas排序顺序加上偏移量
        ApplySortingSettings(canvasSortingOrder + sortingOrderOffset, customSortingLayer);
    }
    /// <summary>
    /// 应用排序设置到所有渲染器和粒子系统
    /// </summary>
    private void ApplySortingSettings(int sortingOrder, string sortingLayer)
    {
        // 应用到渲染器
        foreach (Renderer renderer in effectRenderers)
        {
            if (renderer != null)
            {
                renderer.sortingOrder = sortingOrder;
                if (!string.IsNullOrEmpty(sortingLayer))
                {
                    renderer.sortingLayerName = sortingLayer;
                }
            }
        }
        // 应用到粒子系统
        foreach (ParticleSystem ps in particleSystems)
        {
            if (ps != null)
            {
                ParticleSystemRenderer psRenderer = ps.GetComponent<ParticleSystemRenderer>();
                if (psRenderer != null)
                {
                    psRenderer.sortingOrder = sortingOrder;
                    if (!string.IsNullOrEmpty(sortingLayer))
                    {
                        psRenderer.sortingLayerName = sortingLayer;
                    }
                }
            }
        }
    }
    /// <summary>
    /// 手动设置排序顺序
    /// </summary>
    public void SetSortingOrder(int sortingOrder, string sortingLayer = null)
    {
        customSortingOrder = sortingOrder;
        if (!string.IsNullOrEmpty(sortingLayer))
        {
            customSortingLayer = sortingLayer;
        }
        autoAdjustSorting = false;
        ApplySortingSettings(customSortingOrder, customSortingLayer);
    }
    /// <summary>
    /// 设置父级Canvas
    /// </summary>
    public void SetParentCanvas(Canvas canvas)
    {
        parentCanvas = canvas;
        if (autoAdjustSorting)
        {
            UpdateSortingOrder();
        }
    }
}
Main/Tools/UI/EffectPenetrationBlocker.cs.meta
copy from Main/Character/CharacterBase.cs.meta copy to Main/Tools/UI/EffectPenetrationBlocker.cs.meta
File was copied from Main/Character/CharacterBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 446cfdee2e270e2459fa4dbb2c33b152
guid: 39babeee8ad50ae4f9dc961d33ec973a
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
Main/UI/UIBase.cs
@@ -3,6 +3,7 @@
using UnityEngine;
using DG.Tweening;
using UnityEngine.UI; // DOTween 插件引用
using Cysharp.Threading.Tasks;
public enum UILayer
{
@@ -56,6 +57,7 @@
    // 内部状态
    protected bool isActive = false;
    protected bool isAnimating = false;
    protected bool isClosing = false; // 新增:标记是否正在关闭
    // 组件引用
    protected Canvas canvas;
@@ -149,12 +151,26 @@
        }
    }
    protected virtual void OnPreOpen()
    {
        // 子类可以重写此方法进行额外的预打开操作
    }
    protected virtual void OnPreClose()
    {
        // 子类可以重写此方法进行额外的预关闭操作
    }
    // 打开UI
    public virtual void HandleOpen()
    {
        OnPreOpen();
        // 如果正在播放动画,先停止
        StopCurrentAnimation();
        // 重置关闭标记
        isClosing = false;
        gameObject.SetActive(true);
        isActive = true;
@@ -162,24 +178,52 @@
        PlayOpenAnimation();
        OnOpen();
    }
    // 关闭UI
    // 关闭UI - 修改后的方法
    public virtual void HandleClose()
    {
        // 如果已经在关闭过程中,直接返回
        if (isClosing) return;
        OnPreClose();
        // 如果正在播放动画,先停止
        StopCurrentAnimation();
        // 设置关闭标记
        isClosing = true;
        isActive = false;
        // 禁用交互但保持可见
        if (canvasGroup != null)
        {
            canvasGroup.interactable = false;
            canvasGroup.blocksRaycasts = false;
        }
        // 根据动画类型播放关闭动画
        PlayCloseAnimation();
        // 调用关闭回调
        OnClose();
        gameObject.SetActive(false);
        isActive = false;
        // 如果没有关闭动画,直接禁用游戏对象
        if (closeAnimationType == UIAnimationType.None)
        {
            CompleteClose();
        }
        // 否则在动画完成后禁用游戏对象(在PlayCloseAnimation中处理)
    }
    public void CloseWindow()
    // 完成关闭过程 - 新增方法
    protected virtual void CompleteClose()
    {
        gameObject.SetActive(false);
        isClosing = false;
    }
    public virtual void CloseWindow()
    {
        UIManager.Instance.CloseWindow(this);
    }
@@ -206,6 +250,144 @@
        Destroy(gameObject);
    }
    #endregion
    #region 特效相关
    /// <summary>
    /// 播放UI特效
    /// </summary>
    /// <param name="effectName">特效资源名称</param>
    /// <param name="parent">特效父节点,默认为当前UI</param>
    /// <param name="autoDestroy">是否自动销毁,默认为true</param>
    /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param>
    /// <returns>特效游戏对象</returns>
    public async UniTask<GameObject> PlayUIEffect(string effectName, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f)
    {
        // 使用默认值
        if (parent == null) parent = transform;
        // 加载特效资源
        GameObject effectPrefab = await ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
        if (effectPrefab == null)
        {
            Debug.LogError($"加载UI特效失败: {effectName}");
            return null;
        }
        // 实例化特效
        GameObject effectObj = Instantiate(effectPrefab, parent);
        effectObj.name = $"Effect_{effectName}";
        // 添加特效穿透阻挡器
        EffectPenetrationBlocker blocker = effectObj.AddComponent<EffectPenetrationBlocker>();
        blocker.parentCanvas = canvas;
        blocker.UpdateSortingOrder();
        // 自动销毁
        if (autoDestroy)
        {
            Destroy(effectObj, destroyDelay);
        }
        return effectObj;
    }
    /// <summary>
    /// 在两个UI元素之间播放特效(按照sortingOrder的中间值)
    /// </summary>
    /// <param name="effectName">特效资源名称</param>
    /// <param name="frontElement">前景UI元素(Image或RawImage)</param>
    /// <param name="backElement">背景UI元素(Image或RawImage)</param>
    /// <param name="autoDestroy">是否自动销毁,默认为true</param>
    /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param>
    /// <returns>特效游戏对象</returns>
    public async UniTask<GameObject> PlayEffectBetweenUIElements(string effectName, Graphic frontElement, Graphic backElement, bool autoDestroy = true, float destroyDelay = 5f)
    {
        if (frontElement == null || backElement == null)
        {
            Debug.LogError("前景或背景UI元素为空");
            return null;
        }
        // 确保UI元素在当前UIBase的Canvas下
        if (frontElement.canvas != canvas || backElement.canvas != canvas)
        {
            Debug.LogError("UI元素不在当前UIBase的Canvas下");
            return null;
        }
        // 加载特效资源
        GameObject effectPrefab = await ResManager.Instance.LoadAsset<GameObject>("UIEffect", effectName);
        if (effectPrefab == null)
        {
            Debug.LogError($"加载UI特效失败: {effectName}");
            return null;
        }
        // 创建一个新的GameObject作为特效容器
        GameObject container = new GameObject($"EffectContainer_{effectName}");
        container.transform.SetParent(transform, false);
        // 设置容器位置
        RectTransform containerRect = container.AddComponent<RectTransform>();
        containerRect.anchorMin = new Vector2(0.5f, 0.5f);
        containerRect.anchorMax = new Vector2(0.5f, 0.5f);
        containerRect.pivot = new Vector2(0.5f, 0.5f);
        containerRect.anchoredPosition = Vector2.zero;
        containerRect.sizeDelta = new Vector2(100, 100); // 默认大小,可以根据需要调整
        // 获取前景和背景元素的siblingIndex
        int frontIndex = frontElement.transform.GetSiblingIndex();
        int backIndex = backElement.transform.GetSiblingIndex();
        // 设置特效容器的siblingIndex在两者之间
        if (frontIndex > backIndex)
        {
            // 前景在背景之后,特效应该在中间
            container.transform.SetSiblingIndex((frontIndex + backIndex) / 2 + 1);
        }
        else
        {
            // 背景在前景之后,特效应该在中间
            container.transform.SetSiblingIndex((frontIndex + backIndex) / 2);
        }
        // 实例化特效
        GameObject effectObj = Instantiate(effectPrefab, container.transform);
        effectObj.name = $"Effect_{effectName}";
        // 添加特效穿透阻挡器
        EffectPenetrationBlocker blocker = effectObj.AddComponent<EffectPenetrationBlocker>();
        // 直接设置特效渲染器的排序顺序
        Renderer[] renderers = effectObj.GetComponentsInChildren<Renderer>(true);
        foreach (Renderer renderer in renderers)
        {
            renderer.sortingOrder = canvas.sortingOrder;
            renderer.sortingLayerName = canvas.sortingLayerName;
        }
        // 设置粒子系统渲染器的排序顺序
        ParticleSystem[] particleSystems = effectObj.GetComponentsInChildren<ParticleSystem>(true);
        foreach (ParticleSystem ps in particleSystems)
        {
            ParticleSystemRenderer psRenderer = ps.GetComponent<ParticleSystemRenderer>();
            if (psRenderer != null)
            {
                psRenderer.sortingOrder = canvas.sortingOrder;
                psRenderer.sortingLayerName = canvas.sortingLayerName;
            }
        }
        // 自动销毁
        if (autoDestroy)
        {
            Destroy(container, destroyDelay);
        }
        return effectObj;
    }
    #endregion
    #region 动画方法
@@ -393,29 +575,16 @@
        }
    }
    // 播放关闭动画
    // 播放关闭动画 - 修改后的方法
    protected virtual void PlayCloseAnimation()
    {
        if (closeAnimationType == UIAnimationType.None)
        {
            // 无动画,直接禁用交互
            if (canvasGroup != null)
            {
                canvasGroup.alpha = 0f;
                canvasGroup.interactable = false;
                canvasGroup.blocksRaycasts = false;
            }
            // 无动画,直接返回,让HandleClose方法处理
            return;
        }
        isAnimating = true;
        // 禁用交互,但保持可见
        if (canvasGroup != null)
        {
            canvasGroup.interactable = false;
            canvasGroup.blocksRaycasts = false;
        }
        try
        {
@@ -496,36 +665,25 @@
                    break;
            }
            // 动画完成后的回调
            // 动画完成后的回调 - 修改为调用CompleteClose
            currentAnimation.OnComplete(() =>
            {
                isAnimating = false;
                // 确保UI不可见且不可交互
                if (canvasGroup != null)
                // 动画完成后,完成关闭过程
                if (isClosing)
                {
                    canvasGroup.alpha = 0f;
                    canvasGroup.interactable = false;
                    canvasGroup.blocksRaycasts = false;
                    CompleteClose();
                }
                // 延迟禁用GameObject,避免频繁的Enable/Disable操作
                // 如果需要立即释放资源,可以取消注释下面的代码
                // gameObject.SetActive(false);
            });
        }
        catch (System.Exception e)
        {
            Debug.LogError($"播放关闭动画时出错: {e.Message}");
            // 出错时确保UI不可见且不可交互
            if (canvasGroup != null)
            {
                canvasGroup.alpha = 0f;
                canvasGroup.interactable = false;
                canvasGroup.blocksRaycasts = false;
            }
            // 出错时直接完成关闭
            isAnimating = false;
            CompleteClose();
        }
    }
Main/UI/UIManager.cs
@@ -37,6 +37,38 @@
    #region 初始化方法
    
    #region 缓存变量
    // 缓存Transform查找结果
    private Dictionary<UILayer, Transform> layerTransformCache = new Dictionary<UILayer, Transform>();
    // 缓存层级对应的基础排序顺序
    private Dictionary<UILayer, int> layerSortingOrderCache = new Dictionary<UILayer, int>();
    #endregion
    // 初始化缓存
    private void InitCache()
    {
        // 初始化层级Transform缓存
        layerTransformCache.Clear();
        layerTransformCache[UILayer.Static] = staticTrans;
        layerTransformCache[UILayer.Bottom] = bottomTrans;
        layerTransformCache[UILayer.Mid] = midTrans;
        layerTransformCache[UILayer.Top] = topTrans;
        layerTransformCache[UILayer.System] = systemTrans;
        // 初始化层级排序顺序缓存
        layerSortingOrderCache.Clear();
        layerSortingOrderCache[UILayer.Static] = BASE_SORTING_ORDER;
        layerSortingOrderCache[UILayer.Bottom] = BASE_SORTING_ORDER * 10;
        layerSortingOrderCache[UILayer.Mid] = BASE_SORTING_ORDER * 100;
        layerSortingOrderCache[UILayer.Top] = BASE_SORTING_ORDER * 1000;
        layerSortingOrderCache[UILayer.System] = BASE_SORTING_ORDER * 10000;
    }
    // 初始化
    public void Init()
    {
@@ -91,41 +123,69 @@
    // 获取UI层级对应的基础排序顺序
    private int GetBaseSortingOrderForLayer(UILayer layer)
    {
        if (layerSortingOrderCache.TryGetValue(layer, out int order))
            return order;
        // 如果缓存中没有,使用原来的方法计算并缓存结果
        int result;
        switch (layer)
        {
            case UILayer.Static:
                return BASE_SORTING_ORDER;
                result = BASE_SORTING_ORDER;
                break;
            case UILayer.Bottom:
                return BASE_SORTING_ORDER * 10;
                result = BASE_SORTING_ORDER * 10;
                break;
            case UILayer.Mid:
                return BASE_SORTING_ORDER * 100;
                result = BASE_SORTING_ORDER * 100;
                break;
            case UILayer.Top:
                return BASE_SORTING_ORDER * 1000;
                result = BASE_SORTING_ORDER * 1000;
                break;
            case UILayer.System:
                return BASE_SORTING_ORDER * 10000;
                result = BASE_SORTING_ORDER * 10000;
                break;
            default:
                return BASE_SORTING_ORDER * 10;
                result = BASE_SORTING_ORDER * 10;
                break;
        }
        layerSortingOrderCache[layer] = result;
        return result;
    }
    // 获取层级对应的Transform
    private Transform GetTransForLayer(UILayer layer)
    {
        if (layerTransformCache.TryGetValue(layer, out Transform trans))
            return trans;
        // 如果缓存中没有,使用原来的方法获取并缓存结果
        Transform result;
        switch (layer)
        {
            case UILayer.Static:
                return staticTrans;
                result = staticTrans;
                break;
            case UILayer.Bottom:
                return bottomTrans;
                result = bottomTrans;
                break;
            case UILayer.Mid:
                return midTrans;
                result = midTrans;
                break;
            case UILayer.Top:
                return topTrans;
                result = topTrans;
                break;
            case UILayer.System:
                return systemTrans;
                result = systemTrans;
                break;
            default:
                return bottomTrans;
                result = bottomTrans;
                break;
        }
        layerTransformCache[layer] = result;
        return result;
    }
    
    // 获取UI实例,如果不存在则返回null
Utility/StringUtility.cs
File was deleted