调整部分数据表配置,优化 SpriteCache 功能

This commit is contained in:
2026-09-13 20:36:21 +08:00
parent de53890de6
commit 7dc529a840
520 changed files with 24231 additions and 967 deletions
@@ -1,7 +0,0 @@
namespace SepCore.Definition
{
public sealed partial class LevelUpRewardConfig
{
public string IconAssetName => $"levelupreward_{(Id >= 1000 ? Id - 900 : Id)}_icon";
}
}
@@ -1,8 +0,0 @@
namespace SepCore.Definition
{
public sealed partial class PropConfig
{
public string Title => Name;
public string IconAssetName => $"prop_{(Id >= 1000 ? Id - 900 : Id)}_icon";
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 37131c7b023611f4b83978960f4b3df4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,10 +0,0 @@
namespace SepCore.Definition
{
public sealed partial class RoleConfig
{
public int Id => Name == "老人" ? 102 : 101;
public string RoleName => Name;
public string IconName => $"role_{Id}_icon";
public int WeaponCapacity => 6;
}
}
@@ -1,10 +0,0 @@
namespace SepCore.Definition
{
public sealed partial class WeaponConfig
{
/// <summary>
/// 图标资源名称(映射 weapon_1_icon ~ weapon_5_icon)。
/// </summary>
public string IconAssetName => $"weapon_{(Id >= 1000 ? Id % 1000 : Id)}_icon";
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 430f837865b92144c82328dc2ce58823
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -18,6 +18,7 @@ namespace SepCore.Definition
public const int DataTableAsset = 100;
public const int DictionaryAsset = 100;
public const int FontAsset = 50;
public const int SpriteAsset = 40;
public const int MusicAsset = 20;
public const int SceneAsset = 0;
public const int SoundAsset = 30;
@@ -16,9 +16,9 @@ namespace SepCore.Definition
{
_modifiers.AddRange(prop.Modifiers);
}
Title = prop.Title;
Title = prop.Name;
Rarity = prop.Rarity;
IconAssetName = prop.IconAssetName;
IconAssetName = prop.Sprite;
}
public PropItem(IEnumerable<modifier> modifiers)
@@ -1,14 +0,0 @@
namespace SepCore.Definition
{
public enum EnemyType : byte
{
None = 0,
MeleeEnemy = 1,
RemoteEnemy = 2,
BatEnemy = 3,
SkeletonEnemy = 4,
SkeletonGiantEnemy = 5,
GhostEnemy = 6,
FireMageEnemy = 7,
}
}
@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 2aa817d65bcc425a9e015f3c1de7c9a9
timeCreated: 1770209105
@@ -1,12 +0,0 @@
namespace SepCore.Definition
{
public enum WeaponType : int
{
None = 0,
WeaponKnife = 1001,
WeaponHandgun = 1002,
WeaponSlash = 1003,
WeaponLightning = 1004,
WeaponLance = 1005,
}
}
@@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
using SepCore.Definition;
using UnityEngine;
namespace SepCore.Entity
{
[Serializable]
public class EnemyData : TargetableObjectData
{
private readonly EnemyConfig _enemyConfig;
private readonly EnemyType _enemyType;
public EnemyData(int entityId, EnemyConfig enemyConfig, EnemyType enemyType, int level)
: base(enemyConfig != null ? enemyConfig.Prefab : string.Empty, entityId, CampType.Enemy)
{
_enemyConfig = enemyConfig;
_enemyType = enemyType;
int effectiveLevel = Mathf.Max(1, level);
MaxHealthBase = _enemyConfig != null
? _enemyConfig.MaxHealth + _enemyConfig.HpAddPerLevel * (effectiveLevel - 1)
: 100;
}
public EnemyType EnemyType => _enemyType;
public override int MaxHealthBase { get; }
public int AttackDamage => _enemyConfig?.AttackDamage ?? 0;
public float AttackCooldown => _enemyConfig?.AttackCooldown ?? 1f;
public float AttackRange => _enemyConfig?.AttackRange ?? 1.5f;
public float SpeedBase => _enemyConfig?.Speed ?? 2f;
public int DropCoin => _enemyConfig?.CoinDrop ?? 0;
public int DropExp => _enemyConfig?.ExpDrop ?? 0;
public float DropPercent => _enemyConfig?.DropPercent ?? 0f;
public float Scale => _enemyConfig?.Scale ?? 1f;
public Color Color
{
get
{
if (_enemyConfig != null &&
!string.IsNullOrEmpty(_enemyConfig.Color) &&
ColorUtility.TryParseHtmlString(_enemyConfig.Color, out Color color))
{
return color;
}
return Color.white;
}
}
public IReadOnlyDictionary<string, string> Params => null;
public bool TryGetParam(string key, out string value)
{
value = null;
return false;
}
}
}
@@ -9,10 +9,6 @@ namespace SepCore.Entity
_value = value;
}
public CoinData(int value, int entityId, int typeId) : this(value, entityId, "CoinEntity")
{
}
public int Value
{
get => _value;
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using SepCore.Definition;
using UnityEngine;
namespace SepCore.Entity
{
[Serializable]
public class EnemyData : TargetableObjectData
{
private readonly EnemyConfig _enemyConfig;
public EnemyData(int entityId, EnemyConfig enemyConfig, int level)
: base(enemyConfig.Prefab, entityId, CampType.Enemy)
{
_enemyConfig = enemyConfig;
int effectiveLevel = Mathf.Max(1, level);
MaxHealthBase = enemyConfig.MaxHealth + enemyConfig.HpAddPerLevel * (effectiveLevel - 1);
}
public EnemyType EnemyType => _enemyConfig.EnemyType;
public string LogicType => _enemyConfig.LogicType;
public override int MaxHealthBase { get; }
public int AttackDamage => _enemyConfig.AttackDamage;
public float AttackCooldown => _enemyConfig.AttackCooldown;
public float AttackRange => _enemyConfig.AttackRange;
public float SpeedBase => _enemyConfig.Speed;
public int DropCoin => _enemyConfig.CoinDrop;
public int DropExp => _enemyConfig.ExpDrop;
public float DropPercent => _enemyConfig.DropPercent;
public float Scale => _enemyConfig.Scale;
public Color Color
{
get
{
// 空/非法颜色值视为无染色(乘以白色)。
return ColorUtility.TryParseHtmlString(_enemyConfig.Color, out Color color)
? color
: Color.white;
}
}
public IReadOnlyDictionary<string, string> Params => null;
public bool TryGetParam(string key, out string value)
{
value = null;
return false;
}
}
}
@@ -9,10 +9,6 @@ namespace SepCore.Entity
_value = value;
}
public ExpData(int value, int entityId, int typeId) : this(value, entityId, "ExpEntity")
{
}
public int Value
{
get => _value;
@@ -13,10 +13,6 @@ namespace SepCore.Entity
MaxHealthBase = 100;
}
public PlayerData(int entityId, int typeId) : this(entityId, "Player")
{
}
public override int MaxHealthBase { get; }
}
}
@@ -17,13 +17,15 @@ namespace SepCore.Entity
public WeaponConfig Config => _weaponConfig;
public WeaponType WeaponType => (WeaponType)_weaponConfig.Id;
public WeaponType WeaponType => _weaponConfig.WeaponType;
public string LogicType => _weaponConfig.LogicType;
public int Attack => _weaponConfig.Attack;
public string Title => _weaponConfig.Name;
public string Title => _weaponConfig.WeaponType.ToString();
public string IconAssetName => _weaponConfig.IconAssetName;
public string IconAssetName => _weaponConfig.Sprite;
public Rarity Rarity => _weaponConfig.Rarity;
@@ -9,18 +9,18 @@ namespace SepCore.Event
public override int Id => EventId;
public int RoleId { get; private set; } = -1;
public string RoleName { get; private set; }
public static SelectRoleHoverEventArgs Create(int roleId)
public static SelectRoleHoverEventArgs Create(string roleName)
{
var args = ReferencePool.Acquire<SelectRoleHoverEventArgs>();
args.RoleId = roleId;
args.RoleName = roleName;
return args;
}
public override void Clear()
{
RoleId = -1;
RoleName = null;
}
}
}
@@ -16,7 +16,8 @@ public sealed partial class EnemyConfig : Luban.BeanBase
{
public EnemyConfig(ByteBuf _buf)
{
Name = _buf.ReadString();
EnemyType = (EnemyType)_buf.ReadInt();
LogicType = _buf.ReadString();
MaxHealth = _buf.ReadInt();
HpAddPerLevel = _buf.ReadInt();
AttackDamage = _buf.ReadInt();
@@ -38,9 +39,13 @@ public sealed partial class EnemyConfig : Luban.BeanBase
}
/// <summary>
/// 名称
/// 敌人类型
/// </summary>
public readonly string Name;
public readonly EnemyType EnemyType;
/// <summary>
/// 逻辑类型
/// </summary>
public readonly string LogicType;
/// <summary>
/// 最大生命
/// </summary>
@@ -108,13 +113,15 @@ public sealed partial class EnemyConfig : Luban.BeanBase
Prefab_Ref = tables.TbEntityConfig.GetOrDefault(Prefab);
}
public override string ToString()
{
return "{ "
+ "name:" + Name + ","
+ "enemyType:" + EnemyType + ","
+ "logicType:" + LogicType + ","
+ "maxHealth:" + MaxHealth + ","
+ "hpAddPerLevel:" + HpAddPerLevel + ","
+ "attackDamage:" + AttackDamage + ","
@@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SepCore.Definition
{
/// <summary>
/// 敌人类型
/// </summary>
public enum EnemyType : byte
{
/// <summary>
/// 无
/// </summary>
None = 0,
/// <summary>
/// 近战敌人
/// </summary>
MeleeEnemy = 1,
/// <summary>
/// 远程敌人
/// </summary>
RemoteEnemy = 2,
/// <summary>
/// 蝙蝠
/// </summary>
BatEnemy = 3,
/// <summary>
/// 骷髅兵
/// </summary>
SkeletonEnemy = 4,
/// <summary>
/// 骷髅巨人
/// </summary>
SkeletonGiantEnemy = 5,
/// <summary>
/// 幽灵
/// </summary>
GhostEnemy = 6,
/// <summary>
/// 火焰法师
/// </summary>
FireMageEnemy = 7,
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6d60ad7c035b4aa4abd87deb1d572847
guid: a8fa6fc84c7516d4c88f81a40a1b61ea
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -16,7 +16,7 @@ public sealed partial class GlobalConfig : Luban.BeanBase
{
public GlobalConfig(ByteBuf _buf)
{
ElapsedTime = _buf.ReadInt();
WeaponCapacity = _buf.ReadInt();
}
public static GlobalConfig DeserializeGlobalConfig(ByteBuf _buf)
@@ -24,7 +24,10 @@ public sealed partial class GlobalConfig : Luban.BeanBase
return new GlobalConfig(_buf);
}
public readonly int ElapsedTime;
/// <summary>
/// 最大持有武器数量
/// </summary>
public readonly int WeaponCapacity;
public const int __ID__ = -958250779;
public override int GetTypeId() => __ID__;
@@ -37,7 +40,7 @@ public sealed partial class GlobalConfig : Luban.BeanBase
public override string ToString()
{
return "{ "
+ "elapsedTime:" + ElapsedTime + ","
+ "weaponCapacity:" + WeaponCapacity + ","
+ "}";
}
}
@@ -18,7 +18,9 @@ public sealed partial class GoodsConfig : Luban.BeanBase
{
Id = _buf.ReadInt();
GoodsType = (GoodsType)_buf.ReadInt();
GoodsTypeId = _buf.ReadInt();
PropId = _buf.ReadInt();
PropId_Ref = null;
WeaponType = (WeaponType)_buf.ReadInt();
}
public static GoodsConfig DeserializeGoodsConfig(ByteBuf _buf)
@@ -35,9 +37,14 @@ public sealed partial class GoodsConfig : Luban.BeanBase
/// </summary>
public readonly GoodsType GoodsType;
/// <summary>
/// 商品对应物品Id
/// 道具商品Id
/// </summary>
public readonly int GoodsTypeId;
public readonly int PropId;
public PropConfig PropId_Ref;
/// <summary>
/// 武器商品类型
/// </summary>
public readonly WeaponType WeaponType;
public const int __ID__ = 1358452248;
public override int GetTypeId() => __ID__;
@@ -46,15 +53,17 @@ public sealed partial class GoodsConfig : Luban.BeanBase
{
PropId_Ref = tables.TbPropConfig.GetOrDefault(PropId);
}
public override string ToString()
{
return "{ "
+ "Id:" + Id + ","
+ "GoodsType:" + GoodsType + ","
+ "GoodsTypeId:" + GoodsTypeId + ","
+ "id:" + Id + ","
+ "goodsType:" + GoodsType + ","
+ "propId:" + PropId + ","
+ "weaponType:" + WeaponType + ","
+ "}";
}
}
@@ -20,6 +20,8 @@ public sealed partial class LevelUpRewardConfig : Luban.BeanBase
Title = _buf.ReadString();
Rarity = (Rarity)_buf.ReadInt();
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);Modifiers = new System.Collections.Generic.List<modifier>(n0);for(var i0 = 0 ; i0 < n0 ; i0++) { modifier _e0; _e0 = modifier.Deserializemodifier(_buf); Modifiers.Add(_e0);}}
Sprite = _buf.ReadString();
Sprite_Ref = null;
}
public static LevelUpRewardConfig DeserializeLevelUpRewardConfig(ByteBuf _buf)
@@ -40,6 +42,11 @@ public sealed partial class LevelUpRewardConfig : Luban.BeanBase
/// </summary>
public readonly Rarity Rarity;
public readonly System.Collections.Generic.List<modifier> Modifiers;
/// <summary>
/// 图标
/// </summary>
public readonly string Sprite;
public SpriteConfig Sprite_Ref;
public const int __ID__ = 1603299856;
public override int GetTypeId() => __ID__;
@@ -50,6 +57,7 @@ public sealed partial class LevelUpRewardConfig : Luban.BeanBase
foreach (var _e in Modifiers) { _e?.ResolveRef(tables); }
Sprite_Ref = tables.TbSpriteConfig.GetOrDefault(Sprite);
}
public override string ToString()
@@ -59,6 +67,7 @@ public sealed partial class LevelUpRewardConfig : Luban.BeanBase
+ "title:" + Title + ","
+ "rarity:" + Rarity + ","
+ "modifiers:" + Luban.StringUtil.CollectionToString(Modifiers) + ","
+ "sprite:" + Sprite + ","
+ "}";
}
}
@@ -21,6 +21,8 @@ public sealed partial class PropConfig : Luban.BeanBase
Rarity = (Rarity)_buf.ReadInt();
Price = _buf.ReadInt();
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);Modifiers = new System.Collections.Generic.List<modifier>(n0);for(var i0 = 0 ; i0 < n0 ; i0++) { modifier _e0; _e0 = modifier.Deserializemodifier(_buf); Modifiers.Add(_e0);}}
Sprite = _buf.ReadString();
Sprite_Ref = null;
}
public static PropConfig DeserializePropConfig(ByteBuf _buf)
@@ -45,6 +47,11 @@ public sealed partial class PropConfig : Luban.BeanBase
/// </summary>
public readonly int Price;
public readonly System.Collections.Generic.List<modifier> Modifiers;
/// <summary>
/// 图标
/// </summary>
public readonly string Sprite;
public SpriteConfig Sprite_Ref;
public const int __ID__ = 91068581;
public override int GetTypeId() => __ID__;
@@ -56,6 +63,7 @@ public sealed partial class PropConfig : Luban.BeanBase
foreach (var _e in Modifiers) { _e?.ResolveRef(tables); }
Sprite_Ref = tables.TbSpriteConfig.GetOrDefault(Sprite);
}
public override string ToString()
@@ -66,6 +74,7 @@ public sealed partial class PropConfig : Luban.BeanBase
+ "rarity:" + Rarity + ","
+ "price:" + Price + ","
+ "modifiers:" + Luban.StringUtil.CollectionToString(Modifiers) + ","
+ "sprite:" + Sprite + ","
+ "}";
}
}
@@ -24,6 +24,8 @@ public sealed partial class RoleConfig : Luban.BeanBase
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);InitialItems = new System.Collections.Generic.List<int>(n0);for(var i0 = 0 ; i0 < n0 ; i0++) { int _e0; _e0 = _buf.ReadInt(); InitialItems.Add(_e0);}}
Prefab = _buf.ReadString();
Prefab_Ref = null;
Sprite = _buf.ReadString();
Sprite_Ref = null;
}
public static RoleConfig DeserializeRoleConfig(ByteBuf _buf)
@@ -42,6 +44,8 @@ public sealed partial class RoleConfig : Luban.BeanBase
public readonly System.Collections.Generic.List<int> InitialItems;
public readonly string Prefab;
public EntityConfig Prefab_Ref;
public readonly string Sprite;
public SpriteConfig Sprite_Ref;
public const int __ID__ = -1280631944;
public override int GetTypeId() => __ID__;
@@ -55,6 +59,7 @@ public sealed partial class RoleConfig : Luban.BeanBase
foreach (var _e in Modifiers) { _e?.ResolveRef(tables); }
Prefab_Ref = tables.TbEntityConfig.GetOrDefault(Prefab);
Sprite_Ref = tables.TbSpriteConfig.GetOrDefault(Sprite);
}
public override string ToString()
@@ -67,6 +72,7 @@ public sealed partial class RoleConfig : Luban.BeanBase
+ "modifiers:" + Luban.StringUtil.CollectionToString(Modifiers) + ","
+ "initialItems:" + Luban.StringUtil.CollectionToString(InitialItems) + ","
+ "prefab:" + Prefab + ","
+ "sprite:" + Sprite + ","
+ "}";
}
}
@@ -17,12 +17,12 @@ namespace SepCore.Definition
/// </summary>
public partial class TbEnemyConfig
{
private readonly System.Collections.Generic.Dictionary<string, EnemyConfig> _dataMap;
private readonly System.Collections.Generic.Dictionary<EnemyType, EnemyConfig> _dataMap;
private readonly System.Collections.Generic.List<EnemyConfig> _dataList;
public TbEnemyConfig(ByteBuf _buf)
{
_dataMap = new System.Collections.Generic.Dictionary<string, EnemyConfig>();
_dataMap = new System.Collections.Generic.Dictionary<EnemyType, EnemyConfig>();
_dataList = new System.Collections.Generic.List<EnemyConfig>();
for(int n = _buf.ReadSize() ; n > 0 ; --n)
@@ -30,16 +30,16 @@ public partial class TbEnemyConfig
EnemyConfig _v;
_v = EnemyConfig.DeserializeEnemyConfig(_buf);
_dataList.Add(_v);
_dataMap.Add(_v.Name, _v);
_dataMap.Add(_v.EnemyType, _v);
}
}
public System.Collections.Generic.Dictionary<string, EnemyConfig> DataMap => _dataMap;
public System.Collections.Generic.Dictionary<EnemyType, EnemyConfig> DataMap => _dataMap;
public System.Collections.Generic.List<EnemyConfig> DataList => _dataList;
public EnemyConfig GetOrDefault(string key) => _dataMap.TryGetValue(key, out var v) ? v : null;
public EnemyConfig Get(string key) => _dataMap[key];
public EnemyConfig this[string key] => _dataMap[key];
public EnemyConfig GetOrDefault(EnemyType key) => _dataMap.TryGetValue(key, out var v) ? v : null;
public EnemyConfig Get(EnemyType key) => _dataMap[key];
public EnemyConfig this[EnemyType key] => _dataMap[key];
public void ResolveRef(Tables tables)
{
@@ -30,7 +30,10 @@ public partial class TbGlobalConfig
}
public int ElapsedTime => _data.ElapsedTime;
/// <summary>
/// 最大持有武器数量
/// </summary>
public int WeaponCapacity => _data.WeaponCapacity;
public void ResolveRef(Tables tables)
{
@@ -17,12 +17,12 @@ namespace SepCore.Definition
/// </summary>
public partial class TbWeaponConfig
{
private readonly System.Collections.Generic.Dictionary<int, WeaponConfig> _dataMap;
private readonly System.Collections.Generic.Dictionary<WeaponType, WeaponConfig> _dataMap;
private readonly System.Collections.Generic.List<WeaponConfig> _dataList;
public TbWeaponConfig(ByteBuf _buf)
{
_dataMap = new System.Collections.Generic.Dictionary<int, WeaponConfig>();
_dataMap = new System.Collections.Generic.Dictionary<WeaponType, WeaponConfig>();
_dataList = new System.Collections.Generic.List<WeaponConfig>();
for(int n = _buf.ReadSize() ; n > 0 ; --n)
@@ -30,16 +30,16 @@ public partial class TbWeaponConfig
WeaponConfig _v;
_v = WeaponConfig.DeserializeWeaponConfig(_buf);
_dataList.Add(_v);
_dataMap.Add(_v.Id, _v);
_dataMap.Add(_v.WeaponType, _v);
}
}
public System.Collections.Generic.Dictionary<int, WeaponConfig> DataMap => _dataMap;
public System.Collections.Generic.Dictionary<WeaponType, WeaponConfig> DataMap => _dataMap;
public System.Collections.Generic.List<WeaponConfig> DataList => _dataList;
public WeaponConfig GetOrDefault(int key) => _dataMap.TryGetValue(key, out var v) ? v : null;
public WeaponConfig Get(int key) => _dataMap[key];
public WeaponConfig this[int key] => _dataMap[key];
public WeaponConfig GetOrDefault(WeaponType key) => _dataMap.TryGetValue(key, out var v) ? v : null;
public WeaponConfig Get(WeaponType key) => _dataMap[key];
public WeaponConfig this[WeaponType key] => _dataMap[key];
public void ResolveRef(Tables tables)
{
@@ -16,8 +16,8 @@ public sealed partial class WeaponConfig : Luban.BeanBase
{
public WeaponConfig(ByteBuf _buf)
{
Id = _buf.ReadInt();
Name = _buf.ReadString();
WeaponType = (WeaponType)_buf.ReadInt();
LogicType = _buf.ReadString();
Rarity = (Rarity)_buf.ReadInt();
Price = _buf.ReadInt();
Attack = _buf.ReadInt();
@@ -28,6 +28,8 @@ public sealed partial class WeaponConfig : Luban.BeanBase
{int n0 = System.Math.Min(_buf.ReadSize(), _buf.Size);Modifiers = new System.Collections.Generic.List<modifier>(n0);for(var i0 = 0 ; i0 < n0 ; i0++) { modifier _e0; _e0 = modifier.Deserializemodifier(_buf); Modifiers.Add(_e0);}}
Prefab = _buf.ReadString();
Prefab_Ref = null;
Sprite = _buf.ReadString();
Sprite_Ref = null;
}
public static WeaponConfig DeserializeWeaponConfig(ByteBuf _buf)
@@ -36,13 +38,13 @@ public sealed partial class WeaponConfig : Luban.BeanBase
}
/// <summary>
/// 武器id
/// 武器类型
/// </summary>
public readonly int Id;
public readonly WeaponType WeaponType;
/// <summary>
/// 武器名
/// 逻辑类型
/// </summary>
public readonly string Name;
public readonly string LogicType;
/// <summary>
/// 道具品质
/// </summary>
@@ -77,6 +79,11 @@ public sealed partial class WeaponConfig : Luban.BeanBase
/// </summary>
public readonly string Prefab;
public EntityConfig Prefab_Ref;
/// <summary>
/// 图标
/// </summary>
public readonly string Sprite;
public SpriteConfig Sprite_Ref;
public const int __ID__ = 127041694;
public override int GetTypeId() => __ID__;
@@ -94,13 +101,14 @@ public sealed partial class WeaponConfig : Luban.BeanBase
foreach (var _e in Modifiers) { _e?.ResolveRef(tables); }
Prefab_Ref = tables.TbEntityConfig.GetOrDefault(Prefab);
Sprite_Ref = tables.TbSpriteConfig.GetOrDefault(Sprite);
}
public override string ToString()
{
return "{ "
+ "id:" + Id + ","
+ "name:" + Name + ","
+ "weaponType:" + WeaponType + ","
+ "logicType:" + LogicType + ","
+ "rarity:" + Rarity + ","
+ "price:" + Price + ","
+ "attack:" + Attack + ","
@@ -110,6 +118,7 @@ public sealed partial class WeaponConfig : Luban.BeanBase
+ "parameters:" + Luban.StringUtil.CollectionToString(Parameters) + ","
+ "modifiers:" + Luban.StringUtil.CollectionToString(Modifiers) + ","
+ "prefab:" + Prefab + ","
+ "sprite:" + Sprite + ","
+ "}";
}
}
@@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SepCore.Definition
{
/// <summary>
/// 武器类型
/// </summary>
public enum WeaponType : byte
{
/// <summary>
/// 无
/// </summary>
None = 0,
/// <summary>
/// 小刀
/// </summary>
Knife = 1,
/// <summary>
/// 手枪
/// </summary>
Handgun = 2,
/// <summary>
/// 斧头
/// </summary>
Axe = 3,
/// <summary>
/// 闪电
/// </summary>
Lightning = 4,
/// <summary>
/// 长枪
/// </summary>
Lance = 5,
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1e4fe53d087154645ad496d2f178c843
guid: 98dbb9ae443a07e4284d96741de14f3d
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -19,8 +19,7 @@ public sealed partial class enemySpawnConfig : Luban.BeanBase
{
public enemySpawnConfig(ByteBuf _buf)
{
EnemyName = _buf.ReadString();
EnemyName_Ref = null;
EnemyType = (EnemyType)_buf.ReadInt();
EnemyCount = _buf.ReadInt();
Interval = _buf.ReadInt();
}
@@ -33,8 +32,7 @@ public sealed partial class enemySpawnConfig : Luban.BeanBase
/// <summary>
/// 要出的怪名
/// </summary>
public readonly string EnemyName;
public EnemyConfig EnemyName_Ref;
public readonly EnemyType EnemyType;
/// <summary>
/// 一次出的数量
/// </summary>
@@ -49,7 +47,7 @@ public sealed partial class enemySpawnConfig : Luban.BeanBase
public void ResolveRef(Tables tables)
{
EnemyName_Ref = tables.TbEnemyConfig.GetOrDefault(EnemyName);
}
@@ -57,7 +55,7 @@ public sealed partial class enemySpawnConfig : Luban.BeanBase
public override string ToString()
{
return "{ "
+ "enemyName:" + EnemyName + ","
+ "enemyType:" + EnemyType + ","
+ "enemyCount:" + EnemyCount + ","
+ "interval:" + Interval + ","
+ "}";
@@ -65,9 +65,12 @@ namespace SepCore.CustomUtility
return Utility.Text.Format("Assets/GameMain/UI/UISounds/{0}.wav", assetName);
}
public static string GetUITextureIconAsset(string assetName)
/// <summary>
/// 获取图片资源路径,assetName 为相对 Assets/GameMain/Textures 的路径,需包含扩展名
/// </summary>
public static string GetSpriteAsset(string assetName)
{
return Utility.Text.Format("Assets/GameMain/UI/UISprites/Icons/{0}.png", assetName);
return Utility.Text.Format("Assets/GameMain/Textures/{0}", assetName);
}
}
}
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SepCore.Definition;
using SepCore.Entity;
@@ -18,8 +19,8 @@ namespace SepCore.Editor
private int _selectedIndex;
private int _addCount = 1;
private Vector2 _scroll;
private PropConfig[] _allProps = Array.Empty<PropConfig>();
private PropConfig[] _filteredProps = Array.Empty<PropConfig>();
private IReadOnlyList<PropConfig> _allProps;
private IReadOnlyList<PropConfig> _filteredProps;
private string[] _displayNames = Array.Empty<string>();
private float _spawnRateScaleInput = 1f;
@@ -188,7 +189,7 @@ namespace SepCore.Editor
if (selectedProp == null) return;
_scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.Height(120f));
EditorGUILayout.LabelField("Title", selectedProp.Title);
EditorGUILayout.LabelField("Title", selectedProp.Name);
EditorGUILayout.LabelField("Rarity", selectedProp.Rarity.ToString());
EditorGUILayout.LabelField("Description");
EditorGUILayout.HelpBox(ItemDescUtility.CreatePropDescription(selectedProp.Modifiers), MessageType.None);
@@ -215,7 +216,7 @@ namespace SepCore.Editor
player.AddProp(new PropItem(selectedProp));
}
ShowNotification(new GUIContent($"Added Buff: {selectedProp.Title} x{_addCount}"));
ShowNotification(new GUIContent($"Added Buff: {selectedProp.Name} x{_addCount}"));
}
private void RefreshPropList()
@@ -227,16 +228,15 @@ namespace SepCore.Editor
_displayNames = Array.Empty<string>();
return;
}
var table = GameEntry.Luban.GetTable<PropConfig>();
_allProps = table != null ? table.ToArray() : Array.Empty<PropConfig>();
_allProps = GameEntry.Luban.GetTable<PropConfig>();
_selectedIndex = 0;
ApplyFilter(_searchText);
}
private void ApplyFilter(string searchText)
{
if (_allProps == null || _allProps.Length == 0)
if (_allProps == null || _allProps.Count == 0)
{
_filteredProps = Array.Empty<PropConfig>();
_displayNames = Array.Empty<string>();
@@ -252,11 +252,11 @@ namespace SepCore.Editor
string keyword = searchText.Trim();
_filteredProps = _allProps.Where(p =>
p != null &&
(p.Title?.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0 ||
(p.Name?.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0 ||
p.Id.ToString().Contains(keyword))).ToArray();
}
_displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Title} ({p.Rarity})").ToArray();
_displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Name} ({p.Rarity})").ToArray();
if (_displayNames.Length == 0)
{
_selectedIndex = 0;
@@ -268,8 +268,8 @@ namespace SepCore.Editor
private PropConfig GetSelectedProp()
{
if (_filteredProps == null || _filteredProps.Length == 0) return null;
_selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Length - 1);
if (_filteredProps == null || _filteredProps.Count == 0) return null;
_selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Count - 1);
return _filteredProps[_selectedIndex];
}
@@ -1,5 +1,6 @@
using System;
using Cysharp.Threading.Tasks;
using SepCore.AsyncTask;
using SepCore.Event;
using TMPro;
using UnityEngine;
@@ -68,7 +69,7 @@ namespace SepCore.UI
if (_iconArea != null && !string.IsNullOrEmpty(_context.IconAssetName))
{
string iconAssetName = _context.IconAssetName;
var sprite = await GameEntry.SpriteCache.GetSprite(iconAssetName);
var sprite = await SpriteLoader.LoadSpriteByKeyAsync(iconAssetName);
if (_context != null && _context.IconAssetName == iconAssetName)
{
_iconArea.OnInit(sprite, context.Rarity);
@@ -59,7 +59,7 @@ namespace SepCore.UI
Icon = null,
Rarity = reward.Rarity,
Description = ItemDescUtility.CreatePropDescription(reward.Modifiers),
IconAssetName = reward.IconAssetName
IconAssetName = reward.Sprite
});
}
@@ -1,4 +1,5 @@
using Cysharp.Threading.Tasks;
using SepCore.AsyncTask;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -42,7 +43,7 @@ namespace SepCore.UI
if (string.IsNullOrEmpty(iconAssetName)) return;
var sprite = await GameEntry.SpriteCache.GetSprite(iconAssetName);
var sprite = await SpriteLoader.LoadSpriteByKeyAsync(iconAssetName);
_iconArea.SetIcon(sprite);
}
}
@@ -1,4 +1,5 @@
using Cysharp.Threading.Tasks;
using SepCore.AsyncTask;
using SepCore.Event;
using UnityEngine;
using UnityEngine.UI;
@@ -29,7 +30,7 @@ namespace SepCore.UI
if (_iconArea != null)
{
var sprite = await GameEntry.SpriteCache.GetSprite(_context.IconAssetName);
var sprite = await SpriteLoader.LoadSpriteByKeyAsync(_context.IconAssetName);
_iconArea.OnInit(sprite, context.Rarity);
}
}
@@ -8,7 +8,7 @@ namespace SepCore.UI
{
public class GoodsItemContext : UIContext
{
public string Title;
public string Name;
public Rarity Rarity;
public Sprite Icon;
public ItemType ItemType;
@@ -17,7 +17,7 @@ namespace SepCore.UI
public GoodsItemContext()
{
Title = string.Empty;
Name = string.Empty;
Description = string.Empty;
Rarity = Rarity.White;
Price = 0;
@@ -29,7 +29,7 @@ namespace SepCore.UI
{
if (rawData == null)
{
Title = string.Empty;
Name = string.Empty;
Description = string.Empty;
Rarity = Rarity.White;
Price = 0;
@@ -45,25 +45,25 @@ namespace SepCore.UI
if (rawData.DataRow == null)
{
Icon = null;
Title = string.Empty;
Name = string.Empty;
}
else if (ItemType == ItemType.Weapon)
{
if (rawData.DataRow is WeaponConfig weaponConfig)
{
Title = weaponConfig.Name;
Name = weaponConfig.WeaponType.ToString();
Description = ItemDescUtility.CreateWeaponDescription(weaponConfig);
}
else if (rawData.DataRow is WeaponData weaponData)
{
Title = weaponData.Title;
Name = weaponData.Title;
Description = ItemDescUtility.CreateWeaponDescription(weaponData);
}
}
else
{
var prop = (PropConfig)rawData.DataRow;
Title = prop.Title;
Name = prop.Name;
Description = ItemDescUtility.CreatePropDescription(prop.Modifiers);
}
}
@@ -1,8 +1,8 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using SepCore.AsyncTask;
using SepCore.Definition;
using SepCore.Entity;
using SepCore.Entity.Weapon;
using UnityGameFramework.Runtime;
namespace SepCore.UI
@@ -164,13 +164,13 @@ namespace SepCore.UI
var context = new GoodsItemContext(rawData);
context.Icon = context.ItemType switch
{
ItemType.Weapon => await GameEntry.SpriteCache.GetSprite(rawData.DataRow switch
ItemType.Weapon => await SpriteLoader.LoadSpriteByKeyAsync(rawData.DataRow switch
{
WeaponConfig weaponConfig => weaponConfig.IconAssetName,
WeaponConfig weaponConfig => weaponConfig.Sprite,
WeaponData weaponData => weaponData.IconAssetName,
_ => string.Empty
}),
ItemType.Prop => await GameEntry.SpriteCache.GetSprite(((PropConfig)rawData.DataRow).IconAssetName),
ItemType.Prop => await SpriteLoader.LoadSpriteByKeyAsync(((PropConfig)rawData.DataRow).Sprite),
_ => null
};
return context;
@@ -1,7 +1,7 @@
using Cysharp.Threading.Tasks;
using SepCore.Event;
using SepCore.Definition;
using SepCore.Entity.Weapon;
using SepCore.Entity;
using GameFramework.Event;
using UnityEngine;
using UnityGameFramework.Runtime;
@@ -22,7 +22,7 @@ namespace SepCore.UI
public void Init(GoodsItemContext data)
{
_iconArea.OnInit(data.Icon, data.Rarity);
_titleText.text = data.Title;
_titleText.text = data.Name;
_typeText.text = data.ItemType switch
{
ItemType.None => "error",
@@ -1,4 +1,5 @@
using Cysharp.Threading.Tasks;
using SepCore.AsyncTask;
using SepCore.Event;
using UnityEngine;
using UnityEngine.UI;
@@ -19,7 +20,7 @@ namespace SepCore.UI
return;
}
_roleImage.sprite = await GameEntry.SpriteCache.GetSprite(_context.IconName);
_roleImage.sprite = await SpriteLoader.LoadSpriteByKeyAsync(_context.IconName);
}
public void OnReset()
@@ -34,7 +35,7 @@ namespace SepCore.UI
return;
}
GameEntry.Event.Fire(this, SelectRoleHoverEventArgs.Create(_context.RoleId));
GameEntry.Event.Fire(this, SelectRoleHoverEventArgs.Create(_context.RoleName));
}
public void OnConfirmRoleClick()
@@ -2,7 +2,7 @@ namespace SepCore.UI
{
public class RoleItemContext : UIContext
{
public int RoleId;
public string RoleName;
public string IconName;
}
}
@@ -50,7 +50,7 @@ namespace SepCore.UI
RoleItemRawData itemRawData = rawData.RoleItems[i];
roleItems[i] = new RoleItemContext
{
RoleId = itemRawData.RoleId,
RoleName = itemRawData.RoleName,
IconName = itemRawData.IconName
};
}
@@ -60,7 +60,7 @@ namespace SepCore.UI
{
propertyContext = new RolePropertyAreaContext
{
RoleName = rawData.SelectedRole.RoleName,
RoleName = rawData.SelectedRole.Name,
InitialPropertyText = ItemDescUtility.CreatePropDescription(rawData.SelectedRole.InitialProperties)
?? string.Empty
};
@@ -168,7 +168,7 @@ namespace SepCore.UI
return;
}
SelectRoleRawData rawData = _useCase.SelectRole(args.RoleId);
SelectRoleRawData rawData = _useCase.SelectRole(args.RoleName);
await OpenUIAsync(rawData);
}
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Text;
using SepCore.Definition;
using SepCore.Entity;
using SepCore.Entity.Weapon;
using UnityGameFramework.Runtime;
namespace SepCore.CustomUtility
@@ -87,7 +87,7 @@ namespace SepCore.Procedure
GameEntry.InputModule?.SetGameplayExploreContext();
CurrentLevel = 1;
_currentPlayerData = new PlayerData(-1, 1001);
_currentPlayerData = new PlayerData(-1);
EnterAsync(procedureOwner).Forget();
}
@@ -130,11 +130,9 @@ namespace SepCore.Procedure
GameEntry.CameraModule?.SetTarget(Player != null ? Player.CachedTransform : null);
await GameEntry.UIRouter.OpenUIAsync(UIFormType.HudForm);
int selectedRoleId = procedureOwner.GetData<VarInt32>("SelectedRoleId").Value;
var roles = GameEntry.Luban.GetTable<RoleConfig>();
var role = roles.FirstOrDefault(r => r.Id == selectedRoleId)
?? (selectedRoleId >= 0 && selectedRoleId < roles.Count ? roles[selectedRoleId] : roles[0]);
var expConfig = GameEntry.Luban.Get<LevelExperienceConfig>(role.Name);
string selectedRoleName = procedureOwner.GetData<VarString>("SelectedRoleName").Value;
var role = GameEntry.Luban.Get<RoleConfig>(selectedRoleName);
var expConfig = GameEntry.Luban.Get<LevelExperienceConfig>(selectedRoleName);
Player.InitRole(role, expConfig);
InitGameState();
@@ -13,11 +13,11 @@ namespace SepCore.Procedure
private bool _startGame = false;
private int _selectedRoleId = 0;
private string _selectedRoleName = null;
public void ConfirmSelectRole(int roleId)
public void ConfirmSelectRole(string roleName)
{
_selectedRoleId = roleId;
_selectedRoleName = roleName;
_startGame = true;
}
@@ -50,7 +50,7 @@ namespace SepCore.Procedure
if (_startGame)
{
procedureOwner.SetData<VarInt32>("NextSceneType", (int)SceneType.Game);
procedureOwner.SetData<VarInt32>("SelectedRoleId", _selectedRoleId);
procedureOwner.SetData<VarString>("SelectedRoleName", _selectedRoleName);
ChangeState<ProcedureChangeScene>(procedureOwner);
}
}
@@ -5,7 +5,6 @@ using SepCore.EnemyManager;
using SepCore.HPBar;
using SepCore.InputModule.Runtime;
using SepCore.CameraModule;
using SepCore.SpriteCache;
using SepCore.UIRouter;
using SepCore.Simulation;
using SepCore.Timer;
@@ -27,8 +26,6 @@ public partial class GameEntry
public static SimulationWorld SimulationWorld { get; private set; }
public static SpriteCacheComponent SpriteCache { get; private set; }
public static UIRouterComponent UIRouter { get; private set; }
public static InputModuleComponent InputModule { get; private set; }
@@ -45,7 +42,6 @@ public partial class GameEntry
DamageText = UnityGameFramework.Runtime.GameEntry.GetComponent<DamageTextComponent>();
EnemyManager = UnityGameFramework.Runtime.GameEntry.GetComponent<EnemyManagerComponent>();
SimulationWorld = UnityGameFramework.Runtime.GameEntry.GetComponent<SimulationWorld>();
SpriteCache = UnityGameFramework.Runtime.GameEntry.GetComponent<SpriteCacheComponent>();
UIRouter = UnityGameFramework.Runtime.GameEntry.GetComponent<UIRouterComponent>();
InputModule = UnityGameFramework.Runtime.GameEntry.GetComponent<InputModuleComponent>();
CameraModule = UnityGameFramework.Runtime.GameEntry.GetComponent<CameraModuleComponent>();
@@ -5,7 +5,6 @@ using Cysharp.Threading.Tasks;
using SepCore.CustomUtility;
using SepCore.Definition;
using SepCore.Entity;
using SepCore.Entity.Weapon;
using UnityGameFramework.Runtime;
using HideEntityCompleteEventArgs = UnityGameFramework.Runtime.HideEntityCompleteEventArgs;
using ShowEntityFailureEventArgs = UnityGameFramework.Runtime.ShowEntityFailureEventArgs;
@@ -162,22 +161,11 @@ namespace SepCore.AsyncTask
float timeout = 30f,
CancellationToken cancellationToken = default)
{
if (data == null)
{
Log.Warning("Enemy data is invalid.");
return UniTask.FromResult<EnemyBase>(null);
}
Type enemyType = TryGetType(data.EnemyType.ToString());
Type enemyType = GetLogicType(data.LogicType);
EntityConfig entityConfig = GameEntry.Luban.Get<EntityConfig>(data.AssetName);
if (enemyType == null || entityConfig == null)
{
Log.Warning("Can not load enemy logic type or entity config for assetName '{0}'.", data.AssetName);
return UniTask.FromResult<EnemyBase>(null);
}
return entityComponent
.ShowEntityAsync(data.Id, enemyType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), "Enemy",
return entityComponent.ShowEntityAsync(
data.Id, enemyType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), "Enemy",
Constant.AssetPriority.EnemyAsset, data, timeout, cancellationToken)
.ContinueWith(entity => entity?.Logic as EnemyBase);
}
@@ -190,22 +178,11 @@ namespace SepCore.AsyncTask
float timeout = 30f,
CancellationToken cancellationToken = default)
{
if (data == null)
{
Log.Warning("Weapon data is invalid.");
return UniTask.FromResult<WeaponBase>(null);
}
Type weaponType = TryGetType("Weapon." + data.WeaponType);
Type weaponType = GetLogicType(data.LogicType);
EntityConfig entityConfig = GameEntry.Luban.Get<EntityConfig>(data.AssetName);
if (weaponType == null || entityConfig == null)
{
Log.Warning("Can not load weapon logic type or entity config for assetName '{0}'.", data.AssetName);
return UniTask.FromResult<WeaponBase>(null);
}
return entityComponent
.ShowEntityAsync(data.Id, weaponType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), "Weapon",
return entityComponent.ShowEntityAsync(
data.Id, weaponType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), "Weapon",
Constant.AssetPriority.WeaponAsset, data, timeout, cancellationToken)
.ContinueWith(entity => entity?.Logic as WeaponBase);
}
@@ -298,24 +275,13 @@ namespace SepCore.AsyncTask
float timeout,
CancellationToken cancellationToken) where T : EntityLogic
{
if (data == null)
{
Log.Warning("Data is invalid.");
return UniTask.FromResult<T>(null);
}
EntityConfig entityConfig = GameEntry.Luban.Get<EntityConfig>(data.AssetName);
if (entityConfig == null)
{
Log.Warning("Can not load entity assetName '{0}' from data table.", data.AssetName);
return UniTask.FromResult<T>(null);
}
return entityComponent.ShowEntityAsync<T>(data.Id, AssetUtility.GetEntityAsset(entityConfig.PrefabPath),
entityGroupName, priority, data, timeout, cancellationToken);
}
private static Type TryGetType(string rawTypeName)
private static Type GetLogicType(string rawTypeName)
{
string typeName = EntityNamespace + rawTypeName;
if (!_typeDict.TryGetValue(typeName, out Type type))
@@ -323,8 +289,7 @@ namespace SepCore.AsyncTask
type = Type.GetType(typeName);
if (type == null)
{
Log.Warning("Can not load entity type '{0}'.", typeName);
return null;
throw new InvalidOperationException($"Can not load entity type '{typeName}'.");
}
_typeDict.Add(typeName, type);
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using GameFramework.Resource;
using UnityGameFramework.Runtime;
@@ -20,14 +21,33 @@ namespace SepCore.AsyncTask
/// <param name="resourceComponent">资源组件</param>
/// <param name="assetName">资源名称</param>
/// <param name="priority">加载优先级</param>
/// <returns>加载完成的资源</returns>
public static UniTask<T> LoadAssetAsync<T>(this ResourceComponent resourceComponent, string assetName, int priority = 0)
/// <param name="userData">用户自定义数据</param>
/// <param name="progress">加载进度</param>
/// <param name="timeout">超时时间(秒),0表示不超时</param>
/// <returns>加载的资源</returns>
public static UniTask<T> LoadAssetAsync<T>(this ResourceComponent resourceComponent,
string assetName,
int priority = 0,
object userData = null,
IProgress<float> progress = null,
float timeout = 0f) where T : class
{
var tcs = AutoResetUniTaskCompletionSource<T>.Create();
resourceComponent.LoadAsset(assetName, priority, new LoadAssetCallbacks(
(_, asset, _, _) => tcs.TrySetResult((T)asset),
(_, _, errorMessage, _) => tcs.TrySetException(new Exception(errorMessage))
));
var tcs = new UniTaskCompletionSource<T>();
var callbacks = new LoadAssetCallbacks(
(name, asset, duration, ud) => tcs.TrySetResult((T)asset),
(name, status, errorMessage, ud) => tcs.TrySetException(new Exception($"加载资源失败: {name}, status: {status}, error: {errorMessage}")),
(name, p, ud) => progress?.Report(p)
);
resourceComponent.LoadAsset(assetName, typeof(T), priority, callbacks, userData);
if (timeout > 0f)
{
UniTask.Delay(TimeSpan.FromSeconds(timeout), cancellationToken: CancellationToken.None)
.ContinueWith(() => tcs.TrySetException(new TimeoutException($"加载资源超时: {assetName}, {timeout}秒")));
}
return tcs.Task;
}
@@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using SepCore.CustomUtility;
using SepCore.Definition;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace SepCore.AsyncTask
{
/// <summary>
/// 图集 Sprite 加载器,通过图集名 + 序号定位 Sprite。
/// 序号 -1 表示图集本身就是一张完整 Sprite,不需要切分。
/// </summary>
public static class SpriteLoader
{
private const float DefaultPixelsPerUnit = 32f;
private static readonly Dictionary<string, Texture2D> _textureCache = new();
private static readonly Dictionary<string, Task<Texture2D>> _loadingTextures = new();
private static readonly Dictionary<string, Dictionary<int, Sprite>> _spriteCache = new();
/// <summary>
/// 异步加载图集 Sprite
/// </summary>
/// <param name="config">Sprite 配置</param>
/// <param name="tileSize">切分块尺寸(像素),默认 32</param>
/// <param name="pixelsPerUnit">Sprite 像素单位比,默认 32</param>
/// <param name="timeout">超时时间(秒),0 表示不超时</param>
/// <returns>加载的 Sprite,失败时返回 null</returns>
public static UniTask<Sprite> LoadSpriteAsync(SpriteConfig config, int tileSize = 32,
float pixelsPerUnit = DefaultPixelsPerUnit, float timeout = 0f)
{
return LoadSpriteAsync(config.AtlasPath, config.SpriteIndex, tileSize, pixelsPerUnit, timeout);
}
/// <summary>
/// 异步加载图集 Sprite,按资源键查 tbspriteconfig 表定位
/// </summary>
/// <param name="key">tbspriteconfig 的资源键</param>
/// <param name="tileSize">切分块尺寸(像素),默认 32</param>
/// <param name="pixelsPerUnit">Sprite 像素单位比,默认 32</param>
/// <param name="timeout">超时时间(秒),0 表示不超时</param>
/// <returns>加载的 Sprite,失败时返回 null</returns>
public static UniTask<Sprite> LoadSpriteByKeyAsync(string key, int tileSize = 32,
float pixelsPerUnit = DefaultPixelsPerUnit, float timeout = 0f)
{
SpriteConfig config = global::GameEntry.Luban.Get<SpriteConfig>(key);
if (config == null)
{
Log.Error("Sprite config not found: {0}", key);
return default;
}
return LoadSpriteAsync(config, tileSize, pixelsPerUnit, timeout);
}
/// <summary>
/// 异步加载图集 Sprite
/// </summary>
/// <param name="atlasName">图集名称(相对 Assets/GameMain/Textures 的路径,含扩展名,如 32rogues/monsters.png)</param>
/// <param name="index">序号,-1 表示整张图集作为一张 Sprite</param>
/// <param name="tileSize">切分块尺寸(像素),默认 32</param>
/// <param name="pixelsPerUnit">Sprite 像素单位比,默认 32</param>
/// <param name="timeout">超时时间(秒),0 表示不超时</param>
/// <returns>加载的 Sprite,失败时返回 null</returns>
public static async UniTask<Sprite> LoadSpriteAsync(string atlasName, int index, int tileSize = 32,
float pixelsPerUnit = DefaultPixelsPerUnit, float timeout = 0f)
{
Texture2D texture = await GetTextureAsync(atlasName, timeout);
if (texture == null)
{
return null;
}
int cacheKey = index < 0 ? -1 : index;
if (!_spriteCache.TryGetValue(atlasName, out Dictionary<int, Sprite> sprites))
{
sprites = new Dictionary<int, Sprite>();
_spriteCache[atlasName] = sprites;
}
if (sprites.TryGetValue(cacheKey, out Sprite cached))
{
return cached;
}
Sprite sprite = CreateSprite(texture, cacheKey, tileSize, pixelsPerUnit);
if (sprite != null)
{
sprites[cacheKey] = sprite;
}
return sprite;
}
/// <summary>
/// 释放指定图集的所有 Sprite 和纹理引用
/// </summary>
public static void Release(string atlasName)
{
if (_spriteCache.TryGetValue(atlasName, out Dictionary<int, Sprite> sprites))
{
foreach (Sprite sprite in sprites.Values)
{
if (sprite != null)
{
UnityEngine.Object.Destroy(sprite);
}
}
sprites.Clear();
_spriteCache.Remove(atlasName);
}
if (_textureCache.TryGetValue(atlasName, out Texture2D texture))
{
global::GameEntry.Resource.UnloadAsset(texture);
_textureCache.Remove(atlasName);
}
}
/// <summary>
/// 释放所有图集的 Sprite 和纹理引用
/// </summary>
public static void ReleaseAll()
{
List<string> atlasNames = new List<string>(_textureCache.Keys);
foreach (string atlasName in atlasNames)
{
Release(atlasName);
}
}
private static async UniTask<Texture2D> GetTextureAsync(string atlasName, float timeout)
{
if (_textureCache.TryGetValue(atlasName, out Texture2D cached))
{
return cached;
}
if (_loadingTextures.TryGetValue(atlasName, out Task<Texture2D> loading))
{
return await loading;
}
Task<Texture2D> task = LoadTextureAsync(atlasName, timeout).AsTask();
_loadingTextures[atlasName] = task;
try
{
Texture2D texture = await task;
if (texture != null)
{
_textureCache[atlasName] = texture;
}
return texture;
}
finally
{
_loadingTextures.Remove(atlasName);
}
}
private static async UniTask<Texture2D> LoadTextureAsync(string atlasName, float timeout)
{
try
{
return await global::GameEntry.Resource.LoadAssetAsync<Texture2D>(
AssetUtility.GetSpriteAsset(atlasName), Constant.AssetPriority.SpriteAsset, timeout: timeout);
}
catch (Exception e)
{
Log.Error("加载图集失败: {0}, error: {1}", atlasName, e);
return null;
}
}
private static Sprite CreateSprite(Texture2D texture, int index, int tileSize, float pixelsPerUnit)
{
if (index < 0)
{
return Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height),
new Vector2(0.5f, 0.5f), pixelsPerUnit, 0, SpriteMeshType.FullRect);
}
int columns = Mathf.Max(1, texture.width / tileSize);
int rows = Mathf.Max(1, texture.height / tileSize);
int column = index % columns;
int row = index / columns;
if (row >= rows)
{
Log.Error("图集 {0} 序号 {1} 超出范围 (cols: {2}, rows: {3})", texture.name, index, columns, rows);
return null;
}
float x = column * tileSize;
float y = texture.height - (row + 1) * tileSize;
// 交互描边需要完整矩形网格,才能在 Shader 中为图案四周扩展留白。
return Sprite.Create(texture, new Rect(x, y, tileSize, tileSize),
new Vector2(0.5f, 0.5f), pixelsPerUnit, 0, SpriteMeshType.FullRect);
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a30aae743bbd22b4cac1ef60f96a1bed
guid: d7c896f5a3874033ab7cb99a06dbc0b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -1,23 +1,10 @@
using System;
using System.Collections.Generic;
using SepCore.Definition;
using UnityGameFramework.Runtime;
using SepCore.CustomUtility;
namespace SepCore.Entity
{
public static class EntityExtension
{
private static int s_SerialId = -10;
private static int _serialId = 0;
private const string EntityNamespace = "SepCore.Entity.";
private static readonly Dictionary<string, Type> _typeDict;
static EntityExtension()
{
_typeDict = new Dictionary<string, Type>();
}
public static EntityBase GetGameEntity(this EntityComponent entityComponent, int entityId)
{
@@ -41,116 +28,9 @@ namespace SepCore.Entity
entityComponent.AttachEntity(entityBase.Entity, ownerId, parentTransformPath, userData);
}
public static void ShowEntity<T>(this EntityComponent entityComponent, EntityDataBase data, string group,
int priority) where T : EntityBase
{
if (data == null)
{
Log.Warning("Data is invalid.");
return;
}
EntityConfig entityConfig = GameEntry.Luban.Get<EntityConfig>(data.AssetName);
if (entityConfig == null)
{
Log.Warning("Can not load entity assetName '{0}' from data table.", data.AssetName);
return;
}
entityComponent.ShowEntity(data.Id, typeof(T), AssetUtility.GetEntityAsset(entityConfig.PrefabPath), group,
priority, data);
}
public static void ShowPlayer(this EntityComponent entityComponent, PlayerData data)
{
entityComponent.ShowEntity(typeof(Player), "Player", Constant.AssetPriority.PlayerAsset, data);
}
public static void ShowEnemy(this EntityComponent entityComponent, EnemyData data)
{
if (data == null)
{
Log.Warning("Enemy data is invalid.");
return;
}
var enemyType = TryGetType(data.EnemyType.ToString());
entityComponent.ShowEntity(enemyType, "Enemy", Constant.AssetPriority.EnemyAsset, data);
}
public static void ShowWeapon(this EntityComponent entityComponent, WeaponData data)
{
if (data == null)
{
Log.Warning("Weapon data is invalid.");
return;
}
var weaponType = TryGetType("Weapon." + data.WeaponType);
entityComponent.ShowEntity(weaponType, "Weapon", Constant.AssetPriority.WeaponAsset, data);
}
public static void ShowEffect(this EntityComponent entityComponent, EffectData data)
{
entityComponent.ShowEntity(typeof(Effect), "Effect", Constant.AssetPriority.EffectAsset, data);
}
public static void ShowCoin(this EntityComponent entityComponent, CoinData data)
{
entityComponent.ShowEntity(typeof(CoinEntity), "Drop", Constant.AssetPriority.EffectAsset, data);
}
public static void ShowExp(this EntityComponent entityComponent, ExpData data)
{
entityComponent.ShowEntity(typeof(ExpEntity), "Drop", Constant.AssetPriority.EffectAsset, data);
}
private static void ShowEntity(this EntityComponent entityComponent, Type logicType, string entityGroup,
int priority, EntityDataBase data)
{
if (data == null)
{
Log.Warning("Data is invalid.");
return;
}
EntityConfig entityConfig = GameEntry.Luban.Get<EntityConfig>(data.AssetName);
if (entityConfig == null)
{
Log.Warning("Can not load entity assetName '{0}' from data table.", data.AssetName);
return;
}
entityComponent.ShowEntity(data.Id, logicType, AssetUtility.GetEntityAsset(entityConfig.PrefabPath), entityGroup,
priority, data);
}
private static Type TryGetType(string rawTypeName)
{
string typeName = EntityNamespace + rawTypeName;
if (!_typeDict.TryGetValue(typeName, out Type type))
{
type = Type.GetType(typeName);
if (type == null)
{
Log.Warning("Can not load entity type '{0}'.", typeName);
return null;
}
_typeDict.Add(typeName, type);
}
return type;
}
public static int NextId(this EntityComponent entityComponent)
{
return --s_SerialId;
}
public static int SerialId(this EntityComponent entityComponent)
{
return ++_serialId;
}
}
}
@@ -1,7 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using SepCore.Entity;
using SepCore.Entity.Weapon;
using UnityEngine;
namespace SepCore.Components
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using SepCore.Definition;
using SepCore.Entity.Weapon;
using SepCore.Entity;
using UnityEngine;
@@ -8,11 +7,6 @@ namespace SepCore.Components
{
public class BackpackComponent : MonoBehaviour
{
/// <summary>
/// 武器槽容量,由 RoleConfig 决定。
/// </summary>
private int _weaponCapacity;
/// <summary>
/// 玩家类引用。
/// </summary>
@@ -40,14 +34,13 @@ namespace SepCore.Components
public IReadOnlyList<WeaponBase> Weapons => _weapons;
public IReadOnlyList<PropItem> Props => _props;
public int WeaponCapacity => _weaponCapacity;
public int WeaponCapacity => GameEntry.Luban.Global.WeaponCapacity;
public void OnInit(Player player, int weaponCapacity)
public void OnInit(Player player)
{
_weaponCapacity = weaponCapacity;
_player = player;
_weapons = new List<WeaponBase>(_weaponCapacity);
_weapons = new List<WeaponBase>(WeaponCapacity);
_props = new List<PropItem>();
_statComponent = GetComponent<StatComponent>();
}
@@ -60,7 +53,7 @@ namespace SepCore.Components
public bool AttachWeapon(WeaponBase weapon)
{
if (_weapons.Count == _weaponCapacity) return false;
if (_weapons.Count == WeaponCapacity) return false;
GameEntry.Entity.AttachEntity(weapon.Id, _player.Id, _weaponSlots[_weapons.Count]);
_weapons.Add(weapon);
weapon.SetEnabled(true);
@@ -19,7 +19,7 @@ namespace SepCore.EnemyManager
private EnemyRegistry _enemyRegistry;
private EnemySpawnScheduler _spawnScheduler;
public IReadOnlyCollection<EntityBase> Enemies => _enemyRegistry?.Enemies;
public IReadOnlyCollection<EntityBase> Enemies => _enemyRegistry.Enemies;
[SerializeField] private int _spawnEnemyMaxCount = 5000;
[SerializeField] private int _spawnDistanceFromPlayer = 20;
@@ -38,10 +38,10 @@ namespace SepCore.EnemyManager
// 此时 _isStopped 为真,由 OnShowEntitySuccess 在出生瞬间兜底 Hide 掉。
private bool _isStopped;
public float SpawnRateScale => _spawnScheduler?.SpawnRateScale ?? 1f;
public float SpawnRateScale => _spawnScheduler.SpawnRateScale;
public float BattleDuration => _duration;
public float ElapsedBattleTime => _spawnScheduler?.ElapsedTime ?? 0f;
public int CurrentEnemyCount => _enemyRegistry?.Count ?? 0;
public float ElapsedBattleTime => _spawnScheduler.ElapsedTime;
public int CurrentEnemyCount => _enemyRegistry.Count;
#region Lifecycle
@@ -71,9 +71,15 @@ namespace SepCore.EnemyManager
public void OnInit(LevelConfig level, Player player)
{
if (player == null)
{
Log.Error("Can not init enemy manager without a player.");
return;
}
_isStopped = false;
_player = player != null ? player.CachedTransform : null;
_player = player.CachedTransform;
_spawnPositionStrategy = new RandomCircleSpawnStrategy(_spawnDistanceFromPlayer);
_baseDuration = level.Duration;
@@ -116,14 +122,13 @@ namespace SepCore.EnemyManager
_currentLevel = 0;
_baseDuration = 0;
_duration = 0;
_player = null;
}
#endregion
private async UniTaskVoid SpawnEnemyAsync(EnemyType enemyType)
{
if (_player == null) return;
if (_enemyRegistry.Count >= _spawnEnemyMaxCount) return;
int entityId = _currentSpawnEnemyId++;
@@ -198,7 +203,7 @@ namespace SepCore.EnemyManager
private void OnShowEntitySuccess(object sender, GameEventArgs e)
{
if (e is not ShowEntitySuccessEventArgs ne) return;
if (ne.Entity.EntityGroup?.Name != EnemyGroupName)
if (ne.Entity.EntityGroup.Name != EnemyGroupName)
{
return;
}
@@ -6,6 +6,8 @@ namespace SepCore.EnemyManager
public class EnemyRegistry
{
private readonly Dictionary<int, EntityBase> _enemyById;
// PruneInvalidEntries 由 OnUpdate 每帧调用,复用缓冲避免每帧分配。
private readonly List<int> _pruneBuffer;
public int Count => _enemyById.Count;
public IReadOnlyCollection<EntityBase> Enemies => _enemyById.Values;
@@ -13,11 +15,11 @@ namespace SepCore.EnemyManager
public EnemyRegistry()
{
_enemyById = new Dictionary<int, EntityBase>();
_pruneBuffer = new List<int>();
}
public void Register(EnemyBase enemy)
{
if (enemy == null) return;
_enemyById[enemy.Id] = enemy;
}
@@ -35,16 +37,16 @@ namespace SepCore.EnemyManager
public void PruneInvalidEntries()
{
var invalidIds = new List<int>();
_pruneBuffer.Clear();
foreach (var kvp in _enemyById)
{
if (kvp.Value == null || !kvp.Value.Available)
{
invalidIds.Add(kvp.Key);
_pruneBuffer.Add(kvp.Key);
}
}
foreach (int id in invalidIds)
foreach (int id in _pruneBuffer)
{
_enemyById.Remove(id);
}
@@ -1,7 +1,7 @@
using System;
using SepCore.CustomUtility;
using SepCore.Definition;
using SepCore.Timer;
using UnityGameFramework.Runtime;
using UnityEngine;
namespace SepCore.EnemyManager
@@ -20,7 +20,7 @@ namespace SepCore.EnemyManager
public float SpawnRateScale => _spawnRateScale;
public float ElapsedTime => _elapsedTime;
public int WaveCount => _enemyTypes?.Length ?? 0;
public int WaveCount => _enemyTypes.Length;
public void Init(LevelConfig level, Action<EnemyType, int> onSpawn)
{
@@ -37,7 +37,7 @@ namespace SepCore.EnemyManager
{
var spawnConfig = level.EnemySpawnConfigs[i];
_baseIntervals[i] = spawnConfig.Interval / 1000f;
_enemyTypes[i] = EntityDataFactory.GetEnemyType(spawnConfig.EnemyName);
_enemyTypes[i] = spawnConfig.EnemyType;
_spawnCounts[i] = spawnConfig.EnemyCount;
}
@@ -57,8 +57,13 @@ namespace SepCore.EnemyManager
public void SetSpawnRateScale(float scale)
{
if (_waveHandles == null)
{
Log.Error("Can not set spawn rate scale before scheduler init.");
return;
}
_spawnRateScale = Mathf.Max(MinSpawnRateScale, scale);
if (_waveHandles == null) return;
for (int i = 0; i < _waveHandles.Length; i++)
{
@@ -81,7 +86,7 @@ namespace SepCore.EnemyManager
private void OnWaveTick(int waveIndex)
{
_onSpawn?.Invoke(_enemyTypes[waveIndex], _spawnCounts[waveIndex]);
_onSpawn(_enemyTypes[waveIndex], _spawnCounts[waveIndex]);
}
private static float GetScaledInterval(float baseInterval, float scale)
@@ -49,7 +49,7 @@ namespace SepCore.CustomComponent
{
{
typeof(EnemyConfig),
StringAccessor(tables => key => tables.TbEnemyConfig.GetOrDefault(key),
Accessor(tables => key => tables.TbEnemyConfig.GetOrDefault((EnemyType)key),
tables => tables.TbEnemyConfig.DataList)
},
{
@@ -124,7 +124,7 @@ namespace SepCore.CustomComponent
},
{
typeof(WeaponConfig),
Accessor(tables => id => tables.TbWeaponConfig.GetOrDefault(id),
Accessor(tables => id => tables.TbWeaponConfig.GetOrDefault((WeaponType)id),
tables => tables.TbWeaponConfig.DataList)
},
};
@@ -1,7 +1,6 @@
using SepCore.Event;
using SepCore.Definition;
using SepCore.Entity;
using SepCore.Entity.Weapon;
using UnityEngine;
namespace SepCore.Simulation
@@ -1,5 +1,4 @@
using SepCore.Entity;
using SepCore.Entity.Weapon;
using UnityEngine;
namespace SepCore.Simulation
@@ -1,7 +1,6 @@
using SepCore.Event;
using SepCore.Entity;
using SepCore.AsyncTask;
using SepCore.Entity.Weapon;
using Cysharp.Threading.Tasks;
using GameFramework.Event;
using UnityEngine;
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 3069a4f1cc8f5b84d98b3bf5745c6450
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,50 +0,0 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using GameFramework.Resource;
using SepCore.AsyncTask;
using SepCore.CustomUtility;
using SepCore.Definition;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace SepCore.SpriteCache
{
public class SpriteCacheComponent : GameFrameworkComponent
{
[SerializeField] private float _pixelsPerUnit = 100f;
[SerializeField] private Vector2 _defaultPivot = new(0.5f, 0.5f);
private Dictionary<string, Sprite> _spriteCache;
private ResourceComponent _resource;
void Start()
{
_spriteCache = new Dictionary<string, Sprite>();
_resource = GameEntry.Resource;
}
public async UniTask<Sprite> GetSprite(string assetName)
{
if (_spriteCache.TryGetValue(assetName, out var sprite))
return sprite;
var texture = await _resource.LoadAssetAsync<Texture2D>(
AssetUtility.GetUITextureIconAsset(assetName),
Constant.AssetPriority.UIFormAsset);
var newSprite = Sprite.Create(
texture,
new Rect(0, 0, texture.width, texture.height),
_defaultPivot,
_pixelsPerUnit);
_spriteCache.TryAdd(assetName, newSprite);
return newSprite;
}
private void OnDestroy()
{
_spriteCache.Clear();
_resource = null;
}
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: aae7fd2af99064a4088471109952ad96
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More