├── .editorconfig ├── .gitignore ├── Icons.meta ├── Icons ├── Audio.png ├── Audio.png.meta ├── BehaviourTree.png ├── BehaviourTree.png.meta ├── RecyclableObject.png ├── RecyclableObject.png.meta ├── UI.png └── UI.png.meta ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── Resources.meta ├── Resources ├── BlackFade.prefab └── BlackFade.prefab.meta ├── Scripts.meta ├── Scripts ├── Minity.meta ├── Minity │ ├── Audio.meta │ ├── Audio │ │ ├── AudioManager.cs │ │ ├── AudioManager.cs.meta │ │ ├── AudioPlayer.cs │ │ ├── AudioPlayer.cs.meta │ │ ├── AudioPreset.cs │ │ ├── AudioPreset.cs.meta │ │ ├── AudioResources.cs │ │ ├── AudioResources.cs.meta │ │ ├── Editor.meta │ │ └── Editor │ │ │ ├── AudioPresetEditor.cs │ │ │ └── AudioPresetEditor.cs.meta │ ├── Behaviour.meta │ ├── Behaviour │ │ ├── BehaviourContext.cs │ │ ├── BehaviourContext.cs.meta │ │ ├── BehaviourState.cs │ │ ├── BehaviourState.cs.meta │ │ ├── BehaviourTree.cs │ │ ├── BehaviourTree.cs.meta │ │ ├── Nodes.meta │ │ └── Nodes │ │ │ ├── ActionNode.cs │ │ │ ├── ActionNode.cs.meta │ │ │ ├── ConditionNode.cs │ │ │ ├── ConditionNode.cs.meta │ │ │ ├── IBehaviourNode.cs │ │ │ ├── IBehaviourNode.cs.meta │ │ │ ├── InverterNode.cs │ │ │ ├── InverterNode.cs.meta │ │ │ ├── RepeaterNode.cs │ │ │ ├── RepeaterNode.cs.meta │ │ │ ├── SelectorNode.cs │ │ │ ├── SelectorNode.cs.meta │ │ │ ├── SequenceNode.cs │ │ │ ├── SequenceNode.cs.meta │ │ │ ├── WaitNode.cs │ │ │ └── WaitNode.cs.meta │ ├── General.meta │ ├── General │ │ ├── EnumIdentifier.cs │ │ └── EnumIdentifier.cs.meta │ ├── Infra.meta │ ├── Infra │ │ ├── GlobalSingleton.cs │ │ ├── GlobalSingleton.cs.meta │ │ ├── SceneSingleton.cs │ │ └── SceneSingleton.cs.meta │ ├── Logger.meta │ ├── Logger │ │ ├── DebugLog.cs │ │ └── DebugLog.cs.meta │ ├── Pooling.meta │ ├── Pooling │ │ ├── Editor.meta │ │ ├── Editor │ │ │ ├── PoolGuardEditor.cs │ │ │ └── PoolGuardEditor.cs.meta │ │ ├── ObjectPool.cs │ │ ├── ObjectPool.cs.meta │ │ ├── PoolContext.cs │ │ ├── PoolContext.cs.meta │ │ ├── PoolGuard.cs │ │ ├── PoolGuard.cs.meta │ │ ├── PoolModel.cs │ │ ├── PoolModel.cs.meta │ │ ├── PoolableObject.cs │ │ ├── PoolableObject.cs.meta │ │ ├── ScenePoolGuard.cs │ │ └── ScenePoolGuard.cs.meta │ ├── SceneRouter.meta │ ├── SceneRouter │ │ ├── BlackFade.cs │ │ ├── BlackFade.cs.meta │ │ ├── LoadingAnimator.cs │ │ ├── LoadingAnimator.cs.meta │ │ ├── LoadingAnimatorData.cs │ │ ├── LoadingAnimatorData.cs.meta │ │ ├── SceneRouter.cs │ │ ├── SceneRouter.cs.meta │ │ ├── SceneRouterConfig.cs │ │ ├── SceneRouterConfig.cs.meta │ │ ├── SceneRouterContext.cs │ │ ├── SceneRouterContext.cs.meta │ │ ├── SceneRouterNode.cs │ │ └── SceneRouterNode.cs.meta │ ├── UI.meta │ ├── UI │ │ ├── Binding.cs │ │ ├── Binding.cs.meta │ │ ├── BindingView.cs │ │ ├── BindingView.cs.meta │ │ ├── BindingViewGuard.cs │ │ ├── BindingViewGuard.cs.meta │ │ ├── Editor.meta │ │ ├── Editor │ │ │ ├── UIListInspector.cs │ │ │ └── UIListInspector.cs.meta │ │ ├── ManagedUI.cs │ │ ├── ManagedUI.cs.meta │ │ ├── SimpleManagedUI.cs │ │ ├── SimpleManagedUI.cs.meta │ │ ├── UI.cs │ │ ├── UI.cs.meta │ │ ├── UIContext.cs │ │ ├── UIContext.cs.meta │ │ ├── UIList.cs │ │ ├── UIList.cs.meta │ │ ├── UIManager.cs │ │ ├── UIManager.cs.meta │ │ ├── VarBinding.cs │ │ └── VarBinding.cs.meta │ ├── Variable.meta │ └── Variable │ │ ├── CommonVariables.ignore │ │ ├── CommonVariables.ignore.meta │ │ ├── CommonVariables.tt │ │ ├── CommonVariables.tt.meta │ │ ├── Editor.meta │ │ ├── Editor │ │ ├── MinityVariableInspector.cs │ │ └── MinityVariableInspector.cs.meta │ │ ├── General.meta │ │ ├── General │ │ ├── ComponentVar.cs │ │ ├── ComponentVar.cs.meta │ │ ├── GameObjectVar.cs │ │ ├── GameObjectVar.cs.meta │ │ ├── RectTransformVar.cs │ │ ├── RectTransformVar.cs.meta │ │ ├── TransformVar.cs │ │ └── TransformVar.cs.meta │ │ ├── Graphics.meta │ │ ├── Graphics │ │ ├── MaterialVar.cs │ │ ├── MaterialVar.cs.meta │ │ ├── MeshVar.cs │ │ ├── MeshVar.cs.meta │ │ ├── SpriteVar.cs │ │ ├── SpriteVar.cs.meta │ │ ├── Texture2DVar.cs │ │ ├── Texture2DVar.cs.meta │ │ ├── TextureVar.cs │ │ └── TextureVar.cs.meta │ │ ├── MinityVariable.cs │ │ ├── MinityVariable.cs.meta │ │ ├── MinityVariableGuard.cs │ │ ├── MinityVariableGuard.cs.meta │ │ ├── Physics.meta │ │ ├── Physics │ │ ├── Collider2DVar.cs │ │ ├── Collider2DVar.cs.meta │ │ ├── ColliderVar.cs │ │ ├── ColliderVar.cs.meta │ │ ├── Rigidbody2DVar.cs │ │ ├── Rigidbody2DVar.cs.meta │ │ ├── RigidbodyVar.cs │ │ └── RigidbodyVar.cs.meta │ │ ├── Primitive.meta │ │ ├── Primitive │ │ ├── BoolVar.cs │ │ ├── BoolVar.cs.meta │ │ ├── DoubleVar.cs │ │ ├── DoubleVar.cs.meta │ │ ├── FloatVar.cs │ │ ├── FloatVar.cs.meta │ │ ├── IntVar.cs │ │ ├── IntVar.cs.meta │ │ ├── StringVar.cs │ │ └── StringVar.cs.meta │ │ ├── Struct.meta │ │ └── Struct │ │ ├── ColorVar.cs │ │ ├── ColorVar.cs.meta │ │ ├── RectVar.cs │ │ ├── RectVar.cs.meta │ │ ├── Vector2Var.cs │ │ ├── Vector2Var.cs.meta │ │ ├── Vector3Var.cs │ │ └── Vector3Var.cs.meta ├── dev.milthm.minity.asmdef └── dev.milthm.minity.asmdef.meta ├── manifest.json ├── manifest.json.meta ├── package.json ├── package.json.meta ├── xLua Support.unitypackage └── xLua Support.unitypackage.meta /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | insert_final_newline = true 8 | spaces_around_operators = true 9 | end_of_line = lf 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | # /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Uu]ser[Ss]ettings/ 12 | /Release/ 13 | /Design/ 14 | /Scenes/ 15 | 16 | /Textures/ 17 | /Demos/ 18 | /TextMesh Pro/ 19 | 20 | # MemoryCaptures can get excessive in size. 21 | # They also could contain extremely sensitive data 22 | /[Mm]emoryCaptures/ 23 | 24 | # Asset meta data should only be ignored when the corresponding asset is also ignored 25 | !/[Aa]ssets/**/*.meta 26 | 27 | # Uncomment this line if you wish to ignore the asset store tools plugin 28 | # /[Aa]ssets/AssetStoreTools* 29 | 30 | # Autogenerated Jetbrains Rider plugin 31 | /[Aa]ssets/Plugins/Editor/JetBrains* 32 | 33 | # Visual Studio cache directory 34 | .vs/ 35 | .vscode/ 36 | # Gradle cache directory 37 | .gradle/ 38 | 39 | Certificates/ 40 | 41 | # Autogenerated VS/MD/Consulo solution and project files 42 | ExportedObj/ 43 | .consulo/ 44 | *.csproj 45 | *.unityproj 46 | *.sln 47 | *.suo 48 | *.tmp 49 | *.user 50 | *.userprefs 51 | *.pidb 52 | *.booproj 53 | *.svd 54 | *.pdb 55 | *.mdb 56 | *.opendb 57 | *.VC.db 58 | 59 | # Unity3D generated meta files 60 | *.pidb.meta 61 | *.pdb.meta 62 | *.mdb.meta 63 | 64 | # Unity3D generated file on crash reports 65 | sysinfo.txt 66 | 67 | # Builds 68 | *.apk 69 | *.aab 70 | 71 | # Crashlytics generated file 72 | crashlytics-build.properties 73 | 74 | # Packed Addressables 75 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* 76 | 77 | # Temporary auto-generated Android Assets 78 | /[Aa]ssets/[Ss]treamingAssets/aa.meta 79 | /[Aa]ssets/[Ss]treamingAssets/aa/* 80 | 81 | 82 | ## Ignore Visual Studio temporary files, build results, and 83 | ## files generated by popular Visual Studio add-ons. 84 | ## 85 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 86 | 87 | # User-specific files 88 | *.rsuser 89 | *.suo 90 | *.user 91 | *.userosscache 92 | *.sln.docstates 93 | 94 | # User-specific files (MonoDevelop/Xamarin Studio) 95 | *.userprefs 96 | 97 | # Mono auto generated files 98 | mono_crash.* 99 | 100 | # Build results 101 | [Dd]ebug/ 102 | [Dd]ebugPublic/ 103 | [Rr]elease/ 104 | [Rr]eleases/ 105 | x64/ 106 | x86/ 107 | [Ww][Ii][Nn]32/ 108 | [Aa][Rr][Mm]/ 109 | [Aa][Rr][Mm]64/ 110 | bld/ 111 | [Bb]in/ 112 | [Oo]bj/ 113 | [Ll]og/ 114 | [Ll]ogs/ 115 | 116 | # Visual Studio 2015/2017 cache/options directory 117 | .vs/ 118 | # Uncomment if you have tasks that create the project's static files in wwwroot 119 | #wwwroot/ 120 | 121 | # Visual Studio 2017 auto generated files 122 | Generated\ Files/ 123 | 124 | # MSTest test Results 125 | [Tt]est[Rr]esult*/ 126 | [Bb]uild[Ll]og.* 127 | 128 | # NUnit 129 | *.VisualState.xml 130 | TestResult.xml 131 | nunit-*.xml 132 | 133 | # Build Results of an ATL Project 134 | [Dd]ebugPS/ 135 | [Rr]eleasePS/ 136 | dlldata.c 137 | 138 | # Benchmark Results 139 | BenchmarkDotNet.Artifacts/ 140 | 141 | # .NET Core 142 | project.lock.json 143 | project.fragment.lock.json 144 | artifacts/ 145 | 146 | # ASP.NET Scaffolding 147 | ScaffoldingReadMe.txt 148 | 149 | # StyleCop 150 | StyleCopReport.xml 151 | 152 | # Files built by Visual Studio 153 | *_i.c 154 | *_p.c 155 | *_h.h 156 | *.ilk 157 | # *.meta 158 | *.iobj 159 | *.pch 160 | *.pdb 161 | *.ipdb 162 | *.pgc 163 | *.pgd 164 | *.rsp 165 | *.sbr 166 | *.tlb 167 | *.tli 168 | *.tlh 169 | *.tmp 170 | *.tmp_proj 171 | *_wpftmp.csproj 172 | *.log 173 | *.vspscc 174 | *.vssscc 175 | .builds 176 | *.pidb 177 | *.svclog 178 | *.scc 179 | 180 | # Chutzpah Test files 181 | _Chutzpah* 182 | 183 | # Visual C++ cache files 184 | ipch/ 185 | *.aps 186 | *.ncb 187 | *.opendb 188 | *.opensdf 189 | *.sdf 190 | *.cachefile 191 | *.VC.db 192 | *.VC.VC.opendb 193 | 194 | # Visual Studio profiler 195 | *.psess 196 | *.vsp 197 | *.vspx 198 | *.sap 199 | 200 | # Visual Studio Trace Files 201 | *.e2e 202 | 203 | # TFS 2012 Local Workspace 204 | $tf/ 205 | 206 | # Guidance Automation Toolkit 207 | *.gpState 208 | 209 | # ReSharper is a .NET coding add-in 210 | _ReSharper*/ 211 | *.[Rr]e[Ss]harper 212 | *.DotSettings.user 213 | 214 | # TeamCity is a build add-in 215 | _TeamCity* 216 | 217 | # DotCover is a Code Coverage Tool 218 | *.dotCover 219 | 220 | # AxoCover is a Code Coverage Tool 221 | .axoCover/* 222 | !.axoCover/settings.json 223 | 224 | # Coverlet is a free, cross platform Code Coverage Tool 225 | coverage*.json 226 | coverage*.xml 227 | coverage*.info 228 | 229 | # Visual Studio code coverage results 230 | *.coverage 231 | *.coveragexml 232 | 233 | # NCrunch 234 | _NCrunch_* 235 | .*crunch*.local.xml 236 | nCrunchTemp_* 237 | 238 | # MightyMoose 239 | *.mm.* 240 | AutoTest.Net/ 241 | 242 | # Web workbench (sass) 243 | .sass-cache/ 244 | 245 | # Installshield output folder 246 | [Ee]xpress/ 247 | 248 | # DocProject is a documentation generator add-in 249 | DocProject/buildhelp/ 250 | DocProject/Help/*.HxT 251 | DocProject/Help/*.HxC 252 | DocProject/Help/*.hhc 253 | DocProject/Help/*.hhk 254 | DocProject/Help/*.hhp 255 | DocProject/Help/Html2 256 | DocProject/Help/html 257 | 258 | # Click-Once directory 259 | publish/ 260 | 261 | # Publish Web Output 262 | *.[Pp]ublish.xml 263 | *.azurePubxml 264 | # Note: Comment the next line if you want to checkin your web deploy settings, 265 | # but database connection strings (with potential passwords) will be unencrypted 266 | *.pubxml 267 | *.publishproj 268 | 269 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 270 | # checkin your Azure Web App publish settings, but sensitive information contained 271 | # in these scripts will be unencrypted 272 | PublishScripts/ 273 | 274 | # NuGet Packages 275 | *.nupkg 276 | # NuGet Symbol Packages 277 | *.snupkg 278 | # The packages folder can be ignored because of Package Restore 279 | **/[Pp]ackages/* 280 | # except build/, which is used as an MSBuild target. 281 | !**/[Pp]ackages/build/ 282 | # except Unity package References 283 | !Packages/*.json 284 | 285 | # Uncomment if necessary however generally it will be regenerated when needed 286 | #!**/[Pp]ackages/repositories.config 287 | # NuGet v3's project.json files produces more ignorable files 288 | *.nuget.props 289 | *.nuget.targets 290 | 291 | # Microsoft Azure Build Output 292 | csx/ 293 | *.build.csdef 294 | 295 | # Microsoft Azure Emulator 296 | ecf/ 297 | rcf/ 298 | 299 | # Windows Store app package directories and files 300 | AppPackages/ 301 | BundleArtifacts/ 302 | Package.StoreAssociation.xml 303 | _pkginfo.txt 304 | *.appx 305 | *.appxbundle 306 | *.appxupload 307 | 308 | # Visual Studio cache files 309 | # files ending in .cache can be ignored 310 | *.[Cc]ache 311 | # but keep track of directories ending in .cache 312 | !?*.[Cc]ache/ 313 | 314 | # Others 315 | ClientBin/ 316 | ~$* 317 | *~ 318 | *.dbmdl 319 | *.dbproj.schemaview 320 | *.jfm 321 | *.pfx 322 | *.publishsettings 323 | orleans.codegen.cs 324 | 325 | # Including strong name files can present a security risk 326 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 327 | #*.snk 328 | 329 | # Since there are multiple workflows, uncomment next line to ignore bower_components 330 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 331 | #bower_components/ 332 | 333 | # RIA/Silverlight projects 334 | Generated_Code/ 335 | 336 | # Backup & report files from converting an old project file 337 | # to a newer Visual Studio version. Backup files are not needed, 338 | # because we have git ;-) 339 | _UpgradeReport_Files/ 340 | Backup*/ 341 | UpgradeLog*.XML 342 | UpgradeLog*.htm 343 | ServiceFabricBackup/ 344 | *.rptproj.bak 345 | 346 | # SQL Server files 347 | *.mdf 348 | *.ldf 349 | *.ndf 350 | 351 | # Business Intelligence projects 352 | *.rdl.data 353 | *.bim.layout 354 | *.bim_*.settings 355 | *.rptproj.rsuser 356 | *- [Bb]ackup.rdl 357 | *- [Bb]ackup ([0-9]).rdl 358 | *- [Bb]ackup ([0-9][0-9]).rdl 359 | 360 | # Microsoft Fakes 361 | FakesAssemblies/ 362 | 363 | # GhostDoc plugin setting file 364 | *.GhostDoc.xml 365 | 366 | # Node.js Tools for Visual Studio 367 | .ntvs_analysis.dat 368 | node_modules/ 369 | 370 | # Visual Studio 6 build log 371 | *.plg 372 | 373 | # Visual Studio 6 workspace options file 374 | *.opt 375 | 376 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 377 | *.vbw 378 | 379 | # Visual Studio LightSwitch build output 380 | **/*.HTMLClient/GeneratedArtifacts 381 | **/*.DesktopClient/GeneratedArtifacts 382 | **/*.DesktopClient/ModelManifest.xml 383 | **/*.Server/GeneratedArtifacts 384 | **/*.Server/ModelManifest.xml 385 | _Pvt_Extensions 386 | 387 | # Paket dependency manager 388 | .paket/paket.exe 389 | paket-files/ 390 | 391 | # FAKE - F# Make 392 | .fake/ 393 | 394 | # CodeRush personal settings 395 | .cr/personal 396 | 397 | # Python Tools for Visual Studio (PTVS) 398 | __pycache__/ 399 | *.pyc 400 | 401 | # Cake - Uncomment if you are using it 402 | # tools/** 403 | # !tools/packages.config 404 | 405 | # Tabs Studio 406 | *.tss 407 | 408 | # Telerik's JustMock configuration file 409 | *.jmconfig 410 | 411 | # BizTalk build output 412 | *.btp.cs 413 | *.btm.cs 414 | *.odx.cs 415 | *.xsd.cs 416 | 417 | # OpenCover UI analysis results 418 | OpenCover/ 419 | 420 | # Azure Stream Analytics local run output 421 | ASALocalRun/ 422 | 423 | # MSBuild Binary and Structured Log 424 | *.binlog 425 | 426 | # NVidia Nsight GPU debugger configuration file 427 | *.nvuser 428 | 429 | # MFractors (Xamarin productivity tool) working folder 430 | .mfractor/ 431 | 432 | # Local History for Visual Studio 433 | .localhistory/ 434 | 435 | # BeatPulse healthcheck temp database 436 | healthchecksdb 437 | 438 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 439 | MigrationBackup/ 440 | 441 | # Ionide (cross platform F# VS Code tools) working folder 442 | .ionide/ 443 | 444 | # Fody - auto-generated XML schema 445 | FodyWeavers.xsd 446 | # why .wav?? 447 | # *.wav 448 | *.vsconfig 449 | .idea 450 | 451 | Assets/ 452 | ProjectSettings/ShaderGraphSettings.asset 453 | 454 | Assets/Epic Toon FX/Upgrade/ETFX 2019.4.24f1 URP Upgrade.unitypackage.meta 455 | Assets/Le Tai's Asset/TranslucentImage/UniversalRP support.unitypackage.meta 456 | Assets/Epic Toon FX/Upgrade/ETFX 2019.4.24f1 URP Upgrade.unitypackage.meta 457 | Assets/Le Tai's Asset/TranslucentImage/UniversalRP support.unitypackage.meta 458 | Demos.meta 459 | TextMesh Pro.meta 460 | Textures.meta 461 | /Resources/Demos 462 | 463 | Resources/UIList.asset 464 | 465 | Resources/UIList.asset.meta 466 | 467 | ProjectSettings/ 468 | 469 | ProjectSettings.meta 470 | 471 | XLua/ 472 | 473 | XLua.meta 474 | 475 | AddressableAssetsData/ 476 | 477 | AddressableAssetsData.meta 478 | 479 | Plugins/ 480 | 481 | Plugins.meta 482 | 483 | StreamingAssets/ 484 | 485 | StreamingAssets.meta 486 | 487 | Milease.CodeGen/ 488 | 489 | Milease.CodeGen.meta 490 | -------------------------------------------------------------------------------- /Icons.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8118578769bfe944d8ee04f3572bae43 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Icons/Audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MorizeroDev/Minity/4e0559c1b5ebeb1262c2b38a27e6bfc3b1db457c/Icons/Audio.png -------------------------------------------------------------------------------- /Icons/Audio.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9d64dbacfd38564a8db3b6a1eba221a 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 13 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 1 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: iPhone 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | - serializedVersion: 3 110 | buildTarget: Android 111 | maxTextureSize: 2048 112 | resizeAlgorithm: 0 113 | textureFormat: -1 114 | textureCompression: 1 115 | compressionQuality: 50 116 | crunchedCompression: 0 117 | allowsAlphaSplitting: 0 118 | overridden: 0 119 | ignorePlatformSupport: 0 120 | androidETC2FallbackOverride: 0 121 | forceMaximumCompressionQuality_BC6H_BC7: 0 122 | spriteSheet: 123 | serializedVersion: 2 124 | sprites: [] 125 | outline: [] 126 | physicsShape: [] 127 | bones: [] 128 | spriteID: 5e97eb03825dee720800000000000000 129 | internalID: 0 130 | vertices: [] 131 | indices: 132 | edges: [] 133 | weights: [] 134 | secondaryTextures: [] 135 | nameFileIdTable: {} 136 | mipmapLimitGroupName: 137 | pSDRemoveMatte: 0 138 | userData: 139 | assetBundleName: 140 | assetBundleVariant: 141 | -------------------------------------------------------------------------------- /Icons/BehaviourTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MorizeroDev/Minity/4e0559c1b5ebeb1262c2b38a27e6bfc3b1db457c/Icons/BehaviourTree.png -------------------------------------------------------------------------------- /Icons/BehaviourTree.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6750889bcf23384584b9c2f7c1983e6 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 13 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 1 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: iPhone 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | - serializedVersion: 3 110 | buildTarget: Android 111 | maxTextureSize: 2048 112 | resizeAlgorithm: 0 113 | textureFormat: -1 114 | textureCompression: 1 115 | compressionQuality: 50 116 | crunchedCompression: 0 117 | allowsAlphaSplitting: 0 118 | overridden: 0 119 | ignorePlatformSupport: 0 120 | androidETC2FallbackOverride: 0 121 | forceMaximumCompressionQuality_BC6H_BC7: 0 122 | spriteSheet: 123 | serializedVersion: 2 124 | sprites: [] 125 | outline: [] 126 | physicsShape: [] 127 | bones: [] 128 | spriteID: 5e97eb03825dee720800000000000000 129 | internalID: 0 130 | vertices: [] 131 | indices: 132 | edges: [] 133 | weights: [] 134 | secondaryTextures: [] 135 | nameFileIdTable: {} 136 | mipmapLimitGroupName: 137 | pSDRemoveMatte: 0 138 | userData: 139 | assetBundleName: 140 | assetBundleVariant: 141 | -------------------------------------------------------------------------------- /Icons/RecyclableObject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MorizeroDev/Minity/4e0559c1b5ebeb1262c2b38a27e6bfc3b1db457c/Icons/RecyclableObject.png -------------------------------------------------------------------------------- /Icons/RecyclableObject.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 079ec8372b6cccf44a6fc79d5efb6323 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 13 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 1 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 128 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: iPhone 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | - serializedVersion: 3 110 | buildTarget: Android 111 | maxTextureSize: 2048 112 | resizeAlgorithm: 0 113 | textureFormat: -1 114 | textureCompression: 1 115 | compressionQuality: 50 116 | crunchedCompression: 0 117 | allowsAlphaSplitting: 0 118 | overridden: 0 119 | ignorePlatformSupport: 0 120 | androidETC2FallbackOverride: 0 121 | forceMaximumCompressionQuality_BC6H_BC7: 0 122 | spriteSheet: 123 | serializedVersion: 2 124 | sprites: [] 125 | outline: [] 126 | physicsShape: [] 127 | bones: [] 128 | spriteID: 5e97eb03825dee720800000000000000 129 | internalID: 0 130 | vertices: [] 131 | indices: 132 | edges: [] 133 | weights: [] 134 | secondaryTextures: [] 135 | nameFileIdTable: {} 136 | mipmapLimitGroupName: 137 | pSDRemoveMatte: 0 138 | userData: 139 | assetBundleName: 140 | assetBundleVariant: 141 | -------------------------------------------------------------------------------- /Icons/UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MorizeroDev/Minity/4e0559c1b5ebeb1262c2b38a27e6bfc3b1db457c/Icons/UI.png -------------------------------------------------------------------------------- /Icons/UI.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3b6c38d8557f8e4d8a58d413f09c94d 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 13 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 1 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: Standalone 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: iPhone 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | - serializedVersion: 3 110 | buildTarget: Android 111 | maxTextureSize: 2048 112 | resizeAlgorithm: 0 113 | textureFormat: -1 114 | textureCompression: 1 115 | compressionQuality: 50 116 | crunchedCompression: 0 117 | allowsAlphaSplitting: 0 118 | overridden: 0 119 | ignorePlatformSupport: 0 120 | androidETC2FallbackOverride: 0 121 | forceMaximumCompressionQuality_BC6H_BC7: 0 122 | spriteSheet: 123 | serializedVersion: 2 124 | sprites: [] 125 | outline: [] 126 | physicsShape: [] 127 | bones: [] 128 | spriteID: 5e97eb03825dee720800000000000000 129 | internalID: 0 130 | vertices: [] 131 | indices: 132 | edges: [] 133 | weights: [] 134 | secondaryTextures: [] 135 | nameFileIdTable: {} 136 | mipmapLimitGroupName: 137 | pSDRemoveMatte: 0 138 | userData: 139 | assetBundleName: 140 | assetBundleVariant: 141 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dfaa89ddb2cc7af4faa8ea3858d1f12e 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minity 2 | 3 | **Mi**lthm u**nity** framework, a Unity extension framework that includes features such as object pooling, scene routing, UI manager, and behavior trees. 4 | 5 | ## **Setup** 6 | 7 | Unity Editor -> Package Manger -> Add package from git URL... 8 | 9 | ``` 10 | # Minity Core 11 | https://github.com/MorizeroDev/Minity.git 12 | 13 | # Milease Core 14 | https://github.com/MorizeroDev/Milease.git 15 | 16 | # Color Tools 17 | https://github.com/ParaParty/ParaPartyUtil.git?path=Colors 18 | ``` 19 | 20 | Or including these in `manifest.json`: 21 | 22 | ``` 23 | "dev.milthm.minity": "https://github.com/MorizeroDev/Minity.git", 24 | "com.morizero.milease": "https://github.com/MorizeroDev/Milease.git", 25 | "party.para.util.colors": "https://github.com/ParaParty/ParaPartyUtil.git?path=Colors", 26 | ``` 27 | 28 | ## **Resource Mapping by Enum Values** 29 | 30 | Using enum values as identifiers for various resources enhances the maintainability of your project. For instance, when you're working with scene routing or object pooling, you can associate enum values with specific resources during the initialization phase, and later reference these resources by using the enum values. 31 | 32 | Additionally, Minity does not rely on the integer data of enum values. Even if you have two enums with identical integer values, Minity can still differentiate between them. 33 | 34 | ## **Object Pool** 35 | 36 | Minity provides features like object pooling and automatic returning. Object pools are commonly used in Unity development to reduce the overhead of frequent creation and destruction of game objects, thus improving performance. 37 | 38 | 39 | Minity will also batch return any excess objects created during peak usage based on the current usage situation. 40 | 41 | First, you need to attach the `PoolableObject` component to the prefab of the object type you want to pool, and configure its parameters. 42 | 43 | For example, you can set the objects to automatically return to the pool after being active for a certain period, or wait for manual recycling. 44 | 45 | Next, use the following method to register a poolable object prefab and define the lifecycle of the created objects: 46 | ```csharp 47 | ObjectPool.EnsurePrefabRegistered(EnumValue, Prefab, BaseCount); 48 | ``` 49 | 50 | To retrieve an object managed by the object pool, use the following method: 51 | ```csharp 52 | ObjectPool.Request(EnumValue); 53 | ``` 54 | 55 | ## **Scene Router** 56 | 57 | Have you encountered a situation during game development where you need to return to a previous scene, but due to a special game process, an intermediary scene is inserted between two scenes that originally had a parent-child relationship? This might break the "back" functionality, preventing it from returning properly to the previous scene. Alternatively, manually specifying the scene name for the return can be problematic if you need to change a scene’s name later on, and you realize that it's referenced by strings all over your project, making refactoring a complex task. 58 | 59 | The scene router was created to solve these issues. It also wraps loading animations, making it easier to use them during scene transitions. 60 | 61 | First, we need to configure the scene router: 62 | 63 | ```csharp 64 | private enum SceneIdentifier 65 | { 66 | TitleScreen, MainMenu, StoryMenu, Story 67 | } 68 | 69 | [RuntimeInitializeOnLoadMethod] 70 | public static void SetupSceneRouter() 71 | { 72 | SceneRouter.Setup(new SceneRouterConfig() 73 | { 74 | SceneNodes = new[] 75 | { 76 | SceneRouter.Root(SceneIdentifier.TitleScreen, "Title"), 77 | SceneRouter.Node(SceneIdentifier.MainMenu, "main", "Main"), 78 | SceneRouter.Node(SceneIdentifier.StoryMenu, "main/storymenu", "StoryMenu"), 79 | SceneRouter.Node(SceneIdentifier.Story, "main/storymenu/story", "Story") 80 | } 81 | }); 82 | } 83 | ``` 84 | This way, if you need to jump from `StoryMenu` to something like `CGScreen`, and then to `Story` due to a special game process, the `Story` scene will correctly return to its parent `StoryMenu`. 85 | 86 | Use the following method to switch scenes: 87 | ```csharp 88 | SceneRouter.GoTo(SceneIdentifier.MainMenu); 89 | ``` 90 | 91 | To quickly return to the previous scene, use: 92 | ```csharp 93 | SceneRouter.Back(); 94 | ``` 95 | 96 | Both methods will return a `SceneRouterContext`, which allows you to pass data between scenes using a fluent interface: 97 | ```csharp 98 | SceneRouter.GoTo(SceneIdentifier.MainMenu).Parameters(data); 99 | ``` 100 | 101 | You can retrieve the data in another scene like this: 102 | ```csharp 103 | SceneRouter.FetchParameters(); 104 | ``` 105 | 106 | ## **UI Manager** 107 | 108 | Quickly build easy-to-use, managed UIs by implementing abstract classes `ManagedUIReturnValueOnly`, `ManagedUI`, and `ManagedUI`. 109 | 110 | In the design of Minity, we consider that each UI can have "parameters" and "return values", and the results returned by the "UI" are passed to subsequent processing functions via callbacks. Of course, we also provide asynchronous functions for your choice. 111 | 112 | For generic parameters: 113 | 114 | - `T`: A Type ID for the UI. Generally, you should specify this as the specific derived class. 115 | - `P`: The Parameter type for the UI. 116 | - `R`: The Return Value type for the UI. 117 | 118 | Let's assume we have an `InputBox`, which pops up a window for the player to enter a name, then returns the entered name. 119 | 120 | We can use it like this: 121 | 122 | ```c# 123 | public class InputBox : ManagedUI {} 124 | ``` 125 | 126 | If you feel that using just `string` isn't intuitive enough, you can further encapsulate it: 127 | 128 | ```c# 129 | public class InputBoxRequest { 130 | public string Title; 131 | public string Prompt; 132 | } 133 | 134 | public class InputBoxResponse { 135 | public string PlayerName; 136 | } 137 | 138 | public class InputBox : ManagedUI {} 139 | ``` 140 | 141 | Next, we need to bind it with the prefab at the point of initializing the UI manager: 142 | 143 | ```c# 144 | [RuntimeInitializeOnLoadMethod] 145 | public static void SetupUI() 146 | { 147 | UIManager.Setup(new [] 148 | { 149 | // Both methods are acceptable 150 | UI.FromPrefab(prefab), 151 | UI.FromResources("path/to/your/prefab"), 152 | }); 153 | } 154 | ``` 155 | 156 | Now, we can use the UI directly through any of the following methods: 157 | 158 | ```c# 159 | InputBox.Open("Please enter your name", (name) => Debug.Log($"The player name is {name}")); 160 | 161 | var playerName = await InputBox.OpenAsync("Please enter your name"); 162 | ``` 163 | 164 | ## **Binding View** 165 | 166 | The **Binding View** provides the functionality to bind `TextMeshPro` text components to data. For example, you can create a class `DemoBindingView` that inherits from the abstract class `BindingView`. 167 | 168 | We use `Binding` to declare data with binding functionality. 169 | 170 | ```c# 171 | public class DemoBindingView : BindingView 172 | { 173 | // Specify Format Culture 174 | protected override CultureInfo Formatter { get; } = CultureInfo.CurrentCulture; 175 | 176 | private Binding time; 177 | private Binding userName; 178 | private Binding score; 179 | 180 | // Custom Data Formatter 181 | private Binding date = new((v) => v.ToShortDateString()); 182 | 183 | protected override void Initialize() 184 | { 185 | score.Value = 100.23333f; 186 | userName.Value = "Buger404"; 187 | time.Value = DateTime.Now; 188 | date.Value = DateTime.Now; 189 | } 190 | 191 | public void MakeSomeChanges() 192 | { 193 | score.Value = Random.Range(0f, 100f); 194 | time.Value = DateTime.Now; 195 | date.Value = DateTime.Now; 196 | 197 | // Apply operations to all text components bound to the score data 198 | score.Do((t) => t.color = Color.red); 199 | } 200 | } 201 | ``` 202 | 203 | Next, attach this component to your Canvas, and you can freely use the declared data within that Canvas. Whenever the data changes, the text will automatically update. 204 | 205 | > **Note:** If a text component is bound to multiple data fields, modifying multiple data fields simultaneously will not cause multiple updates. Instead, changes are batched and processed at the end of the frame. Similarly, making multiple modifications to the same data field within a frame will not cause redundant updates. (In other words, while updates have a slight delay, there are no visual issues.) 206 | 207 | You can set your text content to something like: 208 | 209 | ``` 210 | Hello, I am {{ userName }}, the current time is {{ time:HH:mm:ss }}, and my current score is: {{ score:F2 }} 211 | ``` 212 | 213 | After initialization, the text will dynamically update to: 214 | 215 | ``` 216 | Hello, I am Buger404, the current time is 11:45:14, and my current score is: 100.233 217 | ``` 218 | 219 | The format for binding data is: `{{ FieldName:FormatString }}`, where the format string is optional. For instance, `{{ time:HH:mm:ss }}` is equivalent to: 220 | 221 | ```c# 222 | yourTextComponent.text = time.ToString("HH:mm:ss"); 223 | ``` 224 | 225 | Additionally, you do not need to manually instantiate empty `Binding` instances. They will be automatically managed by Minity. 226 | 227 | ## **Custom Loading Animations** 228 | 229 | You can create custom loading animations by extending `LoadingAnimator` and assigning it to the scene router. 230 | 231 | For example, here’s a default black fade transition that uses `Milease`, a lightweight animation library designed for Unity UI development: 232 | 233 | ```csharp 234 | public class BlackFade : LoadingAnimator 235 | { 236 | public Image Panel; 237 | 238 | public override void AboutToLoad() 239 | { 240 | MilInstantAnimator.Start( 241 | 0.5f / Panel.MQuad(x => x.color, Color.clear, Color.black) 242 | ) 243 | .Then( 244 | new Action(ReadyToLoad).AsMileaseKeyEvent() 245 | ) 246 | .UsingResetMode(RuntimeAnimationPart.AnimationResetMode.ResetToInitialState) 247 | .PlayImmediately(); 248 | } 249 | 250 | public override void OnLoaded() 251 | { 252 | MilInstantAnimator.Start( 253 | 0.5f / Panel.MQuad(x => x.color, Color.black, Color.clear) 254 | ) 255 | .Then( 256 | new Action(FinishLoading).AsMileaseKeyEvent() 257 | ) 258 | .UsingResetMode(RuntimeAnimationPart.AnimationResetMode.ResetToInitialState) 259 | .PlayImmediately(); 260 | } 261 | } 262 | ``` 263 | In `AboutToLoad()`, you need to cover the screen with the animation and call `ReadyToLoad()` at the end of the animation to notify the scene router to begin loading. 264 | 265 | During loading, you can get the loading progress via the `base.Progress` property to update the screen. 266 | 267 | Once the scene is fully loaded, the router will call `OnLoaded()`, where you should play the closing animation and call `FinishLoading()` to inform the router that everything is complete. 268 | 269 | You can then associate these loading animation prefabs with enum values in the scene router configuration and use them during scene transitions. 270 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4c301d4fd9a66b74282e58688d6dead0 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aee012120b71ddd43bafa7066b851992 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Resources/BlackFade.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &3243085547551554605 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 7668615909034629943} 12 | - component: {fileID: 3152847446343604557} 13 | - component: {fileID: 5730729626844867679} 14 | m_Layer: 5 15 | m_Name: Panel 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!224 &7668615909034629943 22 | RectTransform: 23 | m_ObjectHideFlags: 0 24 | m_CorrespondingSourceObject: {fileID: 0} 25 | m_PrefabInstance: {fileID: 0} 26 | m_PrefabAsset: {fileID: 0} 27 | m_GameObject: {fileID: 3243085547551554605} 28 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 29 | m_LocalPosition: {x: 0, y: 0, z: 0} 30 | m_LocalScale: {x: 1, y: 1, z: 1} 31 | m_ConstrainProportionsScale: 0 32 | m_Children: [] 33 | m_Father: {fileID: 404787983952973704} 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | m_AnchorMin: {x: 0, y: 0} 36 | m_AnchorMax: {x: 1, y: 1} 37 | m_AnchoredPosition: {x: 0, y: 0} 38 | m_SizeDelta: {x: 0, y: 0} 39 | m_Pivot: {x: 0.5, y: 0.5} 40 | --- !u!222 &3152847446343604557 41 | CanvasRenderer: 42 | m_ObjectHideFlags: 0 43 | m_CorrespondingSourceObject: {fileID: 0} 44 | m_PrefabInstance: {fileID: 0} 45 | m_PrefabAsset: {fileID: 0} 46 | m_GameObject: {fileID: 3243085547551554605} 47 | m_CullTransparentMesh: 1 48 | --- !u!114 &5730729626844867679 49 | MonoBehaviour: 50 | m_ObjectHideFlags: 0 51 | m_CorrespondingSourceObject: {fileID: 0} 52 | m_PrefabInstance: {fileID: 0} 53 | m_PrefabAsset: {fileID: 0} 54 | m_GameObject: {fileID: 3243085547551554605} 55 | m_Enabled: 1 56 | m_EditorHideFlags: 0 57 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 58 | m_Name: 59 | m_EditorClassIdentifier: 60 | m_Material: {fileID: 0} 61 | m_Color: {r: 0, g: 0, b: 0, a: 1} 62 | m_RaycastTarget: 1 63 | m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} 64 | m_Maskable: 1 65 | m_OnCullStateChanged: 66 | m_PersistentCalls: 67 | m_Calls: [] 68 | m_Sprite: {fileID: 0} 69 | m_Type: 1 70 | m_PreserveAspect: 0 71 | m_FillCenter: 1 72 | m_FillMethod: 4 73 | m_FillAmount: 1 74 | m_FillClockwise: 1 75 | m_FillOrigin: 0 76 | m_UseSpriteMesh: 0 77 | m_PixelsPerUnitMultiplier: 1 78 | --- !u!1 &7193528060274215022 79 | GameObject: 80 | m_ObjectHideFlags: 0 81 | m_CorrespondingSourceObject: {fileID: 0} 82 | m_PrefabInstance: {fileID: 0} 83 | m_PrefabAsset: {fileID: 0} 84 | serializedVersion: 6 85 | m_Component: 86 | - component: {fileID: 404787983952973704} 87 | - component: {fileID: 2239229030367825156} 88 | - component: {fileID: 1801002314718224328} 89 | - component: {fileID: 3300831641929415027} 90 | - component: {fileID: 2528767357373036278} 91 | m_Layer: 5 92 | m_Name: BlackFade 93 | m_TagString: Untagged 94 | m_Icon: {fileID: 0} 95 | m_NavMeshLayer: 0 96 | m_StaticEditorFlags: 0 97 | m_IsActive: 1 98 | --- !u!224 &404787983952973704 99 | RectTransform: 100 | m_ObjectHideFlags: 0 101 | m_CorrespondingSourceObject: {fileID: 0} 102 | m_PrefabInstance: {fileID: 0} 103 | m_PrefabAsset: {fileID: 0} 104 | m_GameObject: {fileID: 7193528060274215022} 105 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 106 | m_LocalPosition: {x: 0, y: 0, z: 0} 107 | m_LocalScale: {x: 0, y: 0, z: 0} 108 | m_ConstrainProportionsScale: 0 109 | m_Children: 110 | - {fileID: 7668615909034629943} 111 | m_Father: {fileID: 0} 112 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 113 | m_AnchorMin: {x: 0, y: 0} 114 | m_AnchorMax: {x: 0, y: 0} 115 | m_AnchoredPosition: {x: 0, y: 0} 116 | m_SizeDelta: {x: 0, y: 0} 117 | m_Pivot: {x: 0, y: 0} 118 | --- !u!223 &2239229030367825156 119 | Canvas: 120 | m_ObjectHideFlags: 0 121 | m_CorrespondingSourceObject: {fileID: 0} 122 | m_PrefabInstance: {fileID: 0} 123 | m_PrefabAsset: {fileID: 0} 124 | m_GameObject: {fileID: 7193528060274215022} 125 | m_Enabled: 1 126 | serializedVersion: 3 127 | m_RenderMode: 0 128 | m_Camera: {fileID: 0} 129 | m_PlaneDistance: 100 130 | m_PixelPerfect: 0 131 | m_ReceivesEvents: 1 132 | m_OverrideSorting: 0 133 | m_OverridePixelPerfect: 0 134 | m_SortingBucketNormalizedSize: 0 135 | m_VertexColorAlwaysGammaSpace: 0 136 | m_AdditionalShaderChannelsFlag: 0 137 | m_UpdateRectTransformForStandalone: 0 138 | m_SortingLayerID: 0 139 | m_SortingOrder: 32767 140 | m_TargetDisplay: 0 141 | --- !u!114 &1801002314718224328 142 | MonoBehaviour: 143 | m_ObjectHideFlags: 0 144 | m_CorrespondingSourceObject: {fileID: 0} 145 | m_PrefabInstance: {fileID: 0} 146 | m_PrefabAsset: {fileID: 0} 147 | m_GameObject: {fileID: 7193528060274215022} 148 | m_Enabled: 1 149 | m_EditorHideFlags: 0 150 | m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} 151 | m_Name: 152 | m_EditorClassIdentifier: 153 | m_UiScaleMode: 1 154 | m_ReferencePixelsPerUnit: 100 155 | m_ScaleFactor: 1 156 | m_ReferenceResolution: {x: 1920, y: 1080} 157 | m_ScreenMatchMode: 0 158 | m_MatchWidthOrHeight: 0 159 | m_PhysicalUnit: 3 160 | m_FallbackScreenDPI: 96 161 | m_DefaultSpriteDPI: 96 162 | m_DynamicPixelsPerUnit: 1 163 | m_PresetInfoIsWorld: 0 164 | --- !u!114 &3300831641929415027 165 | MonoBehaviour: 166 | m_ObjectHideFlags: 0 167 | m_CorrespondingSourceObject: {fileID: 0} 168 | m_PrefabInstance: {fileID: 0} 169 | m_PrefabAsset: {fileID: 0} 170 | m_GameObject: {fileID: 7193528060274215022} 171 | m_Enabled: 1 172 | m_EditorHideFlags: 0 173 | m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} 174 | m_Name: 175 | m_EditorClassIdentifier: 176 | m_IgnoreReversedGraphics: 1 177 | m_BlockingObjects: 0 178 | m_BlockingMask: 179 | serializedVersion: 2 180 | m_Bits: 4294967295 181 | --- !u!114 &2528767357373036278 182 | MonoBehaviour: 183 | m_ObjectHideFlags: 0 184 | m_CorrespondingSourceObject: {fileID: 0} 185 | m_PrefabInstance: {fileID: 0} 186 | m_PrefabAsset: {fileID: 0} 187 | m_GameObject: {fileID: 7193528060274215022} 188 | m_Enabled: 1 189 | m_EditorHideFlags: 0 190 | m_Script: {fileID: 11500000, guid: 7be2054d782a73d47b7b5b7c5fc6cdd7, type: 3} 191 | m_Name: 192 | m_EditorClassIdentifier: 193 | Panel: {fileID: 5730729626844867679} 194 | -------------------------------------------------------------------------------- /Resources/BlackFade.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a0b867d5544ba0647a02f658a0688143 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c5e98b6c350978d409f5647b2a0676b2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 315e64eec8e2d6a409548dd509e2e51e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bce875aa8b0c43828a7d9d3a196c34d6 3 | timeCreated: 1729491282 -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Minity.Logger; 4 | using Minity.General; 5 | using UnityEngine; 6 | 7 | namespace Minity.Audio 8 | { 9 | public class AudioManager 10 | { 11 | internal static readonly Dictionary ResourcesList = new Dictionary(); 12 | internal static bool Enabled = false; 13 | internal static AudioPlayer Player; 14 | 15 | public static void Setup(string resPath) 16 | { 17 | if (Enabled) 18 | { 19 | DebugLog.LogError("Duplicated audio manager initialization."); 20 | return; 21 | } 22 | 23 | var collection = Resources.LoadAll(resPath); 24 | foreach (var list in collection) 25 | { 26 | list.SetupDictionary(ResourcesList); 27 | } 28 | 29 | var go = new GameObject("[Audio Manager]", typeof(AudioPlayer)); 30 | go.SetActive(true); 31 | Player = go.GetComponent(); 32 | 33 | Enabled = true; 34 | } 35 | 36 | public static void SetBGM(T audio, bool transition = true, float startPosition = 0f) where T : Enum 37 | => SetAudio(AudioPlayerType.BGMPlayer, audio, transition, startPosition); 38 | 39 | public static void SetBGS(T audio, bool transition = true, float startPosition = 0f) where T : Enum 40 | => SetAudio(AudioPlayerType.BGSPlayer, audio, transition, startPosition); 41 | 42 | public static void StopBGM(bool transition = true) 43 | => Player.SwitchClip(AudioPlayerType.BGMPlayer, null, transition, 0f); 44 | 45 | public static void StopBGS(bool transition = true) 46 | => Player.SwitchClip(AudioPlayerType.BGSPlayer, null, transition, 0f); 47 | 48 | public static float PlaySnd(T audio) where T : Enum 49 | { 50 | if (!Enabled) 51 | { 52 | DebugLog.LogError("The audio manager is not setup yet."); 53 | return 0f; 54 | } 55 | 56 | if (audio == null) 57 | { 58 | return 0f; 59 | } 60 | 61 | var key = EnumIdentifier.Wrap(audio); 62 | if (!ResourcesList.ContainsKey(key)) 63 | { 64 | DebugLog.LogError($"Specific audio resources '{key}' is not included in the setup."); 65 | return 0f; 66 | } 67 | 68 | var clip = ResourcesList[key]; 69 | Player.PlaySnd(clip); 70 | 71 | return clip.length; 72 | } 73 | 74 | public static float GetVolume(AudioPlayerType type) 75 | { 76 | if (!Enabled) 77 | { 78 | DebugLog.LogError("The audio manager is not setup yet."); 79 | return 0f; 80 | } 81 | 82 | return Player.GetVolume(type); 83 | } 84 | 85 | public static void SetVolume(AudioPlayerType type, float volume) 86 | { 87 | if (!Enabled) 88 | { 89 | DebugLog.LogError("The audio manager is not setup yet."); 90 | return; 91 | } 92 | 93 | Player.SetVolume(type, volume); 94 | } 95 | 96 | internal static void SetAudio(AudioPlayerType type, T audio, bool transition = true, float startPosition = 0f) where T : Enum 97 | { 98 | if (!Enabled) 99 | { 100 | DebugLog.LogError("The audio manager is not setup yet."); 101 | return; 102 | } 103 | 104 | if (audio == null) 105 | { 106 | Player.SwitchClip(type, null, transition, startPosition); 107 | return; 108 | } 109 | 110 | var key = EnumIdentifier.Wrap(audio); 111 | if (!ResourcesList.ContainsKey(key)) 112 | { 113 | DebugLog.LogError($"Specific audio resources '{key}' is not included in the setup."); 114 | return; 115 | } 116 | 117 | Player.SwitchClip(type, ResourcesList[key], transition, startPosition); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6b30a1efb6c643a6a8440b2fac185802 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: b9d64dbacfd38564a8db3b6a1eba221a, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioPlayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Milease.Core.Animator; 4 | using Milease.DSL; 5 | using Milease.Enums; 6 | using Milease.Utils; 7 | using UnityEngine; 8 | 9 | namespace Minity.Audio 10 | { 11 | public enum AudioPlayerType 12 | { 13 | BGMPlayer, BGSPlayer, SndPlayer 14 | } 15 | [AddComponentMenu("")] 16 | internal class AudioPlayer : MonoBehaviour 17 | { 18 | private class PlayerData 19 | { 20 | public AudioSource AudioSource; 21 | public AudioClip TargetClip; 22 | public float Volume; 23 | public readonly string VolumeKey; 24 | 25 | public PlayerData(AudioPlayerType type, AudioSource source, float defaultVolume) 26 | { 27 | VolumeKey = "Milutools.Audio.Volume." + type; 28 | Volume = PlayerPrefs.GetFloat(VolumeKey, defaultVolume); 29 | AudioSource = source; 30 | AudioSource.volume = Volume; 31 | } 32 | } 33 | 34 | private PlayerData[] players; 35 | 36 | private AudioSource GenerateAudioSource(bool loop) 37 | { 38 | var source = gameObject.AddComponent(); 39 | source.loop = loop; 40 | return source; 41 | } 42 | 43 | private void Awake() 44 | { 45 | DontDestroyOnLoad(gameObject); 46 | 47 | var list = new List 48 | { 49 | new PlayerData(AudioPlayerType.BGMPlayer, GenerateAudioSource(true), 0.5f), 50 | new PlayerData(AudioPlayerType.BGSPlayer, GenerateAudioSource(true), 0.5f), 51 | new PlayerData(AudioPlayerType.SndPlayer, GenerateAudioSource(false), 1f) 52 | }; 53 | 54 | players = list.ToArray(); 55 | } 56 | 57 | internal float GetVolume(AudioPlayerType type) 58 | => players[(int)type].Volume; 59 | 60 | internal void SetVolume(AudioPlayerType type, float volume) 61 | { 62 | var player = players[(int)type]; 63 | player.Volume = volume; 64 | player.AudioSource.volume = volume; 65 | PlayerPrefs.SetFloat(player.VolumeKey, volume); 66 | } 67 | 68 | internal void SwitchClip(AudioPlayerType type, AudioClip clip, bool transition, float startPosition) 69 | { 70 | var player = players[(int)type]; 71 | if (transition) 72 | { 73 | if (!player.AudioSource.clip) 74 | { 75 | player.TargetClip = clip; 76 | player.AudioSource.clip = clip; 77 | player.AudioSource.Play(); 78 | player.AudioSource.time = startPosition; 79 | player.AudioSource.MQuadOut(x => x.volume, 1f / 0f.To(player.Volume)) 80 | .PlayImmediately(); 81 | } 82 | else 83 | { 84 | player.TargetClip = clip; 85 | player.AudioSource.MQuadOut(x => x.volume, 1f / 0f.ToThis()) 86 | .Then(new Action(() => 87 | { 88 | player.AudioSource.clip = player.TargetClip; 89 | player.AudioSource.Play(); 90 | player.AudioSource.time = startPosition; 91 | }).AsMileaseKeyEvent()) 92 | .Then( 93 | player.AudioSource.MQuadOut(x => x.volume, 1f / 0f.To(player.Volume)) 94 | ).PlayImmediately(); 95 | } 96 | } 97 | else 98 | { 99 | player.TargetClip = clip; 100 | player.AudioSource.clip = clip; 101 | player.AudioSource.Play(); 102 | player.AudioSource.time = startPosition; 103 | } 104 | } 105 | 106 | internal void PlaySnd(AudioClip clip) 107 | => players[(int)AudioPlayerType.SndPlayer].AudioSource.PlayOneShot(clip); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioPlayer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: de83dd247c674ac3950473d7e00489f8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: b9d64dbacfd38564a8db3b6a1eba221a, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioPreset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | namespace Minity.Audio 7 | { 8 | public class AudioPreset : MonoBehaviour 9 | { 10 | public enum AudioBehaviour 11 | { 12 | Replace, Keep 13 | } 14 | 15 | [Serializable] 16 | public class PresetData 17 | { 18 | public AudioResources Resources; 19 | public AudioBehaviour Behaviour; 20 | public int ID; 21 | public float StartTime; 22 | } 23 | 24 | public PresetData BGM, BGS; 25 | 26 | private void Start() 27 | { 28 | if (BGM.Behaviour == AudioBehaviour.Replace && BGM.Resources) 29 | { 30 | AudioManager.Player.SwitchClip(AudioPlayerType.BGMPlayer, BGM.Resources.GetClip(BGM.ID), true, BGM.StartTime); 31 | } 32 | if (BGS.Behaviour == AudioBehaviour.Replace && BGS.Resources) 33 | { 34 | AudioManager.Player.SwitchClip(AudioPlayerType.BGSPlayer, BGS.Resources.GetClip(BGS.ID), true, BGS.StartTime); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioPreset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 75b3c02707f900846aa8e16659c8bda3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: b9d64dbacfd38564a8db3b6a1eba221a, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioResources.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Minity.Logger; 6 | using Minity.General; 7 | #if !NET_STANDARD_2_1 8 | using Paraparty.UnityPolyfill; 9 | #endif 10 | using UnityEngine; 11 | 12 | namespace Minity.Audio 13 | { 14 | public abstract class AudioResources : ScriptableObject 15 | { 16 | internal abstract void SetupDictionary(Dictionary dictionary); 17 | internal abstract AudioClip GetClip(int rawID); 18 | } 19 | public class AudioResources : AudioResources where T : Enum, IConvertible 20 | { 21 | [Serializable] 22 | public class AudioItem 23 | { 24 | [HideInInspector] 25 | public string Name; 26 | public T Identifier; 27 | public AudioClip Clip; 28 | 29 | [NonSerialized] 30 | internal T lstIdentifier; 31 | } 32 | 33 | [SerializeField] 34 | public List Items = new List(); 35 | 36 | private void OnEnable() 37 | { 38 | foreach (var item in Enum.GetValues(typeof(T))) 39 | { 40 | if (Items.Exists(x => x.Identifier.Equals(item))) 41 | { 42 | continue; 43 | } 44 | Items.Add(new AudioItem() 45 | { 46 | Identifier = (T)item, 47 | Name = item.ToString() 48 | }); 49 | } 50 | } 51 | 52 | private void OnValidate() 53 | { 54 | foreach (var item in Items) 55 | { 56 | if (!item.lstIdentifier.Equals(item.Identifier) || string.IsNullOrEmpty(item.Name)) 57 | { 58 | item.Name = item.Identifier.ToString(); 59 | item.lstIdentifier = item.Identifier; 60 | } 61 | } 62 | } 63 | 64 | internal override void SetupDictionary(Dictionary dictionary) 65 | { 66 | foreach (var item in Items) 67 | { 68 | var key = EnumIdentifier.Wrap(item.Identifier); 69 | if (!dictionary.TryAdd(key, item.Clip)) 70 | { 71 | DebugLog.LogError($"Specific audio resources '{key}' is duplicated."); 72 | } 73 | } 74 | } 75 | 76 | internal override AudioClip GetClip(int rawID) 77 | => Items.FirstOrDefault(x => (int)(object)x.Identifier == rawID)?.Clip; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/AudioResources.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca6e51121a9f48348cab423c6d5360e0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: b9d64dbacfd38564a8db3b6a1eba221a, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 83e53b3664e04f919311a6fdcb6af64d 3 | timeCreated: 1729687590 -------------------------------------------------------------------------------- /Scripts/Minity/Audio/Editor/AudioPresetEditor.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | namespace Minity.Audio.Editor 7 | { 8 | [CustomEditor(typeof(AudioPreset))] 9 | public class AudioPresetEditor : UnityEditor.Editor 10 | { 11 | private void DrawInspector(string title, AudioPreset.PresetData data) 12 | { 13 | EditorGUILayout.LabelField(title); 14 | EditorGUI.indentLevel++; 15 | data.Behaviour = (AudioPreset.AudioBehaviour)EditorGUILayout.EnumPopup("Behaviour", data.Behaviour); 16 | if (data.Behaviour == AudioPreset.AudioBehaviour.Replace) 17 | { 18 | var resources = (AudioResources) 19 | EditorGUILayout.ObjectField("Resources", data.Resources, typeof(AudioResources), true); 20 | if (resources != data.Resources) 21 | { 22 | data.Resources = resources; 23 | data.StartTime = 0f; 24 | data.ID = -1; 25 | } 26 | if (!data.Resources) 27 | { 28 | goto end; 29 | } 30 | 31 | var type = data.Resources.GetType(); 32 | while (type != null && type.BaseType != null) 33 | { 34 | if (type.IsGenericType && type.BaseType == typeof(AudioResources)) 35 | { 36 | break; 37 | } 38 | type = type.BaseType; 39 | } 40 | 41 | var enumType = type.GetGenericArguments()[0]; 42 | var id = (int)(object)EditorGUILayout.EnumPopup("ID", (Enum)Enum.ToObject(enumType, data.ID)); 43 | if (id != data.ID) 44 | { 45 | data.ID = id; 46 | data.StartTime = 0f; 47 | } 48 | 49 | var clip = resources.GetClip(id); 50 | if (!clip) 51 | { 52 | EditorGUILayout.LabelField("⚠ Specific ID links to no audio."); 53 | } 54 | } 55 | 56 | end: 57 | EditorGUI.indentLevel--; 58 | } 59 | public override void OnInspectorGUI() 60 | { 61 | var preset = (AudioPreset)target; 62 | DrawInspector("BGM", preset.BGM); 63 | DrawInspector("BGS", preset.BGS); 64 | } 65 | } 66 | } 67 | #endif 68 | -------------------------------------------------------------------------------- /Scripts/Minity/Audio/Editor/AudioPresetEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c571ab2eb2bc4a2f909efa68a556bce8 3 | timeCreated: 1729687696 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4de3dc31ff5e44f4be1babe476efb38c 3 | timeCreated: 1730189149 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/BehaviourContext.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Minity.Behaviour 4 | { 5 | public abstract class BehaviourContext : MonoBehaviour 6 | { 7 | public BehaviourTree Tree { get; internal set; } 8 | 9 | public abstract void UpdateContext(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/BehaviourContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 292a28dd76bd4d568f72cfcb852be7b4 3 | timeCreated: 1730189219 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/BehaviourState.cs: -------------------------------------------------------------------------------- 1 | namespace Minity.Behaviour 2 | { 3 | public delegate BehaviourState BehaviourFunction(T context); 4 | public enum BehaviourState 5 | { 6 | Succeed, Failed, Running 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/BehaviourState.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ebddddd3a8948a5a1cb31b0bda57248 3 | timeCreated: 1730192305 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/BehaviourTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Minity.Behaviour.Nodes; 4 | using Minity.Logger; 5 | using UnityEngine; 6 | 7 | namespace Minity.Behaviour 8 | { 9 | public abstract class BehaviourTree : MonoBehaviour 10 | { 11 | public IBehaviourNode CurrentRunningNode { get; internal set; } 12 | 13 | public enum UpdateMethods 14 | { 15 | OnUpdate, OnFixedUpdate 16 | } 17 | 18 | public UpdateMethods UpdateMethod = UpdateMethods.OnFixedUpdate; 19 | } 20 | 21 | public abstract class BehaviourTree : BehaviourTree where T : BehaviourContext 22 | { 23 | #region Exposed API 24 | 25 | public abstract IBehaviourNode Build(T context); 26 | 27 | protected static IBehaviourNode Sequence(params IBehaviourNode[] children) 28 | => new SequenceNode(children); 29 | 30 | protected static IBehaviourNode Selector(params IBehaviourNode[] children) 31 | => new SelectorNode(children); 32 | 33 | protected static IBehaviourNode Condition(Predicate condition, IBehaviourNode child = null) 34 | => new ConditionNode(child) { Handler = condition }; 35 | 36 | protected static IBehaviourNode Repeater(Predicate condition, IBehaviourNode child) 37 | => new RepeaterNode(child) { Condition = condition }; 38 | 39 | protected static IBehaviourNode Repeater(int repeatCount, IBehaviourNode child) 40 | => new RepeaterNode(child) { RepeatCount = repeatCount }; 41 | 42 | protected static IBehaviourNode Inverter(IBehaviourNode child) 43 | => new InverterNode(child); 44 | 45 | protected static IBehaviourNode Action(BehaviourFunction action) 46 | => new ActionNode() { Handler = action }; 47 | 48 | protected static IBehaviourNode Wait(float time) 49 | => new WaitNode() { Time = time }; 50 | 51 | #endregion 52 | 53 | #region Logic 54 | 55 | private IBehaviourNode RootNode; 56 | 57 | public BehaviourContext Context; 58 | 59 | public bool RunOnAwake = true; 60 | public bool Loop = true; 61 | 62 | public bool Running { get; private set; } 63 | 64 | public event BehaviourFunction OnFinished; 65 | 66 | private bool stopped = false; 67 | 68 | private void Awake() 69 | { 70 | if (!Context) 71 | { 72 | DebugLog.LogError("Context is not set."); 73 | } 74 | else 75 | { 76 | Context.Tree = this; 77 | } 78 | 79 | RootNode = Build((T)Context); 80 | if (RootNode == null) 81 | { 82 | DebugLog.LogError("Null behaviour tree, this is not allowed."); 83 | } 84 | 85 | if (RunOnAwake) 86 | { 87 | Running = true; 88 | } 89 | } 90 | 91 | public void Start() 92 | { 93 | Running = true; 94 | stopped = false; 95 | } 96 | 97 | public void Stop() 98 | { 99 | Running = false; 100 | stopped = true; 101 | } 102 | 103 | public void ResetTree() 104 | { 105 | RootNode.Reset(); 106 | } 107 | 108 | private void Finish() 109 | { 110 | Running = false; 111 | ResetTree(); 112 | OnFinished?.Invoke((T)Context); 113 | } 114 | 115 | private void UpdateTree() 116 | { 117 | if (!Running && (!Loop || stopped)) 118 | { 119 | return; 120 | } 121 | 122 | Context.UpdateContext(); 123 | if (CurrentRunningNode == null) 124 | { 125 | if (RootNode.Run(Context) != BehaviourState.Running) 126 | { 127 | Finish(); 128 | } 129 | } 130 | else 131 | { 132 | var state = CurrentRunningNode.Run(Context); 133 | if (state != BehaviourState.Running) 134 | { 135 | // Restore behaviour tree state 136 | var node = CurrentRunningNode; 137 | CurrentRunningNode = null; 138 | while (node.Previous != null) 139 | { 140 | node = node.Previous; 141 | state = node.Resume(Context, state); 142 | if (state == BehaviourState.Running) 143 | { 144 | return; 145 | } 146 | } 147 | 148 | Finish(); 149 | } 150 | } 151 | } 152 | 153 | private void Update() 154 | { 155 | if (UpdateMethod != UpdateMethods.OnUpdate) 156 | { 157 | return; 158 | } 159 | 160 | UpdateTree(); 161 | } 162 | 163 | private void FixedUpdate() 164 | { 165 | if (UpdateMethod != UpdateMethods.OnFixedUpdate) 166 | { 167 | return; 168 | } 169 | 170 | UpdateTree(); 171 | } 172 | 173 | #endregion 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/BehaviourTree.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d928f9b887246c2a0077ea5bebabe2e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: a6750889bcf23384584b9c2f7c1983e6, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f870b6281a2f457ba80a33859e5c6f39 3 | timeCreated: 1730190172 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/ActionNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Minity.Behaviour.Nodes 4 | { 5 | public class ActionNode : IBehaviourNode where T : BehaviourContext 6 | { 7 | internal BehaviourFunction Handler; 8 | IBehaviourNode IBehaviourNode.Previous { get; set; } 9 | BehaviourState IBehaviourNode.State { get; set; } 10 | 11 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 12 | { 13 | var state = Handler((T)context); 14 | if (state == BehaviourState.Running) 15 | { 16 | context.Tree.CurrentRunningNode = this; 17 | } 18 | 19 | return state; 20 | } 21 | 22 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | 27 | void IBehaviourNode.Reset() 28 | { 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/ActionNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5226338e3a84446ca346c2c03942a728 3 | timeCreated: 1730192043 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/ConditionNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Minity.Behaviour.Nodes 4 | { 5 | public class ConditionNode : IBehaviourNode where T : BehaviourContext 6 | { 7 | internal Predicate Handler; 8 | internal IBehaviourNode Node; 9 | IBehaviourNode IBehaviourNode.Previous { get; set; } 10 | BehaviourState IBehaviourNode.State { get; set; } 11 | 12 | internal ConditionNode(IBehaviourNode node) 13 | { 14 | Node = node; 15 | if (node != null) 16 | { 17 | node.Previous = this; 18 | } 19 | } 20 | 21 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 22 | { 23 | if (Handler((T)context)) 24 | { 25 | return Node?.Run(context) ?? BehaviourState.Succeed; 26 | } 27 | 28 | return BehaviourState.Failed; 29 | } 30 | 31 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 32 | { 33 | return innerState; 34 | } 35 | 36 | void IBehaviourNode.Reset() 37 | { 38 | Node?.Reset(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/ConditionNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf4bbb81cd284fbcb23ceaf5fc748d85 3 | timeCreated: 1730190514 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/IBehaviourNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Minity.Behaviour.Nodes 5 | { 6 | public interface IBehaviourNode 7 | { 8 | internal BehaviourState State { get; set; } 9 | internal IBehaviourNode Previous { get; set; } 10 | internal BehaviourState Run(BehaviourContext context); 11 | internal BehaviourState Resume(BehaviourContext context, BehaviourState innerState); 12 | internal void Reset(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/IBehaviourNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 20e3551ea68b4ea691808ef42dc1c0dc 3 | timeCreated: 1730189336 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/InverterNode.cs: -------------------------------------------------------------------------------- 1 | namespace Minity.Behaviour.Nodes 2 | { 3 | public class InverterNode : IBehaviourNode 4 | { 5 | internal IBehaviourNode Node; 6 | IBehaviourNode IBehaviourNode.Previous { get; set; } 7 | BehaviourState IBehaviourNode.State { get; set; } 8 | 9 | internal InverterNode(IBehaviourNode node) 10 | { 11 | Node = node; 12 | if (node != null) 13 | { 14 | node.Previous = this; 15 | } 16 | } 17 | 18 | BehaviourState InvertState(BehaviourState state) 19 | { 20 | return state switch 21 | { 22 | BehaviourState.Failed => BehaviourState.Succeed, 23 | BehaviourState.Succeed => BehaviourState.Failed, 24 | _ => state 25 | }; 26 | } 27 | 28 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 29 | { 30 | return InvertState(Node.Run(context)); 31 | } 32 | 33 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 34 | { 35 | return InvertState(innerState); 36 | } 37 | 38 | void IBehaviourNode.Reset() 39 | { 40 | Node.Reset(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/InverterNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c26ea409faa941ec8db808513193c136 3 | timeCreated: 1730191930 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/RepeaterNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Minity.Behaviour.Nodes 4 | { 5 | public class RepeaterNode : IBehaviourNode where T : BehaviourContext 6 | { 7 | internal int RepeatCount = -1; 8 | internal Predicate Condition; 9 | internal IBehaviourNode Node; 10 | IBehaviourNode IBehaviourNode.Previous { get; set; } 11 | BehaviourState IBehaviourNode.State { get; set; } 12 | 13 | private int count = 0; 14 | 15 | internal RepeaterNode(IBehaviourNode node) 16 | { 17 | Node = node; 18 | if (node != null) 19 | { 20 | node.Previous = this; 21 | } 22 | } 23 | 24 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 25 | { 26 | if (RepeatCount == -1) 27 | { 28 | while (!Condition((T)context)) 29 | { 30 | if (Node.Run(context) == BehaviourState.Running) 31 | { 32 | return BehaviourState.Running; 33 | } 34 | } 35 | } 36 | else 37 | { 38 | for (; count < RepeatCount; count++) 39 | { 40 | if (Node.Run(context) == BehaviourState.Running) 41 | { 42 | return BehaviourState.Running; 43 | } 44 | } 45 | } 46 | 47 | return BehaviourState.Succeed; 48 | } 49 | 50 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 51 | { 52 | count++; 53 | return ((IBehaviourNode)this).Run(context); 54 | } 55 | 56 | void IBehaviourNode.Reset() 57 | { 58 | count = 0; 59 | Node.Reset(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/RepeaterNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6d19218f159343a2b9dacf0894ac2fa1 3 | timeCreated: 1730191375 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/SelectorNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Minity.Behaviour.Nodes 5 | { 6 | public class SelectorNode : IBehaviourNode 7 | { 8 | internal List Nodes; 9 | IBehaviourNode IBehaviourNode.Previous { get; set; } 10 | BehaviourState IBehaviourNode.State { get; set; } 11 | 12 | private int index = 0; 13 | 14 | internal SelectorNode(IBehaviourNode[] nodes) 15 | { 16 | Nodes = nodes.ToList(); 17 | foreach (var node in Nodes) 18 | { 19 | node.Previous = this; 20 | } 21 | } 22 | 23 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 24 | { 25 | for (; index < Nodes.Count; index++) 26 | { 27 | var node = Nodes[index]; 28 | var state = node.Run(context); 29 | if (state == BehaviourState.Succeed) 30 | { 31 | return state; 32 | } 33 | if (state == BehaviourState.Running) 34 | { 35 | return state; 36 | } 37 | } 38 | return BehaviourState.Failed; 39 | } 40 | 41 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 42 | { 43 | if (innerState == BehaviourState.Succeed) 44 | { 45 | return innerState; 46 | } 47 | index++; 48 | return ((IBehaviourNode)this).Run(context); 49 | } 50 | 51 | void IBehaviourNode.Reset() 52 | { 53 | index = 0; 54 | foreach (var node in Nodes) 55 | { 56 | node.Reset(); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/SelectorNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 053ee99e50b84b0cbb83aff9bc0b910c 3 | timeCreated: 1730190438 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/SequenceNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Minity.Behaviour.Nodes 5 | { 6 | public class SequenceNode : IBehaviourNode 7 | { 8 | internal List Nodes; 9 | IBehaviourNode IBehaviourNode.Previous { get; set; } 10 | BehaviourState IBehaviourNode.State { get; set; } 11 | 12 | private int index = 0; 13 | 14 | internal SequenceNode(IBehaviourNode[] nodes) 15 | { 16 | Nodes = nodes.ToList(); 17 | foreach (var node in Nodes) 18 | { 19 | node.Previous = this; 20 | } 21 | } 22 | 23 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 24 | { 25 | for (; index < Nodes.Count; index++) 26 | { 27 | var node = Nodes[index]; 28 | var state = node.Run(context); 29 | if (state == BehaviourState.Failed) 30 | { 31 | return state; 32 | } 33 | if (state == BehaviourState.Running) 34 | { 35 | return state; 36 | } 37 | } 38 | return BehaviourState.Succeed; 39 | } 40 | 41 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 42 | { 43 | if (innerState == BehaviourState.Failed) 44 | { 45 | return innerState; 46 | } 47 | index++; 48 | return ((IBehaviourNode)this).Run(context); 49 | } 50 | 51 | void IBehaviourNode.Reset() 52 | { 53 | index = 0; 54 | foreach (var node in Nodes) 55 | { 56 | node.Reset(); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/SequenceNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: baab69d0a5794950af889b3dee2c3d30 3 | timeCreated: 1730190211 -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/WaitNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Behaviour.Nodes 5 | { 6 | public class WaitNode : IBehaviourNode 7 | { 8 | internal float Time = 0f; 9 | IBehaviourNode IBehaviourNode.Previous { get; set; } 10 | BehaviourState IBehaviourNode.State { get; set; } 11 | 12 | private float tick = 0f; 13 | 14 | BehaviourState IBehaviourNode.Run(BehaviourContext context) 15 | { 16 | tick += context.Tree.UpdateMethod == BehaviourTree.UpdateMethods.OnUpdate ? 17 | UnityEngine.Time.deltaTime : UnityEngine.Time.fixedDeltaTime; 18 | var finished = tick >= Time; 19 | if (!finished) 20 | { 21 | context.Tree.CurrentRunningNode = this; 22 | } 23 | return finished ? BehaviourState.Succeed : BehaviourState.Running; 24 | } 25 | 26 | BehaviourState IBehaviourNode.Resume(BehaviourContext context, BehaviourState innerState) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | 31 | void IBehaviourNode.Reset() 32 | { 33 | tick = 0f; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Scripts/Minity/Behaviour/Nodes/WaitNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 611085f6fa644b01a46408ef066014e7 3 | timeCreated: 1730204280 -------------------------------------------------------------------------------- /Scripts/Minity/General.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3c0fc785bdd4f3e9099838cf34d04a8 3 | timeCreated: 1728462360 -------------------------------------------------------------------------------- /Scripts/Minity/General/EnumIdentifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Minity.General 4 | { 5 | public struct EnumIdentifier 6 | { 7 | public int Value; 8 | public Type Type; 9 | 10 | public string Name { get; private set; } 11 | 12 | public static EnumIdentifier Wrap(T identifier) where T : Enum 13 | { 14 | return new EnumIdentifier() 15 | { 16 | Value = (int)(object)identifier, 17 | Type = typeof(T), 18 | Name = typeof(T).FullName + "." + identifier 19 | }; 20 | } 21 | 22 | public static EnumIdentifier WrapType(Type type, Enum identifier) 23 | { 24 | return new EnumIdentifier() 25 | { 26 | Value = (int)(object)identifier, 27 | Type = type, 28 | Name = type.FullName + "." + identifier 29 | }; 30 | } 31 | 32 | public static EnumIdentifier WrapReflection(Enum identifier) 33 | { 34 | var type = identifier.GetType(); 35 | return new EnumIdentifier() 36 | { 37 | Value = (int)(object)identifier, 38 | Type = type, 39 | Name = type.FullName + "." + identifier 40 | }; 41 | } 42 | 43 | public override string ToString() 44 | { 45 | return Name; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Scripts/Minity/General/EnumIdentifier.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f19620b450594db39b2d2d2983cb917e 3 | timeCreated: 1728462376 -------------------------------------------------------------------------------- /Scripts/Minity/Infra.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18ee36a55b184341b2b2d2a20bf4806f 3 | timeCreated: 1738229984 -------------------------------------------------------------------------------- /Scripts/Minity/Infra/GlobalSingleton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Minity.Infra 6 | { 7 | public abstract class GlobalSingleton : MonoBehaviour where T : MonoBehaviour 8 | { 9 | private static T _instance; 10 | 11 | public static T Instance 12 | { 13 | get 14 | { 15 | if (!_instance) 16 | { 17 | var go = new GameObject($"[{typeof(T).Name}]", typeof(T)); 18 | go.SetActive(true); 19 | DontDestroyOnLoad(go); 20 | _instance = go.GetComponent(); 21 | } 22 | 23 | return _instance; 24 | } 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Scripts/Minity/Infra/GlobalSingleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3efe01cc65045e1a14a51018c6a0da2 3 | timeCreated: 1738230021 -------------------------------------------------------------------------------- /Scripts/Minity/Infra/SceneSingleton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | #if !NET_STANDARD_2_1 4 | using Paraparty.UnityPolyfill; 5 | #endif 6 | using UnityEngine; 7 | using Object = UnityEngine.Object; 8 | 9 | namespace Minity.Infra 10 | { 11 | public class SceneSingleton : MonoBehaviour 12 | { 13 | private static readonly Dictionary instances = new Dictionary(); 14 | 15 | public static T Get() where T : Object 16 | { 17 | if (!instances.TryGetValue(typeof(T), out var instance)) 18 | { 19 | throw new Exception($"'{typeof(T).Name}' instance is not registered."); 20 | } 21 | 22 | if (!instance) 23 | { 24 | throw new Exception($"'{typeof(T).Name}' instance is destroyed."); 25 | } 26 | 27 | return (T)instance; 28 | } 29 | 30 | public static void Register(T instance) where T : Object 31 | { 32 | var type = typeof(T); 33 | if (!instances.TryAdd(type, instance)) 34 | { 35 | if (instances[type]) 36 | { 37 | Debug.LogWarning($"'{type.Name}' instance is duplicated."); 38 | } 39 | instances[type] = instance; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Scripts/Minity/Infra/SceneSingleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d78958d473d74db3a4195bb475d1a330 3 | timeCreated: 1738234540 -------------------------------------------------------------------------------- /Scripts/Minity/Logger.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1c22a959886693d4f88093f84ac69fdf 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Logger/DebugLog.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | #if UNITY_EDITOR 3 | using UnityEditor; 4 | #endif 5 | 6 | namespace Minity.Logger 7 | { 8 | internal static class DebugLog 9 | { 10 | #if UNITY_EDITOR 11 | private const string PREFIX = 12 | "[" + 13 | "M" + 14 | "i" + 15 | "n" + 16 | "i" + 17 | "t" + 18 | "y" + 19 | "] "; 20 | 21 | private enum LogLevel 22 | { 23 | Info, Warning, Error 24 | } 25 | 26 | private const string LogLevelKey = "_unity_debug_milutools_log_level"; 27 | 28 | private static LogLevel _logLevel = LogLevel.Info; 29 | 30 | [InitializeOnEnterPlayMode] 31 | private static void ReadConfig() 32 | { 33 | _logLevel = (LogLevel)EditorPrefs.GetInt(LogLevelKey, (int)LogLevel.Warning); 34 | } 35 | 36 | [MenuItem("Minity/Log Level/Error", false, 2)] 37 | private static void SwitchLogLevelError() 38 | { 39 | SwitchLogLevel(LogLevel.Error); 40 | } 41 | 42 | [MenuItem("Minity/Log Level/Warning", false, 1)] 43 | private static void SwitchLogLevelWarning() 44 | { 45 | SwitchLogLevel(LogLevel.Warning); 46 | } 47 | 48 | [MenuItem("Minity/Log Level/Info", false, 0)] 49 | private static void SwitchLogLevelInfo() 50 | { 51 | SwitchLogLevel(LogLevel.Info); 52 | } 53 | 54 | private static void SwitchLogLevel(LogLevel level) 55 | { 56 | _logLevel = level; 57 | EditorPrefs.SetInt(LogLevelKey, (int)level); 58 | EditorUtility.DisplayDialog("Minity", "Switched Milutools log level to " + level, "OK"); 59 | } 60 | 61 | internal static void Log(string content) 62 | { 63 | if (_logLevel > LogLevel.Info) 64 | { 65 | return; 66 | } 67 | Debug.Log(PREFIX + content); 68 | } 69 | 70 | internal static void LogWarning(string content) 71 | { 72 | if (_logLevel > LogLevel.Warning) 73 | { 74 | return; 75 | } 76 | Debug.LogWarning(PREFIX + content); 77 | } 78 | 79 | internal static void LogError(string content) 80 | { 81 | if (_logLevel > LogLevel.Error) 82 | { 83 | return; 84 | } 85 | Debug.LogError(PREFIX + content); 86 | } 87 | #else 88 | internal static void Log(string content) 89 | { 90 | 91 | } 92 | 93 | internal static void LogWarning(string content) 94 | { 95 | 96 | } 97 | 98 | internal static void LogError(string content) 99 | { 100 | 101 | } 102 | #endif 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Scripts/Minity/Logger/DebugLog.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 380ff86463305b246909ab1e0506d155 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a0030c3fdd878a44baea89a02ff96a1a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e1cc2525386c469b9c2496641d31727f 3 | timeCreated: 1727797960 -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/Editor/PoolGuardEditor.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using UnityEditor; 6 | using UnityEngine; 7 | 8 | namespace Minity.Pooling.Editor 9 | { 10 | [CustomEditor(typeof(PoolGuard))] 11 | public class PoolGuardEditor : UnityEditor.Editor 12 | { 13 | private static Dictionary foldout = new Dictionary(); 14 | private static Dictionary objFoldout = new Dictionary(); 15 | public override void OnInspectorGUI() 16 | { 17 | EditorGUILayout.LabelField("Active prefab count: " + ObjectPool.contexts.Count); 18 | EditorGUILayout.Separator(); 19 | 20 | foreach (PoolLifeCyclePolicy policy in Enum.GetValues(typeof(PoolLifeCyclePolicy))) 21 | { 22 | if (!foldout.ContainsKey(policy)) 23 | { 24 | foldout.Add(policy, false); 25 | objFoldout.Add(policy, null); 26 | } 27 | 28 | var collection = 29 | ObjectPool.contexts.Values.Where(x => x.LifeCyclePolicy == policy).ToArray(); 30 | 31 | EditorGUI.indentLevel = 0; 32 | foldout[policy] = EditorGUILayout.Foldout(foldout[policy], policy + " (" + collection.Length + ")", true); 33 | if (!foldout[policy]) 34 | { 35 | continue; 36 | } 37 | foreach (var context in collection) 38 | { 39 | var open = objFoldout[policy] == context; 40 | EditorGUI.indentLevel = 1; 41 | open = EditorGUILayout.Foldout(open, context.Name, true); 42 | if (open) 43 | { 44 | EditorGUI.indentLevel = 2; 45 | EditorGUILayout.LabelField("Base Amount", context.MinimumObjectCount.ToString()); 46 | EditorGUILayout.LabelField("Current Amount", context.Objects.Count.ToString()); 47 | EditorGUILayout.LabelField("Current Usage", context.CurrentUsage.ToString()); 48 | EditorGUILayout.LabelField("Recent Usage", (context.PeriodUsage / PoolGuard.usageTrackCount).ToString()); 49 | if (objFoldout[policy] != context) 50 | { 51 | objFoldout[policy] = context; 52 | } 53 | } 54 | } 55 | } 56 | 57 | EditorUtility.SetDirty(target); 58 | } 59 | } 60 | } 61 | #endif 62 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/Editor/PoolGuardEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 61df5450e2f143c19f42dc7f6a35d12b 3 | timeCreated: 1727797972 -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/ObjectPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Minity.Logger; 5 | using Minity.General; 6 | using UnityEngine; 7 | using UnityEngine.SceneManagement; 8 | 9 | namespace Minity.Pooling 10 | { 11 | public static class ObjectPool 12 | { 13 | /// 14 | /// When enabled, the object pool will track the usage of objects and periodically release 15 | /// the excess, infrequently used objects generated during peak usage. 16 | /// However, if the number of prefabs in the pool is large, 17 | /// enabling this option may cause stuttering. 18 | /// 19 | public static bool AutoReleaseUnusedObjects { get; set; } = true; 20 | 21 | internal static readonly Dictionary contexts = new Dictionary(); 22 | internal static readonly Dictionary objectDict = new Dictionary(); 23 | 24 | private static bool initialized = false; 25 | 26 | internal static Transform scenePoolParent { get; private set; } 27 | internal static Transform poolParent { get; private set; } 28 | 29 | private static void EnsureInitialized() 30 | { 31 | if (initialized) 32 | { 33 | return; 34 | } 35 | 36 | initialized = true; 37 | 38 | var go = new GameObject("[Object Pool]", typeof(PoolGuard)); 39 | GameObject.DontDestroyOnLoad(go); 40 | go.SetActive(true); 41 | poolParent = go.transform; 42 | } 43 | 44 | internal static void CreateScenePoolGuard() 45 | { 46 | if (scenePoolParent) 47 | { 48 | return; 49 | } 50 | var guard = new GameObject("[Scene Object Pool]", typeof(ScenePoolGuard)); 51 | guard.SetActive(true); 52 | scenePoolParent = guard.transform; 53 | } 54 | 55 | /// 56 | /// Return the object back to the pool 57 | /// 58 | /// 59 | public static void ReturnToPool(GameObject gameObject) 60 | { 61 | #if UNITY_EDITOR 62 | if (!objectDict.ContainsKey(gameObject)) 63 | { 64 | DebugLog.LogWarning("The specific game object is not managed by the object pool."); 65 | GameObject.Destroy(gameObject); 66 | return; 67 | } 68 | #endif 69 | objectDict[gameObject].ReturnToPool(); 70 | } 71 | 72 | /// 73 | /// To unregister a prefab. 74 | /// NOTE: this will dispose all the objects in the pool of the previous registered prefab. 75 | /// 76 | /// an enum value to identify a specific prefab 77 | public static void UnregisterPrefabAndDestroy(T id) where T : Enum 78 | { 79 | EnsureInitialized(); 80 | 81 | var key = EnumIdentifier.Wrap(id); 82 | if (contexts.TryGetValue(key, out var existing)) 83 | { 84 | foreach (var obj in existing.Objects) 85 | { 86 | obj.PoolableController.ReadyToDestroy = true; 87 | UnityEngine.Object.Destroy(obj.GameObject); 88 | } 89 | contexts.Remove(key); 90 | 91 | if (existing.LifeCyclePolicy == PoolLifeCyclePolicy.DestroyOnLoad) 92 | { 93 | ScenePoolGuard.PrefabInScene.Remove(key); 94 | } 95 | } 96 | else 97 | { 98 | Debug.LogWarning($"Prefab {key} is not registered, no need to unregister."); 99 | } 100 | } 101 | 102 | /// 103 | /// To ensure the prefab is registered. 104 | /// You must first register it before requesting a poolable object from the prefab. 105 | /// 106 | /// an enum value to identify a specific prefab 107 | /// the prefab object 108 | /// set the minimum object count and prepare specific amount of objects beforehand 109 | /// when the prefab and its objects get destroyed 110 | public static void EnsurePrefabRegistered(T id, GameObject prefab, 111 | uint minimumObjectCount, 112 | PoolLifeCyclePolicy lifeCyclePolicy = PoolLifeCyclePolicy.DestroyOnLoad) where T : Enum 113 | { 114 | EnsureInitialized(); 115 | 116 | var key = EnumIdentifier.Wrap(id); 117 | 118 | // 强制检查 119 | if (contexts.TryGetValue(key, out var existing)) 120 | { 121 | if (existing.Prefab == prefab && existing.LifeCyclePolicy == lifeCyclePolicy) 122 | { 123 | DebugLog.LogWarning($"Prefab '{key}' is already registered."); 124 | return; 125 | } 126 | 127 | throw new ArgumentException($"Prefab '{key}' is already registered. " + 128 | $"Each prefab must have a unique name.", nameof(id)); 129 | } 130 | 131 | if (lifeCyclePolicy == PoolLifeCyclePolicy.DestroyOnLoad) 132 | { 133 | if (!ScenePoolGuard.Instance) 134 | { 135 | CreateScenePoolGuard(); 136 | } 137 | ScenePoolGuard.PrefabInScene.Add(key); 138 | } 139 | 140 | var poolableObject = prefab.GetComponent(); 141 | if (!poolableObject) 142 | { 143 | throw new InvalidOperationException($"Prefab '{key}' must have a PoolableObject component. " + 144 | $"Please add the component manually before registering."); 145 | } 146 | 147 | poolableObject.IsPrefab = true; 148 | 149 | var context = new PoolContext() 150 | { 151 | Prefab = prefab, 152 | Name = $"{typeof(T).FullName}.{id}", 153 | ID = id, 154 | LifeCyclePolicy = lifeCyclePolicy, 155 | MinimumObjectCount = minimumObjectCount, 156 | ComponentTypes = poolableObject.Components?.Where(x => x) 157 | .Select(x => x.GetType()).ToArray() ?? Array.Empty() 158 | }; 159 | 160 | contexts.Add(key, context); 161 | 162 | //context.Prepare(minimumObjectCount); 163 | } 164 | 165 | /// 166 | /// Retrieve an object with the specified prefab ID from the pool and obtain its object set, 167 | /// including all associated components and related information. 168 | /// 169 | /// an enum value to identify a specific prefab 170 | /// an function to do something with the collection 171 | /// the parent of the retrieved object to be set 172 | /// 173 | public static void Request(T prefab, Action handler, Transform parent = null) where T : Enum 174 | { 175 | var key = EnumIdentifier.Wrap(prefab); 176 | var collection = contexts[key].Request(); 177 | collection.Transform.SetParent(parent, false); 178 | handler(collection); 179 | } 180 | 181 | /// 182 | /// Retrieve an object with the specified prefab ID from the pool and obtain its object set, 183 | /// including all associated components and related information. 184 | /// 185 | /// an enum value to identify a specific prefab 186 | /// the parent of the retrieved object to be set 187 | /// 188 | public static PooledEntity Request(T prefab, Transform parent = null) where T : Enum 189 | { 190 | var key = EnumIdentifier.Wrap(prefab); 191 | var collection = contexts[key].Request(); 192 | collection.Transform.SetParent(parent, false); 193 | return collection; 194 | } 195 | 196 | /// 197 | /// Retrieve an object with the specified prefab ID from the pool and obtain its GameObject. 198 | /// 199 | /// an enum value to identify a specific prefab 200 | /// the parent of the retrieved object to be set 201 | /// 202 | public static GameObject RequestGameObject(T prefab, Transform parent = null) where T : Enum 203 | { 204 | return Request(prefab, parent).GameObject; 205 | } 206 | 207 | /// 208 | /// Retrieve an object with the specified prefab ID from the pool and obtain its associated primary component. 209 | /// 210 | /// an enum value to identify a specific prefab 211 | /// the parent of the retrieved object to be set 212 | /// Component Type 213 | /// Prefab ID Enum 214 | /// 215 | public static T RequestMainComponent(E prefab, Transform parent = null) where T : Component where E : Enum 216 | { 217 | return (T)Request(prefab, parent).MainComponent; 218 | } 219 | 220 | /// 221 | /// Retrieve an object with the specified prefab ID from the pool and obtain its associated component of a specific type. 222 | /// 223 | /// an enum value to identify a specific prefab 224 | /// the parent of the retrieved object to be set 225 | /// Component Type 226 | /// Prefab ID Enum 227 | /// 228 | public static T RequestComponent(E prefab, Transform parent = null) where T : Component where E : Enum 229 | { 230 | return Request(prefab, parent).GetComponent(); 231 | } 232 | 233 | /// 234 | /// Immediately return all objects with the specified prefab ID to the pool. 235 | /// 236 | /// an enum value to identify a specific prefab 237 | public static void ReturnAllObjects(T prefab) where T : Enum 238 | { 239 | var key = EnumIdentifier.Wrap(prefab); 240 | contexts[key].RecycleAllObjects(); 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/ObjectPool.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6c849b62ff1d4e13aacf6d208c42cad2 3 | timeCreated: 1726654634 -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using Minity.Logger; 5 | #if !NET_STANDARD_2_1 6 | using Paraparty.UnityPolyfill; 7 | #endif 8 | using UnityEngine; 9 | using Object = UnityEngine.Object; 10 | 11 | namespace Minity.Pooling 12 | { 13 | public class PoolContext 14 | { 15 | public GameObject Prefab { get; internal set; } 16 | public string Name { get; internal set; } 17 | public IReadOnlyList AllObjects => Objects; 18 | public PoolLifeCyclePolicy LifeCyclePolicy { get; internal set; } 19 | public uint MinimumObjectCount { get; internal set; } 20 | 21 | internal List Objects { get; } = new List(); 22 | 23 | internal Type[] ComponentTypes; 24 | internal object ID; 25 | 26 | internal readonly Queue UsageRecords = new Queue(); 27 | internal uint PeriodUsage = 0; 28 | internal uint CurrentUsage = 0; 29 | internal uint IdleTick = 0; 30 | 31 | private Stack _objectStack { get; } = new Stack(); 32 | 33 | public T GetID() where T : Enum 34 | { 35 | return (T)ID; 36 | } 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | private Transform GetPoolParent() 40 | { 41 | return LifeCyclePolicy switch 42 | { 43 | PoolLifeCyclePolicy.Eternity => ObjectPool.poolParent, 44 | PoolLifeCyclePolicy.DestroyOnLoad => ObjectPool.scenePoolParent, 45 | _ => null 46 | }; 47 | } 48 | 49 | private PooledEntity Produce() 50 | { 51 | var gameObject = Object.Instantiate(Prefab, GetPoolParent()); 52 | gameObject.name = $"[RE{gameObject.GetInstanceID()}] {Name}"; 53 | gameObject.SetActive(false); 54 | 55 | var poolableObject = gameObject.GetComponent(); 56 | ObjectPool.objectDict.Add(gameObject, poolableObject); 57 | 58 | if (LifeCyclePolicy == PoolLifeCyclePolicy.Eternity) 59 | { 60 | Object.DontDestroyOnLoad(gameObject); 61 | } 62 | 63 | var collection = new PooledEntity() 64 | { 65 | GameObject = gameObject, 66 | Transform = gameObject.transform, 67 | PoolableController = poolableObject, 68 | MainComponent = poolableObject.MainComponent 69 | }; 70 | 71 | for (var i = 0; i < ComponentTypes.Length; i++) 72 | { 73 | #if UNITY_EDITOR 74 | if (collection.Components.ContainsKey(ComponentTypes[i])) 75 | { 76 | DebugLog.LogError($"You are trying to link multiple components with a same type '{ComponentTypes[i]}'\n" + 77 | $", this is not supported. (ID: {ID})"); 78 | continue; 79 | } 80 | #endif 81 | collection.Components.Add(ComponentTypes[i], poolableObject.Components[i]); 82 | } 83 | 84 | poolableObject.Initialize(this, collection); 85 | 86 | Objects.Add(collection); 87 | 88 | return collection; 89 | } 90 | 91 | internal void RecycleAllObjects() 92 | { 93 | foreach (var obj in AllObjects) 94 | { 95 | if (!obj.PoolableController.Using) 96 | { 97 | continue; 98 | } 99 | obj.PoolableController.ReturnToPool(); 100 | } 101 | } 102 | 103 | internal void Prepare(uint count) 104 | { 105 | for (var i = 0; i < count; i++) 106 | { 107 | _objectStack.Push(Produce()); 108 | } 109 | } 110 | 111 | internal void Clear() 112 | { 113 | _objectStack.Clear(); 114 | Objects.Clear(); 115 | CurrentUsage = 0; 116 | } 117 | 118 | internal PooledEntity Request() 119 | { 120 | if (LifeCyclePolicy == PoolLifeCyclePolicy.DestroyOnLoad) 121 | { 122 | if (!ScenePoolGuard.Instance) 123 | { 124 | ObjectPool.CreateScenePoolGuard(); 125 | } 126 | } 127 | 128 | if (!_objectStack.TryPop(out var collection)) 129 | { 130 | collection = Produce(); 131 | } 132 | else 133 | { 134 | collection.PoolableController.OnReset?.Invoke(); 135 | } 136 | 137 | CurrentUsage++; 138 | collection.PoolableController.Using = true; 139 | return collection; 140 | } 141 | 142 | internal void ReturnToPool(PooledEntity collection) 143 | { 144 | CurrentUsage--; 145 | collection.Transform.SetParent(GetPoolParent()); 146 | collection.GameObject.SetActive(false); 147 | _objectStack.Push(collection); 148 | } 149 | 150 | internal int GetObjectCount() 151 | => _objectStack.Count; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 78478acbcfd445979c3bfd0ee0349753 3 | timeCreated: 1726654444 -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolGuard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Minity.Logger; 3 | using UnityEngine; 4 | using Random = System.Random; 5 | 6 | namespace Minity.Pooling 7 | { 8 | [AddComponentMenu("")] 9 | internal class PoolGuard : MonoBehaviour 10 | { 11 | internal const int usageTrackCount = 10; 12 | private float tick = 0f; 13 | 14 | private void FixedUpdate() 15 | { 16 | if (!ObjectPool.AutoReleaseUnusedObjects) 17 | { 18 | return; 19 | } 20 | 21 | tick += Time.fixedDeltaTime; 22 | if (tick >= 1f) 23 | { 24 | tick -= 1f; 25 | foreach (var context in ObjectPool.contexts.Values) 26 | { 27 | context.UsageRecords.Enqueue(context.CurrentUsage); 28 | context.PeriodUsage += context.CurrentUsage; 29 | if (context.UsageRecords.Count > usageTrackCount) 30 | { 31 | context.PeriodUsage -= context.UsageRecords.Dequeue(); 32 | } 33 | 34 | if (context.PeriodUsage == 0) 35 | { 36 | context.IdleTick++; 37 | } 38 | else 39 | { 40 | context.IdleTick = 0; 41 | } 42 | } 43 | } 44 | 45 | foreach (var context in ObjectPool.contexts.Values) 46 | { 47 | var cnt = Math.Max(context.CurrentUsage, context.PeriodUsage / usageTrackCount) 48 | + context.MinimumObjectCount 49 | - Math.Max(context.IdleTick - 10, 0); 50 | if (context.GetObjectCount() > cnt - context.CurrentUsage) 51 | { 52 | var collection = context.Request(); 53 | collection.PoolableController.ReadyToDestroy = true; 54 | Destroy(collection.GameObject); 55 | context.Objects.Remove(collection); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolGuard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3423e80b034c4e679f53f19e439a9898 3 | timeCreated: 1727009455 -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Minity.Pooling 6 | { 7 | public enum PoolLifeCyclePolicy 8 | { 9 | /// 10 | /// Until the process exits 11 | /// 12 | Eternity, 13 | /// 14 | /// Destroy collectively upon scene transition 15 | /// 16 | DestroyOnLoad 17 | } 18 | 19 | public class PooledEntity 20 | { 21 | public GameObject GameObject { get; internal set; } 22 | public Transform Transform { get; internal set; } 23 | public PoolableObject PoolableController { get; internal set; } 24 | internal Component MainComponent { get; set; } 25 | internal Dictionary Components { get; } = new Dictionary(); 26 | 27 | public T GetComponent() where T : Component 28 | { 29 | return (T)Components[typeof(T)]; 30 | } 31 | 32 | public T GetMainComponent() where T : Component 33 | { 34 | return (T)MainComponent; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolModel.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18cda192a89240c0830abc049463b134 3 | timeCreated: 1726654480 -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolableObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Minity.Logger; 5 | using UnityEngine; 6 | using UnityEngine.Events; 7 | using UnityEngine.Serialization; 8 | 9 | namespace Minity.Pooling 10 | { 11 | [DisallowMultipleComponent] 12 | public sealed class PoolableObject : MonoBehaviour 13 | { 14 | [FormerlySerializedAs("AutoRecycleTimeOut")] 15 | [FormerlySerializedAs("RecycleTimeOut")] 16 | [Tooltip("Automatically return the object to the pool after specific seconds.\n* -1 means disabling auto recycling.")] 17 | public float AutoReturnTimeOut = -1f; 18 | 19 | [FormerlySerializedAs("LinkComponent")] 20 | [Tooltip("Link a main component, then you can access it using ObjectPool.Request function.\n" + 21 | "This would avoid using GetComponent function frequently as GetComponent function may made the program slow.")] 22 | public Component MainComponent; 23 | 24 | [FormerlySerializedAs("DictComponent")] 25 | [Tooltip("Link more components, then you can access it using PoolableEntity.GetComponent function.\n" + 26 | "This would avoid using GetComponent function frequently as GetComponent function may made the program slow.\n" + 27 | "NOTICE: involving multiple components with a same type is not supported.")] 28 | public Component[] Components; 29 | 30 | public UnityEvent OnReset; 31 | 32 | internal bool Using { get; set; } 33 | internal bool IsPrefab { get; set; } = false; 34 | internal bool ReadyToDestroy = false; 35 | 36 | private PooledEntity _pooledEntity; 37 | private PoolContext _parentContext; 38 | private int _objectHash; 39 | 40 | private float returnTick = 0f; 41 | 42 | #if UNITY_EDITOR 43 | private bool warned = false; 44 | #endif 45 | 46 | internal void Initialize(PoolContext context, PooledEntity collection) 47 | { 48 | _parentContext = context; 49 | _pooledEntity = collection; 50 | _objectHash = GetHashCode(); 51 | 52 | DebugLog.Log($"PoolableObject created: Hash={_objectHash}, Name={gameObject.name}, PrefabName={context.Name}"); 53 | } 54 | 55 | private void OnDestroy() 56 | { 57 | #if UNITY_EDITOR 58 | if (IsPrefab) 59 | { 60 | throw new Exception( 61 | "The prefab object is unexpectedly destroyed, the object pool would fail when producing new objects!"); 62 | } 63 | 64 | if (_parentContext == null) 65 | { 66 | return; 67 | } 68 | 69 | if (!ReadyToDestroy) 70 | { 71 | if (_parentContext.LifeCyclePolicy == PoolLifeCyclePolicy.Eternity) 72 | { 73 | throw new Exception($"PoolableObject is unexpectedly destroyed, this has broken the object pool: Hash={_objectHash}, Name={gameObject.name}, PrefabName={_parentContext.Name}"); 74 | } 75 | else 76 | { 77 | ScenePoolGuard.Instance.DestroyRecords.AppendLine($"Hash={_objectHash}, Name={gameObject.name}, PrefabName={_parentContext.Name}"); 78 | } 79 | } 80 | else 81 | { 82 | if (Using) 83 | { 84 | _parentContext.CurrentUsage--; 85 | } 86 | } 87 | 88 | ObjectPool.objectDict.Remove(gameObject); 89 | 90 | DebugLog.Log($"PoolableObject destroyed: Hash={_objectHash}, Name={gameObject.name}, PrefabName={_parentContext.Name}"); 91 | #endif 92 | } 93 | 94 | /// 95 | /// Use ReturnToPool() instead. 96 | /// 97 | [Obsolete] 98 | public void WaitForRecycle() 99 | => ReturnToPool(); 100 | 101 | /// 102 | /// Return the object to the pool 103 | /// 104 | public void ReturnToPool() 105 | { 106 | if (!Using) 107 | { 108 | #if UNITY_EDITOR 109 | DebugLog.LogWarning("The object is not using, returning back to pool is not necessary."); 110 | #endif 111 | return; 112 | } 113 | #if UNITY_EDITOR 114 | if (IsPrefab) 115 | { 116 | DebugLog.LogError("You are trying to return a prefab to the pool, this is not allowed."); 117 | return; 118 | } 119 | if (_parentContext == null) 120 | { 121 | Destroy(gameObject); 122 | DebugLog.LogWarning("You are trying to return an object that is not managed by the object pool, this is not allowed."); 123 | return; 124 | } 125 | #endif 126 | Using = false; 127 | _pooledEntity.Transform.SetParent(null); 128 | _parentContext.ReturnToPool(_pooledEntity); 129 | } 130 | 131 | private void FixedUpdate() 132 | { 133 | #if UNITY_EDITOR 134 | if (IsPrefab) 135 | { 136 | DebugLog.LogWarning("The prefab for the object pool must be inactive."); 137 | return; 138 | } 139 | 140 | if (_parentContext == null && !warned) 141 | { 142 | warned = true; 143 | DebugLog.LogWarning("This object is not managed by the object pool, please use 'ObjectPool.Request' function to create the object."); 144 | return; 145 | } 146 | #endif 147 | 148 | if (AutoReturnTimeOut <= 0f) 149 | { 150 | return; 151 | } 152 | 153 | returnTick += Time.fixedDeltaTime; 154 | if (returnTick >= AutoReturnTimeOut) 155 | { 156 | ReturnToPool(); 157 | returnTick = 0f; 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/PoolableObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80e755b1aacd34443931dd77c1835d2f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {fileID: 2800000, guid: 079ec8372b6cccf44a6fc79d5efb6323, type: 3} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/ScenePoolGuard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Minity.Logger; 5 | using Minity.General; 6 | using UnityEngine; 7 | 8 | namespace Minity.Pooling 9 | { 10 | [AddComponentMenu("")] 11 | internal class ScenePoolGuard : MonoBehaviour 12 | { 13 | public static ScenePoolGuard Instance { get; private set; } 14 | 15 | internal static readonly List PrefabInScene = new List(); 16 | internal readonly StringBuilder DestroyRecords = new StringBuilder(); 17 | 18 | private void Awake() 19 | { 20 | Instance = this; 21 | } 22 | 23 | private void OnDestroy() 24 | { 25 | foreach (var prefab in PrefabInScene) 26 | { 27 | ObjectPool.contexts[prefab].Clear(); 28 | } 29 | } 30 | 31 | private void Update() 32 | { 33 | if (DestroyRecords.Length > 0) 34 | { 35 | DebugLog.LogError("Several poolable objects were unexpectedly destroyed, this will break the object pool!\n" + 36 | DestroyRecords); 37 | DestroyRecords.Clear(); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Scripts/Minity/Pooling/ScenePoolGuard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9610a329ae3474ca723c841848f50c5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: -999 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2ffbd1caf38a5aa4681ab0729bb22588 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/BlackFade.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using Milease.Core; 5 | using Milease.Core.Animator; 6 | using Milease.DSL; 7 | using Milease.Utils; 8 | using UnityEngine; 9 | using UnityEngine.UI; 10 | 11 | namespace Minity.SceneRouter 12 | { 13 | public class BlackFade : LoadingAnimator 14 | { 15 | public Image Panel; 16 | 17 | public override void AboutToLoad() 18 | { 19 | MilInstantAnimator.Start( 20 | 0.5f / Panel.MQuad(x => x.color, Color.clear, Color.black) 21 | ) 22 | .Then( 23 | new Action(ReadyToLoad).AsMileaseKeyEvent() 24 | ) 25 | .UsingResetMode(AnimationResetMode.ResetToInitialState) 26 | .PlayImmediately(); 27 | } 28 | 29 | public override void OnLoaded() 30 | { 31 | MilInstantAnimator.Start( 32 | 0.5f / Panel.MQuad(x => x.color, Color.black, Color.clear) 33 | ) 34 | .Then( 35 | new Action(FinishLoading).AsMileaseKeyEvent() 36 | ) 37 | .UsingResetMode(AnimationResetMode.ResetToInitialState) 38 | .PlayImmediately(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/BlackFade.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7be2054d782a73d47b7b5b7c5fc6cdd7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/LoadingAnimator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEngine.SceneManagement; 4 | 5 | namespace Minity.SceneRouter 6 | { 7 | public abstract class LoadingAnimator : MonoBehaviour 8 | { 9 | public float Progress => loadingOperation?.progress ?? 0f; 10 | public string TargetScene { get; internal set; } 11 | 12 | private AsyncOperation loadingOperation; 13 | 14 | private void Awake() 15 | { 16 | DontDestroyOnLoad(gameObject); 17 | AboutToLoad(); 18 | } 19 | 20 | /// 21 | /// Call when the loading animator is ready 22 | /// 23 | protected void ReadyToLoad() 24 | { 25 | loadingOperation = SceneManager.LoadSceneAsync(TargetScene); 26 | loadingOperation!.completed += (_) => OnLoaded(); 27 | } 28 | 29 | /// 30 | /// Call when the loading animator finishes 31 | /// 32 | protected void FinishLoading() 33 | { 34 | Destroy(gameObject); 35 | } 36 | 37 | public abstract void AboutToLoad(); 38 | 39 | public abstract void OnLoaded(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/LoadingAnimator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bdc7e7acdd6f4888b1f6259f16a4dad6 3 | timeCreated: 1728388227 -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/LoadingAnimatorData.cs: -------------------------------------------------------------------------------- 1 | using Minity.General; 2 | using UnityEngine; 3 | 4 | namespace Minity.SceneRouter 5 | { 6 | public class LoadingAnimatorData 7 | { 8 | internal EnumIdentifier Identifier; 9 | internal GameObject Prefab; 10 | 11 | internal LoadingAnimatorData() 12 | { 13 | 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/LoadingAnimatorData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b17ea1d6b6d4a5394515e5bc27a287c 3 | timeCreated: 1728827917 -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.CompilerServices; 6 | using Minity.Logger; 7 | using Minity.General; 8 | using UnityEngine; 9 | using UnityEngine.SceneManagement; 10 | 11 | namespace Minity.SceneRouter 12 | { 13 | public class SceneRouter : MonoBehaviour 14 | { 15 | private const char PathSeparator = '/'; 16 | 17 | internal static bool Enabled = false; 18 | 19 | internal readonly static Dictionary Nodes = new Dictionary(); 20 | internal readonly static Dictionary LoadingAnimators = new Dictionary(); 21 | 22 | internal static SceneRouterNode RootNode, CurrentNode; 23 | 24 | internal static LoadingAnimatorData LoadingAnimatorPrefab; 25 | internal static object Parameters; 26 | 27 | /// 28 | /// When calling the Back() method at the root node, should the game exit directly? 29 | /// 30 | public static bool QuitOnRootNode { get; set; } = true; 31 | 32 | public static void Setup(SceneRouterConfig config) 33 | { 34 | if (Enabled) 35 | { 36 | DebugLog.LogError("Duplicated setup is not allowed."); 37 | return; 38 | } 39 | 40 | LoadingAnimatorPrefab = new LoadingAnimatorData() 41 | { 42 | Prefab = Resources.Load("BlackFade") 43 | }; 44 | 45 | foreach (var node in config.SceneNodes) 46 | { 47 | if (node.IsRoot) 48 | { 49 | if (RootNode != null) 50 | { 51 | DebugLog.LogError("There should be only an root node."); 52 | return; 53 | } 54 | 55 | RootNode = node; 56 | } 57 | Nodes.Add(node.Identifier, node); 58 | } 59 | 60 | CurrentNode = config.SceneNodes.FirstOrDefault(x => x.Scene == SceneManager.GetActiveScene().name); 61 | if (CurrentNode == null) 62 | { 63 | DebugLog.LogWarning($"Current scene '{SceneManager.GetActiveScene().name}' is not included in this scene notes, " + 64 | $"SceneRouter.Back() won't work properly in this scene."); 65 | } 66 | 67 | foreach (var animator in config.LoadingAnimators) 68 | { 69 | LoadingAnimators.Add(animator.Identifier, animator); 70 | } 71 | 72 | #if UNITY_EDITOR 73 | SceneManager.activeSceneChanged += (_, scene) => 74 | { 75 | if (CurrentNode != null && CurrentNode.Scene == scene.name) 76 | { 77 | return; 78 | } 79 | DebugLog.LogError("You seem to be trying to manage the scenes on your own, " + 80 | "but this might hinder the normal functioning of the scene router, " + 81 | "and it doesn't align with the design principles."); 82 | }; 83 | #endif 84 | 85 | Enabled = true; 86 | } 87 | 88 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 89 | private static bool ValidateLoadingPrefab(GameObject prefab) 90 | { 91 | var result = prefab.TryGetComponent(out _); 92 | if (!result) 93 | { 94 | DebugLog.LogError($"The loading prefab '{prefab.name}' must has a LoadingAnimator component on its root object."); 95 | } 96 | return result; 97 | } 98 | 99 | public static T FetchParameters() 100 | => (T)Parameters; 101 | 102 | public static void SetLoadingAnimator(T animator) where T : Enum 103 | { 104 | var key = EnumIdentifier.Wrap(animator); 105 | if (!LoadingAnimators.TryGetValue(key, out var loadingAnimator)) 106 | { 107 | DebugLog.LogError($"Specific loading animator '{key}' is not configured."); 108 | return; 109 | } 110 | 111 | LoadingAnimatorPrefab = loadingAnimator; 112 | } 113 | 114 | public static LoadingAnimatorData GetLoadingAnimator(T animator) where T : Enum 115 | { 116 | var key = EnumIdentifier.Wrap(animator); 117 | if (!LoadingAnimators.TryGetValue(key, out var loadingAnimator)) 118 | { 119 | DebugLog.LogError($"Specific loading animator '{key}' is not configured."); 120 | return null; 121 | } 122 | 123 | return loadingAnimator; 124 | } 125 | 126 | public static LoadingAnimatorData LoadingAnimator(T identifier, GameObject prefab) where T : Enum 127 | { 128 | return new LoadingAnimatorData() 129 | { 130 | Identifier = EnumIdentifier.Wrap(identifier), 131 | Prefab = prefab 132 | }; 133 | } 134 | 135 | private static SceneRouterNode Node(T identifier, string path, string scene, bool isRoot) where T : Enum 136 | { 137 | return new SceneRouterNode() 138 | { 139 | Identifier = EnumIdentifier.Wrap(identifier), 140 | Path = path.Split(PathSeparator), 141 | FullPath = path, 142 | Scene = scene, 143 | IsRoot = isRoot 144 | }; 145 | } 146 | 147 | public static SceneRouterNode Root(T identifier, string scene) where T : Enum 148 | => Node(identifier, "", scene, true); 149 | 150 | public static SceneRouterNode Node(T identifier, string path, string scene) where T : Enum 151 | => Node(identifier, path, scene, false); 152 | 153 | private static SceneRouterContext GoTo(SceneRouterNode node, LoadingAnimatorData loadingAnimator = null) 154 | { 155 | if (!Enabled) 156 | { 157 | DebugLog.LogError("Scene router is not enabled, please configure the scene nodes first."); 158 | return null; 159 | } 160 | var data = loadingAnimator ?? LoadingAnimatorPrefab; 161 | var go = Instantiate(data.Prefab); 162 | var animator = go.GetComponent(); 163 | animator.TargetScene = node.Scene; 164 | go.SetActive(true); 165 | 166 | Parameters = null; 167 | CurrentNode = node; 168 | 169 | return new SceneRouterContext(); 170 | } 171 | 172 | public static SceneRouterContext GoTo(T scene, LoadingAnimatorData loadingAnimator = null) where T : Enum 173 | { 174 | var key = EnumIdentifier.Wrap(scene); 175 | if (!Nodes.ContainsKey(key)) 176 | { 177 | DebugLog.LogError($"The specific scene node '{key}' is not found."); 178 | } 179 | 180 | return GoTo(Nodes[key], loadingAnimator); 181 | } 182 | 183 | public static SceneRouterContext Back(LoadingAnimatorData loadingAnimator = null) 184 | { 185 | if (CurrentNode.Path.Length < 2) 186 | { 187 | if (QuitOnRootNode && CurrentNode == RootNode) 188 | { 189 | DebugLog.LogWarning("At this point, the compiled game will terminate the process."); 190 | Application.Quit(); 191 | return null; 192 | } 193 | return GoTo(RootNode, loadingAnimator); 194 | } 195 | var path = string.Join(PathSeparator.ToString(), CurrentNode.Path.Take(CurrentNode.Path.Length - 1)); 196 | var node = Nodes.Values.FirstOrDefault(x => x.FullPath == path); 197 | if (node == null) 198 | { 199 | DebugLog.LogWarning($"The parent node of scene node '{CurrentNode.Identifier}' is not configured, the router will navigate to the root node."); 200 | node = RootNode; 201 | } 202 | return GoTo(node, loadingAnimator); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8914d67b267be05478145cbbc944c503 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouterConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Minity.SceneRouter 6 | { 7 | public class SceneRouterConfig 8 | { 9 | public IEnumerable SceneNodes = Array.Empty(); 10 | public IEnumerable LoadingAnimators = Array.Empty(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouterConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a9c703abbc54476cbee10b6f3dd1d65d 3 | timeCreated: 1728827461 -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouterContext.cs: -------------------------------------------------------------------------------- 1 | namespace Minity.SceneRouter 2 | { 3 | public class SceneRouterContext 4 | { 5 | public void Parameters(object data) 6 | { 7 | SceneRouter.Parameters = data; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouterContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 23f86ef81bde4cb585f37d0b28aa7a22 3 | timeCreated: 1728392096 -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouterNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Minity.General; 3 | using UnityEngine; 4 | 5 | namespace Minity.SceneRouter 6 | { 7 | public class SceneRouterNode 8 | { 9 | internal EnumIdentifier Identifier; 10 | internal string[] Path; 11 | internal string FullPath; 12 | internal string Scene; 13 | internal bool IsRoot; 14 | 15 | internal SceneRouterNode() 16 | { 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Scripts/Minity/SceneRouter/SceneRouterNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b95a011d28c949fd8fd52541b8d8e0b9 3 | timeCreated: 1728225441 -------------------------------------------------------------------------------- /Scripts/Minity/UI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6d340ebb8604994c8d42ce1219a3931 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/Binding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Globalization; 5 | using TMPro; 6 | 7 | namespace Minity.UI 8 | { 9 | public delegate string FormatterDelegate(T data); 10 | public delegate void OnBindingChangedDelegate(BindingBase sender); 11 | 12 | public class Binding : BindingBase 13 | { 14 | public FormatterDelegate Formatter; 15 | 16 | private T data = default; 17 | public T Value 18 | { 19 | set 20 | { 21 | data = value; 22 | RaiseUpValueChangedEvent(); 23 | } 24 | get => data; 25 | } 26 | 27 | [Obsolete("Empty binding does not need to be constructed by yourself.")] 28 | public Binding() 29 | { 30 | 31 | } 32 | 33 | public Binding(T initial) 34 | { 35 | data = initial; 36 | } 37 | 38 | public Binding(FormatterDelegate formatter) 39 | { 40 | Formatter = formatter; 41 | } 42 | 43 | public Binding(T initial, FormatterDelegate formatter) 44 | { 45 | data = initial; 46 | Formatter = formatter; 47 | } 48 | 49 | internal override object GetValue() 50 | { 51 | if (Formatter != null) 52 | { 53 | return Formatter(data); 54 | } 55 | return data; 56 | } 57 | } 58 | 59 | public abstract class BindingBase 60 | { 61 | internal readonly HashSet Components = new HashSet(); 62 | internal event OnBindingChangedDelegate OnValueChanged; 63 | internal abstract object GetValue(); 64 | 65 | internal void RaiseUpValueChangedEvent() 66 | { 67 | OnValueChanged?.Invoke(this); 68 | } 69 | 70 | public void Do(Action action) 71 | { 72 | foreach (var component in Components) 73 | { 74 | action.Invoke(component); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/Binding.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 179eca761fdd43eda7a7c008607c5f7f 3 | timeCreated: 1737098286 -------------------------------------------------------------------------------- /Scripts/Minity/UI/BindingView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using TMPro; 8 | using UnityEngine; 9 | 10 | namespace Minity.UI 11 | { 12 | [RequireComponent(typeof(Canvas))] 13 | public abstract class BindingView : MonoBehaviour 14 | { 15 | protected abstract CultureInfo Formatter { get; } 16 | 17 | private static readonly Regex regex = new Regex(@"{{(.*?)}}", RegexOptions.Compiled); 18 | 19 | private class TextSegment 20 | { 21 | public string Content; 22 | public string Formatter; 23 | public BindingBase Binding; 24 | public bool IsDynamicText; 25 | } 26 | 27 | private class Link 28 | { 29 | public TMP_Text Component; 30 | public CultureInfo Formatter; 31 | public List Segments = new List(); 32 | 33 | internal void ScheduleUpdateText(BindingBase sender) 34 | { 35 | if (!Component) 36 | { 37 | if (sender != null) 38 | { 39 | sender.Components.Remove(Component); 40 | sender.OnValueChanged -= ScheduleUpdateText; 41 | } 42 | return; 43 | } 44 | BindingViewGuard.ScheduleUpdate(UpdateText); 45 | } 46 | 47 | internal void UpdateText() 48 | { 49 | var sb = new StringBuilder(); 50 | foreach (var segment in Segments) 51 | { 52 | if (segment.IsDynamicText) 53 | { 54 | var value = segment.Binding.GetValue(); 55 | if (value is IFormattable formattable) 56 | { 57 | sb.Append(formattable.ToString(segment.Formatter, Formatter)); 58 | } 59 | else 60 | { 61 | sb.Append(value); 62 | } 63 | } 64 | else 65 | { 66 | sb.Append(segment.Content); 67 | } 68 | } 69 | 70 | Component.text = sb.ToString(); 71 | } 72 | } 73 | 74 | private readonly Dictionary bindings = new Dictionary(); 75 | private bool initialized = false; 76 | 77 | private BindingBase GetBinding(string path) 78 | { 79 | if (bindings.TryGetValue(path, out var binding)) 80 | { 81 | return binding; 82 | } 83 | 84 | var items = path.Split('.'); 85 | var type = this.GetType(); 86 | object current = this; 87 | object parent = this; 88 | FieldInfo field = null; 89 | 90 | foreach (var item in items) 91 | { 92 | field = type.GetField(item, 93 | BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 94 | if (field == null) 95 | { 96 | Debug.LogWarning($"Could not find the binding '{path}'"); 97 | return null; 98 | } 99 | 100 | parent = current; 101 | current = field.GetValue(current); 102 | 103 | type = field.FieldType; 104 | } 105 | 106 | if (type.BaseType != typeof(BindingBase)) 107 | { 108 | Debug.LogWarning($"the type of binding '{path}' must be Binding"); 109 | return null; 110 | } 111 | 112 | BindingBase ret; 113 | if (current == null) 114 | { 115 | ret = (BindingBase)Activator.CreateInstance(type); 116 | field.SetValue(parent, ret); 117 | } 118 | else 119 | { 120 | ret = current as BindingBase; 121 | } 122 | 123 | bindings.Add(path, ret); 124 | 125 | return ret; 126 | } 127 | 128 | public void CreateLink(TMP_Text component) 129 | { 130 | var text = component.text; 131 | var matches = regex.Matches(text); 132 | 133 | if (matches.Count == 0) 134 | { 135 | return; 136 | } 137 | 138 | var link = new Link() 139 | { 140 | Component = component, 141 | Formatter = Formatter 142 | }; 143 | var lastIndex = 0; 144 | 145 | foreach (Match match in matches) 146 | { 147 | if (match.Success) 148 | { 149 | if (match.Index > lastIndex) 150 | { 151 | link.Segments.Add(new TextSegment() 152 | { 153 | Content = text.Substring(lastIndex, match.Index - lastIndex) 154 | }); 155 | } 156 | 157 | var content = match.Groups[1].Value.Trim(); 158 | var index = content.IndexOf(':'); 159 | string formatter = null; 160 | 161 | if (index != -1) 162 | { 163 | formatter = content.Substring(index + 1); 164 | content = content.Substring(0, index); 165 | } 166 | 167 | var binding = GetBinding(content); 168 | if (binding == null) 169 | { 170 | link.Segments.Add(new TextSegment()); 171 | } 172 | else 173 | { 174 | link.Segments.Add(new TextSegment() 175 | { 176 | Binding = binding, 177 | Formatter = formatter, 178 | IsDynamicText = true 179 | }); 180 | binding.OnValueChanged += link.ScheduleUpdateText; 181 | binding.Components.Add(component); 182 | } 183 | 184 | lastIndex = match.Index + match.Length; 185 | } 186 | } 187 | 188 | if (lastIndex < text.Length) 189 | { 190 | link.Segments.Add(new TextSegment() 191 | { 192 | Content = text.Substring(lastIndex) 193 | }); 194 | } 195 | 196 | link.ScheduleUpdateText(null); 197 | } 198 | 199 | public void Awake() 200 | { 201 | EnsureInitialized(); 202 | } 203 | 204 | public void EnsureInitialized() 205 | { 206 | if (initialized) 207 | { 208 | return; 209 | } 210 | 211 | var components = GetComponentsInChildren(true); 212 | foreach (var component in components) 213 | { 214 | CreateLink(component); 215 | } 216 | 217 | Initialize(); 218 | initialized = true; 219 | } 220 | 221 | protected virtual void Initialize() 222 | { 223 | 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/BindingView.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dde7687408754d24bbaf871edeae9792 3 | timeCreated: 1737098270 -------------------------------------------------------------------------------- /Scripts/Minity/UI/BindingViewGuard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using UnityEngine; 5 | 6 | namespace Minity.UI 7 | { 8 | public class BindingViewGuard : MonoBehaviour 9 | { 10 | internal static BindingViewGuard Instance; 11 | internal static readonly HashSet ScheduledUpdates = new HashSet(); 12 | 13 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 14 | public static void EnsureCreated() 15 | { 16 | if (Instance) 17 | { 18 | return; 19 | } 20 | 21 | var go = new GameObject("[Binding View Guard]", typeof(BindingViewGuard)); 22 | Instance = go.GetComponent(); 23 | go.SetActive(true); 24 | 25 | DontDestroyOnLoad(go); 26 | } 27 | 28 | internal static void ScheduleUpdate(Action updateAction) 29 | { 30 | EnsureCreated(); 31 | ScheduledUpdates.Add(updateAction); 32 | } 33 | 34 | private void LateUpdate() 35 | { 36 | foreach (var action in ScheduledUpdates) 37 | { 38 | action.Invoke(); 39 | } 40 | 41 | ScheduledUpdates.Clear(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/BindingViewGuard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 193361f6d1b840bb8c00e82bdd7344f5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 1000 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e26c7436f7c947bb8fea4ee24e3afe1c 3 | timeCreated: 1737968792 -------------------------------------------------------------------------------- /Scripts/Minity/UI/Editor/UIListInspector.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using UnityEditor; 6 | using UnityEngine; 7 | using UnityEngine.UIElements; 8 | 9 | namespace Minity.UI.Editor 10 | { 11 | [CustomEditor(typeof(UIList))] 12 | public class UIListInspector : UnityEditor.Editor 13 | { 14 | private string[] modeNames; 15 | private int[] modeValues; 16 | private HashSet foldoutSet; 17 | 18 | private void OnEnable() 19 | { 20 | foldoutSet = new HashSet(); 21 | modeNames = Enum.GetNames(typeof(UIMode)); 22 | modeValues = Enum.GetValues(typeof(UIMode)).Cast().ToArray(); 23 | } 24 | 25 | public override void OnInspectorGUI() 26 | { 27 | var errorHeader = new GUIStyle(EditorStyles.foldoutHeader) 28 | { 29 | normal = 30 | { 31 | textColor = Color.red 32 | }, 33 | active = 34 | { 35 | textColor = Color.red 36 | }, 37 | focused = 38 | { 39 | textColor = Color.red 40 | } 41 | }; 42 | 43 | var set = new HashSet(); 44 | 45 | var list = (UIList)target; 46 | var dirty = false; 47 | for (var i = 0; i < list.List.Count; i++) 48 | { 49 | if (i >= list.List.Count) 50 | { 51 | break; 52 | } 53 | 54 | var ui = list.List[i]; 55 | var duplicated = ui.UI && set.Contains(ui.GetType()); 56 | 57 | if (ui.UI) 58 | { 59 | set.Add(ui.GetType()); 60 | } 61 | 62 | EditorGUILayout.BeginVertical(EditorStyles.helpBox); 63 | 64 | EditorGUILayout.BeginHorizontal(); 65 | EditorGUI.indentLevel = 1; 66 | var foldout = foldoutSet.Contains(ui); 67 | foldout = EditorGUILayout.Foldout(foldout, ui.UI?.EditorName ?? "", ui.UI && !duplicated ? EditorStyles.foldoutHeader : errorHeader); 68 | if (foldout != foldoutSet.Contains(ui)) 69 | { 70 | if (foldout) 71 | { 72 | foldoutSet.Add(ui); 73 | } 74 | else 75 | { 76 | foldoutSet.Remove(ui); 77 | } 78 | } 79 | if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Minus"))) 80 | { 81 | list.List.RemoveAt(i); 82 | i--; 83 | dirty = true; 84 | } 85 | EditorGUI.indentLevel = 0; 86 | EditorGUILayout.EndHorizontal(); 87 | 88 | if (duplicated) 89 | { 90 | EditorGUILayout.HelpBox(" Duplicated UI", MessageType.Error); 91 | } 92 | 93 | if (!foldout) 94 | { 95 | EditorGUILayout.EndVertical(); 96 | continue; 97 | } 98 | 99 | EditorGUI.indentLevel = 1; 100 | var newUI = EditorGUILayout.ObjectField("Prefab Asset", ui.UI, typeof(ManagedUI), false); 101 | if (newUI != ui.UI) 102 | { 103 | list.List[i].UI = (ManagedUI)newUI; 104 | dirty = true; 105 | } 106 | 107 | var newMode = (UIMode)EditorGUILayout.IntPopup("Mode", (int)ui.Mode, modeNames, modeValues); 108 | if (newMode != ui.Mode) 109 | { 110 | list.List[i].Mode = newMode; 111 | dirty = true; 112 | } 113 | 114 | EditorGUILayout.Space(5f); 115 | EditorGUI.indentLevel = 0; 116 | 117 | EditorGUILayout.EndVertical(); 118 | } 119 | EditorGUILayout.Space(10); 120 | if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Plus"))) 121 | { 122 | var item = new UIList.UIConfig(); 123 | list.List.Add(item); 124 | foldoutSet.Add(item); 125 | dirty = true; 126 | } 127 | 128 | if (dirty) 129 | { 130 | EditorUtility.SetDirty(target); 131 | AssetDatabase.SaveAssets(); 132 | } 133 | } 134 | } 135 | } 136 | #endif 137 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/Editor/UIListInspector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93d7888135e44bd0b555373b69e67dbc 3 | timeCreated: 1737968803 -------------------------------------------------------------------------------- /Scripts/Minity/UI/ManagedUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | using Milease.Core; 6 | using Milease.Core.Animator; 7 | using Milease.DSL; 8 | using Milease.Enums; 9 | using Milease.Utils; 10 | using Minity.Logger; 11 | using UnityEngine; 12 | using UnityEngine.UI; 13 | 14 | namespace Minity.UI 15 | { 16 | [RequireComponent(typeof(Canvas))] 17 | [RequireComponent(typeof(CanvasGroup))] 18 | public abstract class ManagedUI : MonoBehaviour 19 | { 20 | internal abstract string EditorName { get; } 21 | 22 | internal UI Source; 23 | internal Action CloseInternalCallback; 24 | internal object Callback; 25 | 26 | internal bool WithTransition; 27 | 28 | private MilInstantAnimator fadeInAnimator, fadeOutAnimator; 29 | private CanvasGroup group; 30 | private Canvas canvas; 31 | 32 | private bool closing = false; 33 | private bool opening = false; 34 | 35 | internal void SetSortingOrder(int order) 36 | { 37 | canvas.sortingOrder = order; 38 | } 39 | 40 | protected void OverrideInTransition(MilInstantAnimator animator) 41 | => fadeInAnimator = animator; 42 | 43 | protected void OverrideOutTransition(MilInstantAnimator animator) 44 | => fadeOutAnimator = animator; 45 | 46 | 47 | private void Awake() 48 | { 49 | group = GetComponent(); 50 | canvas = GetComponent(); 51 | 52 | Begin(); 53 | 54 | fadeInAnimator ??= 55 | (0.25f / group.MQuadOut(x => x.alpha, 0f, 1f)) 56 | .UsingResetMode(AnimationResetMode.ResetToInitialState); 57 | 58 | fadeOutAnimator ??= 59 | (0.25f / group.MQuad(x => x.alpha, 1f, 0f)) 60 | .UsingResetMode(AnimationResetMode.ResetToInitialState); 61 | } 62 | 63 | private void OnEnable() 64 | { 65 | closing = false; 66 | if (WithTransition) 67 | { 68 | opening = true; 69 | group.enabled = true; 70 | group.alpha = 1f; 71 | fadeInAnimator.PlayImmediately(() => 72 | { 73 | opening = false; 74 | group.enabled = false; 75 | }); 76 | } 77 | else 78 | { 79 | opening = false; 80 | group.enabled = false; 81 | } 82 | } 83 | 84 | protected abstract void Begin(); 85 | protected abstract void AboutToClose(); 86 | 87 | internal abstract void Open(object parameter); 88 | 89 | private void OnClosed() 90 | { 91 | CloseInternalCallback?.Invoke(); 92 | closing = false; 93 | if (Source.Mode != UIMode.Singleton) 94 | { 95 | Destroy(gameObject); 96 | } 97 | else 98 | { 99 | gameObject.SetActive(false); 100 | } 101 | } 102 | 103 | internal void CloseInternal() 104 | { 105 | if (opening) 106 | { 107 | return; 108 | } 109 | 110 | if (closing) 111 | { 112 | DebugLog.LogWarning("Duplicated closing operation on UI."); 113 | return; 114 | } 115 | 116 | UIManager.CurrentSortingOrder--; 117 | if (WithTransition) 118 | { 119 | closing = true; 120 | group.enabled = true; 121 | group.alpha = 1f; 122 | fadeOutAnimator.PlayImmediately(OnClosed); 123 | } 124 | else 125 | { 126 | OnClosed(); 127 | } 128 | } 129 | } 130 | 131 | public abstract class ManagedUIReturnValueOnly : ManagedUI 132 | { 133 | internal override string EditorName => $"{typeof(R).Name} {typeof(T).Name}();"; 134 | public static void Open(Action callback = null) 135 | { 136 | UIManager.Get(typeof(ManagedUIReturnValueOnly)) 137 | .Open(callback); 138 | } 139 | 140 | public static Task OpenAsync() 141 | { 142 | var tcs = new TaskCompletionSource(); 143 | UIManager.Get(typeof(ManagedUIReturnValueOnly)) 144 | .Open((R ret) => tcs.TrySetResult(ret)); 145 | return tcs.Task; 146 | } 147 | 148 | internal override void Open(object parameter) 149 | { 150 | AboutToOpen(); 151 | } 152 | 153 | public void Close(R returnValue) 154 | { 155 | CloseInternalCallback = () => 156 | { 157 | ((Action)Callback)?.Invoke(returnValue); 158 | }; 159 | AboutToClose(); 160 | CloseInternal(); 161 | } 162 | 163 | public abstract void AboutToOpen(); 164 | } 165 | 166 | public abstract class ManagedUI : ManagedUI 167 | { 168 | internal override string EditorName => $"void {typeof(T).Name}({typeof(P).Name} parameter);"; 169 | public static void Open(P parameter, Action callback = null) 170 | { 171 | UIManager.Get(typeof(ManagedUI)) 172 | .SetParameter(parameter) 173 | .Open(callback); 174 | } 175 | 176 | public static Task OpenAsync(P parameter) 177 | { 178 | var tcs = new TaskCompletionSource(); 179 | UIManager.Get(typeof(ManagedUI)) 180 | .SetParameter(parameter) 181 | .Open(() => tcs.TrySetResult(true)); 182 | return tcs.Task; 183 | } 184 | 185 | internal override void Open(object parameter) 186 | { 187 | AboutToOpen((P)parameter); 188 | } 189 | 190 | public void Close() 191 | { 192 | CloseInternalCallback = () => 193 | { 194 | ((Action)Callback)?.Invoke(); 195 | }; 196 | AboutToClose(); 197 | CloseInternal(); 198 | } 199 | 200 | public abstract void AboutToOpen(P parameter); 201 | } 202 | 203 | public abstract class ManagedUI : ManagedUI 204 | { 205 | internal override string EditorName => $"{typeof(R).Name} {typeof(T).Name}({typeof(P).Name} parameter);"; 206 | public static void Open(P parameter, Action callback = null) 207 | { 208 | UIManager.Get(typeof(ManagedUI)) 209 | .SetParameter(parameter) 210 | .Open(callback); 211 | } 212 | 213 | public static Task OpenAsync(P parameter) 214 | { 215 | var tcs = new TaskCompletionSource(); 216 | UIManager.Get(typeof(ManagedUI)) 217 | .SetParameter(parameter) 218 | .Open((R ret) => tcs.TrySetResult(ret)); 219 | return tcs.Task; 220 | } 221 | 222 | internal override void Open(object parameter) 223 | { 224 | AboutToOpen((P)parameter); 225 | } 226 | 227 | public void Close(R returnValue) 228 | { 229 | CloseInternalCallback = () => 230 | { 231 | ((Action)Callback)?.Invoke(returnValue); 232 | }; 233 | AboutToClose(); 234 | CloseInternal(); 235 | } 236 | 237 | public abstract void AboutToOpen(P parameter); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/ManagedUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f514fd557e5343d497838c24a64431c3 3 | timeCreated: 1729061532 -------------------------------------------------------------------------------- /Scripts/Minity/UI/SimpleManagedUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Minity.UI 4 | { 5 | public class SimpleManagedUI : ManagedUI 6 | { 7 | internal override string EditorName => $"void {name}();"; 8 | 9 | protected override void Begin() 10 | { 11 | 12 | } 13 | 14 | protected override void AboutToClose() 15 | { 16 | 17 | } 18 | 19 | internal override void Open(object parameter) 20 | { 21 | 22 | } 23 | 24 | public void Close() 25 | { 26 | CloseInternalCallback = null; 27 | CloseInternal(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/SimpleManagedUI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9935c9e8de534c0988f5f3ae383ae644 3 | timeCreated: 1729063952 -------------------------------------------------------------------------------- /Scripts/Minity/UI/UI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Minity.Logger; 5 | using Minity.General; 6 | using UnityEngine; 7 | using Object = UnityEngine.Object; 8 | 9 | namespace Minity.UI 10 | { 11 | public enum UIMode 12 | { 13 | Default, Singleton 14 | } 15 | 16 | public enum BuiltinUI 17 | { 18 | AnonymousUI 19 | } 20 | 21 | public class UI 22 | { 23 | internal EnumIdentifier Identifier; 24 | internal Type ParameterType = null; 25 | internal Type ReturnValueType = null; 26 | internal Type TypeDefinition; 27 | internal GameObject Prefab; 28 | internal UIMode Mode = UIMode.Default; 29 | 30 | internal GameObject Instance; 31 | 32 | internal UI() 33 | { 34 | 35 | } 36 | 37 | internal GameObject Create() 38 | { 39 | if (Mode == UIMode.Singleton) 40 | { 41 | if (!Instance) 42 | { 43 | Instance = Object.Instantiate(Prefab); 44 | } 45 | Object.DontDestroyOnLoad(Instance); 46 | return Instance; 47 | } 48 | 49 | return Object.Instantiate(Prefab); 50 | } 51 | 52 | public static IEnumerable FromUIList(string uiListPath) 53 | { 54 | var list = Resources.Load(uiListPath); 55 | return list.List.Select(x => 56 | { 57 | if (!x.UI) 58 | { 59 | return null; 60 | } 61 | var ui = FromPrefab(BuiltinUI.AnonymousUI, x.UI.gameObject); 62 | ui.Mode = x.Mode; 63 | return ui; 64 | }); 65 | } 66 | 67 | public static UI FromResources(string prefabPath) 68 | => FromPrefab(BuiltinUI.AnonymousUI, Resources.Load(prefabPath)); 69 | 70 | public static UI FromPrefab(GameObject prefab) 71 | => FromPrefab(BuiltinUI.AnonymousUI, prefab); 72 | 73 | public static UI FromResources(T identifier, string prefabPath) where T : Enum 74 | => FromPrefab(identifier, Resources.Load(prefabPath)); 75 | 76 | public static UI FromPrefab(T identifier, GameObject prefab) where T : Enum 77 | { 78 | if (!prefab.TryGetComponent(out var ui)) 79 | { 80 | throw new Exception($"UI '{identifier}'({prefab.name}) must have a ManagedUI component."); 81 | } 82 | 83 | var type = ui.GetType(); 84 | while (type != null && type.BaseType != null) 85 | { 86 | if (type.IsGenericType && type.BaseType == typeof(ManagedUI)) 87 | { 88 | break; 89 | } 90 | type = type.BaseType; 91 | } 92 | 93 | if (identifier is BuiltinUI id && id == BuiltinUI.AnonymousUI && type == typeof(SimpleManagedUI)) 94 | { 95 | throw new Exception($"SimpleManagedUI '{identifier}'({prefab.name}) must have an identifier."); 96 | } 97 | 98 | var data = new UI() 99 | { 100 | Identifier = EnumIdentifier.Wrap(identifier), 101 | Prefab = prefab, 102 | TypeDefinition = type 103 | }; 104 | prefab.SetActive(false); 105 | 106 | var genericType = type.GetGenericTypeDefinition(); 107 | var args = type.GetGenericArguments(); 108 | 109 | if (genericType == typeof(ManagedUI<,>)) 110 | { 111 | data.ParameterType = args[1]; 112 | } 113 | else if (genericType == typeof(ManagedUI<,,>)) 114 | { 115 | data.ParameterType = args[1]; 116 | data.ReturnValueType = args[2]; 117 | } 118 | else if (genericType == typeof(ManagedUIReturnValueOnly<,>)) 119 | { 120 | data.ReturnValueType = args[1]; 121 | } 122 | 123 | return data; 124 | } 125 | 126 | public UI SingletonMode() 127 | { 128 | Mode = UIMode.Singleton; 129 | return this; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/UI.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 646a44eba109434a8aadf46446535dcd 3 | timeCreated: 1729062270 -------------------------------------------------------------------------------- /Scripts/Minity/UI/UIContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Minity.Logger; 3 | 4 | namespace Minity.UI 5 | { 6 | public class UIContext 7 | { 8 | internal UI UI; 9 | internal object Parameter = null; 10 | internal bool WithTransition = true; 11 | 12 | public UIContext SetParameter(T parameter) 13 | { 14 | if (UI.ParameterType == null) 15 | { 16 | DebugLog.LogError($"UI '{UI.Identifier}' does not need a parameter."); 17 | return this; 18 | } 19 | if (typeof(T) != UI.ParameterType) 20 | { 21 | DebugLog.LogError($"Parameter for UI '{UI.Identifier}' is incorrect, " + 22 | $"expected type: {UI.ParameterType.FullName}, actual: {typeof(T).FullName}"); 23 | return this; 24 | } 25 | 26 | Parameter = parameter; 27 | return this; 28 | } 29 | 30 | public UIContext WithoutTransition() 31 | { 32 | WithTransition = false; 33 | return this; 34 | } 35 | 36 | public void Open(Action callback = null) 37 | { 38 | OpenInternal(callback); 39 | } 40 | 41 | public void Open(Action callback = null) 42 | { 43 | if (UI.ReturnValueType != null && callback != null) 44 | { 45 | DebugLog.LogError($"Specific UI '{UI.Identifier}' has return value, use Open() instead."); 46 | return; 47 | } 48 | OpenInternal(callback); 49 | } 50 | 51 | private void OpenInternal(object callback) 52 | { 53 | if (Parameter == null && UI.ParameterType != null) 54 | { 55 | DebugLog.LogWarning($"UI '{UI.Identifier}' requires {UI.ParameterType.FullName} parameter, but it is absent."); 56 | } 57 | var go = UI.Create(); 58 | var ui = go.GetComponent(); 59 | ui.Source = UI; 60 | ui.WithTransition = WithTransition; 61 | ui.Callback = callback; 62 | ui.Open(Parameter); 63 | go.SetActive(true); 64 | 65 | ui.SetSortingOrder(UIManager.CurrentSortingOrder); 66 | UIManager.CurrentSortingOrder++; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/UIContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93f991ce9a4941cea172492b180a3a54 3 | timeCreated: 1729063510 -------------------------------------------------------------------------------- /Scripts/Minity/UI/UIList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace Minity.UI 6 | { 7 | [CreateAssetMenu(fileName = "UIList", menuName = "Minity/UI List")] 8 | public class UIList : ScriptableObject 9 | { 10 | [Serializable] 11 | public class UIConfig 12 | { 13 | public ManagedUI UI; 14 | public UIMode Mode; 15 | } 16 | public List List = new List(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/UIList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e75181dc8b2747109d0131cb80df5a6b 3 | timeCreated: 1737967195 -------------------------------------------------------------------------------- /Scripts/Minity/UI/UIManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Minity.Logger; 4 | using Minity.General; 5 | #if !NET_STANDARD_2_1 6 | using Paraparty.UnityPolyfill; 7 | #endif 8 | 9 | namespace Minity.UI 10 | { 11 | public static class UIManager 12 | { 13 | internal static readonly Dictionary UIDict = new Dictionary(); 14 | internal static readonly Dictionary UIDictInternal = new Dictionary(); 15 | 16 | internal static int CurrentSortingOrder = 1000; 17 | 18 | private static bool configured = false; 19 | 20 | public static void Setup(IEnumerable ui) 21 | { 22 | if (configured) 23 | { 24 | DebugLog.LogError("Duplicated configuring UI manager."); 25 | return; 26 | } 27 | 28 | foreach (var u in ui) 29 | { 30 | if (u == null) 31 | { 32 | continue; 33 | } 34 | 35 | if (!(u.Identifier.Type == typeof(BuiltinUI) && u.Identifier.Value == (int)BuiltinUI.AnonymousUI)) 36 | { 37 | UIDict.Add(u.Identifier, u); 38 | } 39 | 40 | if (u.TypeDefinition == typeof(SimpleManagedUI)) 41 | { 42 | continue; 43 | } 44 | 45 | if (!UIDictInternal.TryAdd(u.TypeDefinition, u)) 46 | { 47 | DebugLog.LogError($"Duplicated UI type: {u.TypeDefinition.FullName}"); 48 | } 49 | } 50 | 51 | configured = true; 52 | } 53 | 54 | public static UIContext Get(T identifier) where T : Enum 55 | { 56 | if (!configured) 57 | { 58 | DebugLog.LogError("UI manager has not been setup."); 59 | return null; 60 | } 61 | 62 | var key = EnumIdentifier.Wrap(identifier); 63 | if (!UIDict.ContainsKey(key)) 64 | { 65 | DebugLog.LogError($"Specific UI '{key}' was not registered, please configure the UI manager first."); 66 | } 67 | 68 | return new UIContext() 69 | { 70 | UI = UIDict[key] 71 | }; 72 | } 73 | 74 | internal static UIContext Get(Type type) 75 | { 76 | if (!configured) 77 | { 78 | DebugLog.LogError("UI manager has not been setup."); 79 | return null; 80 | } 81 | 82 | if (type == typeof(SimpleManagedUI)) 83 | { 84 | DebugLog.LogError("Cannot open a SimpleManagedUI by this method."); 85 | return null; 86 | } 87 | 88 | if (!UIDictInternal.ContainsKey(type)) 89 | { 90 | DebugLog.LogError($"Specific UI '{type.FullName}' was not registered, please configure the UI manager first."); 91 | } 92 | 93 | return new UIContext() 94 | { 95 | UI = UIDictInternal[type] 96 | }; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/UIManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4d0086823e5c40a58eb486b5a0605b6e 3 | timeCreated: 1729061480 -------------------------------------------------------------------------------- /Scripts/Minity/UI/VarBinding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Minity.Variable; 3 | using UnityEngine; 4 | 5 | namespace Minity.UI 6 | { 7 | [Serializable] 8 | public class VarBinding : BindingBase, ISerializationCallbackReceiver 9 | { 10 | [SerializeField] 11 | private MinityVariable Variable; 12 | 13 | public T Value 14 | { 15 | set => Variable.SetValue(value); 16 | get => (T)Variable.GetValue(); 17 | } 18 | 19 | internal override object GetValue() 20 | { 21 | return Variable.GetValue(); 22 | } 23 | 24 | public void OnBeforeSerialize() 25 | { 26 | 27 | } 28 | 29 | public void OnAfterDeserialize() 30 | { 31 | if (!Variable) 32 | { 33 | return; 34 | } 35 | Variable.InternalChangedEvent += RaiseUpValueChangedEvent; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Scripts/Minity/UI/VarBinding.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01157878eb45419b9f9a45df949be849 3 | timeCreated: 1737979549 -------------------------------------------------------------------------------- /Scripts/Minity/Variable.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 24d9c7db234a4ee9a1d6f880f6e68001 3 | timeCreated: 1737975447 -------------------------------------------------------------------------------- /Scripts/Minity/Variable/CommonVariables.ignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/CommonVariables.ignore.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8127037ee44036c4391b8b744f01dd20 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/CommonVariables.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="true" language="C#" #> 2 | <#@ output extension=".ignore" #> 3 | <#@ assembly name="System.Core" #> 4 | <#@ import namespace="System" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ import namespace="System.IO" #> 7 | 8 | <# 9 | var types = new Dictionary() 10 | { 11 | ["Primitive"] = [ "int", "bool", "float", "string", "double" ], 12 | ["General"] = [ "GameObject", "Component", "Transform", "RectTransform" ], 13 | ["Graphics"] = [ "Sprite", "Texture2D", "Texture", "Material", "Mesh" ], 14 | ["Physics"] = [ "Collider", "Collider2D", "Rigidbody", "Rigidbody2D" ], 15 | ["Struct"] = [ "Color", "Vector2", "Vector3", "Rect" ], 16 | }; 17 | 18 | var outputDir = Path.GetDirectoryName(Host.TemplateFile); 19 | 20 | foreach (var pair in types) 21 | { 22 | foreach (var type in pair.Value) 23 | { 24 | var name = type; 25 | if (char.IsLower(name[0])) 26 | { 27 | name = char.ToUpper(name[0]) + name.Substring(1); 28 | } 29 | var path = Path.Combine(outputDir, pair.Key); 30 | if (!Directory.Exists(path)) 31 | { 32 | Directory.CreateDirectory(path); 33 | } 34 | 35 | var code = $@"using System; 36 | using UnityEngine; 37 | 38 | namespace Minity.Variable 39 | {{ 40 | [CreateAssetMenu(fileName = ""{name}"", menuName = ""Minity/Variable/{pair.Key}/{name}Var"")] 41 | public class {name}Var : MinityVariable<{type}> {{}} 42 | }} 43 | "; 44 | File.WriteAllText(Path.Combine(path, $"{name}Var.cs"), code); 45 | } 46 | } 47 | #> 48 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/CommonVariables.tt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e66dd88f27b4b18abf2b4cf269207fb 3 | timeCreated: 1737976406 -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 226745fa9d11479598ad339ee32d2abd 3 | timeCreated: 1737977356 -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Editor/MinityVariableInspector.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | #if !NET_STANDARD_2_1 6 | using Paraparty.UnityPolyfill; 7 | #endif 8 | using UnityEditor; 9 | using UnityEngine; 10 | 11 | namespace Minity.Variable.Editor 12 | { 13 | [InitializeOnLoad] 14 | public class MinityVariableReset 15 | { 16 | public static readonly Stack Variables = new Stack(); 17 | 18 | static MinityVariableReset() 19 | { 20 | EditorApplication.playModeStateChanged += OnPlayModeStateChanged; 21 | } 22 | 23 | private static void OnPlayModeStateChanged(PlayModeStateChange state) 24 | { 25 | if (state == PlayModeStateChange.ExitingPlayMode) 26 | { 27 | while (Variables.TryPop(out var variable)) 28 | { 29 | variable.ResetToInitial(); 30 | } 31 | } 32 | } 33 | } 34 | 35 | [CustomEditor(typeof(MinityVariableBase), true)] 36 | public class MinityVariableInspector : UnityEditor.Editor 37 | { 38 | public override void OnInspectorGUI() 39 | { 40 | serializedObject.Update(); 41 | var variable = (MinityVariableBase)target; 42 | 43 | EditorGUILayout.LabelField("General", EditorStyles.boldLabel); 44 | EditorGUILayout.PropertyField(serializedObject.FindProperty("InspectorValue"), new GUIContent("Value")); 45 | 46 | EditorGUILayout.Separator(); 47 | 48 | EditorGUILayout.LabelField("Status", EditorStyles.boldLabel); 49 | GUI.enabled = false; 50 | EditorGUILayout.ToggleLeft("Changed since last update", variable.ChangedSinceLastUpdate); 51 | EditorGUILayout.ToggleLeft("Changed since last fixedUpdate", variable.ChangedSinceLastFixedUpdate); 52 | GUI.enabled = true; 53 | 54 | serializedObject.ApplyModifiedProperties(); 55 | } 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Editor/MinityVariableInspector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9016fbd4ed3424fa29823e191a21bd0 3 | timeCreated: 1737977366 -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56a2d04bc83616e43aafdd032097d9a1 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/ComponentVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Component", menuName = "Minity/Variable/General/ComponentVar")] 7 | public class ComponentVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/ComponentVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e9bdf366af9cfb408aecf5dfed97d1f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/GameObjectVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "GameObject", menuName = "Minity/Variable/General/GameObjectVar")] 7 | public class GameObjectVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/GameObjectVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eb71559557d9e1f46870bd569f021864 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/RectTransformVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "RectTransform", menuName = "Minity/Variable/General/RectTransformVar")] 7 | public class RectTransformVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/RectTransformVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6bdd84030b411094992cb5298317d35f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/TransformVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Transform", menuName = "Minity/Variable/General/TransformVar")] 7 | public class TransformVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/General/TransformVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 763407e37cbe1844bb7c060b3e0739e8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f510ec376210de547933ddb77fb6e557 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/MaterialVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Material", menuName = "Minity/Variable/Graphics/MaterialVar")] 7 | public class MaterialVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/MaterialVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd67fd7094647b540a7fab44294b57d7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/MeshVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Mesh", menuName = "Minity/Variable/Graphics/MeshVar")] 7 | public class MeshVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/MeshVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 643f495887066ae4fa27cc4e8a7aab52 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/SpriteVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Sprite", menuName = "Minity/Variable/Graphics/SpriteVar")] 7 | public class SpriteVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/SpriteVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aa34928df3df02245b8de883bafad993 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/Texture2DVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Texture2D", menuName = "Minity/Variable/Graphics/Texture2DVar")] 7 | public class Texture2DVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/Texture2DVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a4b0e70b8e7048a49afa896441297c68 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/TextureVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Texture", menuName = "Minity/Variable/Graphics/TextureVar")] 7 | public class TextureVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Graphics/TextureVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d74d273cc07927a4cb84e15c607159b1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/MinityVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | #if UNITY_EDITOR 3 | using Minity.Variable.Editor; 4 | #endif 5 | using UnityEngine; 6 | 7 | namespace Minity.Variable 8 | { 9 | public delegate void VariableChangedEvent(T lastValue, T newValue); 10 | 11 | public abstract class MinityVariableBase : ScriptableObject 12 | { 13 | public bool ChangedSinceLastUpdate { get; internal set; } 14 | public bool ChangedSinceLastFixedUpdate { get; internal set; } 15 | 16 | protected object _value; 17 | 18 | internal event Action InternalChangedEvent; 19 | 20 | internal object GetValue() 21 | { 22 | return _value; 23 | } 24 | 25 | internal abstract void SetValue(object value); 26 | internal abstract void SetInspectorValue(object value); 27 | internal abstract void RegisterOnChangedListener(object listener); 28 | internal abstract void ResetToInitial(); 29 | 30 | internal void RaiseInternalChangedEvent() 31 | { 32 | InternalChangedEvent?.Invoke(); 33 | } 34 | } 35 | 36 | public abstract class MinityVariable : MinityVariableBase 37 | { 38 | public T Value 39 | { 40 | get => (T)_value; 41 | set 42 | { 43 | OnChanged?.Invoke((T)_value, value); 44 | RaiseInternalChangedEvent(); 45 | 46 | _value = value; 47 | 48 | muteValidate = true; 49 | InspectorValue = value; 50 | muteValidate = false; 51 | 52 | ChangedSinceLastUpdate = true; 53 | ChangedSinceLastFixedUpdate = true; 54 | 55 | MinityVariableGuard.ChangedSinceLastUpdate.Push(this); 56 | MinityVariableGuard.ChangedSinceLastFixedUpdate.Push(this); 57 | } 58 | } 59 | 60 | [SerializeField] 61 | internal T InspectorValue; 62 | 63 | private T initialValue; 64 | 65 | public event VariableChangedEvent OnChanged; 66 | 67 | private bool muteValidate = false; 68 | 69 | internal override void SetInspectorValue(object value) 70 | { 71 | muteValidate = true; 72 | InspectorValue = (T)value; 73 | muteValidate = false; 74 | } 75 | 76 | internal override void RegisterOnChangedListener(object listener) 77 | { 78 | OnChanged += (VariableChangedEvent)listener; 79 | } 80 | 81 | internal override void SetValue(object value) 82 | { 83 | Value = (T)value; 84 | } 85 | 86 | private void OnEnable() 87 | { 88 | _value = InspectorValue; 89 | initialValue = InspectorValue; 90 | #if UNITY_EDITOR 91 | MinityVariableReset.Variables.Push(this); 92 | #endif 93 | } 94 | 95 | internal override void ResetToInitial() 96 | { 97 | InspectorValue = initialValue; 98 | } 99 | 100 | private void OnValidate() 101 | { 102 | if (muteValidate) 103 | { 104 | return; 105 | } 106 | 107 | Value = InspectorValue; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/MinityVariable.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5f729496a01e43a0ace70ce0a96c36e1 3 | timeCreated: 1737975464 -------------------------------------------------------------------------------- /Scripts/Minity/Variable/MinityVariableGuard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | #if !NET_STANDARD_2_1 4 | using Paraparty.UnityPolyfill; 5 | #endif 6 | using UnityEngine; 7 | 8 | namespace Minity.Variable 9 | { 10 | public class MinityVariableGuard : MonoBehaviour 11 | { 12 | internal static MinityVariableGuard Instance; 13 | internal static readonly Stack ChangedSinceLastUpdate = new Stack(); 14 | internal static readonly Stack ChangedSinceLastFixedUpdate = new Stack(); 15 | 16 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] 17 | internal static void EnsureInitialized() 18 | { 19 | if (Instance) 20 | { 21 | return; 22 | } 23 | 24 | var go = new GameObject("[Minity Variable Guard]", typeof(MinityVariableGuard)); 25 | go.SetActive(true); 26 | Instance = go.GetComponent(); 27 | DontDestroyOnLoad(go); 28 | } 29 | 30 | private void FixedUpdate() 31 | { 32 | while (ChangedSinceLastFixedUpdate.TryPop(out var variable)) 33 | { 34 | variable.ChangedSinceLastFixedUpdate = false; 35 | } 36 | } 37 | 38 | private void LateUpdate() 39 | { 40 | while (ChangedSinceLastUpdate.TryPop(out var variable)) 41 | { 42 | variable.ChangedSinceLastUpdate = false; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/MinityVariableGuard.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ee2c8a0a8dc4ccb909e7b1de8367775 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 1100 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3f56f31aac1013e4898260dcb87d1936 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/Collider2DVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Collider2D", menuName = "Minity/Variable/Physics/Collider2DVar")] 7 | public class Collider2DVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/Collider2DVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3819335706ee04438a8880907ae1137 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/ColliderVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Collider", menuName = "Minity/Variable/Physics/ColliderVar")] 7 | public class ColliderVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/ColliderVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 73633c9291232c34083b02c88f80a5c6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/Rigidbody2DVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Rigidbody2D", menuName = "Minity/Variable/Physics/Rigidbody2DVar")] 7 | public class Rigidbody2DVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/Rigidbody2DVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d267456ccb9c58444a4e462c170f9459 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/RigidbodyVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Rigidbody", menuName = "Minity/Variable/Physics/RigidbodyVar")] 7 | public class RigidbodyVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Physics/RigidbodyVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1a7dc62e5e7b6b40a089d260b5ecda1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dea6d80ff0b088c41b8c98b18ab28e7a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/BoolVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Bool", menuName = "Minity/Variable/Primitive/BoolVar")] 7 | public class BoolVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/BoolVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 72424ead7e8089945a4ebe2fbe9911b5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/DoubleVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Double", menuName = "Minity/Variable/Primitive/DoubleVar")] 7 | public class DoubleVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/DoubleVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16a0f2f8e0029da44b0a368ead435741 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/FloatVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Float", menuName = "Minity/Variable/Primitive/FloatVar")] 7 | public class FloatVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/FloatVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1932237d796a2f4ab8615acbde1f83f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/IntVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Int", menuName = "Minity/Variable/Primitive/IntVar")] 7 | public class IntVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/IntVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e994e580ccb21bc4aa5187bb3da9e691 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/StringVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "String", menuName = "Minity/Variable/Primitive/StringVar")] 7 | public class StringVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Primitive/StringVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 37256f20691b9c04b880a921c2a5cb03 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5e041431850b721479c6ba704dae6b69 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/ColorVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Color", menuName = "Minity/Variable/Struct/ColorVar")] 7 | public class ColorVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/ColorVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2234849666b4f174b80a71a76fff8ec5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/RectVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Rect", menuName = "Minity/Variable/Struct/RectVar")] 7 | public class RectVar : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/RectVar.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3d38cec5ee04d34a8187c78d612b4c6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/Vector2Var.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Vector2", menuName = "Minity/Variable/Struct/Vector2Var")] 7 | public class Vector2Var : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/Vector2Var.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c6396cdfd3a7e44ea935b5596fdee0b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/Vector3Var.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | namespace Minity.Variable 5 | { 6 | [CreateAssetMenu(fileName = "Vector3", menuName = "Minity/Variable/Struct/Vector3Var")] 7 | public class Vector3Var : MinityVariable {} 8 | } 9 | -------------------------------------------------------------------------------- /Scripts/Minity/Variable/Struct/Vector3Var.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d0baed2d76cf3b4daabfe39836d9fa5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/dev.milthm.minity.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dev.milthm.minity", 3 | "rootNamespace": "Minity", 4 | "references": [ 5 | "GUID:6055c4ca3d336984698eda24b99f7071", 6 | "GUID:5baad4e8b0c589044b804563fec3b23b", 7 | "GUID:6055be8ebefd69e48b49212b09b47b2f", 8 | "GUID:bb775c4a28c173f4a81035e4d2cff768", 9 | "GUID:b9110418f5f00484e89198f034f1d7d7" 10 | ], 11 | "includePlatforms": [], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": false, 14 | "overrideReferences": false, 15 | "precompiledReferences": [], 16 | "autoReferenced": true, 17 | "defineConstraints": [], 18 | "versionDefines": [], 19 | "noEngineReferences": false 20 | } -------------------------------------------------------------------------------- /Scripts/dev.milthm.minity.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8104722c17399b458f20070a8e097c3 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.collab-proxy": "2.2.0", 4 | "com.unity.feature.2d": "2.0.0", 5 | "com.unity.ide.rider": "3.0.24", 6 | "com.unity.ide.visualstudio": "2.0.18", 7 | "com.unity.test-framework": "1.1.33", 8 | "com.unity.textmeshpro": "3.0.6", 9 | "com.unity.timeline": "1.7.5", 10 | "com.unity.ugui": "1.0.0", 11 | "com.unity.visualscripting": "1.9.0", 12 | "com.unity.modules.ai": "1.0.0", 13 | "com.unity.modules.androidjni": "1.0.0", 14 | "com.unity.modules.animation": "1.0.0", 15 | "com.unity.modules.assetbundle": "1.0.0", 16 | "com.unity.modules.audio": "1.0.0", 17 | "com.unity.modules.cloth": "1.0.0", 18 | "com.unity.modules.director": "1.0.0", 19 | "com.unity.modules.imageconversion": "1.0.0", 20 | "com.unity.modules.imgui": "1.0.0", 21 | "com.unity.modules.jsonserialize": "1.0.0", 22 | "com.unity.modules.particlesystem": "1.0.0", 23 | "com.unity.modules.physics": "1.0.0", 24 | "com.unity.modules.physics2d": "1.0.0", 25 | "com.unity.modules.screencapture": "1.0.0", 26 | "com.unity.modules.terrain": "1.0.0", 27 | "com.unity.modules.terrainphysics": "1.0.0", 28 | "com.unity.modules.tilemap": "1.0.0", 29 | "com.unity.modules.ui": "1.0.0", 30 | "com.unity.modules.uielements": "1.0.0", 31 | "com.unity.modules.umbra": "1.0.0", 32 | "com.unity.modules.unityanalytics": "1.0.0", 33 | "com.unity.modules.unitywebrequest": "1.0.0", 34 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 35 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 36 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 37 | "com.unity.modules.unitywebrequestwww": "1.0.0", 38 | "com.unity.modules.vehicles": "1.0.0", 39 | "com.unity.modules.video": "1.0.0", 40 | "com.unity.modules.vr": "1.0.0", 41 | "com.unity.modules.wind": "1.0.0", 42 | "com.unity.modules.xr": "1.0.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /manifest.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15d8d6851ab6ece44b7f1dd7ba098d78 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dev.milthm.minity", 3 | "author": "Morizero", 4 | "displayName": "Minity", 5 | "version": "1.0.0", 6 | "unity": "2021.3", 7 | "description": "A Unity extension framework that includes features such as object pooling, scene routing, UI manager, and behavior trees." 8 | } 9 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b94191b01d536d4cbef593974fb1e65 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /xLua Support.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MorizeroDev/Minity/4e0559c1b5ebeb1262c2b38a27e6bfc3b1db457c/xLua Support.unitypackage -------------------------------------------------------------------------------- /xLua Support.unitypackage.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9d9e27bbd040b846a3808220f0aaec9 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------