Обновить игровые системы и интерфейс

This commit is contained in:
Сергей Бондарь 2026-09-14 14:59:46 +03:00
parent 826ff5782a
commit ded80f043f
90 changed files with 2743 additions and 222 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 829cdffc69d3d174aaeb8e8e5c5a6aa4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,118 @@
%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: 468a46d0ae32c3544b7d98094e6448a9, type: 3}
m_Name: AddressableAssetSettings
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetSettings
m_DefaultGroup: df2065112a43a624f9b4aa0dd0c03c94
m_currentHash:
serializedVersion: 2
Hash: 00000000000000000000000000000000
m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0
m_CatalogRequestsTimeout: 0
m_DisableCatalogUpdateOnStart: 0
m_InternalIdNamingMode: 0
m_InternalBundleIdMode: 1
m_AssetLoadMode: 0
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_IgnoreUnsupportedFilesInBuild: 0
m_UniqueBundleIds: 0
m_EnableJsonCatalog: 0
m_NonRecursiveBuilding: 1
m_AllowNestedBundleFolders: 0
m_CCDEnabled: 0
m_maxConcurrentWebRequests: 3
m_UseUWRForLocalBundles: 0
m_BundleTimeout: 0
m_BundleRetryCount: 0
m_BundleRedirectLimit: -1
m_SharedBundleSettings: 0
m_SharedBundleSettingsCustomGroupIndex: 0
m_simulatedLoadDelay: 0.1
m_ContiguousBundles: 1
m_StripUnityVersionFromBundleBuild: 0
m_DisableVisibleSubAssetRepresentations: 0
m_BuiltInBundleNaming: 0
mBuiltInBundleCustomNaming:
m_MonoScriptBundleNaming: 0
m_CheckForContentUpdateRestrictionsOption: 0
m_MonoScriptBundleCustomNaming:
m_RemoteCatalogBuildPath:
m_Id:
m_RemoteCatalogLoadPath:
m_Id:
m_ContentStateBuildPathProfileVariableName:
m_CustomContentStateBuildPath:
m_ContentStateBuildPath:
m_BuildAddressablesWithPlayerBuild: 1
m_overridePlayerVersion: '[UnityEditor.PlayerSettings.bundleVersion]'
m_GroupAssets:
- {fileID: 11400000, guid: 9b91d9014e8b8754a8f6961e7c28aeb0, type: 2}
- {fileID: 11400000, guid: 516edc17c98cb9a42bbe9ee23cfecdba, type: 2}
- {fileID: 11400000, guid: 67a7a9d11ea585547a828fefd5376422, type: 2}
m_BuildSettings:
m_LogResourceManagerExceptions: 1
m_BundleBuildPath: Temp/com.unity.addressables/AssetBundles
m_ProfileSettings:
m_Profiles:
- m_InheritedParent:
m_Id: f05f041b83f2a4e4f8f92ecb9f3a093b
m_ProfileName: Default
m_Values:
- m_Id: 2d2eaaa3af3c3794a9e3db1a1292a81d
m_Value: '[UnityEngine.AddressableAssets.Addressables.BuildPath]/[BuildTarget]'
- m_Id: 5fb3a60ecc1ab1e448f6afac94a2d17f
m_Value: '{UnityEngine.AddressableAssets.Addressables.RuntimePath}/[BuildTarget]'
- m_Id: cd4968d421c1cb5409adfbbb6b20c5f9
m_Value: '[UnityEditor.EditorUserBuildSettings.activeBuildTarget]'
- m_Id: df5be12b8885af84691477dc5072cb20
m_Value: 'ServerData/[BuildTarget]'
- m_Id: f48d798d4762a944cb1da5825377afb5
m_Value: <undefined>
m_ProfileEntryNames:
- m_Id: 2d2eaaa3af3c3794a9e3db1a1292a81d
m_Name: Local.BuildPath
m_InlineUsage: 0
- m_Id: 5fb3a60ecc1ab1e448f6afac94a2d17f
m_Name: Local.LoadPath
m_InlineUsage: 0
- m_Id: cd4968d421c1cb5409adfbbb6b20c5f9
m_Name: BuildTarget
m_InlineUsage: 0
- m_Id: df5be12b8885af84691477dc5072cb20
m_Name: Remote.BuildPath
m_InlineUsage: 0
- m_Id: f48d798d4762a944cb1da5825377afb5
m_Name: Remote.LoadPath
m_InlineUsage: 0
m_ProfileVersion: 1
m_LabelTable:
m_LabelNames:
- default
m_SchemaTemplates: []
m_GroupTemplateObjects:
- {fileID: 11400000, guid: 67eacf3d10549bb49891ede0b8d3584f, type: 2}
m_InitializationObjects: []
m_CertificateHandlerType:
m_AssemblyName:
m_ClassName:
m_ActivePlayerDataBuilderIndex: 2
m_DataBuilders:
- {fileID: 11400000, guid: 9efdb80b1628cd748b4fb2dd3c826055, type: 2}
- {fileID: 11400000, guid: 6504b9f2a35988546ac36ee6ed1479b1, type: 2}
- {fileID: 11400000, guid: 213887a646363e4458bb35d1a48e3e6d, type: 2}
m_ActiveProfileId: f05f041b83f2a4e4f8f92ecb9f3a093b

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b892e9e50d90fb34f959c42bdc79e8c2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d1ad1ebea50f0c45bc543f02ed3eec0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,79 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-4333636487394161612
MonoBehaviour:
m_ObjectHideFlags: 1
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: ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 0}
m_StaticContent: 0
--- !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: 1a3c5d64ac83548c09dd1678b9f6f1cd, type: 3}
m_Name: Packed Assets
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroupTemplate
m_SchemaObjects:
- {fileID: 6273069629216273552}
- {fileID: -4333636487394161612}
m_Description: Pack assets into asset bundles.
m_Settings: {fileID: 11400000, guid: b892e9e50d90fb34f959c42bdc79e8c2, type: 2}
--- !u!114 &6273069629216273552
MonoBehaviour:
m_ObjectHideFlags: 1
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: BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 0}
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:
m_ClassName:
m_StripDownloadOptions: 0
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:
m_LoadPath:
m_Id:
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName:
m_ClassName:
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67eacf3d10549bb49891ede0b8d3584f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 721dd489e09b2a64d9c9e70d016b4708
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
%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: Character Backgrounds
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Character Backgrounds
m_GUID: 3ba9c2f7f8294b44eb8532b44ac95598
m_SerializeEntries:
- m_GUID: 379e3fc5979e27d4f991c726da0021e4
m_Address: Character Backgrounds/2
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 42068fbdf20fe4c44b71be20e1e4999a
m_Address: Character Backgrounds/4
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 64ca9527c2e40734498ac8fa292a4a9d
m_Address: Character Backgrounds/5
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b4edb37b77e2fdc4dbbf6c1305574e92
m_Address: Character Backgrounds/3
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d43db9ce0594b2f4eaa23aa1f13e6b85
m_Address: Character Backgrounds/1
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: b892e9e50d90fb34f959c42bdc79e8c2, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: c2e54c4a7f304b8419524975a0877041, type: 2}
- {fileID: 11400000, guid: 52cfc4d6e2c87534aaf935dd9ec8851c, type: 2}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9b91d9014e8b8754a8f6961e7c28aeb0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,58 @@
%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: Characters
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Characters
m_GUID: f0b4d85d7ea6b5d4f81c0f3756b777e8
m_SerializeEntries:
- m_GUID: 53736a6cd29210e4eb0f110ef04d344c
m_Address: Characters/02_Electro
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 7702b7919503a1e479151e8fecd78924
m_Address: Characters/01_Cube
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a6618e61e181953458cf6769884c4403
m_Address: Characters/06_PvpPlayer1
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: b268c439fa90d6542ab0c876cd677661
m_Address: Characters/07_PvpPlayer2
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: d2448bca251e50a4ebaae923084264a0
m_Address: Characters/04_Samurai
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: eb3cf1ffcc790864db631f50a02da123
m_Address: Characters/03_Wolf
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f1fc145bd1885e146bc33b2669940862
m_Address: Characters/05_Feeshka
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: b892e9e50d90fb34f959c42bdc79e8c2, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: 116f523337e034f44baa823780ebe97e, type: 2}
- {fileID: 11400000, guid: ad2067ce8159a9a43ae323a78f7c766e, type: 2}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67a7a9d11ea585547a828fefd5376422
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Default Local Group
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Default Local Group
m_GUID: df2065112a43a624f9b4aa0dd0c03c94
m_SerializeEntries: []
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: b892e9e50d90fb34f959c42bdc79e8c2, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: 4c56f53c6ea840d48a8f4c38109408fc, type: 2}
- {fileID: 11400000, guid: 698e7500f10f30a46a2a60499b5343f6, type: 2}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 516edc17c98cb9a42bbe9ee23cfecdba
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 974109a794f3e184ca04abcf84554af5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
%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: Character Backgrounds_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: 9b91d9014e8b8754a8f6961e7c28aeb0, 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_StripDownloadOptions: 0
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: 2d2eaaa3af3c3794a9e3db1a1292a81d
m_LoadPath:
m_Id: 5fb3a60ecc1ab1e448f6afac94a2d17f
m_BundleMode: 1
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c2e54c4a7f304b8419524975a0877041
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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: Character Backgrounds_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: 9b91d9014e8b8754a8f6961e7c28aeb0, type: 2}
m_StaticContent: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 52cfc4d6e2c87534aaf935dd9ec8851c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
%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: Characters_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: 67a7a9d11ea585547a828fefd5376422, 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_StripDownloadOptions: 0
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: 2d2eaaa3af3c3794a9e3db1a1292a81d
m_LoadPath:
m_Id: 5fb3a60ecc1ab1e448f6afac94a2d17f
m_BundleMode: 1
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 116f523337e034f44baa823780ebe97e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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: Characters_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: 67a7a9d11ea585547a828fefd5376422, type: 2}
m_StaticContent: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ad2067ce8159a9a43ae323a78f7c766e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
%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: Default Local Group_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: 516edc17c98cb9a42bbe9ee23cfecdba, 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_StripDownloadOptions: 0
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: 2d2eaaa3af3c3794a9e3db1a1292a81d
m_LoadPath:
m_Id: 5fb3a60ecc1ab1e448f6afac94a2d17f
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_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4c56f53c6ea840d48a8f4c38109408fc
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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: Default Local Group_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: 516edc17c98cb9a42bbe9ee23cfecdba, type: 2}
m_StaticContent: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 698e7500f10f30a46a2a60499b5343f6
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0f934c0f92eb9df4e9e2b2f93395de72
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
%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: 88d21199f5d473f4db36845f2318f180, type: 3}
m_Name: BuildScriptFastMode
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Build.DataBuilders.BuildScriptFastMode
instanceProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.InstanceProvider
sceneProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.SceneProvider

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9efdb80b1628cd748b4fb2dd3c826055
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
%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: 3e2e0ffa088c91d41a086d0b8cb16bdc, type: 3}
m_Name: BuildScriptPackedMode
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Build.DataBuilders.BuildScriptPackedMode
instanceProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.InstanceProvider
sceneProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.SceneProvider

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 213887a646363e4458bb35d1a48e3e6d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
%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: ad8c280d42ee0ed41a27db23b43dd2bf, type: 3}
m_Name: BuildScriptPackedPlayMode
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Build.DataBuilders.BuildScriptPackedPlayMode
instanceProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.InstanceProvider
sceneProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.SceneProvider

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6504b9f2a35988546ac36ee6ed1479b1
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,15 @@
%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: 3a189bb168d8d90478a09ea08c2f3d72, type: 3}
m_Name: DefaultObject
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject
m_AddressableAssetSettingsGuid: b892e9e50d90fb34f959c42bdc79e8c2

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 65c6c2044a27e1e4ea802fce939390bb
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,28 @@
%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: 7e3976da977cb49238499ea3b4c237ae, type: 3}
m_Name: ProfileDataSourceSettings
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.ProfileDataSourceSettings
profileGroupTypes:
- m_GroupTypePrefix: Built-In
m_Variables:
- m_Suffix: BuildPath
m_Value: '[UnityEngine.AddressableAssets.Addressables.BuildPath]/[BuildTarget]'
- m_Suffix: LoadPath
m_Value: '{UnityEngine.AddressableAssets.Addressables.RuntimePath}/[BuildTarget]'
environments: []
currentEnvironment:
id:
projectId:
projectGenesisId:
name:
isDefault: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 10e816464a4720f49aab8c3932d50d67
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7245006759a7c6c46bc11f6162f4c8b1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 000e1b4d2fa45d04487fc17e0c4a3b29
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 87fe8168391b3844fbdbe3e0ae338d3b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 01_Cube
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 0
_characterName: "\u041A\u044C\u044E\u0431"
_iconSmall: {fileID: 6506343174705358099, guid: b84c4d324265bea4ba491f56d3c8b1c8, type: 3}
_difficultyModule: {fileID: 11400000, guid: 63af74f9b3c85a54cb03e0e31e9ee3c3, type: 2}
_prefab:
m_AssetGUID: 7702b7919503a1e479151e8fecd78924
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0
_backgroundVideo:
m_AssetGUID: d43db9ce0594b2f4eaa23aa1f13e6b85
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 071e5a14dee84744bba4903e9bac7e70
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 02_Electro
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 1
_characterName: "\u0422\u043E\u043C"
_iconSmall: {fileID: 3349644112325863184, guid: b84c4d324265bea4ba491f56d3c8b1c8, type: 3}
_difficultyModule: {fileID: 11400000, guid: e178387e848f5864c9a975c933825167, type: 2}
_prefab:
m_AssetGUID: 53736a6cd29210e4eb0f110ef04d344c
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0
_backgroundVideo:
m_AssetGUID: 379e3fc5979e27d4f991c726da0021e4
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 24322052d894cd64e85aeafaaf286150
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 03_Wolf
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 2
_characterName: "\u0420\u043E\u0431\u043E\u0432\u043E\u043B\u043A"
_iconSmall: {fileID: 7174167584646727459, guid: b84c4d324265bea4ba491f56d3c8b1c8, type: 3}
_difficultyModule: {fileID: 11400000, guid: 4c735b14669a55e43b6ff6dd0f0cf508, type: 2}
_prefab:
m_AssetGUID: eb3cf1ffcc790864db631f50a02da123
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0
_backgroundVideo:
m_AssetGUID: b4edb37b77e2fdc4dbbf6c1305574e92
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 717adc8c81757404e9c38556ca05604a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 04_Samurai
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 3
_characterName: "\u0421\u0430\u043C\u0443\u0440\u0430\u0439"
_iconSmall: {fileID: -77006150763170147, guid: b84c4d324265bea4ba491f56d3c8b1c8, type: 3}
_difficultyModule: {fileID: 11400000, guid: 27b47c257b79ff547ac4222555a5ca7d, type: 2}
_prefab:
m_AssetGUID: d2448bca251e50a4ebaae923084264a0
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0
_backgroundVideo:
m_AssetGUID: 42068fbdf20fe4c44b71be20e1e4999a
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: aa5b414569e3d2445952736a93139797
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 05_Feeshka
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 4
_characterName: "\u0424\u0438\u0448\u043A\u0430"
_iconSmall: {fileID: -8315295956674182197, guid: b84c4d324265bea4ba491f56d3c8b1c8, type: 3}
_difficultyModule: {fileID: 11400000, guid: 8625ba3535975b847aeb2c0172511362, type: 2}
_prefab:
m_AssetGUID: f1fc145bd1885e146bc33b2669940862
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0
_backgroundVideo:
m_AssetGUID: 64ca9527c2e40734498ac8fa292a4a9d
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1bbd5b93d9d1944448ba1bb034fa1ccd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 06_PvpPlayer1
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 0
_characterName: "\u0418\u0433\u0440\u043E\u043A 1"
_iconSmall: {fileID: 0}
_difficultyModule: {fileID: 0}
_prefab:
m_AssetGUID: a6618e61e181953458cf6769884c4403
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ebd791f729a9b2e4392928de18feb4da
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
%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: b89b3154a9ca3344c924ccde85596538, type: 3}
m_Name: 07_PvpPlayer2
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.CharacterDefinition
_characterIndex: 1
_characterName: "\u0418\u0433\u0440\u043E\u043A 2"
_iconSmall: {fileID: 0}
_difficultyModule: {fileID: 0}
_prefab:
m_AssetGUID: b268c439fa90d6542ab0c876cd677661
m_SubObjectName:
m_SubObjectType:
m_SubObjectGUID:
m_EditorAssetChanged: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed92c97643a88ab4f8400937dfae7da5
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -955,6 +955,10 @@ MonoBehaviour:
descriptionOpenY: 0
descriptionCloseY: 100
descriptionDuration: 0.2
_recordPrefab: {fileID: 8795707554674279380, guid: 610d9c2c016a8b748acc5353523be0c1, type: 3}
_recordsCount: 3
_recordsSize: {x: 800, y: 190}
_recordSpacing: 4
--- !u!1 &8862341168163577817
GameObject:
m_ObjectHideFlags: 0

