Merge branch 'develop' into feature/签字功能

This commit is contained in:
2025-12-25 22:02:33 +08:00
579 changed files with 121714 additions and 13685 deletions
@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: 09546aca93a801441859af2a811fe53b
m_currentHash:
serializedVersion: 2
Hash: d59a20f3fd4fe19d46cca3d13d0af15a
Hash: 37e2b77ff9725e8b47edbfe62b470aeb
m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0
m_BundleLocalCatalog: 0
@@ -58,6 +58,8 @@ MonoBehaviour:
- {fileID: 11400000, guid: 724eed66b2d8eef4faf77a4bee4d2845, type: 2}
- {fileID: 11400000, guid: aafc8258a2111e94d8339a3152cf50e0, type: 2}
- {fileID: 11400000, guid: 7e4ab0de168458b43a21dc2f9e811ff5, type: 2}
- {fileID: 11400000, guid: 87e1e3fa2e9ad1d4188cc368fdef2059, type: 2}
- {fileID: 11400000, guid: cf2940a91bcc1604b90ce7598e03ffbe, type: 2}
m_BuildSettings:
m_CompileScriptsInVirtualMode: 0
m_CleanupStreamingAssetsAfterBuilds: 1
@@ -82,6 +82,26 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: dc2e1a393256c414d88652162e05b699
m_Address: "Animation/\u9152\u5427\u533B\u751F"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: af92c8803a884704093ca4bd3cdb30b8
m_Address: "Animation/\u9152\u5427\u706B\u5C71"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 6df720d15b0ce4247b4481c891d2054a
m_Address: "Animation/\u9152\u5427\u8C03\u9152\u59B9"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7ba8eca4e18291341a10ef7c8c858bd9
m_Address: "Animation/\u9152\u5427\u533B\u751F"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
@@ -87,6 +87,26 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c0724ae6698e0454da14fa5f9e87918a
m_Address: "BlockShape/\u6761\u72B6"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f55dac113f9a76c44b13c06b35a5f1e8
m_Address: "BlockPuzzle/\u65B9\u5757\u4E34\u65F6"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: df312fbc70840a04e82c04ac39efb188
m_Address: "BlockPuzzle/\u793A\u4F8B"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 149e01175167ecd4da5d9e258cd2d37a
m_Address: BlockPuzzle/Close
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
@@ -62,8 +62,8 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d6c3173f84145714f908d4f8c45ab92a
m_Address: YingliFixScene
- m_GUID: f30bd88801730144fb8628e970058d3e
m_Address: "\u9152\u5427\u573A\u666F"
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
@@ -178,6 +178,23 @@ MonoBehaviour:
- Locale-en
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: dd4a0fe1d258fbc4384ab1db825d5ae3
m_Address: Gts1/Fiction_Gts1 Shared Data.asset/Fiction_Gts1 Shared Data.asset
m_ReadOnly: 1
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 57cfa4d941133b840b4345cf815dda66
m_Address: Assets/Language/Dialog/Fiction_Day2_begin/Fiction_Day2_begin Shared
Data.asset
m_ReadOnly: 1
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: c3d23bd971e02d34cb356b2029523427
m_Address: Assets/Language/Dialog/Fiction_Day1_sleep/Fiction_Day1_sleep Shared
Data.asset
m_ReadOnly: 1
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 1
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
@@ -119,12 +119,6 @@ MonoBehaviour:
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 999ab1a8772cb1a4cba0325144ff5488
m_Address: Fiction_Day1_begin_zh-Hans
m_ReadOnly: 1
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 72755a9b5a5ca5c4e92028ca44c66a6d
m_Address: FP_Peipei3_zh-Hans
m_ReadOnly: 1
@@ -191,6 +185,24 @@ MonoBehaviour:
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9cecc6d4b999d5c489b69406176bab99
m_Address: Fiction_Gts1_zh-Hans
m_ReadOnly: 1
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: fbfb0ced2ba1bf44e86964158ae53d72
m_Address: Fiction_Day1_sleep_zh-Hans
m_ReadOnly: 1
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 999ab1a8772cb1a4cba0325144ff5488
m_Address: Fiction_Day1_begin_zh-Hans
m_ReadOnly: 1
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 1
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
@@ -0,0 +1,31 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Localization-String-Tables-Chinese (Simplified)
m_EditorClassIdentifier:
m_GroupName: Localization-String-Tables-Chinese (Simplified)
m_Data:
m_SerializedData: []
m_GUID: 9348dd0a8788924488a90c1620b5c896
m_SerializeEntries:
- m_GUID: fb7e715498f89454486d42d98aebfec5
m_Address: Fiction_Day2_begin_zh-Hans
m_ReadOnly: 1
m_SerializedLabels:
- Locale-zh-Hans
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 1
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: 443ec58daf8fe0d4b8cfdb39efd4f3e5, type: 2}
- {fileID: 11400000, guid: c0d471a5cc8ca8a4e85145f6af285176, type: 2}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cf2940a91bcc1604b90ce7598e03ffbe
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -119,12 +119,6 @@ MonoBehaviour:
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 30a0c1ae8c45da34f8e3f90692e96e11
m_Address: Fiction_Day1_begin_en
m_ReadOnly: 1
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: fde90ade684482142af49533e4f4ed62
m_Address: FP_Peipei3_en
m_ReadOnly: 1
@@ -191,6 +185,24 @@ MonoBehaviour:
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 1adbe96b15171134584c9a2d7d69c045
m_Address: Fiction_Gts1_en
m_ReadOnly: 1
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9d72f86c018628e418747a7d0a66cb21
m_Address: Fiction_Day1_sleep_en
m_ReadOnly: 1
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 30a0c1ae8c45da34f8e3f90692e96e11
m_Address: Fiction_Day1_begin_en
m_ReadOnly: 1
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 1
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
@@ -0,0 +1,31 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Localization-String-Tables-English
m_EditorClassIdentifier:
m_GroupName: Localization-String-Tables-English
m_Data:
m_SerializedData: []
m_GUID: 63ce97e1ddac4bc43807a808493c0a93
m_SerializeEntries:
- m_GUID: 3c43e9ea4ead9374490aa31c3778b299
m_Address: Fiction_Day2_begin_en
m_ReadOnly: 1
m_SerializedLabels:
- Locale-en
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 1
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: e47bd2f8e7497a945bb6b80906bf1484, type: 2}
- {fileID: 11400000, guid: 3b18c16658755cc4fb71ea6ad7abc855, type: 2}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 87e1e3fa2e9ad1d4188cc368fdef2059
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -82,6 +82,16 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 03e5e9a1437535042ae48b2ba034dd93
m_Address: BlockShape
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f0804046fd11f7a4a8f27886f2bd3cb0
m_Address: ShapeCreateButton
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
@@ -0,0 +1,45 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Localization-String-Tables-Chinese (Simplified)_BundledAssetGroupSchema
m_EditorClassIdentifier:
m_Group: {fileID: 11400000, guid: cf2940a91bcc1604b90ce7598e03ffbe, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 2ae6a7549097a9b4caefe44b61b1fcc5
m_LoadPath:
m_Id: 631ec5c677ab8084fb9be9b9ee39c6ef
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_BundleNaming: 1
m_AssetLoadMode: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 443ec58daf8fe0d4b8cfdb39efd4f3e5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,16 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Localization-String-Tables-Chinese (Simplified)_ContentUpdateGroupSchema
m_EditorClassIdentifier:
m_Group: {fileID: 11400000, guid: cf2940a91bcc1604b90ce7598e03ffbe, type: 2}
m_StaticContent: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c0d471a5cc8ca8a4e85145f6af285176
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,45 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Localization-String-Tables-English_BundledAssetGroupSchema
m_EditorClassIdentifier:
m_Group: {fileID: 11400000, guid: 87e1e3fa2e9ad1d4188cc368fdef2059, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 2ae6a7549097a9b4caefe44b61b1fcc5
m_LoadPath:
m_Id: 631ec5c677ab8084fb9be9b9ee39c6ef
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_BundleNaming: 1
m_AssetLoadMode: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e47bd2f8e7497a945bb6b80906bf1484
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,16 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Localization-String-Tables-English_ContentUpdateGroupSchema
m_EditorClassIdentifier:
m_Group: {fileID: 11400000, guid: 87e1e3fa2e9ad1d4188cc368fdef2059, type: 2}
m_StaticContent: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3b18c16658755cc4fb71ea6ad7abc855
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -28,6 +28,16 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d9e560aff5c70fb4dbeedb5ce64a0055
m_Address: BubbleStyle
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 9a92289d23953c445ba2d385f1698f30
m_Address: BlockPuzzleValidtor
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: 77169ce22e430f64fb36c771815a4a7b, type: 2}
m_SchemaSet:
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: c1e857482a330e24a880d6543c7a379f
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,43 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace AibisDream
{
[CustomEditor(typeof(BlockPuzzleSystem))]
public class BlockPuzzleEditor : Editor
{
private string _shapeKey;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var example = (BlockPuzzleSystem)target;
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("加载"))
{
example.LoadConfig();
}
if (GUILayout.Button("应用"))
{
example.ApplyConfig();
}
if (GUILayout.Button("保存"))
{
example.SaveConfig();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
GUILayout.Label("创建图形");
EditorGUILayout.BeginHorizontal();
_shapeKey = EditorGUILayout.TextField("形状名称", _shapeKey);
if (GUILayout.Button("创建"))
{
example.CreateShapeInEditor(_shapeKey);
}
EditorGUILayout.EndHorizontal();
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 22da87096df02944ab2b2d750825aaca
guid: fe1f9b10108e095408c3816b817d4980
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,43 @@
using UnityEditor;
using UnityEngine;
namespace AibisDream.SystemEditor
{
[CustomEditor(typeof(BlockShape))]
public class BlockShapeEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var example = (BlockShape)target;
EditorGUILayout.BeginHorizontal();
// 增加绘制形状和保存形状按钮
if (GUILayout.Button("绘制"))
{
example.DrawShape();
}
if (GUILayout.Button("保存"))
{
example.SaveShape();
}
EditorGUILayout.EndHorizontal();
GUILayout.Label("编辑器下吸附");
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("旋转"))
{
example.RotateClockwise();
}
if (GUILayout.Button("吸附"))
{
example.SnapToGrid();
}
if (GUILayout.Button("删除"))
{
example.DeleteShape();
}
EditorGUILayout.EndHorizontal();
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0dcb6a63381e46a4686162a05f8897e3
guid: 73fc356b22fa6a147be7a2eb9c78f123
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,19 @@
using UnityEditor;
using UnityEngine;
namespace AibisDream.SystemEditor
{
[CustomEditor(typeof(GridVisualizer))]
public class GridVisualizerEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var example = (GridVisualizer)target;
EditorGUILayout.LabelField("层级设置", EditorStyles.boldLabel);
example.sortingLayer = EditorKit.SortingLayerField("目标层级", example.sortingLayer);
example.sortingOrder = EditorGUILayout.IntField("层级顺序", example.sortingOrder);
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 9c72154e06027eb4698fc7da159c2d6e
guid: 37faa5e9015d2ce4285ec9f35c871fe1
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 620015a8aa9eda64ab4f9508a3d16dfe
guid: d6d1e89d1670e074a9f74578cfc6bc00
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -0,0 +1,27 @@
using UnityEditor;
using UnityEngine;
namespace AibisDream.SystemEditor
{
public static class BlockPuzzleMenuItemCreator
{
private const string BLOCK_SHAPE_PREFAB_PATH = "Assets/Prefabs/BlockPuzzle/BlockShape.prefab";
[MenuItem("GameObject/Block Puzzle/Shape")]
public static BlockShape CreateBlockPuzzleShape()
{
var prefabAsset =AssetDatabase.LoadAssetAtPath<GameObject>(BLOCK_SHAPE_PREFAB_PATH);
if (prefabAsset == null)
{
throw new System.InvalidOperationException(
$"Can't create a new Block Shape: Can't find the prefab to create a Block Shape from."
);
}
var instantiatedPrefab = (GameObject)PrefabUtility.InstantiatePrefab(prefabAsset);
PrefabUtility.UnpackPrefabInstance(instantiatedPrefab, PrefabUnpackMode.Completely, InteractionMode.UserAction);
return instantiatedPrefab.GetComponent<BlockShape>();
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6b20aec8808a25c4b9607bbe72858b7a
guid: 71b77fc2d917b61489a45c2a36d5d049
MonoImporter:
externalObjects: {}
serializedVersion: 2
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cfd74cd0e7d421b41b6fb4fe5306d4c1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+132
View File
@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AibisDream.SystemEditor
{
// 帧数据
[Serializable]
public class FrameData
{
public string name;
public int x;
public int y;
public int width;
public int height;
public float duration; // 毫秒
}
// 动画片段数据
[Serializable]
public class AnimationData
{
public string name;
public List<int> frameIndices;
public bool loop;
public float? frameDuration; // 可选的,覆盖全局frameDuration
public int? sampleRate; // 可选的,覆盖全局sampleRate
}
// Aseprite JSON格式的数据结构
[Serializable]
public class AsepriteFrameInfo
{
public AsepriteFrameRect frame;
public bool rotated;
public bool trimmed;
public AsepriteFrameRect spriteSourceSize;
public AsepriteSize sourceSize;
public float duration; // 毫秒
}
[Serializable]
public class AsepriteFrameRect
{
public int x;
public int y;
public int w;
public int h;
}
[Serializable]
public class AsepriteSize
{
public int w;
public int h;
}
[Serializable]
public class AsepriteFrameTag
{
public string name;
public int from;
public int to;
public string direction;
}
[Serializable]
public class AsepriteMeta
{
public string app;
public string version;
public string image;
public string format;
public AsepriteSize size;
public string scale;
public List<AsepriteFrameTag> frameTags;
public List<object> layers;
public List<object> slices;
}
// Aseprite JSON的包装类(因为Unity JsonUtility不支持Dictionary
[Serializable]
public class AsepriteFrameEntry
{
public string key;
public AsepriteFrameInfo value;
}
[Serializable]
public class AsepriteJsonData
{
public AsepriteMeta meta;
// frames将通过手动解析处理
}
// 手动JSON格式的数据结构
[Serializable]
public class ManualLayout
{
public int rows;
public int columns;
public int? frameCount; // 可选
public string direction; // "horizontal" 或 "vertical"
}
[Serializable]
public class ManualJsonData
{
public string type;
public ManualLayout layout;
public float frameDuration; // 毫秒
public int sampleRate;
public List<AnimationData> animations;
}
// 统一的内部数据格式
public class ProcessedAnimationData
{
public List<FrameData> frames;
public List<ProcessedAnimationClip> animations;
}
public class ProcessedAnimationClip
{
public string name;
public List<int> frameIndices;
public bool loop;
public float frameDuration; // 毫秒(已应用覆盖逻辑)
public int sampleRate; // 已应用覆盖逻辑
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5cd60e41866d0ec418dfc6fdce37a8ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,133 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace AibisDream.SystemEditor
{
public class AnimationClipGenerator : EditorWindow
{
private Texture2D selectedTexture;
private TextAsset selectedJson;
private DefaultAsset outputFolder;
private string outputPath = "";
// 动画类型选项
private enum AnimationTargetType
{
SpriteRenderer, // Sprite动画
Image // UIImage动画
}
private AnimationTargetType animationType = AnimationTargetType.SpriteRenderer;
[MenuItem("Tools/Animation Clip Generator")]
public static void ShowWindow()
{
GetWindow<AnimationClipGenerator>("Animation Clip Generator");
}
private void OnGUI()
{
GUILayout.Label("Animation Clip Generator", EditorStyles.boldLabel);
EditorGUILayout.Space();
// 图片文件选择
EditorGUILayout.LabelField("图片文件 (PNG/JPG)", EditorStyles.boldLabel);
selectedTexture = (Texture2D)EditorGUILayout.ObjectField(
"Texture", selectedTexture, typeof(Texture2D), false);
EditorGUILayout.Space();
// JSON文件选择
EditorGUILayout.LabelField("JSON文件", EditorStyles.boldLabel);
selectedJson = (TextAsset)EditorGUILayout.ObjectField(
"JSON", selectedJson, typeof(TextAsset), false);
EditorGUILayout.Space();
// 动画类型选择
EditorGUILayout.LabelField("动画类型", EditorStyles.boldLabel);
animationType = (AnimationTargetType)EditorGUILayout.EnumPopup(
"Animation Type", animationType);
EditorGUILayout.HelpBox(
animationType == AnimationTargetType.SpriteRenderer
? "生成用于SpriteRenderer的动画(绑定到m_Sprite属性)"
: "生成用于Unity UI Image的动画(绑定到m_Sprite属性)",
MessageType.Info);
EditorGUILayout.Space();
// 输出目录选择
EditorGUILayout.LabelField("输出目录", EditorStyles.boldLabel);
outputFolder = (DefaultAsset)EditorGUILayout.ObjectField(
"Output Folder", outputFolder, typeof(DefaultAsset), false);
// 显示输出路径
if (outputFolder != null)
{
outputPath = AssetDatabase.GetAssetPath(outputFolder);
EditorGUILayout.HelpBox($"输出路径: {outputPath}", MessageType.Info);
}
else
{
outputPath = "";
}
EditorGUILayout.Space();
// 生成按钮
GUI.enabled = selectedTexture != null && selectedJson != null && outputFolder != null;
if (GUILayout.Button("生成 AnimationClip", GUILayout.Height(30)))
{
GenerateAnimationClips();
}
GUI.enabled = true;
EditorGUILayout.Space();
// 说明信息
EditorGUILayout.HelpBox(
"使用说明:\n" +
"1. 选择PNG或JPG图片文件\n" +
"2. 选择JSON文件(Aseprite格式或手动格式)\n" +
"3. 选择输出目录\n" +
"4. 点击生成按钮\n\n" +
"注意: 如果图片的SpriteMode是Single,工具会自动根据JSON切图。",
MessageType.Info);
}
private void GenerateAnimationClips()
{
if (selectedTexture == null || selectedJson == null || outputFolder == null)
{
EditorUtility.DisplayDialog("错误", "请选择图片文件、JSON文件和输出目录", "确定");
return;
}
string texturePath = AssetDatabase.GetAssetPath(selectedTexture);
string jsonPath = AssetDatabase.GetAssetPath(selectedJson);
// 验证文件扩展名
string textureExt = Path.GetExtension(texturePath).ToLower();
if (textureExt != ".png" && textureExt != ".jpg" && textureExt != ".jpeg")
{
EditorUtility.DisplayDialog("错误", "图片文件必须是PNG或JPG格式", "确定");
return;
}
try
{
bool isImageAnimation = animationType == AnimationTargetType.Image;
AnimationClipGeneratorCore.GenerateClips(texturePath, jsonPath, outputPath, isImageAnimation);
EditorUtility.DisplayDialog("成功", $"AnimationClip已生成到: {outputPath}", "确定");
// 刷新资源数据库
AssetDatabase.Refresh();
}
catch (System.Exception e)
{
EditorUtility.DisplayDialog("错误", $"生成失败: {e.Message}", "确定");
Debug.LogError(e);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7472aae8191639b47af5d9ba115b39b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,603 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.U2D.Sprites;
using UnityEngine;
namespace AibisDream.SystemEditor
{
public static class AnimationClipGeneratorCore
{
// 检查SpriteMode
public static SpriteImportMode CheckSpriteMode(string texturePath)
{
TextureImporter textureImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;
if (textureImporter == null)
{
throw new Exception($"无法加载纹理导入器: {texturePath}");
}
return textureImporter.spriteImportMode;
}
// 解析Aseprite JSON
public static ProcessedAnimationData ParseAsepriteJson(string jsonPath, string texturePath)
{
string jsonContent = File.ReadAllText(jsonPath);
// Unity的JsonUtility不支持Dictionary,需要手动解析frames对象
// 使用SimpleJSON或手动解析
ProcessedAnimationData result = ParseAsepriteJsonManual(jsonContent);
if (result.frames == null || result.frames.Count == 0)
{
throw new Exception("无效的Aseprite JSON格式:无法解析frames");
}
return result;
}
private static ProcessedAnimationData ParseAsepriteJsonManual(string jsonContent)
{
List<FrameData> frames = new List<FrameData>();
List<ProcessedAnimationClip> animations = new List<ProcessedAnimationClip>();
try
{
// 解析meta部分
int metaStart = jsonContent.IndexOf("\"meta\":");
if (metaStart == -1)
{
throw new Exception("找不到meta部分");
}
// 找到meta对象的结束位置
int metaBraceStart = jsonContent.IndexOf('{', metaStart);
int metaBraceEnd = FindMatchingBrace(jsonContent, metaBraceStart);
string metaJson = jsonContent.Substring(metaBraceStart, metaBraceEnd - metaBraceStart + 1);
// 移除可能的尾随逗号
metaJson = metaJson.TrimEnd(',', ' ', '\n', '\r');
AsepriteMeta meta = JsonUtility.FromJson<AsepriteMeta>(metaJson);
// 解析frameTags
if (meta.frameTags != null)
{
foreach (var tag in meta.frameTags)
{
List<int> frameIndices = new List<int>();
int start = tag.from;
int end = tag.to;
if (tag.direction == "forward" || tag.direction == "pingpong" || string.IsNullOrEmpty(tag.direction))
{
for (int i = start; i <= end; i++)
{
frameIndices.Add(i);
}
}
else if (tag.direction == "reverse")
{
for (int i = end; i >= start; i--)
{
frameIndices.Add(i);
}
}
animations.Add(new ProcessedAnimationClip
{
name = tag.name,
frameIndices = frameIndices,
loop = true,
frameDuration = 0,
sampleRate = 100
});
}
}
// 解析frames对象 - 使用正则表达式或手动解析
int framesStart = jsonContent.IndexOf("\"frames\":");
if (framesStart == -1)
{
throw new Exception("找不到frames部分");
}
// 找到frames对象的开始和结束
int framesBraceStart = jsonContent.IndexOf('{', framesStart);
int framesBraceEnd = FindMatchingBrace(jsonContent, framesBraceStart);
string framesContent = jsonContent.Substring(framesBraceStart + 1, framesBraceEnd - framesBraceStart - 1);
// 解析每个帧条目
ParseFramesContent(framesContent, frames);
// 按名称排序帧(确保顺序正确)
frames = frames.OrderBy(f => ExtractFrameNumber(f.name)).ThenBy(f => f.name).ToList();
}
catch (Exception e)
{
throw new Exception($"解析Aseprite JSON失败: {e.Message}\n{e.StackTrace}");
}
return new ProcessedAnimationData
{
frames = frames,
animations = animations
};
}
private static void ParseFramesContent(string framesContent, List<FrameData> frames)
{
int pos = 0;
while (pos < framesContent.Length)
{
// 跳过空白字符和逗号
while (pos < framesContent.Length && (char.IsWhiteSpace(framesContent[pos]) || framesContent[pos] == ','))
pos++;
if (pos >= framesContent.Length) break;
// 查找帧名称(在引号中)
if (framesContent[pos] != '"')
{
pos++;
continue;
}
int nameStart = pos + 1;
int nameEnd = framesContent.IndexOf('"', nameStart);
if (nameEnd == -1) break;
string frameName = framesContent.Substring(nameStart, nameEnd - nameStart);
pos = nameEnd + 1;
// 跳过冒号和空白
while (pos < framesContent.Length && (char.IsWhiteSpace(framesContent[pos]) || framesContent[pos] == ':'))
pos++;
if (pos >= framesContent.Length) break;
// 查找帧数据对象
if (framesContent[pos] != '{')
{
continue;
}
int dataStart = pos;
int dataEnd = FindMatchingBrace(framesContent, dataStart);
if (dataEnd == -1) break;
string frameDataJson = framesContent.Substring(dataStart, dataEnd - dataStart + 1);
pos = dataEnd + 1;
try
{
AsepriteFrameInfo frameInfo = JsonUtility.FromJson<AsepriteFrameInfo>(frameDataJson);
if (frameInfo.frame != null)
{
frames.Add(new FrameData
{
name = frameName,
x = frameInfo.frame.x,
y = frameInfo.frame.y,
width = frameInfo.frame.w,
height = frameInfo.frame.h,
duration = frameInfo.duration
});
}
}
catch (Exception e)
{
Debug.LogWarning($"解析帧数据失败: {frameName}, 错误: {e.Message}");
}
}
}
private static int ExtractFrameNumber(string frameName)
{
// 尝试从帧名称中提取数字(例如 "调酒妹侧头 0.aseprite" -> 0
int lastSpace = frameName.LastIndexOf(' ');
if (lastSpace >= 0 && lastSpace < frameName.Length - 1)
{
string numberPart = frameName.Substring(lastSpace + 1);
int dotIndex = numberPart.IndexOf('.');
if (dotIndex > 0)
{
numberPart = numberPart.Substring(0, dotIndex);
}
if (int.TryParse(numberPart, out int number))
{
return number;
}
}
return int.MaxValue; // 如果无法解析,放在最后
}
private static int FindMatchingBrace(string str, int startIndex)
{
if (startIndex < 0 || startIndex >= str.Length) return -1;
int braceCount = 0;
bool foundStart = false;
for (int i = startIndex; i < str.Length; i++)
{
if (str[i] == '{')
{
braceCount++;
foundStart = true;
}
else if (str[i] == '}')
{
braceCount--;
if (braceCount == 0 && foundStart)
{
return i;
}
}
}
return -1;
}
// 解析手动JSON
public static ProcessedAnimationData ParseManualJson(string jsonPath, string texturePath)
{
string jsonContent = File.ReadAllText(jsonPath);
ManualJsonData manualData = JsonUtility.FromJson<ManualJsonData>(jsonContent);
if (manualData.layout == null || manualData.animations == null)
{
throw new Exception("无效的手动JSON格式");
}
// 验证layout参数
if (manualData.layout.rows <= 0 || manualData.layout.columns <= 0)
{
throw new Exception("rows和columns必须大于0");
}
// 读取图片尺寸
TextureImporter textureImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;
if (textureImporter == null)
{
throw new Exception($"无法加载纹理导入器: {texturePath}");
}
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath);
if (texture == null)
{
throw new Exception($"无法加载纹理: {texturePath}");
}
int imageWidth = texture.width;
int imageHeight = texture.height;
// 计算sprite尺寸
int spriteWidth = imageWidth / manualData.layout.columns;
int spriteHeight = imageHeight / manualData.layout.rows;
// 验证图片尺寸能被行列数整除
if (imageWidth % manualData.layout.columns != 0 || imageHeight % manualData.layout.rows != 0)
{
throw new Exception($"图片尺寸({imageWidth}x{imageHeight})无法被行列数({manualData.layout.columns}x{manualData.layout.rows})整除");
}
// 计算总帧数
int totalFrames = manualData.layout.frameCount ?? (manualData.layout.rows * manualData.layout.columns);
if (totalFrames > manualData.layout.rows * manualData.layout.columns)
{
throw new Exception($"frameCount({totalFrames})不能超过rows*columns({manualData.layout.rows * manualData.layout.columns})");
}
// 生成帧数据
List<FrameData> frames = new List<FrameData>();
bool isHorizontal = manualData.layout.direction == "horizontal";
for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++)
{
int row, column;
if (isHorizontal)
{
// 横向排列:按行扫描,从左到右,从上到下
row = frameIndex / manualData.layout.columns;
column = frameIndex % manualData.layout.columns;
}
else
{
// 纵向排列:按列扫描,从上到下,从左到右
column = frameIndex / manualData.layout.rows;
row = frameIndex % manualData.layout.rows;
}
// Unity Y轴从下往上,需要转换
int x = column * spriteWidth;
int y = (manualData.layout.rows - 1 - row) * spriteHeight;
frames.Add(new FrameData
{
name = $"frame_{frameIndex}",
x = x,
y = y,
width = spriteWidth,
height = spriteHeight,
duration = manualData.frameDuration
});
}
// 处理动画片段
List<ProcessedAnimationClip> animations = new List<ProcessedAnimationClip>();
foreach (var anim in manualData.animations)
{
// 应用参数覆盖逻辑
float frameDuration = anim.frameDuration ?? manualData.frameDuration;
int sampleRate = anim.sampleRate ?? manualData.sampleRate;
animations.Add(new ProcessedAnimationClip
{
name = anim.name,
frameIndices = anim.frameIndices,
loop = anim.loop,
frameDuration = frameDuration,
sampleRate = sampleRate
});
}
return new ProcessedAnimationData
{
frames = frames,
animations = animations
};
}
// 根据JSON信息切图
public static void SliceSprites(string texturePath, List<FrameData> frames)
{
TextureImporter textureImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;
if (textureImporter == null)
{
throw new Exception($"无法加载纹理导入器: {texturePath}");
}
// 设置spriteMode为Multiple
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
// 使用新的Sprite Editor Data Provider API (Unity 2020.2+)
var spriteDataProviderFactories = new SpriteDataProviderFactories();
spriteDataProviderFactories.Init();
var dataProvider = spriteDataProviderFactories.GetSpriteEditorDataProviderFromObject(textureImporter);
if (dataProvider == null)
{
throw new Exception($"无法获取Sprite Editor Data Provider: {texturePath}");
}
dataProvider.InitSpriteEditorDataProvider();
// 创建SpriteRect数组
var spriteRects = new SpriteRect[frames.Count];
for (int i = 0; i < frames.Count; i++)
{
var frame = frames[i];
spriteRects[i] = new SpriteRect
{
name = frame.name,
rect = new Rect(frame.x, frame.y, frame.width, frame.height),
pivot = new Vector2(0.5f, 0.5f),
alignment = SpriteAlignment.Center
};
}
dataProvider.SetSpriteRects(spriteRects);
dataProvider.Apply();
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
}
// 创建AnimationClip
public static AnimationClip CreateAnimationClip(
ProcessedAnimationClip animationData,
List<FrameData> frames,
Sprite[] sprites,
string outputPath,
bool isImageAnimation = false)
{
AnimationClip clip = new AnimationClip();
clip.name = animationData.name;
// 设置采样率
AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);
clip.frameRate = animationData.sampleRate;
// 创建Sprite关键帧
List<ObjectReferenceKeyframe> keyframes = new List<ObjectReferenceKeyframe>();
float currentTime = 0f;
foreach (int frameIndex in animationData.frameIndices)
{
if (frameIndex < 0 || frameIndex >= sprites.Length)
{
Debug.LogWarning($"帧索引{frameIndex}超出范围,跳过");
continue;
}
Sprite sprite = sprites[frameIndex];
if (sprite == null)
{
Debug.LogWarning($"帧索引{frameIndex}的Sprite为空,跳过");
continue;
}
// 使用帧的duration(如果是Aseprite格式)或动画的frameDuration(手动格式)
float frameDuration = frames[frameIndex].duration > 0
? frames[frameIndex].duration / 1000f // 毫秒转秒
: animationData.frameDuration / 1000f;
keyframes.Add(new ObjectReferenceKeyframe
{
time = currentTime,
value = sprite
});
currentTime += frameDuration;
}
if (keyframes.Count == 0)
{
throw new Exception($"动画片段{animationData.name}没有有效的关键帧");
}
// 设置循环
if (animationData.loop && keyframes.Count > 1)
{
// 添加最后一帧的重复,确保循环
keyframes.Add(new ObjectReferenceKeyframe
{
time = currentTime,
value = keyframes[0].value
});
}
// 创建EditorCurveBinding - 根据动画类型选择不同的组件
EditorCurveBinding curveBinding = new EditorCurveBinding
{
path = "",
type = isImageAnimation ? typeof(UnityEngine.UI.Image) : typeof(SpriteRenderer),
propertyName = "m_Sprite"
};
// 设置曲线
AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyframes.ToArray());
// 设置循环
settings.loopTime = animationData.loop;
AnimationUtility.SetAnimationClipSettings(clip, settings);
// 保存AnimationClip
string fullPath = Path.Combine(outputPath, $"{animationData.name}.anim");
string assetPath = fullPath.Replace('\\', '/');
if (!assetPath.StartsWith("Assets/"))
{
// 转换为相对路径
string projectPath = Application.dataPath.Replace("Assets", "");
if (assetPath.StartsWith(projectPath))
{
assetPath = assetPath.Substring(projectPath.Length);
}
}
AssetDatabase.CreateAsset(clip, assetPath);
AssetDatabase.SaveAssets();
return clip;
}
// 主流程:生成AnimationClip
public static void GenerateClips(string texturePath, string jsonPath, string outputPath, bool isImageAnimation = false)
{
try
{
EditorUtility.DisplayProgressBar("生成AnimationClip", "检查SpriteMode...", 0f);
// 检查SpriteMode
SpriteImportMode spriteMode = CheckSpriteMode(texturePath);
if (spriteMode == SpriteImportMode.Multiple)
{
Debug.Log("图片的SpriteMode已经是Multiple,将使用现有的Sprite切图");
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "解析JSON...", 0.2f);
// 判断JSON类型并解析
ProcessedAnimationData processedData;
string jsonContent = File.ReadAllText(jsonPath);
if (jsonContent.Contains("\"type\":\"manual\"") || jsonContent.Contains("\"type\": \"manual\""))
{
// 手动格式
processedData = ParseManualJson(jsonPath, texturePath);
}
else
{
// Aseprite格式
processedData = ParseAsepriteJson(jsonPath, texturePath);
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "切图...", 0.4f);
// 如果是Single模式,需要切图
if (spriteMode == SpriteImportMode.Single)
{
SliceSprites(texturePath, processedData.frames);
// 重新加载以确保sprites可用
AssetDatabase.Refresh();
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "加载Sprites...", 0.6f);
// 加载所有Sprites
Sprite[] allSpritesArray = AssetDatabase.LoadAllAssetsAtPath(texturePath)
.OfType<Sprite>()
.ToArray();
if (allSpritesArray.Length == 0)
{
throw new Exception("无法加载任何Sprite,请检查切图设置");
}
// 创建Sprite字典以便快速查找
Dictionary<string, Sprite> spriteDict = allSpritesArray.ToDictionary(s => s.name, s => s);
// 按照frames列表的顺序创建Sprite数组
Sprite[] allSprites = new Sprite[processedData.frames.Count];
for (int i = 0; i < processedData.frames.Count; i++)
{
string frameName = processedData.frames[i].name;
if (spriteDict.TryGetValue(frameName, out Sprite sprite))
{
allSprites[i] = sprite;
}
else
{
Debug.LogWarning($"找不到名为{frameName}的Sprite");
// 尝试使用索引查找
if (i < allSpritesArray.Length)
{
allSprites[i] = allSpritesArray[i];
}
}
}
// 确保输出目录存在
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "创建AnimationClip...", 0.8f);
// 为每个动画片段创建AnimationClip
int animationCount = processedData.animations.Count;
for (int i = 0; i < animationCount; i++)
{
var anim = processedData.animations[i];
EditorUtility.DisplayProgressBar("生成AnimationClip",
$"创建动画片段: {anim.name}", 0.8f + (i / (float)animationCount) * 0.2f);
CreateAnimationClip(anim, processedData.frames, allSprites, outputPath, isImageAnimation);
}
EditorUtility.ClearProgressBar();
Debug.Log($"成功生成{animationCount}个AnimationClip到: {outputPath}");
}
catch (Exception e)
{
EditorUtility.ClearProgressBar();
Debug.LogError($"生成AnimationClip失败: {e.Message}");
throw;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7abb40962ba935419bb10c937b8b2c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29e5bfa8c0e3cf74fab38b400eb5946e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0af68f99223d4f34896f8ab3ba4e2730
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c3d23bd971e02d34cb356b2029523427
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5be51871efa6c3e4eae1703925c8f5ac, type: 3}
m_Name: Fiction_Day1_sleep
m_EditorClassIdentifier:
m_SharedTableData: {fileID: 11400000, guid: c3d23bd971e02d34cb356b2029523427, type: 2}
m_Tables:
- {fileID: 11400000, guid: 9d72f86c018628e418747a7d0a66cb21, type: 2}
- {fileID: 11400000, guid: fbfb0ced2ba1bf44e86964158ae53d72, type: 2}
m_Extensions: []
m_Group: String Table
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 47ed60b0cb437d7408bd2278c11d986d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9620f8c34305754d8cc9a7e49e852d9, type: 3}
m_Name: Fiction_Day1_sleep_en
m_EditorClassIdentifier:
m_LocaleId:
m_Code: en
m_SharedData: {fileID: 11400000, guid: c3d23bd971e02d34cb356b2029523427, type: 2}
m_Metadata:
m_Items: []
m_TableData: []
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9d72f86c018628e418747a7d0a66cb21
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fbfb0ced2ba1bf44e86964158ae53d72
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7bb408f26ded78745babbff38369a49e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,219 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5b11a58205ec3474ca216360e9fa74a8, type: 3}
m_Name: Fiction_Day2_begin Shared Data
m_EditorClassIdentifier:
m_TableCollectionName: Fiction_Day2_begin
m_TableCollectionNameGuidString: 57cfa4d941133b840b4345cf815dda66
m_Entries:
- m_Id: 289997225984
m_Key: line:0640507
m_Metadata:
m_Items:
- rid: 1784249431094460555
- m_Id: 289997225985
m_Key: line:0baf72f
m_Metadata:
m_Items:
- rid: 1784249431094460556
- m_Id: 289997225986
m_Key: line:0fe2db6
m_Metadata:
m_Items:
- rid: 1784249431094460557
- m_Id: 289997225987
m_Key: line:0909de1
m_Metadata:
m_Items:
- rid: 1784249431094460558
- m_Id: 289997225988
m_Key: line:05034c9
m_Metadata:
m_Items:
- rid: 1784249431094460559
- m_Id: 289997225989
m_Key: line:0f03a24
m_Metadata:
m_Items:
- rid: 1784249431094460560
- m_Id: 289997225990
m_Key: line:0da844a
m_Metadata:
m_Items:
- rid: 1784249431094460561
- m_Id: 289997225991
m_Key: line:0ecf468
m_Metadata:
m_Items:
- rid: 1784249431094460562
- m_Id: 289997225992
m_Key: line:08f4bfc
m_Metadata:
m_Items:
- rid: 1784249431094460563
- m_Id: 289997225993
m_Key: line:00567d6
m_Metadata:
m_Items:
- rid: 1784249431094460564
- m_Id: 289997225994
m_Key: line:049bcc1
m_Metadata:
m_Items:
- rid: 1784249431094460565
- m_Id: 289997225995
m_Key: line:0f56737
m_Metadata:
m_Items:
- rid: 1784249431094460566
- m_Id: 289997225996
m_Key: line:0c9ab29
m_Metadata:
m_Items:
- rid: 1784249431094460567
- m_Id: 56494161661952
m_Key: line:043c974
m_Metadata:
m_Items:
- rid: 1784249431094460568
- m_Id: 56494195216384
m_Key: line:0efa469
m_Metadata:
m_Items:
- rid: 1784249431094460569
- m_Id: 56494195216385
m_Key: line:0f4003c
m_Metadata:
m_Items:
- rid: 1784249431094460570
- m_Id: 56494195216386
m_Key: line:0f961a9
m_Metadata:
m_Items:
- rid: 1784249431094460571
- m_Id: 56494195216387
m_Key: line:008904b
m_Metadata:
m_Items:
- rid: 1784249431094460572
- m_Id: 56494195216388
m_Key: line:05bf3c8
m_Metadata:
m_Items:
- rid: 1784249431094460573
m_Metadata:
m_Items: []
m_KeyGenerator:
rid: 7711022820442243766
references:
version: 2
RefIds:
- rid: 1784249431094460555
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460556
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460557
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460558
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460559
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460560
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460561
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460562
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460563
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460564
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460565
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460566
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460567
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460568
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460569
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460570
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460571
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags:
- lastline
- rid: 1784249431094460572
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 1784249431094460573
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 7711022820442243766
type: {class: DistributedUIDGenerator, ns: UnityEngine.Localization.Tables, asm: Unity.Localization}
data:
m_CustomEpoch: 1763551309207
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57cfa4d941133b840b4345cf815dda66
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5be51871efa6c3e4eae1703925c8f5ac, type: 3}
m_Name: Fiction_Day2_begin
m_EditorClassIdentifier:
m_SharedTableData: {fileID: 11400000, guid: 57cfa4d941133b840b4345cf815dda66, type: 2}
m_Tables:
- {fileID: 11400000, guid: 3c43e9ea4ead9374490aa31c3778b299, type: 2}
- {fileID: 11400000, guid: fb7e715498f89454486d42d98aebfec5, type: 2}
m_Extensions: []
m_Group: String Table
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 95dbf118f95f0234a93e3d0b0ee1cc25
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9620f8c34305754d8cc9a7e49e852d9, type: 3}
m_Name: Fiction_Day2_begin_en
m_EditorClassIdentifier:
m_LocaleId:
m_Code: en
m_SharedData: {fileID: 11400000, guid: 57cfa4d941133b840b4345cf815dda66, type: 2}
m_Metadata:
m_Items: []
m_TableData: []
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3c43e9ea4ead9374490aa31c3778b299
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,99 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9620f8c34305754d8cc9a7e49e852d9, type: 3}
m_Name: Fiction_Day2_begin_zh-Hans
m_EditorClassIdentifier:
m_LocaleId:
m_Code: zh-Hans
m_SharedData: {fileID: 11400000, guid: 57cfa4d941133b840b4345cf815dda66, type: 2}
m_Metadata:
m_Items: []
m_TableData:
- m_Id: 289997225996
m_Localized: "me: \u6211\u51C6\u5907\u597D\u4E86\u3002"
m_Metadata:
m_Items: []
- m_Id: 289997225995
m_Localized: "me: \u597D\u5427\u3002\u660E\u5929\u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 289997225994
m_Localized: "me: \uFF08\u53F9\u6C14\uFF09"
m_Metadata:
m_Items: []
- m_Id: 289997225993
m_Localized: "\u653E\u4E0B"
m_Metadata:
m_Items: []
- m_Id: 289997225992
m_Localized: "me: \u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 289997225991
m_Localized: "\u5403"
m_Metadata:
m_Items: []
- m_Id: 289997225990
m_Localized: "me: \uFF08\u53EE\u5F53\uFF0C\u6709\u4E1C\u897F\u6389\u5230\u5730\u4E0A\uFF09"
m_Metadata:
m_Items: []
- m_Id: 289997225989
m_Localized: "me: \u2026\u2026\u91CD\u8981\u7684\u662F\u660E\u5929\u3002"
m_Metadata:
m_Items: []
- m_Id: 289997225988
m_Localized: "me: \u662F\u554A\u2026\u53C8\u6709\u4EC0\u4E48\u533A\u522B\u5462\u3002\u539F\u56E0\u6839\u672C\u5C31\u4E0D\u91CD\u8981\u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 289997225987
m_Localized: "me: \u5934\u597D\u75DB\u3002"
m_Metadata:
m_Items: []
- m_Id: 289997225986
m_Localized: "me: \u6211\u7761\u4E86\u591A\u4E45\u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 289997225985
m_Localized: "me: \u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 289997225984
m_Localized: "me: \u60CA\u9192"
m_Metadata:
m_Items: []
- m_Id: 56494161661952
m_Localized: "me: \u554A\u5BF9\u4E86\u2026"
m_Metadata:
m_Items: []
- m_Id: 56494195216384
m_Localized: "me: \u770B\u4E86\u4E00\u773CBP\u673A\uFF0C\u706B\u5C71\u4F9D\u65E7\u6CA1\u56DE\u590D"
m_Metadata:
m_Items: []
- m_Id: 56494195216385
m_Localized: "me: \u8FD9\u5BB6\u4F19\u2026\u4E0D\u4F1A\u51FA\u4EC0\u4E48\u4E8B\u4E86\u5427\u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 56494195216386
m_Localized: "me: \u4EC0\u4E48\u4E1C\u897F\u2026\u2026"
m_Metadata:
m_Items: []
- m_Id: 56494195216387
m_Localized: "\u6361\u8D77\u6765"
m_Metadata:
m_Items: []
- m_Id: 56494195216388
m_Localized: "me: \u56FE\u7247\u5C55\u793A\uFF1A\u7F50\u5934\uFF0C\u529F\u6548\u662F\u5E73\u590D\u539F\u578B\u6CE2\u52A8"
m_Metadata:
m_Items: []
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fb7e715498f89454486d42d98aebfec5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8a0fe2307740f2541b51666e4641e73d
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dd4a0fe1d258fbc4384ab1db825d5ae3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5be51871efa6c3e4eae1703925c8f5ac, type: 3}
m_Name: Fiction_Gts1
m_EditorClassIdentifier:
m_SharedTableData: {fileID: 11400000, guid: dd4a0fe1d258fbc4384ab1db825d5ae3, type: 2}
m_Tables:
- {fileID: 11400000, guid: 1adbe96b15171134584c9a2d7d69c045, type: 2}
- {fileID: 11400000, guid: 9cecc6d4b999d5c489b69406176bab99, type: 2}
m_Extensions: []
m_Group: String Table
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4605aabbf058e594c8b1aad9643c87fa
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9620f8c34305754d8cc9a7e49e852d9, type: 3}
m_Name: Fiction_Gts1_en
m_EditorClassIdentifier:
m_LocaleId:
m_Code: en
m_SharedData: {fileID: 11400000, guid: dd4a0fe1d258fbc4384ab1db825d5ae3, type: 2}
m_Metadata:
m_Items: []
m_TableData: []
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1adbe96b15171134584c9a2d7d69c045
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9cecc6d4b999d5c489b69406176bab99
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -19,12 +19,12 @@ MonoBehaviour:
m_Key: line:02365db
m_Metadata:
m_Items:
- rid: 5935570708321796308
- rid: 4903297902702231610
- m_Id: 111869431808
m_Key: line:0559767
m_Metadata:
m_Items:
- rid: 5935570708321796309
- rid: 4903297902702231611
- m_Id: 111869431809
m_Key: line:0ee9c21
m_Metadata:
@@ -35,6 +35,16 @@ MonoBehaviour:
m_Metadata:
m_Items:
- rid: 5935570708321796311
- m_Id: 46439178479603712
m_Key: line:0667c6a
m_Metadata:
m_Items:
- rid: 4903297902702231612
- m_Id: 46439178508963840
m_Key: line:054b767
m_Metadata:
m_Items:
- rid: 4903297902702231613
m_Metadata:
m_Items: []
m_KeyGenerator:
@@ -42,20 +52,30 @@ MonoBehaviour:
references:
version: 2
RefIds:
- rid: 4903297902702231610
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 4903297902702231611
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 4903297902702231612
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: "\u65B9\u5757\u62FC\u56FE\u5B8C\u6210"
tags: []
- rid: 4903297902702231613
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: "\u65B9\u5757\u62FC\u56FE\u5B8C\u6210"
tags: []
- rid: 5935570708321796307
type: {class: DistributedUIDGenerator, ns: UnityEngine.Localization.Tables, asm: Unity.Localization}
data:
m_CustomEpoch: 1754395704238
- rid: 5935570708321796308
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 5935570708321796309
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 5935570708321796310
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
@@ -34,6 +34,14 @@ MonoBehaviour:
m_Localized: "me: \u5931\u8D25"
m_Metadata:
m_Items: []
- m_Id: 46439178479603712
m_Localized: "me: \u5B8C\u6210"
m_Metadata:
m_Items: []
- m_Id: 46439178508963840
m_Localized: "me: \u5931\u8D25"
m_Metadata:
m_Items: []
references:
version: 2
RefIds: []
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -24,7 +24,7 @@ MonoBehaviour:
m_Metadata:
m_Items: []
- m_Id: 22296654778368
m_Localized: "\u7231&\u673A\u5668\u4EBA\\n\u7EF4\u4FEE\u6280\u672F"
m_Localized: "\u7231\u4E0E\u673A\u5668\u4EBA\\n\u7EF4\u4FEE\u6280\u672F"
m_Metadata:
m_Items:
- rid: 7917695939544875419
@@ -21,4 +21,4 @@ MonoBehaviour:
- {fileID: 11400000, guid: 7b4c80c072fa1784ab3223a1084225d4, type: 2}
- {fileID: 11400000, guid: 589fde7a8735fa44f8fe167466fd403b, type: 2}
- {fileID: 11400000, guid: 61d3b78d55f36924eb5182b317f09f50, type: 2}
- {fileID: 11400000, guid: 66c13343cc1b9dd4e80fc54742bd1b8c, type: 2}
- {fileID: 11400000, guid: c66ad9188c940404d8d95f3b75bc2e74, type: 2}
@@ -9,370 +9,8 @@ MonoBehaviour:
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f29c16c9fe849e442b4f1bab0c32e28a, type: 3}
m_Script: {fileID: 11500000, guid: b35610ff4f94b48418a96b669a706775, type: 3}
m_Name: StepAppearance
m_EditorClassIdentifier:
tagID: step
timeMode:
startDelay: 0
useUniformTime: 1
waveSize: 0
timeSpeed: 1
emissionCurve:
cycles: 1
duration: 1
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0.04143524
value: 0.9868164
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.92541504
value: 1.0178833
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
animationData:
movementX:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 1
waveSize: 0
movementY:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 1
waveSize: 0
movementZ:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 1
waveSize: 0
scaleX:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 2
waveSize: 0
scaleY:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 2
waveSize: 0
rotX:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 45
waveSize: 0
rotY:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 45
waveSize: 0
rotZ:
enabled: 0
weightOverTime:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0.5
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 1
m_PostInfinity: 1
m_RotationOrder: 4
amplitude: 45
waveSize: 0
colorCurve:
enabled: 0
colorOverTime:
serializedVersion: 2
key0: {r: 1, g: 1, b: 1, a: 1}
key1: {r: 0, g: 1, b: 1, a: 1}
key2: {r: 1, g: 1, b: 1, a: 0}
key3: {r: 0, g: 0, b: 0, a: 0}
key4: {r: 0, g: 0, b: 0, a: 0}
key5: {r: 0, g: 0, b: 0, a: 0}
key6: {r: 0, g: 0, b: 0, a: 0}
key7: {r: 0, g: 0, b: 0, a: 0}
ctime0: 0
ctime1: 34502
ctime2: 65535
ctime3: 0
ctime4: 0
ctime5: 0
ctime6: 0
ctime7: 0
atime0: 0
atime1: 65535
atime2: 0
atime3: 0
atime4: 0
atime5: 0
atime6: 0
atime7: 0
m_Mode: 1
m_ColorSpace: 0
m_NumColorKeys: 3
m_NumAlphaKeys: 2
waveSize: 0
duration: 1
baseDuration: 0.5
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 66c13343cc1b9dd4e80fc54742bd1b8c
guid: c66ad9188c940404d8d95f3b75bc2e74
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
@@ -0,0 +1,45 @@
using Febucci.UI.Core;
using Febucci.UI.Effects;
using UnityEngine;
namespace Febucci.UI.Effects
{
[UnityEngine.Scripting.Preserve]
[CreateAssetMenu(fileName = "Direct Appearance", menuName = "Text Animator/Animations/Appearances/Direct")]
[EffectInfo("step", EffectCategory.Appearances)]
public sealed class DirectAppearance : AppearanceScriptableBase
{
Color32 temp;
public override void ResetContext(TAnimCore animator)
{
base.ResetContext(animator);
}
public override void ApplyEffectTo(ref Core.CharacterData character, TAnimCore animator)
{
float timeProgress = character.passedTime / duration;
// First half: hide (alpha = 0)
// Second half: show (alpha = original)
for (int i = 0; i < TextUtilities.verticesPerChar; i++)
{
temp = character.current.colors[i];
if (timeProgress < 0.5f)
{
// First half: completely transparent
temp.a = 0;
}
else
{
// Second half: use original alpha from source
temp.a = character.source.colors[i].a;
}
character.current.colors[i] = temp;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b35610ff4f94b48418a96b669a706775
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 203b6470a52cede43824c2b766b89464
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1b33e012f04c4b66890fad3401d1abd1
timeCreated: 1765258694
@@ -0,0 +1,11 @@
using UnityEngine;
public class CNNameAttribute : PropertyAttribute
{
public string Name;
public CNNameAttribute(string name)
{
this.Name = name;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 251a6a4e8eda4e9bbfa088b9a34b0e7b
timeCreated: 1765258702
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 108f43113da2467789e5bef2327add79
timeCreated: 1765215242
@@ -0,0 +1,39 @@
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(CNNameAttribute))]
public class CNNameDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// 1. 获取特性中的中文名
CNNameAttribute attr = (CNNameAttribute)attribute;
// 2. 替换原本的 Label
GUIContent newLabel = new GUIContent(attr.Name, label.tooltip);
// 3. 绘制属性(使用中文名)
EditorGUI.PropertyField(position, property, newLabel, true);
// 4. 绘制变量原名(灰色小字,显示在 Label 区域的右侧)
// 计算 Label 的区域
float labelWidth = EditorGUIUtility.labelWidth;
Rect labelRect = new Rect(position.x, position.y, labelWidth, position.height);
// 设置小字样式
GUIStyle subStyle = new GUIStyle(EditorStyles.miniLabel);
subStyle.normal.textColor = new Color(0.5f, 0.5f, 0.5f, 0.6f); // 半透明灰色
subStyle.alignment = TextAnchor.MiddleRight; // 右对齐
subStyle.fontSize = 9;
subStyle.padding = new RectOffset(0, 2, 0, 0); //稍微留点边距
// 绘制变量名 (例如: "maxHP")
GUI.Label(labelRect, property.name, subStyle);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label);
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0c0f975bcc144b9187928b83dc9aaeac
timeCreated: 1765258716
@@ -0,0 +1,164 @@
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Collections.Generic;
[CustomEditor(typeof(SOEditorConfig))]
public class SOEditorConfigEditor : Editor
{
private SerializedProperty _typeNamesProp;
private string _searchText = "";
private void OnEnable()
{
_typeNamesProp = serializedObject.FindProperty("targetTypeNames");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
SOEditorConfig config = (SOEditorConfig)target;
GUILayout.Label("已管理的 SO 类型:", EditorStyles.boldLabel);
// === 1. 绘制已添加的类型列表 ===
EditorGUILayout.BeginVertical("box");
for (int i = 0; i < _typeNamesProp.arraySize; i++)
{
SerializedProperty prop = _typeNamesProp.GetArrayElementAtIndex(i);
string typeName = prop.stringValue;
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label($"{i + 1}. {typeName}", EditorStyles.label);
if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), EditorStyles.iconButton, GUILayout.Width(25)))
{
_typeNamesProp.DeleteArrayElementAtIndex(i);
break;
}
}
EditorGUILayout.EndHorizontal();
}
if (_typeNamesProp.arraySize == 0)
{
GUILayout.Label("暂无类型,请添加", EditorStyles.centeredGreyMiniLabel);
}
EditorGUILayout.EndVertical();
GUILayout.Space(10);
// === 2. 拖拽区域 (核心修改) ===
DrawDragDropArea();
GUILayout.Space(10);
// === 3. 搜索添加 ===
GUILayout.Label("或者:搜索添加", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
_searchText = EditorGUILayout.TextField(_searchText, EditorStyles.toolbarSearchField);
if (GUILayout.Button("搜索", GUILayout.Width(60)))
{
ShowTypeSelectorMenu(config);
}
EditorGUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
private void DrawDragDropArea()
{
// 绘制一个虚线框区域
Rect dropArea = GUILayoutUtility.GetRect(0.0f, 60.0f, GUILayout.ExpandWidth(true));
GUI.Box(dropArea, "\n拖拽文件到这里添加\n(支持 .cs 脚本 或 .asset 资源)", EditorStyles.helpBox);
Event evt = Event.current;
if (evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform)
{
if (!dropArea.Contains(evt.mousePosition)) return;
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (evt.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
foreach (UnityEngine.Object dragged_object in DragAndDrop.objectReferences)
{
Type typeToAdd = null;
// 情况 A: 拖入的是 .cs 脚本文件
if (dragged_object is MonoScript script)
{
typeToAdd = script.GetClass();
}
// 情况 B: 拖入的是 .asset 资源实例 (比如 New Tank.asset)
else if (dragged_object is ScriptableObject soInstance)
{
// 直接获取这个实例的类型
typeToAdd = soInstance.GetType();
}
// 执行添加逻辑
if (typeToAdd != null)
{
// 过滤掉 Config 本身,防止把自己加进去
if (typeToAdd == typeof(SOEditorConfig)) continue;
if (typeToAdd.IsSubclassOf(typeof(ScriptableObject)))
{
AddType(typeToAdd.FullName);
}
}
}
}
}
}
private void ShowTypeSelectorMenu(SOEditorConfig config)
{
GenericMenu menu = new GenericMenu();
var allSoTypes = TypeCache.GetTypesDerivedFrom<ScriptableObject>()
.Where(t => !t.IsAbstract && !t.IsGenericType && !string.IsNullOrEmpty(t.Namespace) && !t.Namespace.StartsWith("Unity") && !t.Namespace.StartsWith("UnityEditor"))
.OrderBy(t => t.Name);
foreach (var type in allSoTypes)
{
if (!string.IsNullOrEmpty(_searchText) && !type.Name.ToLower().Contains(_searchText.ToLower()))
continue;
string menuPath = string.IsNullOrEmpty(type.Namespace) ? type.Name : $"{type.Namespace}/{type.Name}";
menu.AddItem(new GUIContent(menuPath), config.targetTypeNames.Contains(type.FullName), () => { AddType(type.FullName); });
}
menu.ShowAsContext();
}
private void AddType(string typeFullName)
{
serializedObject.Update();
bool exists = false;
for (int i = 0; i < _typeNamesProp.arraySize; i++)
{
if (_typeNamesProp.GetArrayElementAtIndex(i).stringValue == typeFullName)
{
exists = true;
break;
}
}
if (!exists)
{
_typeNamesProp.InsertArrayElementAtIndex(_typeNamesProp.arraySize);
_typeNamesProp.GetArrayElementAtIndex(_typeNamesProp.arraySize - 1).stringValue = typeFullName;
serializedObject.ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 45f4877471fd47efb465a700a6869eb4
timeCreated: 1765219950
@@ -0,0 +1,428 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System;
using System.Linq;
public class UniversalSOManager : EditorWindow
{
// === 布局常量 ===
private const float SIDEBAR_WIDTH = 160f;
private const float ASSET_LIST_WIDTH = 220f;
// === 核心数据 ===
private SOEditorConfig _config;
private Type _selectedType; // 现在直接存 Type,不再存 MonoScript
// === 列表与编辑 ===
private List<ScriptableObject> _assetList = new List<ScriptableObject>();
private ScriptableObject _selectedAsset;
private Editor _cachedEditor;
// === 状态 ===
private string _searchRootPath = "Assets/SOGameData";
private Vector2 _scrollPosTypes;
private Vector2 _scrollPosAssets;
private Vector2 _scrollPosInspector;
private string _searchString = "";
private string _newAssetName = "";
[MenuItem("Tools/万能SO编辑器 (Universal SO Manager)")]
public static void ShowWindow()
{
GetWindow<UniversalSOManager>("SO Manager");
}
private void OnEnable()
{
string configPath = EditorPrefs.GetString("UniversalSOManager_ConfigPath", "");
if (!string.IsNullOrEmpty(configPath))
{
_config = AssetDatabase.LoadAssetAtPath<SOEditorConfig>(configPath);
}
// 加载保存的资源路径
_searchRootPath = EditorPrefs.GetString("UniversalSOManager_SearchRootPath", "Assets/SOGameData");
}
private void OnDisable()
{
if (_cachedEditor != null) DestroyImmediate(_cachedEditor);
if (_config != null)
{
EditorPrefs.SetString("UniversalSOManager_ConfigPath", AssetDatabase.GetAssetPath(_config));
}
// 保存资源路径
EditorPrefs.SetString("UniversalSOManager_SearchRootPath", _searchRootPath);
}
private void OnGUI()
{
DrawTopGlobalBar();
if (_config == null)
{
DrawEmptyState();
return;
}
EditorGUILayout.BeginHorizontal();
{
DrawSidebar();
EditorGUILayout.BeginVertical();
{
DrawTypeOperationHeader();
EditorGUILayout.BeginHorizontal();
{
DrawAssetList();
DrawInspector();
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndHorizontal();
}
// ------------------------------------------------------------------------
// UI 绘制函数
// ------------------------------------------------------------------------
private void DrawTopGlobalBar()
{
EditorGUILayout.BeginHorizontal("box", GUILayout.Height(30));
{
GUILayout.Label("资源路径:", GUILayout.Width(60));
_searchRootPath = EditorGUILayout.TextField(_searchRootPath, GUILayout.Width(150));
if (GUILayout.Button("...", EditorStyles.miniButton, GUILayout.Width(25)))
{
string path = EditorUtility.OpenFolderPanel("选择根目录", Application.dataPath, "");
if (!string.IsNullOrEmpty(path) && path.StartsWith(Application.dataPath))
{
_searchRootPath = "Assets" + path.Substring(Application.dataPath.Length);
RefreshAssetList();
}
}
GUILayout.Space(20);
GUILayout.Label("Config文件:", GUILayout.Width(70));
EditorGUI.BeginChangeCheck();
_config = (SOEditorConfig)EditorGUILayout.ObjectField(_config, typeof(SOEditorConfig), false, GUILayout.Width(200));
if (EditorGUI.EndChangeCheck())
{
_selectedType = null;
_assetList.Clear();
_selectedAsset = null;
GUIUtility.ExitGUI();
}
// 快捷编辑 Config 按钮
if (_config != null)
{
if (GUILayout.Button("编辑Config", EditorStyles.miniButton, GUILayout.Width(80)))
{
Selection.activeObject = _config;
}
}
GUILayout.FlexibleSpace();
if (GUILayout.Button("强制刷新", EditorStyles.toolbarButton, GUILayout.Width(80)))
{
AssetDatabase.Refresh();
RefreshAssetList();
}
}
EditorGUILayout.EndHorizontal();
}
private void DrawSidebar()
{
EditorGUILayout.BeginVertical("box", GUILayout.Width(SIDEBAR_WIDTH), GUILayout.ExpandHeight(true));
GUILayout.Label("SO 种类", EditorStyles.boldLabel);
GUILayout.Space(5);
_scrollPosTypes = EditorGUILayout.BeginScrollView(_scrollPosTypes);
if (_config != null && _config.targetTypeNames != null)
{
foreach (var typeName in _config.targetTypeNames)
{
// 解析类型
Type type = GetTypeByName(typeName);
if (type == null)
{
// 类型丢失(可能代码改名了)
GUI.color = Color.red;
GUILayout.Label($"丢失: {typeName}");
GUI.color = Color.white;
continue;
}
bool isSelected = (_selectedType == type);
if (isSelected) GUI.backgroundColor = new Color(0.6f, 0.8f, 1f);
// 使用短名显示,但在 Tooltip 显示全名
if (GUILayout.Button(new GUIContent(type.Name, type.FullName), EditorStyles.miniButton, GUILayout.Height(28)))
{
SelectType(type);
}
GUI.backgroundColor = Color.white;
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
private void DrawTypeOperationHeader()
{
EditorGUILayout.BeginVertical("box", GUILayout.Height(60), GUILayout.ExpandWidth(true));
string title = _selectedType != null ? _selectedType.Name : "请选择种类";
GUILayout.Label($"当前操作: {title}", EditorStyles.boldLabel);
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
{
GUILayout.Label("搜索:", GUILayout.Width(40));
string newSearch = EditorGUILayout.TextField(_searchString, EditorStyles.toolbarSearchField, GUILayout.Width(200));
if (newSearch != _searchString)
{
_searchString = newSearch;
RefreshAssetList();
}
GUILayout.FlexibleSpace();
GUILayout.Label("新名称:", GUILayout.Width(50));
_newAssetName = EditorGUILayout.TextField(_newAssetName, GUILayout.Width(150));
EditorGUI.BeginDisabledGroup(_selectedType == null);
if (GUILayout.Button("新增 (Create)", EditorStyles.miniButtonRight, GUILayout.Width(100)))
{
CreateAsset();
}
EditorGUI.EndDisabledGroup();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
private void DrawAssetList()
{
EditorGUILayout.BeginVertical("box", GUILayout.Width(ASSET_LIST_WIDTH), GUILayout.ExpandHeight(true));
GUILayout.Label("资源列表", EditorStyles.miniLabel);
_scrollPosAssets = EditorGUILayout.BeginScrollView(_scrollPosAssets);
if (_assetList != null)
{
for (int i = 0; i < _assetList.Count; i++)
{
var asset = _assetList[i];
if (asset == null) continue;
EditorGUILayout.BeginHorizontal("box");
{
if (_selectedAsset == asset) GUI.backgroundColor = Color.green;
if (GUILayout.Button(asset.name, EditorStyles.label, GUILayout.Height(22)))
{
SelectAsset(asset);
}
GUI.backgroundColor = Color.white;
if (GUILayout.Button(EditorGUIUtility.IconContent("d_ViewToolOrbit"), EditorStyles.iconButton, GUILayout.Width(22)))
EditorGUIUtility.PingObject(asset);
if (GUILayout.Button(EditorGUIUtility.IconContent("d_TreeEditor.Duplicate"), EditorStyles.iconButton, GUILayout.Width(22)))
DuplicateAsset(asset);
if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), EditorStyles.iconButton, GUILayout.Width(22)))
{
if (EditorUtility.DisplayDialog("删除确认", $"确定删除 {asset.name} 吗?", "删除", "取消"))
{
DeleteAsset(asset);
GUIUtility.ExitGUI();
}
}
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
private void DrawInspector()
{
EditorGUILayout.BeginVertical("box", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
if (_selectedAsset != null)
{
GUILayout.Label("属性编辑", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
GUILayout.Label("文件名:", GUILayout.Width(50));
string newName = EditorGUILayout.DelayedTextField(_selectedAsset.name);
if (newName != _selectedAsset.name) RenameAsset(_selectedAsset, newName);
EditorGUILayout.EndHorizontal();
GUILayout.Space(10);
_scrollPosInspector = EditorGUILayout.BeginScrollView(_scrollPosInspector);
if (_cachedEditor == null || _cachedEditor.target != _selectedAsset)
{
if (_cachedEditor != null) DestroyImmediate(_cachedEditor);
_cachedEditor = Editor.CreateEditor(_selectedAsset);
}
if (_cachedEditor != null)
{
EditorGUI.BeginChangeCheck();
_cachedEditor.OnInspectorGUI();
if (EditorGUI.EndChangeCheck()) EditorUtility.SetDirty(_selectedAsset);
}
EditorGUILayout.EndScrollView();
}
else
{
GUILayout.FlexibleSpace();
GUILayout.Label("<< 请选择资源", EditorStyles.centeredGreyMiniLabel);
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndVertical();
}
private void DrawEmptyState()
{
EditorGUILayout.BeginVertical();
GUILayout.FlexibleSpace();
EditorGUILayout.HelpBox("请在顶部指定一个 SOEditorConfig 配置文件。", MessageType.Info);
GUILayout.FlexibleSpace();
EditorGUILayout.EndVertical();
}
// ------------------------------------------------------------------------
// 逻辑处理
// ------------------------------------------------------------------------
// 辅助:从字符串获取类型 (遍历所有程序集)
private Type GetTypeByName(string fullName)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var type = assembly.GetType(fullName);
if (type != null) return type;
}
return null;
}
private void SelectType(Type type)
{
_selectedType = type;
_selectedAsset = null;
_newAssetName = "New " + type.Name;
RefreshAssetList();
}
private void SelectAsset(ScriptableObject asset)
{
_selectedAsset = asset;
GUI.FocusControl(null);
}
private void RefreshAssetList()
{
if (_selectedType == null) return;
_assetList.Clear();
// 查找资源
string[] guids = AssetDatabase.FindAssets($"t:{_selectedType.Name}", new[] { _searchRootPath });
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var asset = AssetDatabase.LoadAssetAtPath<ScriptableObject>(path);
// 严格类型检查 (支持继承)
if (asset != null && _selectedType.IsAssignableFrom(asset.GetType()))
{
if (string.IsNullOrEmpty(_searchString) || asset.name.ToLower().Contains(_searchString.ToLower()))
{
_assetList.Add(asset);
}
}
}
_assetList.Sort((a, b) => string.Compare(a.name, b.name, StringComparison.Ordinal));
}
private void CreateAsset()
{
if (_selectedType == null) return;
string targetFolder = $"{_searchRootPath}/{_selectedType.Name}";
if (!AssetDatabase.IsValidFolder(targetFolder))
{
if (AssetDatabase.IsValidFolder(_searchRootPath))
AssetDatabase.CreateFolder(_searchRootPath, _selectedType.Name);
else
targetFolder = _searchRootPath;
}
string fullPath = $"{targetFolder}/{_newAssetName}.asset";
fullPath = AssetDatabase.GenerateUniqueAssetPath(fullPath);
var instance = ScriptableObject.CreateInstance(_selectedType);
AssetDatabase.CreateAsset(instance, fullPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
RefreshAssetList();
SelectAsset(instance);
}
private void DuplicateAsset(ScriptableObject asset)
{
string path = AssetDatabase.GetAssetPath(asset);
string newPath = AssetDatabase.GenerateUniqueAssetPath(path);
AssetDatabase.CopyAsset(path, newPath);
AssetDatabase.SaveAssets();
RefreshAssetList();
}
private void DeleteAsset(ScriptableObject asset)
{
string path = AssetDatabase.GetAssetPath(asset);
AssetDatabase.DeleteAsset(path);
AssetDatabase.SaveAssets();
if (_selectedAsset == asset) _selectedAsset = null;
RefreshAssetList();
}
private void RenameAsset(ScriptableObject asset, string newName)
{
string path = AssetDatabase.GetAssetPath(asset);
AssetDatabase.RenameAsset(path, newName);
AssetDatabase.SaveAssets();
RefreshAssetList();
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 70dc192513964637860b748b8957f0f6
timeCreated: 1765215245
@@ -0,0 +1,9 @@
using UnityEngine;
using System.Collections.Generic;
[CreateAssetMenu(fileName = "SOEditorConfig", menuName = "Tools/SO编辑器配置 (Config)")]
public class SOEditorConfig : ScriptableObject
{
// 存储类型的全名 (例如 "MyGame.TankEngine")
public List<string> targetTypeNames = new List<string>();
}

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