(client) fix:修复DefineManager没有解析数组类型的Define字段导致定义查找失败

This commit is contained in:
m0_75251201
2025-07-25 17:27:08 +08:00
parent c4ddc0d693
commit bbe4955ccf
9 changed files with 194 additions and 65 deletions

View File

@ -686,7 +686,7 @@ MonoBehaviour:
isGlobal: 1 isGlobal: 1
entityLevel: {fileID: 309861628} entityLevel: {fileID: 309861628}
entityPrefab: {fileID: 3332598847335032684, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3} entityPrefab: {fileID: 3332598847335032684, guid: 6cd8b01a0f57372438dc30c864ae1530, type: 3}
defaultEntityPrefab: {fileID: 0} defaultEntityPrefab: {fileID: 7975757421877276383, guid: 89661daa5f100c64783f0ad9cd37a7ff, type: 3}
--- !u!114 &2036983434 --- !u!114 &2036983434
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -87,7 +87,7 @@ namespace Data
position = StringToVector(xmlDef.Attribute("position")?.Value ?? "(0 0)"); position = StringToVector(xmlDef.Attribute("position")?.Value ?? "(0 0)");
FPS = float.TryParse(xmlDef.Attribute("FPS")?.Value, out float result) ? result : 1.0f; FPS = float.TryParse(xmlDef.Attribute("FPS")?.Value, out float result) ? result : 1.0f;
foreach (var childNode in xmlDef.Elements("DrawNodeDef")) foreach (var childNode in xmlDef.Elements())
{ {
var child = new DrawNodeDef(); var child = new DrawNodeDef();
child.Init(childNode); child.Init(childNode);

View File

@ -53,7 +53,6 @@ namespace Entity
aiTree = ConvertToAIBase(pawnDef.behaviorTree); aiTree = ConvertToAIBase(pawnDef.behaviorTree);
affiliation = pawnDef.affiliation; affiliation = pawnDef.affiliation;
InitBody(pawnDef.drawingOrder); InitBody(pawnDef.drawingOrder);
} }
public virtual void InitBody(DrawingOrderDef drawingOrder) public virtual void InitBody(DrawingOrderDef drawingOrder)
@ -71,8 +70,7 @@ namespace Entity
if (drawNode == null) continue; if (drawNode == null) continue;
var directionRoot = new GameObject(orientation.ToString()); var directionRoot = new GameObject(orientation.ToString());
directionRoot.transform.SetParent(body.transform, false); directionRoot.transform.SetParent(body.transform, false);
InitBodyPart(drawNode, directionRoot,drawingOrder.texturePath);
InitBodyPart(drawNode, directionRoot);
bodyNodes[orientation] = directionRoot; bodyNodes[orientation] = directionRoot;
} }
currentOrientation = Orientation.Down; currentOrientation = Orientation.Down;
@ -85,15 +83,27 @@ namespace Entity
} }
// 递归初始化单个绘图节点及其子节点 // 递归初始化单个绘图节点及其子节点
public virtual void InitBodyPart(DrawNodeDef drawNode, GameObject parent) public virtual void InitBodyPart(DrawNodeDef drawNode, GameObject parent,string folderPath)
{ {
if(drawNode==null) return; if(drawNode==null) return;
GameObject nodeObject; GameObject nodeObject;
if (drawNode.nodeName == "noName")
{
nodeObject = new();
nodeObject.transform.SetParent(parent.transform);
}
else
{
switch (drawNode.drawNodeType) switch (drawNode.drawNodeType)
{ {
case DrawNodeType.Image: case DrawNodeType.Image:
nodeObject = Instantiate(imagePrefab.gameObject, parent.transform); nodeObject = Instantiate(imagePrefab.gameObject, parent.transform);
var texture =
Managers.PackagesImageManager.Instance.FindBodyTextures(drawNode.packID, folderPath,
$"{drawNode.nodeName}_{currentOrientation}");
var image = nodeObject.GetComponent<ImagePrefab>();
image.SetSprite(texture[0]);
break; break;
case DrawNodeType.Animation: case DrawNodeType.Animation:
@ -101,15 +111,22 @@ namespace Entity
ITick tick = nodeObject.GetComponent<SpriteAnimator>(); ITick tick = nodeObject.GetComponent<SpriteAnimator>();
if (tick != null) if (tick != null)
bodyAnimationNode[currentOrientation].Add(tick); bodyAnimationNode[currentOrientation].Add(tick);
var textures = Managers.PackagesImageManager.Instance.FindBodyTextures(drawNode.packID,
folderPath,
$"{drawNode.nodeName}_{currentOrientation}");
var animator = nodeObject.GetComponent<SpriteAnimator>();
animator.SetSprites(textures);
break; break;
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
}
nodeObject.transform.localPosition = drawNode.position; nodeObject.transform.localPosition = drawNode.position;
nodeObject.name = drawNode.nodeName;
// 递归初始化子节点 // 递归初始化子节点
foreach (var child in drawNode.children) foreach (var child in drawNode.children)
{ {
InitBodyPart(child, nodeObject); InitBodyPart(child, nodeObject,folderPath);
} }
} }
public void Tick() public void Tick()

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -51,28 +52,37 @@ namespace Managers
string currentPackID = string.Empty; string currentPackID = string.Empty;
void ProcessDefine(Define def) void ProcessDefine(Define def)
{ {
if (def == null || def.isReferene) if (def == null || def.isReferene)
return; return;
def.packID = currentPackID; def.packID = currentPackID;
// 如果字段信息已经缓存,则直接使用缓存 // 如果字段信息已经缓存,则直接使用缓存
if (!fieldCache.TryGetValue(def.GetType(), out var defineFields)) if (!fieldCache.TryGetValue(def.GetType(), out var defineFields))
{ {
// 获取所有字段类型为 Define 或其派生类型的字段 // 获取所有字段类型为 Define 或其派生类型的字段
defineFields = def.GetType() defineFields = def.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Instance) .GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(field => typeof(Define).IsAssignableFrom(field.FieldType)) .ToArray(); // 不再过滤,先获取所有字段
.ToArray();
// 缓存字段信息 // 缓存字段信息
fieldCache[def.GetType()] = defineFields; fieldCache[def.GetType()] = defineFields;
} }
foreach (var defineField in defineFields) foreach (var defineField in defineFields)
{
var fieldType = defineField.FieldType;
// 处理单个 Define 类型的字段
if (typeof(Define).IsAssignableFrom(fieldType))
{ {
var defRef = (Define)defineField.GetValue(def); var defRef = (Define)defineField.GetValue(def);
if (defRef == null) if (defRef == null)
continue; continue;
if (defRef.isReferene) if (defRef.isReferene)
{ {
defineCache.Add(new Tuple<Define, FieldInfo, Define>(def, defineField, defRef)); defineCache.Add(new Tuple<Define, FieldInfo, Define>(def, defineField, defRef));
@ -89,8 +99,46 @@ namespace Managers
ProcessDefine(defRef); ProcessDefine(defRef);
} }
} }
// 处理集合类型字段
else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(List<>))
{
var elementType = fieldType.GenericTypeArguments[0];
if (typeof(Define).IsAssignableFrom(elementType))
{
var list = (IList)defineField.GetValue(def);
if (list != null)
{
foreach (var item in list)
{
if (item is Define defItem && !defItem.isReferene)
{
ProcessDefine(defItem);
}
}
}
}
}
// 处理数组类型字段
else if (fieldType.IsArray)
{
var elementType = fieldType.GetElementType();
if (typeof(Define).IsAssignableFrom(elementType))
{
var array = (Array)defineField.GetValue(def);
if (array != null)
{
foreach (var item in array)
{
if (item is Define defItem && !defItem.isReferene)
{
ProcessDefine(defItem);
}
}
}
}
}
}
} }
foreach (var pack in packs) foreach (var pack in packs)
{ {
currentPackID = pack.Value.packID; currentPackID = pack.Value.packID;
@ -381,3 +429,4 @@ namespace Managers
} }
} }
} }