View File

@ -221,6 +221,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 4260274597846135767}
- component: {fileID: 5150778061717768082}
m_Layer: 5
m_Name: Rating
m_TagString: Untagged
@ -249,6 +250,28 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &5150778061717768082
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1693237235076212455}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cee249e8bb9b66a4a8ddf0d00916ce5e, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::RatingModal
_rowPrefab: {fileID: 8795707554674279380, guid: 610d9c2c016a8b748acc5353523be0c1, type: 3}
_latestRowPrefab: {fileID: 3448606624388700107, guid: 27e265a942f5e944ba64cee964262ed5, type: 3}
_maxRecords: 100
_rowSpacing: 4
_scrollAcceleration: 3600
_scrollDeceleration: 4800
_maxScrollSpeed: 1800
_minimumScrollbarHandleHeight: 30
_inputTimeout: 20
_transitionDuration: 0.25
--- !u!1 &2145754811189384270
GameObject:
m_ObjectHideFlags: 0

View File

@ -3160,12 +3160,6 @@ MonoBehaviour:
_secondaryPlayer: {fileID: 172285188}
_audioSource: {fileID: 172285187}
_menuBackground: {fileID: 32900000, guid: 8006745930823e7468d58b59bfe6016b, type: 3}
_characterBackgrounds:
- {fileID: 32900000, guid: d43db9ce0594b2f4eaa23aa1f13e6b85, type: 3}
- {fileID: 32900000, guid: 379e3fc5979e27d4f991c726da0021e4, type: 3}
- {fileID: 32900000, guid: b4edb37b77e2fdc4dbbf6c1305574e92, type: 3}
- {fileID: 32900000, guid: 42068fbdf20fe4c44b71be20e1e4999a, type: 3}
- {fileID: 32900000, guid: 64ca9527c2e40734498ac8fa292a4a9d, type: 3}
_ads: {fileID: 32900000, guid: a9b78f5df2dea0d43a26c922b9ccb85c, type: 3}
_ending: {fileID: 32900000, guid: a6b4af34fd1c1144aa20b71dd9a857d1, type: 3}
_crossFadeDuration: 1
@ -15071,12 +15065,12 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f79f1e2c50eb4b14583157ed5996c65f, type: 3}
m_Name:
m_EditorClassIdentifier:
characterPrefabs:
- {fileID: 8039207184498597514, guid: 7702b7919503a1e479151e8fecd78924, type: 3}
- {fileID: 8233466963536421093, guid: 53736a6cd29210e4eb0f110ef04d344c, type: 3}
- {fileID: 6676369703225837789, guid: eb3cf1ffcc790864db631f50a02da123, type: 3}
- {fileID: 3215344534852605381, guid: d2448bca251e50a4ebaae923084264a0, type: 3}
- {fileID: 5982990141465619124, guid: f1fc145bd1885e146bc33b2669940862, type: 3}
_characterDefinitions:
- {fileID: 11400000, guid: 071e5a14dee84744bba4903e9bac7e70, type: 2}
- {fileID: 11400000, guid: 24322052d894cd64e85aeafaaf286150, type: 2}
- {fileID: 11400000, guid: 717adc8c81757404e9c38556ca05604a, type: 2}
- {fileID: 11400000, guid: aa5b414569e3d2445952736a93139797, type: 2}
- {fileID: 11400000, guid: 1bbd5b93d9d1944448ba1bb034fa1ccd, type: 2}
--- !u!4 &1542626845
Transform:
m_ObjectHideFlags: 0
@ -18366,9 +18360,9 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2aaf52d670e0dc845807a4d8ba998208, type: 3}
m_Name:
m_EditorClassIdentifier:
_characterPrefabs:
- {fileID: 6069554613919803763, guid: a6618e61e181953458cf6769884c4403, type: 3}
- {fileID: 6156076713058116187, guid: b268c439fa90d6542ab0c876cd677661, type: 3}
_characterDefinitions:
- {fileID: 11400000, guid: ebd791f729a9b2e4392928de18feb4da, type: 2}
- {fileID: 11400000, guid: ed92c97643a88ab4f8400937dfae7da5, type: 2}
_avatarsParent: {fileID: 0}
_player1HiddenLocalPosition: {x: -20, y: -5.86}
_player1ShownLocalPosition: {x: -5, y: -5.86}

View File

