按照spine的示例项目,使用图片对Spine的SkeletonGraphics进行操作,替换部分图片,但是替换之后发现装备居然是两份了,如图所示,图一展示的是从图集里面读取的武器,图二我用空白图替换了武器,图三我用一样的武器图片重新替换,但是变成了两把武器,可能是哪里引入的问题呢。


` private IEnumerator ChangeWeaponAsync(string weaponId, WeaponTypeInfo weaponType)
{
if (skeletonGraphic == null)
{
log.Error("无法更换武器,SkeletonGraphic未初始化");
yield break;
}
// 获取骨骼数据
Skeleton skeleton = skeletonGraphic.Skeleton;
if (skeleton == null)
{
log.Error("无法获取Skeleton对象");
yield break;
}
// 保存当前状态以便恢复
string currentSkinName = skeleton.Skin.Name;
Skin currentSkin = skeleton.Skin;
SkeletonData skeletonData = skeleton.Data;
log.Debug($"开始替换武器,当前皮肤: {currentSkinName}");
// 用于缓存已加载的精灵
Dictionary<string, Sprite> loadedSprites = new Dictionary<string, Sprite>();
// 预加载所有需要的精灵
foreach (var slotAttachment in weaponType.SlotAttachments)
{
if (!loadedSprites.ContainsKey(slotAttachment.SpritePath))
{
var request = Asset.LoadAsync(slotAttachment.SpritePath, typeof(Sprite));
yield return request;
Sprite sprite = request.asset as Sprite;
if (sprite == null)
{
log.Error($"无法加载武器贴图: {slotAttachment.SpritePath}");
yield break;
}
loadedSprites[slotAttachment.SpritePath] = sprite;
log.Debug($"加载武器贴图: {slotAttachment.SpritePath}");
}
}
try
{
// 获取原始材质
Material sourceMaterial = skeletonGraphic.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
log.Debug($"原始材质: {sourceMaterial.name}");
// 创建自定义皮肤
Skin customSkin = new Skin("custom-weapon");
// 处理每个插槽
foreach (var slotAttachment in weaponType.SlotAttachments)
{
// 获取插槽索引
SlotData slotData = skeletonData.FindSlot(slotAttachment.SlotName);
if (slotData == null)
{
log.Error($"未找到武器插槽: {slotAttachment.SlotName}");
continue;
}
int slotIndex = slotData.Index;
log.Debug($"处理插槽: {slotAttachment.SlotName}, 索引: {slotIndex}");
// 获取已加载的精灵
Sprite sprite = loadedSprites[slotAttachment.SpritePath];
// 获取原始附件
Attachment originalAttachment = currentSkin.GetAttachment(slotIndex, slotAttachment.AttachmentName);
if (originalAttachment != null)
{
log.Debug($"找到原始附件: {slotAttachment.AttachmentName}");
// 创建新附件
Attachment newAttachment = originalAttachment.GetRemappedClone(
sprite,
sourceMaterial,
premultiplyAlpha: true,
cloneMeshAsLinked: false,
useOriginalRegionSize: true
);
if (newAttachment != null)
{
customSkin.SetAttachment(slotIndex, slotAttachment.AttachmentName, newAttachment);
log.Debug($"已添加新附件到自定义皮肤: {slotAttachment.AttachmentName}");
}
else
{
log.Error($"创建新附件失败: {slotAttachment.AttachmentName}");
}
}
else
{
log.Error($"未找到原始附件: {slotAttachment.AttachmentName}");
}
}
// 创建组合皮肤
Skin combinedSkin = new Skin("combined-weapon");
combinedSkin.AddSkin(currentSkin);
combinedSkin.AddSkin(customSkin);
log.Debug("已创建组合皮肤");
// 重新打包皮肤以创建新的纹理图集
Texture2D runtimeAtlas;
Material runtimeMaterial;
combinedSkin = combinedSkin.GetRepackedSkin("combined-repacked", sourceMaterial, out runtimeMaterial, out runtimeAtlas);
// 应用新皮肤
skeleton.SetSkin(combinedSkin);
skeleton.SetSlotsToSetupPose();
// 更新骨骼图形
skeletonGraphic.Update(0);
skeletonGraphic.OverrideTexture = runtimeAtlas;
skeletonGraphic.AnimationState.Apply(skeleton);
// 清理缓存
AtlasUtilities.ClearCache();
log.Debug("武器替换完成");
}
catch (System.Exception e)
{
log.Error($"替换武器过程中发生错误: {e.Message}\n{e.StackTrace}");
// 恢复到原始状态
try
{
skeleton.SetSkin(currentSkinName);
skeletonGraphic.Update(0);
}
catch (System.Exception recoveryEx)
{
log.Error($"恢复状态失败: {recoveryEx.Message}");
}
}
}
`