View File

@ -101,7 +101,7 @@ namespace Managers
catch (System.Exception ex) catch (System.Exception ex)
{ {
// 捕获并记录任何异常 // 捕获并记录任何异常
Debug.LogError($"An error occurred while generating the entity: {ex.Message}"); Debug.LogError($"An error occurred while generating the entity: {ex.Message}\nStack Trace: {ex.StackTrace}");
GenerateDefaultEntity(pos); GenerateDefaultEntity(pos);
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using Data; using Data;
using NUnit.Framework; using NUnit.Framework;
using UnityEngine; using UnityEngine;
@ -15,7 +16,7 @@ namespace Managers
//包名,图片名 //包名,图片名
public Dictionary<string, Dictionary<string, Sprite>> sprites = new(); public Dictionary<string, Dictionary<string, Sprite>> sprites = new();
//包名,文件路径,身体部件名 //包名,文件路径,身体部件名
public Dictionary<string, Dictionary<string, Dictionary<string, List<Sprite>>>> bodyTexture = new(); public Dictionary<string, Dictionary<string, Dictionary<string, Sprite>>> bodyTexture = new();
public void Init() public void Init()
{ {
@ -83,7 +84,8 @@ namespace Managers
new Vector2(0.5f, 0.5f) // 中心点 new Vector2(0.5f, 0.5f) // 中心点
); );
var name=Path.GetFileNameWithoutExtension(path); var name=Path.GetFileNameWithoutExtension(path);
InsertBodySprite(drawOrder.packID, drawOrder.texturePath, name, spr); InsertBodyTexture(drawOrder.packID, drawOrder.texturePath, name, spr);
} }
} }
} }
@ -115,7 +117,7 @@ namespace Managers
if (!sprites.ContainsKey(packId)) if (!sprites.ContainsKey(packId))
sprites[packId] = new Dictionary<string, Sprite>(); sprites[packId] = new Dictionary<string, Sprite>();
Rect spriteRect = new Rect(0, 0, textureWidth, textureHeight); var spriteRect = new Rect(0, 0, textureWidth, textureHeight);
var sprite = Sprite.Create(texture, spriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit); var sprite = Sprite.Create(texture, spriteRect, new Vector2(0.5f, 0.5f), pixelsPerUnit);
sprites[packId][baseName] = sprite; sprites[packId][baseName] = sprite;
return; return;
@ -180,34 +182,95 @@ namespace Managers
return GetSprite(packID, fullName); return GetSprite(packID, fullName);
} }
/// <summary> /// <summary>
/// 插入 Sprite 到指定的嵌套字典中 /// 向 bodyTexture 插入一张 Sprite
/// 如果包名、路径或部件名原本不存在,会自动建立对应的 Dictionary。
/// </summary> /// </summary>
/// <param name="packageName">包名</param> /// <param name="packageName">包名</param>
/// <param name="filePath">文件路径</param> /// <param name="filePath">文件路径</param>
/// <param name="bodyPartName">身体部件名</param> /// <param name="bodyPartName">身体部件名</param>
/// <param name="sprite">要插入的 Sprite 对象。</param> /// <param name="sprite">要插入的 Sprite</param>
public void InsertBodySprite(string packageName, string filePath, string bodyPartName, Sprite sprite) public void InsertBodyTexture(string packageName,
string filePath,
string bodyPartName,
Sprite sprite)
{ {
// 确保第一层字典(包名)存在 if (sprite == null)
if (!bodyTexture.ContainsKey(packageName))
{ {
bodyTexture[packageName] = new Dictionary<string, Dictionary<string, List<Sprite>>>(); Debug.LogWarning("InsertBodyTexture: sprite 为 null已忽略。");
return;
} }
// 确保第二层字典(文件路径)存在 // 1) 处理包名层级
if (!bodyTexture[packageName].ContainsKey(filePath)) if (!bodyTexture.TryGetValue(packageName, out var pathDict))
{ {
bodyTexture[packageName][filePath] = new Dictionary<string, List<Sprite>>(); pathDict = new Dictionary<string, Dictionary<string, Sprite>>();
bodyTexture[packageName] = pathDict;
} }
// 确保第三层字典(身体部件名)存在 // 2) 处理文件路径层级
if (!bodyTexture[packageName][filePath].ContainsKey(bodyPartName)) if (!pathDict.TryGetValue(filePath, out var partDict))
{ {
bodyTexture[packageName][filePath][bodyPartName] = new List<Sprite>(); partDict = new Dictionary<string, Sprite>();
pathDict[filePath] = partDict;
} }
// 将 Sprite 添加到列表中 // 3) 插入或覆盖部件名
bodyTexture[packageName][filePath][bodyPartName].Add(sprite); partDict[bodyPartName] = sprite;
}
/// <summary>
/// 查找身体部件的所有Sprite变体支持带编号的图片
/// </summary>
/// <param name="packageName">包名</param>
/// <param name="filePath">文件路径</param>
/// <param name="bodyPartName">身体部件名</param>
/// <returns>按编号排序的Sprite数组未找到时返回空数组</returns>
public Sprite[] FindBodyTextures(string packageName, string filePath, string bodyPartName)
{
// 检查包名是否存在
if (!bodyTexture.TryGetValue(packageName, out var packageDict))
{
Debug.LogWarning($"Package '{packageName}' not found.");
return Array.Empty<Sprite>();
}
// 检查文件路径是否存在
if (!packageDict.TryGetValue(filePath, out var pathDict))
{
Debug.LogWarning($"File path '{filePath}' not found in package '{packageName}'.");
return Array.Empty<Sprite>();
}
// 收集所有匹配的Sprite
var sprites = new List<(int order, Sprite sprite)>();
// 查找完全匹配的项(无编号)
if (pathDict.TryGetValue(bodyPartName, out var baseSprite))
{
sprites.Add((0, baseSprite));
}
// 查找带编号的变体
var prefix = bodyPartName + "_";
foreach (var (key, value) in pathDict)
{
// 检查是否以部件名+下划线开头
if (key.StartsWith(prefix) && key.Length > prefix.Length)
{
var suffix = key.Substring(prefix.Length);
// 尝试解析编号
if (int.TryParse(suffix, out var number))
{
sprites.Add((number, Value: value));
}
}
}
// 按编号排序无编号视为0
return sprites
.OrderBy(x => x.order)
.Select(x => x.sprite)
.ToArray();
} }
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -14,9 +14,9 @@
<attributes>TestCharacter</attributes> <attributes>TestCharacter</attributes>
<affiliation>player</affiliation> <affiliation>player</affiliation>
<drawingOrder> <drawingOrder>
<texturePath>Resources/Character/CatGirl</texturePath> <texturePath>Resources\Character\Test</texturePath>
<drawingOrder_down> <drawingOrder_down>
<node name="body"/> <node name="Body"/>
</drawingOrder_down> </drawingOrder_down>
</drawingOrder> </drawingOrder>
<behaviorTree> <behaviorTree>