@ -14,9 +14,6 @@ namespace CharacterSystem
public void Initialize(int characterIndex)
{
CharacterIndex = characterIndex;
difficultyModule.PullSettings();
SettingsManager.OnSettingsChanged += difficultyModule.PullSettings;
visualModule.Initialize(characterName);
}
@ -27,4 +24,4 @@ namespace CharacterSystem
prizeModule.ResetModule();
}
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Video;
namespace CharacterSystem
{
[Serializable]
public sealed class AssetReferenceVideoClip : AssetReferenceT<VideoClip>
{
public AssetReferenceVideoClip(string guid) : base(guid)
{
}
}
[CreateAssetMenu(fileName = "CharacterDefinition", menuName = "Scriptable Objects/Character Definition")]
public sealed class CharacterDefinition : ScriptableObject
{
[SerializeField] private int _characterIndex;
[SerializeField] private string _characterName;
[SerializeField] private Sprite _iconSmall;
[SerializeField] private DifficultyModule _difficultyModule;
[SerializeField] private AssetReferenceGameObject _prefab;
[SerializeField] private AssetReferenceVideoClip _backgroundVideo;
public int CharacterIndex => _characterIndex;
public string CharacterName => _characterName;
public Sprite IconSmall => _iconSmall;
public DifficultyModule DifficultyModule => _difficultyModule;
public AssetReferenceGameObject Prefab => _prefab;
public AssetReferenceVideoClip BackgroundVideo => _backgroundVideo;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b89b3154a9ca3344c924ccde85596538

View File

@ -1,7 +1,14 @@
using DG.Tweening;
using DG.Tweening;
using PrizeSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.Serialization;
using UnityEngine.Video;
namespace CharacterSystem
{
@ -9,32 +16,73 @@ namespace CharacterSystem
{
public static CharactersController I;
[SerializeField] private List<Character> characterPrefabs;
[SerializeField, FormerlySerializedAs("characterPrefabs")]
private List<CharacterDefinition> _characterDefinitions;
private Character[] characters;
private readonly Dictionary<int, LoadedCharacter> _loadedCharacters = new();
private readonly Dictionary<int, Task<Character>> _loadingCharacters = new();
private readonly Dictionary<int, AsyncOperationHandle<VideoClip>> _loadedVideos = new();
private readonly Dictionary<int, Task<VideoClip>> _loadingVideos = new();
private readonly HashSet<int> _desiredIndices = new();
private bool[] _prizeAvailable;
private int _loadGeneration;
public static int CharacterIndex { get; private set; } = -1;
public static int CharactersAmount => I.characters.Length;
public static Character CurrentCharacter => I.characters[CharacterIndex];
public static int CharactersAmount => I?._characterDefinitions?.Count ?? 0;
public static Character CurrentCharacter => I.GetLoadedCharacter(CharacterIndex);
public static bool HasActiveCharacter
=> I != null && CharacterIndex >= 0 && CharacterIndex < I.characters.Length;
=> I != null && CharacterIndex >= 0 && I._loadedCharacters.ContainsKey(CharacterIndex);
public IReadOnlyCollection<int> LoadedCharacterIndices => _loadedCharacters.Keys;
public IReadOnlyCollection<int> LoadedVideoIndices => _loadedVideos.Keys;
public void Initialize()
private void OnDestroy()
{
SettingsManager.OnSettingsChanged -= PullDifficultySettings;
_loadGeneration++;
ReleaseAllCharacters();
ReleaseAllVideos(true);
if (I == this)
I = null;
}
public async Task InitializeAsync()
{
I = this;
SetupCharacters();
if (_characterDefinitions == null || _characterDefinitions.Count == 0)
throw new InvalidOperationException("Не заданы определения ботов в контроллере.");
ValidateDefinitions();
_prizeAvailable = new bool[_characterDefinitions.Count];
SetAllCharactersPrizeAvailable();
SettingsManager.OnSettingsChanged -= PullDifficultySettings;
SettingsManager.OnSettingsChanged += PullDifficultySettings;
PullDifficultySettings();
await PrepareWindowAsync(-1);
}
public void SetAllCharactersPrizeAvailable()
{
foreach (Character character in I.characters)
character.prizeModule.ResetModule();
if (_prizeAvailable == null)
return;
for (int index = 0; index < _prizeAvailable.Length; index++)
_prizeAvailable[index] = true;
foreach (LoadedCharacter loadedCharacter in _loadedCharacters.Values)
loadedCharacter.Character.prizeModule.ResetModule();
}
public static void ResetAllCharactersDifficulty()
{
foreach (Character character in I.characters)
character.difficultyModule.ResetPresetIndex();
if (I == null)
return;
foreach (CharacterDefinition definition in I._characterDefinitions)
definition.DifficultyModule?.ResetPresetIndex();
}
public static void ResetSystem()
@ -48,63 +96,128 @@ namespace CharacterSystem
public void HideCharacter()
{
if (HasActiveCharacter == false)
if (!HasActiveCharacter)
return;
CurrentCharacter.visualModule.GetHideSequence().PlayForward();
}
public void StartSession(System.Action onComplete = null)
public void ReturnToMenu()
{
int oldIndex = CharacterIndex;
CharacterIndex = -1;
ResetAllCharactersDifficulty();
if (!_loadedCharacters.TryGetValue(oldIndex, out LoadedCharacter loadedCharacter))
{
PreloadMenuCharacter();
return;
}
Sequence sequence = loadedCharacter.Character.visualModule.GetHideSequence();
sequence.AppendCallback(PreloadMenuCharacter);
sequence.PlayForward();
}
public void StartSession(Action onComplete = null)
{
ResetSystem();
SetAllCharactersPrizeAvailable();
ShowCharacter(0, onComplete);
}
public void ApplyFirstCharacterColorsToBoard()
{
VisualModule visualModule = characters[0].visualModule;
if (!_loadedCharacters.TryGetValue(0, out LoadedCharacter loadedCharacter))
{
Debug.LogError("Кьюб не подготовлен к запуску PvE.", this);
return;
}
VisualModule visualModule = loadedCharacter.Character.visualModule;
Board.Instance.SetColorsImmediately(
visualModule.InnerColor,
visualModule.OutlineColor,
visualModule.CellsColor);
}
public static Character[] GetCharactersArray()
=> new List<Character>(I.characters).ToArray();
public CharacterDefinition[] GetDefinitionsArray()
=> _characterDefinitions.ToArray();
private void SetupCharacters()
public CharacterDefinition GetDefinition(int characterIndex)
{
if (characterPrefabs.Count <= 0)
throw new System.Exception("Не заданы боты в контроллере");
if (characterIndex < 0 || characterIndex >= _characterDefinitions.Count)
throw new ArgumentOutOfRangeException(nameof(characterIndex));
int amount = characterPrefabs.Count;
characters = new Character[amount];
return _characterDefinitions[characterIndex];
}
for (int i = 0; i < amount; i++)
{
var character = Instantiate(characterPrefabs[i]);
characters[i] = character;
character.Initialize(i);
}
public IReadOnlyList<Prize> GetPrizes(int characterIndex)
{
List<PrizeSet> sets = PrizeSystemManager.PrizeContainer?.Sets;
RefreshPrizes();
if (sets == null || characterIndex < 0 || characterIndex >= sets.Count)
return Array.Empty<Prize>();
return sets[characterIndex]?.Prizes ?? (IReadOnlyList<Prize>)Array.Empty<Prize>();
}
public bool HasConfiguredPrize(int characterIndex)
=> GetPrizes(characterIndex).Any(prize => prize is not EmptyPrize);
public bool TryFetchCurrentPrizes(out List<Prize> prizes)
{
prizes = null;
if (CharacterIndex < 0 || CharacterIndex >= _prizeAvailable.Length || !_prizeAvailable[CharacterIndex])
return false;
_prizeAvailable[CharacterIndex] = false;
prizes = GetPrizes(CharacterIndex).ToList();
if (_loadedCharacters.TryGetValue(CharacterIndex, out LoadedCharacter loadedCharacter))
loadedCharacter.Character.prizeModule.TryFetchPrize(out _);
return true;
}
public bool TryGetCurrentPrize<T>(out T prize) where T : Prize
{
prize = null;
if (CharacterIndex < 0 || CharacterIndex >= _prizeAvailable.Length || !_prizeAvailable[CharacterIndex])
return false;
prize = GetPrizes(CharacterIndex).OfType<T>().FirstOrDefault();
return prize != null;
}
public void RefreshPrizes()
{
for (int i = 0; i < characters.Length; i++)
{
PrizeSet prizesSet = PrizeSystemManager.PrizeContainer.Sets[i];
characters[i].prizeModule.SetPrizes(prizesSet);
}
foreach (KeyValuePair<int, LoadedCharacter> entry in _loadedCharacters)
SetCharacterPrizes(entry.Key, entry.Value.Character);
}
public void ShowCharacter(int newIndex, System.Action onComplete = null)
public async void ShowCharacter(int newIndex, Action onComplete = null)
{
if (newIndex < 0 || newIndex >= characters.Length)
throw new System.ArgumentOutOfRangeException(nameof(newIndex));
if (newIndex < 0 || newIndex >= _characterDefinitions.Count)
throw new ArgumentOutOfRangeException(nameof(newIndex));
int oldIndex = CharacterIndex;
try
{
await PrepareWindowAsync(newIndex, oldIndex);
}
catch (Exception exception)
{
Debug.LogException(exception, this);
return;
}
if (!_desiredIndices.Contains(newIndex) || !_loadedCharacters.ContainsKey(newIndex))
return;
CharacterIndex = newIndex;
if (newIndex == oldIndex)
@ -113,22 +226,23 @@ namespace CharacterSystem
return;
}
VideoUtility.CrossFadeToCharacter(newIndex);
var newCharacter = characters[newIndex];
VideoUtility.CrossFadeToCharacter(newIndex, GetLoadedVideo(newIndex));
Character newCharacter = GetLoadedCharacter(newIndex);
Sequence sequence = DOTween.Sequence();
Sequence seq = DOTween.Sequence();
if (oldIndex >= 0)
if (_loadedCharacters.TryGetValue(oldIndex, out LoadedCharacter oldCharacter))
{
var oldCharacter = characters[oldIndex];
seq.Append(oldCharacter.visualModule.GetHideSequence());
seq.AppendInterval(0.1f);
sequence.Append(oldCharacter.Character.visualModule.GetHideSequence());
sequence.AppendInterval(0.1f);
}
seq.Append(newCharacter.visualModule.GetShowSequence());
seq.AppendCallback(() =>
sequence.Append(newCharacter.visualModule.GetShowSequence());
sequence.AppendCallback(() =>
{
SetDesiredWindow(newIndex);
ReleaseUndesiredCharacters();
ReleaseUndesiredVideos();
if (oldIndex >= 0 && newIndex < oldIndex)
EventBus.TriggerEvent(GameEvent.Return);
else
@ -136,8 +250,284 @@ namespace CharacterSystem
onComplete?.Invoke();
});
sequence.PlayForward();
}
seq.PlayForward();
public void SuspendForPvp()
{
CharacterIndex = -1;
_loadGeneration++;
_desiredIndices.Clear();
ReleaseUndesiredCharacters();
ReleaseUndesiredVideos();
}
public async void PreloadMenuCharacter()
{
try
{
await PrepareWindowAsync(-1);
}
catch (Exception exception)
{
Debug.LogException(exception, this);
}
}
private async Task PrepareWindowAsync(int centerIndex, int additionalIndex = -1)
{
int generation = ++_loadGeneration;
SetDesiredWindow(centerIndex, additionalIndex);
int[] indicesToLoad = _desiredIndices.ToArray();
List<Task> loadingTasks = new();
foreach (int characterIndex in indicesToLoad)
{
loadingTasks.Add(EnsureCharacterLoadedAsync(characterIndex));
loadingTasks.Add(EnsureVideoLoadedAsync(characterIndex));
}
await Task.WhenAll(loadingTasks);
if (generation == _loadGeneration)
{
ReleaseUndesiredCharacters();
ReleaseUndesiredVideos();
}
}
private async Task<Character> EnsureCharacterLoadedAsync(int characterIndex)
{
if (_loadedCharacters.TryGetValue(characterIndex, out LoadedCharacter loadedCharacter))
return loadedCharacter.Character;
if (_loadingCharacters.TryGetValue(characterIndex, out Task<Character> loadingTask))
return await loadingTask;
Task<Character> newLoadingTask = LoadCharacterAsync(characterIndex);
_loadingCharacters[characterIndex] = newLoadingTask;
try
{
return await newLoadingTask;
}
finally
{
_loadingCharacters.Remove(characterIndex);
}
}
private async Task<Character> LoadCharacterAsync(int characterIndex)
{
CharacterDefinition definition = _characterDefinitions[characterIndex];
AsyncOperationHandle<GameObject> handle = Addressables.InstantiateAsync(definition.Prefab.RuntimeKey);
await handle.Task;
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
{
if (handle.IsValid())
Addressables.Release(handle);
throw new InvalidOperationException($"Не удалось загрузить персонажа {definition.CharacterName}.");
}
Character character = handle.Result.GetComponent<Character>();
if (character == null)
{
Addressables.ReleaseInstance(handle);
throw new InvalidOperationException($"У prefab персонажа {definition.CharacterName} отсутствует Character.");
}
character.Initialize(characterIndex);
SetCharacterPrizes(characterIndex, character);
_loadedCharacters[characterIndex] = new LoadedCharacter(character, handle);
if (!_desiredIndices.Contains(characterIndex))
ReleaseCharacter(characterIndex);
return character;
}
private async Task<VideoClip> EnsureVideoLoadedAsync(int characterIndex)
{
if (_loadedVideos.TryGetValue(characterIndex, out AsyncOperationHandle<VideoClip> loadedHandle))
return loadedHandle.Result;
if (_loadingVideos.TryGetValue(characterIndex, out Task<VideoClip> loadingTask))
return await loadingTask;
Task<VideoClip> newLoadingTask = LoadVideoAsync(characterIndex);
_loadingVideos[characterIndex] = newLoadingTask;
try
{
return await newLoadingTask;
}
finally
{
_loadingVideos.Remove(characterIndex);
}
}
private async Task<VideoClip> LoadVideoAsync(int characterIndex)
{
CharacterDefinition definition = _characterDefinitions[characterIndex];
AsyncOperationHandle<VideoClip> handle = Addressables.LoadAssetAsync<VideoClip>(
definition.BackgroundVideo.RuntimeKey);
await handle.Task;
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
{
if (handle.IsValid())
Addressables.Release(handle);
throw new InvalidOperationException($"Не удалось загрузить видеофон {definition.CharacterName}.");
}
_loadedVideos[characterIndex] = handle;
if (!_desiredIndices.Contains(characterIndex))
ReleaseVideo(characterIndex);
return handle.Result;
}
private void SetDesiredWindow(int centerIndex, int additionalIndex = -1)
{
_desiredIndices.Clear();
if (centerIndex < 0)
{
_desiredIndices.Add(0);
}
else
{
int firstIndex = Mathf.Max(0, centerIndex - 1);
int lastIndex = Mathf.Min(_characterDefinitions.Count - 1, centerIndex + 1);
for (int index = firstIndex; index <= lastIndex; index++)
_desiredIndices.Add(index);
}
if (additionalIndex >= 0 && additionalIndex < _characterDefinitions.Count)
_desiredIndices.Add(additionalIndex);
}
private void ReleaseUndesiredCharacters()
{
int[] indicesToRelease = _loadedCharacters.Keys
.Where(index => !_desiredIndices.Contains(index))
.ToArray();
foreach (int characterIndex in indicesToRelease)
ReleaseCharacter(characterIndex);
}
private void ReleaseUndesiredVideos()
{
int[] indicesToRelease = _loadedVideos.Keys
.Where(index => !_desiredIndices.Contains(index))
.ToArray();
foreach (int characterIndex in indicesToRelease)
ReleaseVideo(characterIndex);
}
private void ReleaseAllCharacters()
{
foreach (int characterIndex in _loadedCharacters.Keys.ToArray())
ReleaseCharacter(characterIndex);
}
private void ReleaseAllVideos(bool immediately)
{
foreach (int characterIndex in _loadedVideos.Keys.ToArray())
ReleaseVideo(characterIndex, immediately);
}
private void ReleaseCharacter(int characterIndex)
{
if (!_loadedCharacters.Remove(characterIndex, out LoadedCharacter loadedCharacter))
return;
if (loadedCharacter.Handle.IsValid())
Addressables.ReleaseInstance(loadedCharacter.Handle);
}
private void ReleaseVideo(int characterIndex, bool immediately = false)
{
if (!_loadedVideos.Remove(characterIndex, out AsyncOperationHandle<VideoClip> handle) ||
!handle.IsValid())
return;
Action release = () =>
{
if (handle.IsValid())
Addressables.Release(handle);
};
if (immediately)
release();
else
VideoUtility.ReleaseBackgroundWhenUnused(handle.Result, release);
}
private Character GetLoadedCharacter(int characterIndex)
{
if (!_loadedCharacters.TryGetValue(characterIndex, out LoadedCharacter loadedCharacter))
throw new InvalidOperationException($"Персонаж с индексом {characterIndex} не загружен.");
return loadedCharacter.Character;
}
private VideoClip GetLoadedVideo(int characterIndex)
{
if (!_loadedVideos.TryGetValue(characterIndex, out AsyncOperationHandle<VideoClip> handle))
throw new InvalidOperationException($"Видеофон с индексом {characterIndex} не загружен.");
return handle.Result;
}
private void SetCharacterPrizes(int characterIndex, Character character)
{
List<PrizeSet> sets = PrizeSystemManager.PrizeContainer?.Sets;
if (sets == null || characterIndex < 0 || characterIndex >= sets.Count || sets[characterIndex] == null)
return;
character.prizeModule.SetPrizes(sets[characterIndex]);
if (_prizeAvailable != null && _prizeAvailable[characterIndex])
character.prizeModule.ResetModule();
}
private void PullDifficultySettings()
{
foreach (CharacterDefinition definition in _characterDefinitions)
definition.DifficultyModule?.PullSettings();
}
private void ValidateDefinitions()
{
for (int index = 0; index < _characterDefinitions.Count; index++)
{
CharacterDefinition definition = _characterDefinitions[index];
if (definition == null || definition.CharacterIndex != index ||
!definition.Prefab.RuntimeKeyIsValid() || !definition.BackgroundVideo.RuntimeKeyIsValid())
throw new InvalidOperationException($"Некорректное определение персонажа с индексом {index}.");
}
}
private sealed class LoadedCharacter
{
public LoadedCharacter(Character character, AsyncOperationHandle<GameObject> handle)
{
Character = character;
Handle = handle;
}
public Character Character { get; }
public AsyncOperationHandle<GameObject> Handle { get; }
}
}
}

View File

@ -109,7 +109,10 @@ public class GameManager : MonoBehaviour
_isLeavingGameplay = false;
if (mode == GameMode.pvp)
{
ResetPvpScores();
CharactersController.I.SuspendForPvp();
}
if (mode == GameMode.pve)
CharactersController.I.ApplyFirstCharacterColorsToBoard();
@ -135,8 +138,10 @@ public class GameManager : MonoBehaviour
}
else
{
DualAvatarController.Instance?.ShowCharacters();
StartRound();
if (DualAvatarController.Instance != null)
DualAvatarController.Instance.ShowCharacters(StartRound);
else
StartRound();
}
}
@ -175,12 +180,12 @@ public class GameManager : MonoBehaviour
if (gameMode == GameMode.pve)
{
CharactersController.I.HideCharacter();
CharactersController.ResetSystem();
CharactersController.I.ReturnToMenu();
}
else
{
DualAvatarController.Instance?.HideCharacters();
CharactersController.I.PreloadMenuCharacter();
}
OnGameFinished?.Invoke(gameMode);
@ -235,7 +240,7 @@ public class GameManager : MonoBehaviour
|| !CharactersController.HasActiveCharacter)
return false;
if (!CharactersController.CurrentCharacter.prizeModule.TryFetchPrize(out List<Prize> configuredPrizes))
if (!CharactersController.I.TryFetchCurrentPrizes(out List<Prize> configuredPrizes))
return false;
List<Prize> availablePrizes = GetAvailablePrizes(configuredPrizes);
@ -378,12 +383,10 @@ public class GameManager : MonoBehaviour
vsBotMoves = 0;
//movesAndTimeCounter.SetVisibility(false);
CharactersController.I.HideCharacter();
CharactersController.I.ReturnToMenu();
CharactersController.I.SetAllCharactersPrizeAvailable();
DualAvatarController.Instance?.HideCharacters();
CharactersController.ResetSystem();
player1score = 0;
player2score = 0;
vsBotScore = 0;
@ -429,8 +432,7 @@ public class GameManager : MonoBehaviour
if (nextIndex >= CharactersController.CharactersAmount)
return null;
List<Prize> nextPrizes = GetAvailablePrizes(
CharactersController.GetCharactersArray()[nextIndex].prizeModule.CheckPrizes());
List<Prize> nextPrizes = GetAvailablePrizes(CharactersController.I.GetPrizes(nextIndex));
return nextPrizes.Count > 0 ? nextPrizes[0] : null;
}

View File

@ -1,6 +1,7 @@
using CharacterSystem;
using PrizeSystem;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
public class Bootstrap : MonoBehaviour
@ -31,9 +32,9 @@ public class Bootstrap : MonoBehaviour
[SerializeField] private CoinCounter _coinCounter;
private void Awake() => Initialize();
private async void Awake() => await InitializeAsync();
private void Initialize()
private async Task InitializeAsync()
{
Application.targetFrameRate = DEFAULT_FRAME_RATE;
Cursor.lockState = CursorLockMode.Locked;
@ -67,7 +68,7 @@ public class Bootstrap : MonoBehaviour
avatarController.GetComponent<AvatarEventBus>().Initialize();
avatarController.Initialize();
characterController.Initialize();
await characterController.InitializeAsync();
gameManager.Initialize();
MachineCountersService.Initialize();

View File

@ -1,13 +1,17 @@
using CharacterSystem;
using System;
using System.Collections;
using System.Collections.Generic;
using CharacterSystem;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.Serialization;
public class DualAvatarController : MonoBehaviour
{
[SerializeField, FormerlySerializedAs("characterPrefabs")] private List<GameObject> _characterPrefabs;
[SerializeField, FormerlySerializedAs("_characterPrefabs")]
private List<CharacterDefinition> _characterDefinitions;
[SerializeField, FormerlySerializedAs("AvatarsParent")] private Transform _avatarsParent;
[SerializeField, FormerlySerializedAs("baseHiddenLocalPosition")] private Vector2 _player1HiddenLocalPosition;
[SerializeField, FormerlySerializedAs("baseShownLocalPosition")] private Vector2 _player1ShownLocalPosition;
@ -24,35 +28,66 @@ public class DualAvatarController : MonoBehaviour
private Coroutine _player2Movement;
private bool _isShowing;
private bool _isVisible;
private bool _hideRequested;
private int _loadGeneration;
public static DualAvatarController Instance { get; private set; }
private void OnDestroy()
{
_loadGeneration++;
StopMovement();
ReleaseCharacters();
if (Instance == this)
Instance = null;
}
public void Initialize()
{
Instance = this;
if (_characters.Count > 0)
return;
if (_characterPrefabs == null || _characterPrefabs.Count < 2 ||
_characterPrefabs[0] == null || _characterPrefabs[1] == null)
if (_characterDefinitions == null || _characterDefinitions.Count < 2 ||
_characterDefinitions[0] == null || _characterDefinitions[1] == null)
{
Debug.LogError("Для PvP не назначены персонажи 6 и 7.", this);
Debug.LogError("Для PvP не назначены определения персонажей 6 и 7.", this);
}
}
public async void ShowCharacters(Action onComplete = null)
{
if (_isVisible)
{
onComplete?.Invoke();
return;
}
_characters[Team.Player1] = CreateCharacter(_characterPrefabs[0], Team.Player1);
_characters[Team.Player2] = CreateCharacter(_characterPrefabs[1], Team.Player2);
}
public void ShowCharacters()
{
if (_characters.Count < 2 || _isVisible || _isShowing)
if (_isShowing)
return;
StopMovement();
_isShowing = true;
_hideRequested = false;
int generation = ++_loadGeneration;
try
{
await LoadCharactersAsync();
}
catch (Exception exception)
{
_isShowing = false;
Debug.LogException(exception, this);
return;
}
if (generation != _loadGeneration || _hideRequested)
{
_isShowing = false;
ReleaseCharacters();
return;
}
StopMovement();
PrepareForAppearance(_characters[Team.Player1]);
PrepareForAppearance(_characters[Team.Player2]);
@ -65,6 +100,7 @@ public class DualAvatarController : MonoBehaviour
_isShowing = false;
_isVisible = true;
onComplete?.Invoke();
};
_player1Movement = StartCoroutine(MoveLocal(
@ -90,32 +126,91 @@ public class DualAvatarController : MonoBehaviour
public void HideCharacters()
{
_hideRequested = true;
_loadGeneration++;
if (_characters.Count < 2)
{
_isShowing = false;
_isVisible = false;
ReleaseCharacters();
return;
}
StopMovement();
_isShowing = false;
_isVisible = false;
int hiddenCharacters = 0;
Action onHidden = () =>
{
hiddenCharacters++;
if (hiddenCharacters >= 2)
ReleaseCharacters();
};
_player1Movement = StartCoroutine(MoveLocal(
_characters[Team.Player1],
GetHiddenPosition(Team.Player1),
false,
null));
onHidden));
_player2Movement = StartCoroutine(MoveLocal(
_characters[Team.Player2],
GetHiddenPosition(Team.Player2),
false,
null));
onHidden));
}
private PvpCharacter CreateCharacter(GameObject prefab, Team team)
private async Task LoadCharactersAsync()
{
GameObject characterObject = Instantiate(prefab, _avatarsParent);
if (_characters.Count == 2)
return;
ReleaseCharacters();
Task<PvpCharacter> player1Task = LoadCharacterAsync(_characterDefinitions[0], Team.Player1);
Task<PvpCharacter> player2Task = LoadCharacterAsync(_characterDefinitions[1], Team.Player2);
PvpCharacter[] characters;
try
{
characters = await Task.WhenAll(player1Task, player2Task);
}
catch
{
ReleaseCompletedCharacter(player1Task);
ReleaseCompletedCharacter(player2Task);
throw;
}
_characters[Team.Player1] = characters[0];
_characters[Team.Player2] = characters[1];
}
private async Task<PvpCharacter> LoadCharacterAsync(CharacterDefinition definition, Team team)
{
AsyncOperationHandle<GameObject> handle = Addressables.InstantiateAsync(
definition.Prefab.RuntimeKey,
_avatarsParent,
false,
true);
await handle.Task;
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
{
if (handle.IsValid())
Addressables.Release(handle);
throw new InvalidOperationException($"Не удалось загрузить PvP-персонажа {definition.CharacterName}.");
}
GameObject characterObject = handle.Result;
Animator animator = characterObject.GetComponentInChildren<Animator>(true);
if (animator == null)
throw new InvalidOperationException($"У PvP-персонажа {prefab.name} отсутствует Animator.");
{
Addressables.ReleaseInstance(handle);
throw new InvalidOperationException($"У PvP-персонажа {definition.CharacterName} отсутствует Animator.");
}
MessageBox messageBox = characterObject.GetComponentInChildren<MessageBox>(true);
if (messageBox != null)
@ -124,7 +219,7 @@ public class DualAvatarController : MonoBehaviour
characterObject.transform.localScale = new Vector3(_characterScale, _characterScale, 1f);
characterObject.transform.localPosition = GetHiddenPosition(team);
animator.enabled = false;
return new PvpCharacter(characterObject.transform, animator);
return new PvpCharacter(characterObject.transform, animator, handle);
}
private void PrepareForAppearance(PvpCharacter character)
@ -148,6 +243,25 @@ public class DualAvatarController : MonoBehaviour
_player2Movement = null;
}
private void ReleaseCharacters()
{
foreach (PvpCharacter character in _characters.Values)
{
if (character.Handle.IsValid())
Addressables.ReleaseInstance(character.Handle);
}
_characters.Clear();
}
private static void ReleaseCompletedCharacter(Task<PvpCharacter> loadingTask)
{
if (!loadingTask.IsCompletedSuccessfully || !loadingTask.Result.Handle.IsValid())
return;
Addressables.ReleaseInstance(loadingTask.Result.Handle);
}
private Vector3 GetHiddenPosition(Team team)
=> team == Team.Player1 ? _player1HiddenLocalPosition : _player2HiddenLocalPosition;
@ -184,13 +298,18 @@ public class DualAvatarController : MonoBehaviour
private sealed class PvpCharacter
{
public PvpCharacter(Transform transform, Animator animator)
public PvpCharacter(
Transform transform,
Animator animator,
AsyncOperationHandle<GameObject> handle)
{
Transform = transform;
Animator = animator;
Handle = handle;
}
public Transform Transform { get; }
public Animator Animator { get; }
public AsyncOperationHandle<GameObject> Handle { get; }
}
}

View File

@ -1,4 +1,5 @@
using CharacterSystem;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
@ -10,9 +11,11 @@ public class EndGameHandler : MonoBehaviour
[SerializeField, FormerlySerializedAs("lossPanel")] private PveLossPanel _lossPanel;
[SerializeField, FormerlySerializedAs("pvpWinPanel")] private PvpWinPanel _pvpWinPanel;
[SerializeField, FormerlySerializedAs("drawPanel")] private PveLossPanel _drawPanel;
[SerializeField] private float _resultPanelDelay = 3f;
private const float WinAnimationFrameRate = 40f;
private Coroutine _resultDelayCoroutine;
private Coroutine _winAnimationCoroutine;
private void OnDisable()
@ -22,6 +25,12 @@ public class EndGameHandler : MonoBehaviour
StopCoroutine(_winAnimationCoroutine);
_winAnimationCoroutine = null;
}
if (_resultDelayCoroutine != null)
{
StopCoroutine(_resultDelayCoroutine);
_resultDelayCoroutine = null;
}
}
public void HandleEndGame(Team lastPlayer, GameMode gameMode, CheckResult lastResult)
@ -39,7 +48,7 @@ public class EndGameHandler : MonoBehaviour
{
MachineCountersService.RecordBotResult(false);
EventBus.TriggerEvent(GameEvent.BotWin);
_lossPanel.Open(GameManager.Instance.ContinueAfterPveLoss);
ShowResultAfterDelay(() => _lossPanel.Open(GameManager.Instance.ContinueAfterPveLoss));
}
private void DrawHandler(GameMode gameMode)
@ -47,17 +56,17 @@ public class EndGameHandler : MonoBehaviour
if (gameMode == GameMode.pve)
{
EventBus.TriggerEvent(GameEvent.Draw);
_drawPanel.Open(GameManager.Instance.ContinueAfterPveDraw);
ShowResultAfterDelay(() => _drawPanel.Open(GameManager.Instance.ContinueAfterPveDraw));
}
else
{
GameManager gameManager = GameManager.Instance;
_pvpWinPanel.Open(
Team.None,
false,
gameManager.player1score,
gameManager.player2score,
gameManager.ContinueAfterPvpRound);
ShowResultAfterDelay(() => _pvpWinPanel.Open(
Team.None,
false,
gameManager.player1score,
gameManager.player2score,
gameManager.ContinueAfterPvpRound));
}
}
@ -72,23 +81,13 @@ public class EndGameHandler : MonoBehaviour
{
MachineCountersService.RecordBotResult(true);
EventBus.TriggerEvent(GameEvent.PlayerWin);
if (GameManager.Instance.TryStartPvePrizeFlow())
return;
bool isLastBot = CharactersController.CharacterIndex
== CharactersController.CharactersAmount - 1;
if (isLastBot)
GameManager.Instance.ShowFinalVictoryNameInput();
else
_winPanel.Open();
ShowResultAfterDelay(ShowPveWinResult);
}
else
{
MachineCountersService.RecordBotResult(false);
EventBus.TriggerEvent(GameEvent.BotWin);
_lossPanel.Open(GameManager.Instance.ContinueAfterPveLoss);
ShowResultAfterDelay(() => _lossPanel.Open(GameManager.Instance.ContinueAfterPveLoss));
}
}
else
@ -97,15 +96,47 @@ public class EndGameHandler : MonoBehaviour
DualAvatarController.Instance?.PlayWin(winner);
gameManager.IncreaseScore(winner);
bool isMatchWin = gameManager.HasPvpMatchWinner(winner);
_pvpWinPanel.Open(
winner,
isMatchWin,
gameManager.player1score,
gameManager.player2score,
isMatchWin ? gameManager.RestartPvpMatch : gameManager.ContinueAfterPvpRound);
Action restartAction = isMatchWin
? gameManager.RestartPvpMatch
: gameManager.ContinueAfterPvpRound;
ShowResultAfterDelay(() => _pvpWinPanel.Open(
winner,
isMatchWin,
gameManager.player1score,
gameManager.player2score,
restartAction));
}
}
private void ShowPveWinResult()
{
if (GameManager.Instance.TryStartPvePrizeFlow())
return;
bool isLastBot = CharactersController.CharacterIndex
== CharactersController.CharactersAmount - 1;
if (isLastBot)
GameManager.Instance.ShowFinalVictoryNameInput();
else
_winPanel.Open();
}
private void ShowResultAfterDelay(Action showResult)
{
if (_resultDelayCoroutine != null)
StopCoroutine(_resultDelayCoroutine);
_resultDelayCoroutine = StartCoroutine(ShowResultAfterDelayCoroutine(showResult));
}
private IEnumerator ShowResultAfterDelayCoroutine(Action showResult)
{
yield return new WaitForSecondsRealtime(Mathf.Max(0f, _resultPanelDelay));
_resultDelayCoroutine = null;
showResult?.Invoke();
}
private void PlayWinChipsAnimation(HashSet<(int row, int col)> winChipsCoords)
{
Chip[,] grid = Board.Instance.Grid;

View File

@ -10,16 +10,16 @@ public sealed class GameplayLevelBar : MonoBehaviour
public Timer Timer => _timer;
public void ConfigurePve(int currentCharacterIndex, Character[] characters)
public void ConfigurePve(int currentCharacterIndex, CharactersController charactersController)
{
_title.text = "ВРЕМЯ ДО ПРОИГРЫША";
for (int index = 0; index < _cells.Length; index++)
{
bool hasCharacter = index < characters.Length;
bool hasCharacter = index < CharactersController.CharactersAmount;
bool filled = hasCharacter && index < currentCharacterIndex;
bool framed = hasCharacter && index == currentCharacterIndex;
bool hasGift = hasCharacter && characters[index].prizeModule.HasConfiguredPrize;
bool hasGift = hasCharacter && charactersController.HasConfiguredPrize(index);
_cells[index].Configure(filled, framed, hasGift);
}
}

View File

@ -47,7 +47,7 @@ public class TimerManager : MonoBehaviour
_player1LevelBar.ConfigurePve(
CharactersController.CharacterIndex,
CharactersController.GetCharactersArray());
CharactersController.I);
Player1Timer.SetupTimer(_pveCharacterTime);
Player2Timer.StopAndReset();
}

View File

@ -12,6 +12,21 @@ public class COMinput : InputSource
private const char POSITIVE = '0';
private const char NEGATIVE = '1';
private static readonly InSignal[] _controlSignals =
{
InSignal.up1,
InSignal.right1,
InSignal.down1,
InSignal.left1,
InSignal.action1,
InSignal.up2,
InSignal.right2,
InSignal.down2,
InSignal.left2,
InSignal.action2,
InSignal.service
};
private bool[] buttonState = new bool[PIN_COUNT];
private bool[] buttonDown = new bool[PIN_COUNT];
private bool[] buttonUp = new bool[PIN_COUNT];
@ -47,63 +62,26 @@ public class COMinput : InputSource
return true;
}
/// <summary>
/// Загружает конфигурацию маппинга пинов из файла elektro_version.rr
/// </summary>
private void LoadPinMappingConfiguration()
{
int elektroVersion = ConfigManager.Config.ElectronicVersion;
ComInputConfiguration configuration = ComInputConfigurationLoader.Load();
Debug.Log($"Определена версия электроники: {elektroVersion}");
pinMappings.Clear();
reverseMappings.Clear();
// Создаем маппинг в зависимости от версии
if (elektroVersion == 1)
{
// Версия 1 (старая распиновка)
pinMappings[InSignal.up1] = 0;
pinMappings[InSignal.right1] = 1;
pinMappings[InSignal.down1] = 2;
pinMappings[InSignal.left1] = 3;
pinMappings[InSignal.action1] = 4;
pinMappings[InSignal.up2] = 5;
pinMappings[InSignal.right2] = 6;
pinMappings[InSignal.down2] = 7;
pinMappings[InSignal.left2] = 8;
pinMappings[InSignal.action2] = 9;
pinMappings[InSignal.startOnePlayer] = 10;
pinMappings[InSignal.startTwoPlayers] = 11;
pinMappings[InSignal.service] = 12;
pinMappings[InSignal.extra] = 13;
pinMappings[InSignal.hasPrize] = 14;
pinMappings[InSignal.prizeGiven] = 15;
Debug.Log($"Используется версия 1 распиновки. Полученная версия: {elektroVersion}");
}
else
{
// Версия 2 (Дефолт)
pinMappings[InSignal.up1] = 0;
pinMappings[InSignal.right1] = 1;
pinMappings[InSignal.down1] = 2;
pinMappings[InSignal.left1] = 3;
pinMappings[InSignal.action1] = 4;
pinMappings[InSignal.up2] = 10;
pinMappings[InSignal.right2] = 7;
pinMappings[InSignal.down2] = 8;
pinMappings[InSignal.left2] = 9;
pinMappings[InSignal.action2] = 11;
pinMappings[InSignal.startOnePlayer] = 5;
pinMappings[InSignal.startTwoPlayers] = 6;
pinMappings[InSignal.service] = 12;
pinMappings[InSignal.extra] = 13;
pinMappings[InSignal.hasPrize] = 14;
pinMappings[InSignal.prizeGiven] = 15;
Debug.Log("Используется версия 2 распиновки (новая)");
}
pinMappings[InSignal.up1] = configuration.LeftJoystick.Up;
pinMappings[InSignal.right1] = configuration.LeftJoystick.Right;
pinMappings[InSignal.down1] = configuration.LeftJoystick.Down;
pinMappings[InSignal.left1] = configuration.LeftJoystick.Left;
pinMappings[InSignal.action1] = configuration.LeftJoystick.Action;
pinMappings[InSignal.up2] = configuration.RightJoystick.Up;
pinMappings[InSignal.right2] = configuration.RightJoystick.Right;
pinMappings[InSignal.down2] = configuration.RightJoystick.Down;
pinMappings[InSignal.left2] = configuration.RightJoystick.Left;
pinMappings[InSignal.action2] = configuration.RightJoystick.Action;
pinMappings[InSignal.service] = configuration.ServiceButton;
pinMappings[InSignal.hasPrize] = 14;
pinMappings[InSignal.prizeGiven] = 15;
// Создаем обратный маппинг для быстрого поиска
foreach (var mapping in pinMappings)
@ -374,15 +352,12 @@ public class COMinput : InputSource
public override bool AnyButton()
{
//отсекаем датчики
for (int i = 0; i < pinMappings.Count - 2; i++)
foreach (InSignal signal in _controlSignals)
{
if (buttonState[i])
{
if (GetButton(signal))
return true;
}
}
return false;
return false;
}
}

View File

@ -0,0 +1,139 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
[Serializable]
public sealed class ComJoystickConfiguration
{
[JsonProperty("up")]
public int Up { get; set; }
[JsonProperty("right")]
public int Right { get; set; }
[JsonProperty("down")]
public int Down { get; set; }
[JsonProperty("left")]
public int Left { get; set; }
[JsonProperty("action")]
public int Action { get; set; }
}
[Serializable]
public sealed class ComInputConfiguration
{
[JsonProperty("leftJoystick")]
public ComJoystickConfiguration LeftJoystick { get; set; } = new()
{
Up = 0,
Right = 1,
Down = 2,
Left = 3,
Action = 4
};
[JsonProperty("rightJoystick")]
public ComJoystickConfiguration RightJoystick { get; set; } = new()
{
Up = 5,
Right = 6,
Down = 7,
Left = 8,
Action = 9
};
[JsonProperty("serviceButton")]
public int ServiceButton { get; set; } = 10;
public bool TryValidate(out string error)
{
if (LeftJoystick == null || RightJoystick == null)
{
error = "Не заданы настройки одного из джойстиков.";
return false;
}
int[] indices =
{
LeftJoystick.Up,
LeftJoystick.Right,
LeftJoystick.Down,
LeftJoystick.Left,
LeftJoystick.Action,
RightJoystick.Up,
RightJoystick.Right,
RightJoystick.Down,
RightJoystick.Left,
RightJoystick.Action,
ServiceButton
};
HashSet<int> uniqueIndices = new();
foreach (int index in indices)
{
if (index < 0 || index > ComInputConfigurationLoader.MaxControlIndex)
{
error = $"Индекс {index} находится вне допустимого диапазона 0-{ComInputConfigurationLoader.MaxControlIndex}.";
return false;
}
if (!uniqueIndices.Add(index))
{
error = $"Индекс {index} назначен нескольким элементам управления.";
return false;
}
}
error = string.Empty;
return true;
}
}
public static class ComInputConfigurationLoader
{
private const int _maxControlIndex = 13;
private const string _fileName = "ComInputConfig.json";
public static int MaxControlIndex => _maxControlIndex;
public static string FileName => _fileName;
public static string ConfigPath => Path.Combine(Application.streamingAssetsPath, FileName);
public static ComInputConfiguration Load()
{
if (!File.Exists(ConfigPath))
{
Debug.LogWarning($"Конфигурация COM-управления не найдена: {ConfigPath}. Используется схема по умолчанию.");
return new ComInputConfiguration();
}
try
{
string json = File.ReadAllText(ConfigPath);
ComInputConfiguration configuration = JsonConvert.DeserializeObject<ComInputConfiguration>(json);
if (configuration == null)
{
Debug.LogError("Конфигурация COM-управления пуста. Используется схема по умолчанию.");
return new ComInputConfiguration();
}
if (configuration.TryValidate(out string error))
{
Debug.Log($"Конфигурация COM-управления загружена: {ConfigPath}");
return configuration;
}
Debug.LogError($"Некорректная конфигурация COM-управления: {error} Используется схема по умолчанию.");
}
catch (Exception exception)
{
Debug.LogError($"Не удалось загрузить конфигурацию COM-управления: {exception.Message}. Используется схема по умолчанию.");
}
return new ComInputConfiguration();
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 471d66f8c18b3ac4ab99df5b724e7cc3

View File

@ -0,0 +1,327 @@
using DG.Tweening;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class RatingModal : MonoBehaviour
{
public event Action Closed;
[Header("Строки")]
[SerializeField] private GameObject _rowPrefab;
[SerializeField] private GameObject _latestRowPrefab;
[SerializeField] private int _maxRecords = 100;
[SerializeField] private float _rowSpacing = 4f;
[Header("Прокрутка")]
[SerializeField] private float _scrollAcceleration = 3600f;
[SerializeField] private float _scrollDeceleration = 4800f;
[SerializeField] private float _maxScrollSpeed = 1800f;
[SerializeField] private float _minimumScrollbarHandleHeight = 30f;
[Header("Модальное окно")]
[SerializeField] private float _inputTimeout = 20f;
[SerializeField] private float _transitionDuration = 0.25f;
private const string DateFormat = "dd.MM.yy HH:mm";
private RectTransform _panel;
private RectTransform _viewport;
private RectTransform _content;
private RectTransform _scrollbarTrack;
private RectTransform _scrollbarHandle;
private RectTransform _latestRow;
private CanvasGroup _canvasGroup;
private Transform _originalParent;
private Sequence _transition;
private Vector3 _panelOpenedScale;
private float _lastInputTime;
private float _scrollOffset;
private float _scrollSpeed;
private float _maxScrollOffset;
private bool _isTransitioning;
public bool IsOpen { get; private set; }
private void Update()
{
if (!IsOpen || _isTransitioning)
return;
bool hasInput = In.AnyButton();
if (hasInput)
_lastInputTime = Time.unscaledTime;
if (Time.unscaledTime - _lastInputTime >= _inputTimeout)
{
Close();
return;
}
UpdateScrolling();
}
public void Open(Transform modalParent)
{
if (IsOpen || modalParent == null)
return;
CacheReferences();
BuildRating();
_originalParent = transform.parent;
transform.SetParent(modalParent, false);
transform.SetAsLastSibling();
RectTransform root = (RectTransform)transform;
root.anchorMin = Vector2.zero;
root.anchorMax = Vector2.one;
root.offsetMin = Vector2.zero;
root.offsetMax = Vector2.zero;
root.localScale = Vector3.one;
gameObject.SetActive(true);
_canvasGroup.alpha = 0f;
_panel.localScale = _panelOpenedScale * 0.9f;
_lastInputTime = Time.unscaledTime;
_isTransitioning = true;
IsOpen = true;
_transition?.Kill();
_transition = DOTween.Sequence().SetUpdate(true);
_transition.Join(_canvasGroup.DOFade(1f, _transitionDuration));
_transition.Join(_panel.DOScale(_panelOpenedScale, _transitionDuration).SetEase(Ease.OutBack));
_transition.OnComplete(() => _isTransitioning = false);
_transition.PlayForward();
}
public void Close()
{
if (!IsOpen)
return;
_isTransitioning = true;
_transition?.Kill();
_transition = DOTween.Sequence().SetUpdate(true);
_transition.Join(_canvasGroup.DOFade(0f, _transitionDuration));
_transition.Join(_panel.DOScale(_panelOpenedScale * 0.9f, _transitionDuration).SetEase(Ease.InBack));
_transition.OnComplete(CompleteClose);
_transition.PlayForward();
}
private void CacheReferences()
{
_panel ??= transform.Find("Panel") as RectTransform;
_viewport ??= transform.Find("Panel/Table VLG") as RectTransform;
_scrollbarTrack ??= transform.Find("Panel/scrollbar") as RectTransform;
_scrollbarHandle ??= transform.Find("Panel/scrollbar/Image") as RectTransform;
if (_canvasGroup == null)
{
_canvasGroup = GetComponent<CanvasGroup>();
if (_canvasGroup == null)
_canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
_panelOpenedScale = _panel.localScale;
VerticalLayoutGroup oldLayout = _viewport.GetComponent<VerticalLayoutGroup>();
if (oldLayout != null)
oldLayout.enabled = false;
}
private void BuildRating()
{
ClearGeneratedRows();
PlayerStatsService statsService = GameManager.Instance?.StatsService;
List<PlayerStatsRecord> records = statsService?.GetTopPlayers(_maxRecords)
?? new List<PlayerStatsRecord>();
float rowHeight = GetRowHeight();
float rowStep = rowHeight + _rowSpacing;
float contentHeight = Mathf.Max(_viewport.rect.height, records.Count * rowStep - _rowSpacing);
GameObject contentObject = new("Rating Content", typeof(RectTransform));
_content = contentObject.GetComponent<RectTransform>();
_content.SetParent(_viewport, false);
_content.anchorMin = new Vector2(0.5f, 1f);
_content.anchorMax = new Vector2(0.5f, 1f);
_content.pivot = new Vector2(0.5f, 1f);
_content.anchoredPosition = Vector2.zero;
_content.sizeDelta = new Vector2(_viewport.rect.width, contentHeight);
for (int i = 0; i < records.Count; i++)
{
RectTransform row = Instantiate(_rowPrefab, _content).GetComponent<RectTransform>();
ConfigureRowTransform(row, i, rowHeight, rowStep);
FillRow(row, i + 1, records[i]);
}
CreateLatestRow(statsService, rowHeight);
_scrollOffset = 0f;
_scrollSpeed = 0f;
_maxScrollOffset = Mathf.Max(0f, contentHeight - _viewport.rect.height);
UpdateContentPosition();
UpdateScrollbar();
}
private void ClearGeneratedRows()
{
for (int i = _viewport.childCount - 1; i >= 0; i--)
{
GameObject child = _viewport.GetChild(i).gameObject;
child.SetActive(false);
Destroy(child);
}
if (_latestRow != null)
{
_latestRow.gameObject.SetActive(false);
Destroy(_latestRow.gameObject);
_latestRow = null;
}
}
private void CreateLatestRow(PlayerStatsService statsService, float rowHeight)
{
PlayerStatsRecord latestRecord = statsService?.GetLatestRecord();
if (latestRecord == null)
return;
_latestRow = Instantiate(_latestRowPrefab, _panel).GetComponent<RectTransform>();
_latestRow.anchorMin = new Vector2(0.5f, 0.5f);
_latestRow.anchorMax = new Vector2(0.5f, 0.5f);
_latestRow.pivot = new Vector2(0.5f, 0.5f);
_latestRow.anchoredPosition = new Vector2(_viewport.anchoredPosition.x, -284f);
ApplyRowSize(_latestRow, rowHeight);
int rank = statsService.GetRecordRank(latestRecord);
FillRow(_latestRow, rank, latestRecord);
}
private void ConfigureRowTransform(RectTransform row, int index, float rowHeight, float rowStep)
{
row.anchorMin = new Vector2(0.5f, 1f);
row.anchorMax = new Vector2(0.5f, 1f);
row.pivot = new Vector2(0.5f, 1f);
row.anchoredPosition = new Vector2(0f, -index * rowStep);
ApplyRowSize(row, rowHeight);
}
private void ApplyRowSize(RectTransform row, float rowHeight)
{
float rowWidth = GetRowWidth();
float horizontalScale = rowWidth > 0f ? _viewport.rect.width / rowWidth : 1f;
row.sizeDelta = new Vector2(rowWidth, rowHeight);
row.localScale = new Vector3(horizontalScale, 1f, 1f);
}
private void FillRow(RectTransform row, int rank, PlayerStatsRecord record)
{
TextMeshProUGUI[] cells = row.GetComponentsInChildren<TextMeshProUGUI>(true);
if (cells.Length < 5)
return;
cells[0].text = rank.ToString();
cells[1].text = record.PlayerName;
cells[2].text = FormatTime(record.CompletionTimeSec);
cells[3].text = record.MovesCount.ToString();
cells[4].text = record.CompletedAt.ToString(DateFormat);
if (row == _latestRow)
cells[4].fontSize = 19f;
}
private void UpdateScrolling()
{
int direction = In.GetAxis(JoystickSide.Both, InteractMode.Continious).y;
float targetSpeed = -direction * _maxScrollSpeed;
float acceleration = direction == 0 ? _scrollDeceleration : _scrollAcceleration;
_scrollSpeed = Mathf.MoveTowards(
_scrollSpeed,
targetSpeed,
acceleration * Time.unscaledDeltaTime);
if (Mathf.Approximately(_scrollSpeed, 0f))
return;
float previousOffset = _scrollOffset;
_scrollOffset = Mathf.Clamp(
_scrollOffset + _scrollSpeed * Time.unscaledDeltaTime,
0f,
_maxScrollOffset);
if (Mathf.Approximately(previousOffset, _scrollOffset))
_scrollSpeed = 0f;
UpdateContentPosition();
UpdateScrollbar();
}
private void UpdateContentPosition()
{
if (_content != null)
_content.anchoredPosition = Vector2.up * _scrollOffset;
}
private void UpdateScrollbar()
{
float trackHeight = _scrollbarTrack.rect.height;
float contentHeight = _content.rect.height;
float handleHeight = contentHeight <= 0f
? trackHeight
: Mathf.Clamp(
trackHeight * _viewport.rect.height / contentHeight,
_minimumScrollbarHandleHeight,
trackHeight);
_scrollbarHandle.anchorMin = new Vector2(0.5f, 1f);
_scrollbarHandle.anchorMax = new Vector2(0.5f, 1f);
_scrollbarHandle.pivot = new Vector2(0.5f, 1f);
_scrollbarHandle.sizeDelta = new Vector2(_scrollbarHandle.sizeDelta.x, handleHeight);
float normalized = _maxScrollOffset <= 0f ? 0f : _scrollOffset / _maxScrollOffset;
_scrollbarHandle.anchoredPosition = new Vector2(
0f,
-normalized * (trackHeight - handleHeight));
}
private void CompleteClose()
{
IsOpen = false;
_isTransitioning = false;
_scrollSpeed = 0f;
_canvasGroup.alpha = 1f;
_panel.localScale = _panelOpenedScale;
transform.SetParent(_originalParent, false);
gameObject.SetActive(false);
_transition = null;
Closed?.Invoke();
}
private float GetRowHeight()
{
RectTransform rowRect = _rowPrefab != null
? _rowPrefab.GetComponent<RectTransform>()
: null;
return rowRect != null && rowRect.rect.height > 0f ? rowRect.rect.height : 66f;
}
private float GetRowWidth()
{
RectTransform rowRect = _rowPrefab != null
? _rowPrefab.GetComponent<RectTransform>()
: null;
return rowRect != null && rowRect.rect.width > 0f ? rowRect.rect.width : _viewport.rect.width;
}
private string FormatTime(float seconds)
{
int totalSeconds = Mathf.Max(0, Mathf.RoundToInt(seconds));
return $"{totalSeconds / 60:D2}:{totalSeconds % 60:D2}";
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cee249e8bb9b66a4a8ddf0d00916ce5e

View File

@ -10,13 +10,13 @@ public class VideoUtility : MonoBehaviour
[SerializeField] private VideoPlayer _secondaryPlayer;
[SerializeField, FormerlySerializedAs("audioSource")] private AudioSource _audioSource;
[SerializeField, FormerlySerializedAs("fon")] private VideoClip _menuBackground;
[SerializeField] private List<VideoClip> _characterBackgrounds;
[SerializeField, FormerlySerializedAs("ads")] private VideoClip _ads;
[SerializeField, FormerlySerializedAs("ending")] private VideoClip _ending;
[SerializeField] private float _crossFadeDuration = 1f;
[SerializeField, FormerlySerializedAs("canvas")] private Canvas _canvas;
private static VideoUtility _instance;
private readonly Dictionary<VideoClip, List<System.Action>> _pendingReleases = new();
private VideoPlayer _activeBackgroundPlayer;
private Coroutine _crossFadeCoroutine;
@ -36,7 +36,20 @@ public class VideoUtility : MonoBehaviour
}
private void OnDestroy()
=> SettingsManager.OnSettingsChanged -= ApplyAudioSettings;
{
SettingsManager.OnSettingsChanged -= ApplyAudioSettings;
foreach (List<System.Action> releases in _pendingReleases.Values)
{
foreach (System.Action release in releases)
release?.Invoke();
}
_pendingReleases.Clear();
if (_instance == this)
_instance = null;
}
public void Initialize()
{
@ -52,15 +65,15 @@ public class VideoUtility : MonoBehaviour
PlayBackgroundImmediately(_menuBackground);
}
public static void CrossFadeToCharacter(int characterIndex)
public static void CrossFadeToCharacter(int characterIndex, VideoClip backgroundVideo)
{
if (characterIndex < 0 || characterIndex >= _instance._characterBackgrounds.Count)
if (backgroundVideo == null)
{
Debug.LogError($"Не найден видеофон для персонажа с индексом {characterIndex}");
return;
}
_instance.StartCrossFade(_instance._characterBackgrounds[characterIndex]);
_instance.StartCrossFade(backgroundVideo);
}
public static void CrossFadeToMenu()
@ -75,6 +88,26 @@ public class VideoUtility : MonoBehaviour
public static void PlayEnding()
=> _instance.PlayForeground(_instance._ending);
public static void ReleaseBackgroundWhenUnused(VideoClip clip, System.Action release)
{
if (release == null)
return;
if (_instance == null || clip == null || !_instance.IsClipAssigned(clip))
{
release.Invoke();
return;
}
if (!_instance._pendingReleases.TryGetValue(clip, out List<System.Action> releases))
{
releases = new List<System.Action>();
_instance._pendingReleases[clip] = releases;
}
releases.Add(release);
}
private void StartCrossFade(VideoClip targetClip)
{
if (targetClip == null)
@ -122,6 +155,7 @@ public class VideoUtility : MonoBehaviour
incomingPlayer.targetCameraAlpha = 1f;
outgoingPlayer.targetCameraAlpha = 0f;
outgoingPlayer.Stop();
ReleasePlayerClip(outgoingPlayer);
_activeBackgroundPlayer = incomingPlayer;
_crossFadeCoroutine = null;
}
@ -142,6 +176,7 @@ public class VideoUtility : MonoBehaviour
_activeBackgroundPlayer.targetCameraAlpha = 1f;
inactivePlayer.targetCameraAlpha = 0f;
inactivePlayer.Stop();
ReleasePlayerClip(inactivePlayer);
}
private VideoPlayer GetInactivePlayer()
@ -151,7 +186,10 @@ public class VideoUtility : MonoBehaviour
{
_secondaryPlayer.Stop();
_secondaryPlayer.targetCameraAlpha = 0f;
ReleasePlayerClip(_secondaryPlayer);
_activeBackgroundPlayer.Stop();
ReleasePlayerClip(_activeBackgroundPlayer);
_activeBackgroundPlayer = _primaryPlayer;
_activeBackgroundPlayer.clip = clip;
_activeBackgroundPlayer.targetCameraAlpha = 1f;
_activeBackgroundPlayer.Play();
@ -172,6 +210,9 @@ public class VideoUtility : MonoBehaviour
NormalizeInterruptedCrossFade();
_primaryPlayer.Stop();
_secondaryPlayer.Stop();
ReleasePlayerClip(_primaryPlayer);
ReleasePlayerClip(_secondaryPlayer);
_activeBackgroundPlayer = _primaryPlayer;
_primaryPlayer.renderMode = VideoRenderMode.CameraNearPlane;
_primaryPlayer.targetCameraAlpha = 1f;
_primaryPlayer.isLooping = false;
@ -196,4 +237,23 @@ public class VideoUtility : MonoBehaviour
private void ApplyAudioSettings()
=> _audioSource.volume = SettingsManager.GetFloat(SettingKey.PROMO_VOLUME);
private bool IsClipAssigned(VideoClip clip)
=> _primaryPlayer.clip == clip || _secondaryPlayer.clip == clip;
private void ReleasePlayerClip(VideoPlayer videoPlayer)
{
VideoClip releasedClip = videoPlayer.clip;
videoPlayer.clip = null;
NotifyClipUnused(releasedClip);
}
private void NotifyClipUnused(VideoClip clip)
{
if (clip == null || IsClipAssigned(clip) || !_pendingReleases.Remove(clip, out List<System.Action> releases))
return;
foreach (System.Action release in releases)
release?.Invoke();
}
}

View File

@ -55,7 +55,7 @@ public class CharacterPrizeConfigurator : MonoBehaviour, IControlable
_activePanel.UpdateControls();
}
private void OpenPrizeSelector(Character character)
private void OpenPrizeSelector(CharacterDefinition character)
{
_characterSelection.gameObject.SetActive(false);
_prizesSelector.Open(character);

View File

@ -9,7 +9,7 @@ using UnityEngine.UI;
public class CharacterSelectionPanel : MonoBehaviour, IControlable
{
public event Action<Character> OnCharacterSelected;
public event Action<CharacterDefinition> OnCharacterSelected;
public event Action OnExitRequested;
[SerializeField, FormerlySerializedAs("CharacterNameLabel")] private TextMeshProUGUI _characterNameLabel;
@ -20,12 +20,12 @@ public class CharacterSelectionPanel : MonoBehaviour, IControlable
[SerializeField] private MSignalButton _selectButton;
[SerializeField] private MSignalButton _exitButton;
private Character[] _characters;
private CharacterDefinition[] _characters;
private int _characterIndex;
private int _buttonIndex;
public int CharactersCount => _characters?.Length ?? 0;
public Character SelectedCharacter => _characters[_characterIndex];
public CharacterDefinition SelectedCharacter => _characters[_characterIndex];
public bool ControlsEnabled { get; set; } = true;
private MSignalButton SelectedButton => _buttons[_buttonIndex];
@ -37,7 +37,7 @@ public class CharacterSelectionPanel : MonoBehaviour, IControlable
private void Start()
{
_characters = CharactersController.GetCharactersArray();
_characters = CharactersController.I.GetDefinitionsArray();
Open();
}
@ -109,8 +109,8 @@ public class CharacterSelectionPanel : MonoBehaviour, IControlable
private void DisplaySelectedCharacter()
{
_characterNameLabel.text = SelectedCharacter.characterName;
_characterIcon.sprite = SelectedCharacter.visualModule.icon;
_characterNameLabel.text = SelectedCharacter.CharacterName;
_characterIcon.sprite = SelectedCharacter.IconSmall;
ClearTable();
PrizeSet prizeSet = PrizeSystemManager.PrizeContainer.Sets[SelectedCharacter.CharacterIndex];

View File

@ -43,7 +43,7 @@ public class PrizesSelector : MonoBehaviour, IControlable
_selectButton.OnClick -= Confirm;
}
public void Open(Character character)
public void Open(CharacterDefinition character)
{
gameObject.SetActive(true);
_prizeSet = PrizeSystemManager.PrizeContainer.Sets[character.CharacterIndex];

View File

@ -43,9 +43,7 @@ public class VitrinaView : MonoBehaviour
return;
}
Character character = CharactersController.CurrentCharacter;
if(character.prizeModule.TryFetchIfTypeMatch(out VitrinaPrize vitrinaPrize))
if (CharactersController.I.TryGetCurrentPrize(out VitrinaPrize vitrinaPrize))
{
gameObject.SetActive(true);

View File

@ -68,7 +68,7 @@ public class QrTestPanel : MonoBehaviour, IControlable
_entries.Clear();
PrizeContainer prizeContainer = PrizeSystemManager.PrizeContainer;
Character[] characters = CharactersController.GetCharactersArray();
CharacterDefinition[] characters = CharactersController.I.GetDefinitionsArray();
if (prizeContainer?.Sets == null || characters == null)
return;
@ -101,8 +101,8 @@ public class QrTestPanel : MonoBehaviour, IControlable
private void ShowCurrentEntry()
{
Entry entry = _entries[_currentIndex];
_characterName.text = entry.Character.characterName;
_characterIcon.sprite = entry.Character.visualModule.icon;
_characterName.text = entry.Character.CharacterName;
_characterIcon.sprite = entry.Character.IconSmall;
_characterIcon.preserveAspect = true;
_counter.text = $"{_currentIndex + 1} / {_entries.Count}";
@ -144,10 +144,10 @@ public class QrTestPanel : MonoBehaviour, IControlable
private readonly struct Entry
{
public Character Character { get; }
public CharacterDefinition Character { get; }
public QrPrize Prize { get; }
public Entry(Character character, QrPrize prize)
public Entry(CharacterDefinition character, QrPrize prize)
{
Character = character;
Prize = prize;

View File

@ -77,6 +77,7 @@ public class Menu : MonoBehaviour, IControlable
private void Disable()
{
ControlsEnabled = false;
menuPanelManager.CloseModal();
_promoTimer.Reset();
_settingsTimer.Reset();
}

View File

@ -23,6 +23,9 @@ public class MenuPanelManager
public void SwitchPanel(int direction)
{
if (CurrentPanel.BlocksNavigation)
return;
//Считаем новый индекс панели
int newIndex = Mathf.Clamp(_currentIndex + direction, 0, _panels.Count - 1);
@ -39,4 +42,7 @@ public class MenuPanelManager
public void InteractCurrent()
=> CurrentPanel.Interact();
public void CloseModal()
=> CurrentPanel.CloseModal();
}

View File

@ -2,8 +2,11 @@
public abstract class MenuPanel : MonoBehaviour
{
public virtual bool BlocksNavigation => false;
public abstract void Initialize();
public abstract void Enable(int direction, float delay);
public abstract void Disable(int direction);
public abstract void Interact();
public virtual void CloseModal() { }
}

View File

@ -19,6 +19,10 @@ public class MenuPanelsScroll : MenuPanel
private bool m_enabled = true;
private bool isTransitioning = false;
public override bool BlocksNavigation => _panels != null
&& _panels.Count > 0
&& currentPanel.BlocksNavigation;
public override void Initialize()
{
BuildLayout();
@ -50,7 +54,7 @@ public class MenuPanelsScroll : MenuPanel
private void Update()
{
if (!m_enabled || isTransitioning) return;
if (!m_enabled || isTransitioning || BlocksNavigation) return;
int dir_v = -In.GetAxis(JoystickSide.Both, InteractMode.Discrete).y;
if (dir_v != 0)
@ -102,4 +106,6 @@ public class MenuPanelsScroll : MenuPanel
}
public override void Interact() => currentPanel.Interact();
public override void CloseModal() => currentPanel.CloseModal();
}

View File

@ -3,6 +3,7 @@ using CharacterSystem;
using PrizeSystem;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PrizesPanel : InfoPanel
{
@ -16,12 +17,76 @@ public class PrizesPanel : InfoPanel
[SerializeField] private RectTransform table;
[SerializeField] private PrizeRecord recordPrefab;
[Header("Модальное окно")]
[SerializeField] private float _modalTimeout = 20f;
[SerializeField] private float _modalFadeDuration = 0.25f;
[SerializeField] private float _modalScale = 1.55f;
[SerializeField] private Color _modalBackgroundColor = new(0f, 0f, 0f, 0.8f);
private readonly List<PrizeRecord> _records = new();
private CanvasGroup _modalCanvasGroup;
private Image _modalBackdrop;
private Sequence _modalSequence;
private Transform _originalParent;
private int _originalSiblingIndex;
private Vector2 _originalAnchorMin;
private Vector2 _originalAnchorMax;
private Vector2 _originalPivot;
private Vector2 _originalSizeDelta;
private Vector2 _originalAnchoredPosition;
private Vector3 _originalScale;
private float _lastInputTime;
private bool _modalOpen;
private bool _modalTransitioning;
public override bool BlocksNavigation => _modalOpen;
public override float closeDelay => (Mathf.Max(infoDuration, buttonDuration, titleDuration)
+ _records.Count * recordDelay
+ titleDuration) / closeSpeedMultiplier;
private void Update()
{
if (!_modalOpen || _modalTransitioning)
return;
if (In.AnyButton())
_lastInputTime = Time.unscaledTime;
if (Time.unscaledTime - _lastInputTime >= _modalTimeout)
CloseModal();
}
public override void Initialize()
{
}
public override void Interact()
{
if (_modalTransitioning)
return;
if (_modalOpen)
CloseModal();
else
OpenModal();
}
public override void CloseModal()
{
if (!_modalOpen || _modalTransitioning)
return;
_modalTransitioning = true;
_modalSequence?.Kill();
_modalSequence = DOTween.Sequence().SetUpdate(true);
_modalSequence.Join(_modalCanvasGroup.DOFade(0f, _modalFadeDuration));
_modalSequence.Join(_modalBackdrop.DOFade(0f, _modalFadeDuration));
_modalSequence.Join(root.DOScale(_originalScale * 0.9f, _modalFadeDuration).SetEase(Ease.InBack));
_modalSequence.OnComplete(RestoreAfterModal);
_modalSequence.PlayForward();
}
protected override void InitializeBeforeOpen()
{
// Очистить макет
@ -31,7 +96,7 @@ public class PrizesPanel : InfoPanel
}
_records.Clear();
Character[] characters = CharactersController.GetCharactersArray();
CharacterDefinition[] characters = CharactersController.I.GetDefinitionsArray();
List<PrizeSet> prizeSets = PrizeSystemManager.PrizeContainer?.Sets;
for (int i = 0; i < characters.Length; i++)
@ -43,8 +108,8 @@ public class PrizesPanel : InfoPanel
record.Init(
i + 1,
characters[i].visualModule.iconSmall,
characters[i].characterName,
characters[i].IconSmall,
characters[i].CharacterName,
characterPrizes);
_records.Add(record);
}
@ -96,7 +161,97 @@ public class PrizesPanel : InfoPanel
return seq;
}
public override void Initialize()
private void OpenModal()
{
Canvas canvas = root.GetComponentInParent<Canvas>()?.rootCanvas;
if (canvas == null)
return;
SaveOriginalTransform();
CreateBackdrop(canvas.transform);
root.SetParent(canvas.transform, false);
root.SetAsLastSibling();
root.anchorMin = Vector2.one * 0.5f;
root.anchorMax = Vector2.one * 0.5f;
root.pivot = Vector2.one * 0.5f;
root.anchoredPosition = Vector2.zero;
root.sizeDelta = _originalSizeDelta;
root.localScale = _originalScale * (_modalScale * 0.85f);
_modalCanvasGroup = root.GetComponent<CanvasGroup>();
if (_modalCanvasGroup == null)
_modalCanvasGroup = root.gameObject.AddComponent<CanvasGroup>();
_modalCanvasGroup.alpha = 0f;
_modalOpen = true;
_modalTransitioning = true;
_lastInputTime = Time.unscaledTime;
_modalSequence?.Kill();
_modalSequence = DOTween.Sequence().SetUpdate(true);
_modalSequence.Join(_modalCanvasGroup.DOFade(1f, _modalFadeDuration));
_modalSequence.Join(_modalBackdrop.DOFade(_modalBackgroundColor.a, _modalFadeDuration));
_modalSequence.Join(root.DOScale(_originalScale * _modalScale, _modalFadeDuration).SetEase(Ease.OutBack));
_modalSequence.OnComplete(() => _modalTransitioning = false);
_modalSequence.PlayForward();
}
private void SaveOriginalTransform()
{
_originalParent = root.parent;
_originalSiblingIndex = root.GetSiblingIndex();
_originalAnchorMin = root.anchorMin;
_originalAnchorMax = root.anchorMax;
_originalPivot = root.pivot;
_originalSizeDelta = root.sizeDelta;
_originalAnchoredPosition = root.anchoredPosition;
_originalScale = root.localScale;
}
private void CreateBackdrop(Transform canvasTransform)
{
GameObject backdrop = new(
"Prizes modal backdrop",
typeof(RectTransform),
typeof(CanvasRenderer),
typeof(Image));
RectTransform backdropRect = backdrop.GetComponent<RectTransform>();
backdropRect.SetParent(canvasTransform, false);
backdropRect.anchorMin = Vector2.zero;
backdropRect.anchorMax = Vector2.one;
backdropRect.offsetMin = Vector2.zero;
backdropRect.offsetMax = Vector2.zero;
backdropRect.SetAsLastSibling();
_modalBackdrop = backdrop.GetComponent<Image>();
_modalBackdrop.color = new Color(
_modalBackgroundColor.r,
_modalBackgroundColor.g,
_modalBackgroundColor.b,
0f);
_modalBackdrop.raycastTarget = true;
}
private void RestoreAfterModal()
{
if (_modalBackdrop != null)
Destroy(_modalBackdrop.gameObject);
root.SetParent(_originalParent, false);
root.SetSiblingIndex(_originalSiblingIndex);
root.anchorMin = _originalAnchorMin;
root.anchorMax = _originalAnchorMax;
root.pivot = _originalPivot;
root.sizeDelta = _originalSizeDelta;
root.anchoredPosition = _originalAnchoredPosition;
root.localScale = _originalScale;
_modalCanvasGroup.alpha = 1f;
_modalBackdrop = null;
_modalOpen = false;
_modalTransitioning = false;
_modalSequence = null;
}
}

View File

@ -1,4 +1,6 @@
using DG.Tweening;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class RatingPanel : InfoPanel
@ -7,10 +9,58 @@ public class RatingPanel : InfoPanel
[SerializeField] private RectTransform descriptionSign;
[SerializeField] private float descriptionOpenY, descriptionCloseY, descriptionDuration;
[Header("Топ рейтинга")]
[SerializeField] private GameObject _recordPrefab;
[SerializeField] private int _recordsCount = 3;
[SerializeField] private Vector2 _recordsSize = new(800f, 190f);
[SerializeField] private float _recordSpacing = 4f;
private RatingModal _modal;
private RectTransform _recordsRoot;
private const string DateFormat = "dd.MM.yy";
public override bool BlocksNavigation => _modal != null && _modal.IsOpen;
public override float closeDelay => (infoDuration + buttonDuration + descriptionDuration
- timeOffset * 3 + titleDuration)
/ closeSpeedMultiplier;
public override void Initialize()
{
}
public override void Interact()
{
if (_modal == null)
_modal = FindFirstObjectByType<RatingModal>(FindObjectsInactive.Include);
if (_modal == null)
{
Debug.LogWarning("Не найдено модальное окно рейтинга.");
return;
}
if (_modal.IsOpen)
{
_modal.Close();
return;
}
Canvas canvas = root.GetComponentInParent<Canvas>()?.rootCanvas;
_modal.Open(canvas != null ? canvas.transform : null);
}
public override void CloseModal()
{
_modal?.Close();
}
protected override void InitializeBeforeOpen()
{
BuildTopRecords();
}
protected override Sequence GetOpenSequence(float delay)
{
Sequence seq = DOTween.Sequence();
@ -47,7 +97,68 @@ public class RatingPanel : InfoPanel
return seq;
}
public override void Initialize()
private void BuildTopRecords()
{
_recordsRoot ??= transform.Find("Info/RecordsGroup") as RectTransform;
if (_recordsRoot == null || _recordPrefab == null)
{
Debug.LogWarning("Не настроен вывод топа рейтинга в главном меню.");
return;
}
ClearTopRecords();
_recordsRoot.sizeDelta = _recordsSize;
PlayerStatsService statsService = GameManager.Instance?.StatsService;
List<PlayerStatsRecord> records = statsService?.GetTopPlayers(_recordsCount)
?? new List<PlayerStatsRecord>();
RectTransform prefabRect = _recordPrefab.GetComponent<RectTransform>();
float prefabWidth = prefabRect != null ? prefabRect.rect.width : _recordsRoot.rect.width;
float prefabHeight = prefabRect != null ? prefabRect.rect.height : 66f;
float scale = prefabWidth > 0f ? _recordsRoot.rect.width / prefabWidth : 1f;
float rowHeight = prefabHeight * scale;
float rowStep = rowHeight + _recordSpacing;
float firstRowY = (records.Count - 1) * rowStep * 0.5f;
for (int i = 0; i < records.Count; i++)
{
RectTransform row = Instantiate(_recordPrefab, _recordsRoot).GetComponent<RectTransform>();
row.anchorMin = new Vector2(0.5f, 0.5f);
row.anchorMax = new Vector2(0.5f, 0.5f);
row.pivot = new Vector2(0.5f, 0.5f);
row.anchoredPosition = new Vector2(0f, firstRowY - i * rowStep);
row.localScale = Vector3.one * scale;
FillTopRecord(row, i + 1, records[i]);
}
}
}
private void ClearTopRecords()
{
for (int i = _recordsRoot.childCount - 1; i >= 0; i--)
{
GameObject child = _recordsRoot.GetChild(i).gameObject;
child.SetActive(false);
Destroy(child);
}
}
private void FillTopRecord(RectTransform row, int rank, PlayerStatsRecord record)
{
TextMeshProUGUI[] cells = row.GetComponentsInChildren<TextMeshProUGUI>(true);
if (cells.Length < 5)
return;
cells[0].text = rank.ToString();
cells[1].text = record.PlayerName;
cells[2].text = FormatTime(record.CompletionTimeSec);
cells[3].text = record.MovesCount.ToString();
cells[4].text = record.CompletedAt.ToString(DateFormat);
}
private string FormatTime(float seconds)
{
int totalSeconds = Mathf.Max(0, Mathf.RoundToInt(seconds));
return $"{totalSeconds / 60:D2}:{totalSeconds % 60:D2}";
}
}

View File

@ -0,0 +1,17 @@
{
"leftJoystick": {
"up": 0,
"right": 1,
"down": 2,
"left": 3,
"action": 4
},
"rightJoystick": {
"up": 5,
"right": 6,
"down": 7,
"left": 8,
"action": 9
},
"serviceButton": 10
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5ce5043b96168aa4282a69aa6767b623
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -3,6 +3,7 @@
"com.coplaydev.unity-mcp": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#main",
"com.github-glitchenzo.nugetforunity": "https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity",
"com.unity.2d.sprite": "1.0.0",
"com.unity.addressables": "2.9.1",
"com.unity.ide.visualstudio": "2.0.27",
"com.unity.render-pipelines.universal": "17.4.0",
"com.unity.ugui": "2.0.0",

View File

@ -30,6 +30,22 @@
"source": "builtin",
"dependencies": {}
},
"com.unity.addressables": {
"version": "2.9.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.profiling.core": "1.0.2",
"com.unity.test-framework": "1.4.5",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.scriptablebuildpipeline": "2.6.1",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.burst": {
"version": "1.8.29",
"depth": 2,
@ -88,6 +104,13 @@
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.profiling.core": {
"version": "1.0.3",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.render-pipelines.core": {
"version": "17.4.0",
"depth": 1,
@ -119,6 +142,16 @@
"com.unity.render-pipelines.core": "17.4.0"
}
},
"com.unity.scriptablebuildpipeline": {
"version": "2.6.1",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.test-framework": "1.4.5",
"com.unity.modules.assetbundle": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.searcher": {
"version": "4.9.4",
"depth": 2,

View File

@ -8,4 +8,5 @@ EditorBuildSettings:
- enabled: 1
path: Assets/Scenes/GameScene3D.unity
guid: d37c4c573ec548a41865b5de88084be1
m_configObjects: {}
m_configObjects:
com.unity.addressableassets: {fileID: 11400000, guid: 65c6c2044a27e1e4ea802fce939390bb, type: 2}

View File

@ -0,0 +1,14 @@
{
"useBuildCacheServer": false,
"cacheServerHost": "",
"cacheServerPort": 8126,
"threadedArchiving": true,
"logCacheMiss": false,
"logAssetWarnings": true,
"slimWriteResults": true,
"maximumCacheSize": 20,
"useDetailedBuildLog": false,
"useV2Hasher": true,
"fileIDHashSeed": 0,
"prefabPackedHeaderSize": 2
}