├── Website ├── banner.png ├── favicon.ico ├── styles.css ├── app.js └── index.html ├── com.cyan.playerobjectpool ├── Editor.meta ├── Editor │ ├── CyanPlayerObjectPoolEditor.cs.meta │ ├── CyanPlayerObjectAssignerEditor.cs.meta │ ├── CyanPlayerObjectPoolEditorHelpers.cs.meta │ ├── Cyan.PlayerObjectPool.Editor.asmdef.meta │ ├── Cyan.PlayerObjectPool.Editor.asmdef │ ├── CyanPlayerObjectPoolEditorHelpers.cs │ ├── CyanPlayerObjectAssignerEditor.cs │ └── CyanPlayerObjectPoolEditor.cs ├── UdonSharp │ ├── CyanPlayerObjectPoolObject.cs.meta │ ├── CyanPlayerObjectPoolEventListener.cs.meta │ ├── Cyan.PlayerObjectPool.UdonSharp.asmdef.meta │ ├── CyanPlayerObjectPool.asset.meta │ ├── CyanPlayerObjectAssigner.asset.meta │ ├── Cyan.PlayerObjectPool.UdonSharp.asset.meta │ ├── CyanPlayerObjectPool.cs.meta │ ├── CyanPlayerObjectAssigner.cs.meta │ ├── Cyan.PlayerObjectPool.UdonSharp.asmdef │ ├── Cyan.PlayerObjectPool.UdonSharp.asset │ ├── CyanPlayerObjectPoolObject.cs │ └── CyanPlayerObjectPoolEventListener.cs ├── LICENSE.md.meta ├── Readme.txt.meta ├── package.json.meta ├── PlayerObjectPool.prefab.meta ├── PlayerObjectAssigner.prefab.meta ├── Runtime.meta ├── UdonSharp.meta ├── Examples~ │ ├── CyanTrigger.meta │ ├── UdonGraph.meta │ ├── UdonSharp.meta │ ├── CyanTrigger │ │ ├── TemplatePooledObject.prefab.meta │ │ ├── TemplatePoolEventListener.prefab.meta │ │ ├── DemoCyanTriggerPooledObject (0).prefab.meta │ │ ├── Example PlayerObjectPool CyanTrigger.unity.meta │ │ ├── TemplatePooledObject.prefab │ │ └── TemplatePoolEventListener.prefab │ ├── UdonSharp │ │ ├── DemoPooledObject (0).prefab.meta │ │ ├── Example PlayerObjectPool UdonSharp.unity.meta │ │ ├── DemoPooledObject.asset.meta │ │ ├── TemplatePooledObject.asset.meta │ │ ├── DemoPoolEventListener.asset.meta │ │ ├── TemplatePoolEventListener.asset.meta │ │ ├── DemoPooledObject.cs.meta │ │ ├── TemplatePooledObject.cs.meta │ │ ├── DemoPoolEventListener.cs.meta │ │ ├── TemplatePoolEventListener.cs.meta │ │ ├── TemplatePooledObject.cs │ │ ├── TemplatePoolEventListener.cs │ │ ├── TemplatePoolEventListener.asset │ │ ├── DemoPoolEventListener.cs │ │ ├── TemplatePooledObject.asset │ │ ├── DemoPooledObject.cs │ │ ├── DemoPoolEventListener.asset │ │ ├── DemoPooledObject.asset │ │ └── DemoPooledObject (0).prefab │ └── UdonGraph │ │ ├── DemoGraphPooledObject (0).prefab.meta │ │ ├── Example PlayerObjectPool UdonGraph.unity.meta │ │ ├── DemoGraphPooledObject.asset.meta │ │ ├── TemplateGraphPooledObject.asset.meta │ │ ├── DemoGraphPoolEventListener.asset.meta │ │ ├── TemplateGraphPoolEventListener.asset.meta │ │ ├── TemplateGraphPooledObject.asset │ │ ├── TemplateGraphPoolEventListener.asset │ │ └── DemoGraphPooledObject (0).prefab ├── Runtime │ ├── Cyan.PlayerObjectPool.asmdef.meta │ ├── CyanPoolSetupHelper.cs.meta │ ├── Cyan.PlayerObjectPool.asmdef │ └── CyanPoolSetupHelper.cs ├── package.json ├── LICENSE.md ├── PlayerObjectPool.prefab ├── PlayerObjectAssigner.prefab └── Readme.txt ├── source.json ├── LICENSE ├── .gitignore ├── .github └── workflows │ └── build-listing.yml └── README.md /Website/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyanLaser/CyanPlayerObjectPool/HEAD/Website/banner.png -------------------------------------------------------------------------------- /Website/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyanLaser/CyanPlayerObjectPool/HEAD/Website/favicon.ico -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e0489f5cc8b49ab9fa53f2450e1c1e1 3 | timeCreated: 1634761425 -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/CyanPlayerObjectPoolEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0a2664244115474cbbff435cc57165f0 3 | timeCreated: 1634760033 -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/CyanPlayerObjectAssignerEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5f58a1769b55448485900e234fe663ec 3 | timeCreated: 1634778313 -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPoolObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 21d803e628ad44d98f321c4a1067adff 3 | timeCreated: 1649437290 -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/CyanPlayerObjectPoolEditorHelpers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 09b1e7dcc5a246989140fb0e1dfa50bf 3 | timeCreated: 1634778388 -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPoolEventListener.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3d8c16541f64656aa40b2929ddabfe3 3 | timeCreated: 1649437355 -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36d2372145098064d855680743c299b8 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Readme.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e59380119d7a8542b9a59033043a9a4 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8ef4366a0e5291445ab6a44475250b7f 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/PlayerObjectPool.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a35f2996ce6d14c4c854aba5420212ed 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/PlayerObjectAssigner.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 86c96d853d1a64c489730cfa917f604e 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cddf600952d54b54d9567559f464df9b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c75d0f6203f237418c36ddb4adb7d47 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f3e3b4fbdbc412683f201121e2161d0 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ef18ab2e47590449b799b4d213277f3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c45dd58fd22b46b4bbbe8c0f5cacec57 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger/TemplatePooledObject.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 297cedfb065a06d49880cc4e34948d7b 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPooledObject (0).prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed831fe36f5de7e42b90df591a9dd1ce 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Runtime/Cyan.PlayerObjectPool.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 03e0840939a09d240a3f4e7330a80c2d 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/Cyan.PlayerObjectPool.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dbafab0e21272254a8571893071ed430 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger/TemplatePoolEventListener.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6b0301a7359bfe4f90fc5eb9ebf76e8 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/DemoGraphPooledObject (0).prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01cc4179d7c96cc47baad190a806d17c 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger/DemoCyanTriggerPooledObject (0).prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c8258a39a64081d4c82d5a732e2a1634 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/Cyan.PlayerObjectPool.UdonSharp.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f9c26e56726b28c4689cb1fb7d79fd0e 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger/Example PlayerObjectPool CyanTrigger.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26b753ccea243384f82b9d439cf82187 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/Example PlayerObjectPool UdonGraph.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ba5b0f441707cb49a66054802a36e88 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/Example PlayerObjectPool UdonSharp.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 346886b2095ab0d459d5b0cc676debc8 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPool.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a57243225bd6a94408379a754932c5b6 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectAssigner.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2198d3daa09eca24186cd87102f01cb5 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPooledObject.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f2cca2eb14c80914ea60dcdbe25e0416 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePooledObject.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 872f978fbabc2d54ca19bdffdf36831a 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/DemoGraphPooledObject.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 50e62c03f5856904490c6643c4260ced 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/TemplateGraphPooledObject.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b632a3d653a90bd4c8ec9f7d9e0aa285 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPoolEventListener.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: de18cb53ffc9b454da13dce4ce842677 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePoolEventListener.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68120802bb8ade540ba00d1c96e85495 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/Cyan.PlayerObjectPool.UdonSharp.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a595cee05857d9143b8fe31580e2d177 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/DemoGraphPoolEventListener.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6d6744dddfa41bc4ca8ea09e944745f4 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/TemplateGraphPoolEventListener.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8d1b68edf69856147abceb2c5e3f7c80 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Runtime/CyanPoolSetupHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d9c0d913d6d4bd741aec5a89b8072b28 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPool.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6922f711e24eb38459bf73a5fd4eac34 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectAssigner.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 511c88e9e2f5ef84aa091d7eca6eeb51 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPooledObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f2969aff4accf794784b87096b734be0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePooledObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 711203916931a5742b74dec08331a5c8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPoolEventListener.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 174795531e5079b4e9018adf5e5fc6f8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePoolEventListener.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 04a144ac3f6dfc34d8f6ebdd09b77f19 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Runtime/Cyan.PlayerObjectPool.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Cyan.PlayerObjectPool", 3 | "references": [ 4 | "Cyan.PlayerObjectPool.UdonSharp", 5 | "UdonSharp.Runtime" 6 | ], 7 | "includePlatforms": [], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [], 14 | "versionDefines": [], 15 | "noEngineReferences": false 16 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/Cyan.PlayerObjectPool.UdonSharp.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Cyan.PlayerObjectPool.UdonSharp", 3 | "references": [ 4 | "UdonSharp.Runtime", 5 | "VRC.Udon" 6 | ], 7 | "includePlatforms": [], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [], 14 | "versionDefines": [], 15 | "noEngineReferences": false 16 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/Cyan.PlayerObjectPool.UdonSharp.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 5136146375e9a0a498a72a0091b40cc1, type: 3} 13 | m_Name: Cyan.PlayerObjectPool.UdonSharp 14 | m_EditorClassIdentifier: 15 | sourceAssembly: {fileID: 5897886265953266890, guid: f9c26e56726b28c4689cb1fb7d79fd0e, 16 | type: 3} 17 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/Cyan.PlayerObjectPool.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Cyan.PlayerObjectPool.Editor", 3 | "references": [ 4 | "Cyan.PlayerObjectPool", 5 | "Cyan.PlayerObjectPool.UdonSharp", 6 | "UdonSharp.Runtime", 7 | "UdonSharp.Editor", 8 | "VRC.Udon" 9 | ], 10 | "includePlatforms": [ 11 | "Editor" 12 | ], 13 | "excludePlatforms": [], 14 | "allowUnsafeCode": false, 15 | "overrideReferences": false, 16 | "precompiledReferences": [], 17 | "autoReferenced": true, 18 | "defineConstraints": [], 19 | "versionDefines": [], 20 | "noEngineReferences": false 21 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePooledObject.cs: -------------------------------------------------------------------------------- 1 | using Cyan.PlayerObjectPool; 2 | using JetBrains.Annotations; 3 | using UnityEngine; 4 | 5 | [AddComponentMenu("")] 6 | public class TemplatePooledObject : CyanPlayerObjectPoolObject 7 | { 8 | // This method will be called on all clients when the object is enabled and the Owner has been assigned. 9 | [PublicAPI] 10 | public override void _OnOwnerSet() 11 | { 12 | // Initialize the object here 13 | } 14 | 15 | // This method will be called on all clients when the original owner has left and the object is about to be disabled. 16 | [PublicAPI] 17 | public override void _OnCleanup() 18 | { 19 | // Cleanup the object here 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPoolObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UdonSharp; 3 | using VRC.SDKBase; 4 | 5 | namespace Cyan.PlayerObjectPool 6 | { 7 | public abstract class CyanPlayerObjectPoolObject : UdonSharpBehaviour 8 | { 9 | // Who is the current owner of this object. Null if object is not currently in use. 10 | [NonSerialized] 11 | public VRCPlayerApi Owner; 12 | 13 | // This method will be called on all clients when the object is enabled and the Owner has been assigned. 14 | public abstract void _OnOwnerSet(); 15 | 16 | // This method will be called on all clients when the original owner has left and the object is about to be disabled. 17 | public abstract void _OnCleanup(); 18 | } 19 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPoolEventListener.cs: -------------------------------------------------------------------------------- 1 | using UdonSharp; 2 | using VRC.SDKBase; 3 | using VRC.Udon; 4 | 5 | namespace Cyan.PlayerObjectPool 6 | { 7 | public abstract class CyanPlayerObjectPoolEventListener : UdonSharpBehaviour 8 | { 9 | // This event is called when the local player's pool object has been assigned. 10 | public abstract void _OnLocalPlayerAssigned(); 11 | 12 | // This event is called when any player is assigned a pool object. 13 | public abstract void _OnPlayerAssigned(VRCPlayerApi player, int poolIndex, UdonBehaviour poolObject); 14 | 15 | // This event is called when any player's object has been unassigned. 16 | public abstract void _OnPlayerUnassigned(VRCPlayerApi player, int poolIndex, UdonBehaviour poolObject); 17 | } 18 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePoolEventListener.cs: -------------------------------------------------------------------------------- 1 | 2 | using Cyan.PlayerObjectPool; 3 | using UnityEngine; 4 | using VRC.SDKBase; 5 | using VRC.Udon; 6 | 7 | [AddComponentMenu("")] 8 | public class TemplatePoolEventListener : CyanPlayerObjectPoolEventListener 9 | { 10 | // This event is called when the local player's pool object has been assigned. 11 | public override void _OnLocalPlayerAssigned() 12 | { 13 | 14 | } 15 | 16 | // This event is called when any player is assigned a pool object. 17 | public override void _OnPlayerAssigned(VRCPlayerApi player, int poolIndex, UdonBehaviour poolObject) 18 | { 19 | 20 | } 21 | 22 | // This event is called when any player's object has been unassigned. 23 | public override void _OnPlayerUnassigned(VRCPlayerApi player, int poolIndex, UdonBehaviour poolObject) 24 | { 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"Cyan Player Object Pool", 3 | "id":"com.cyan.playerobjectpool.vcc-listing", 4 | "url":"https://CyanLaser.github.io/CyanPlayerObjectPool/index.json", 5 | "author":{ 6 | "name":"CyanLaser", 7 | "url":"https://twitter.com/CyanLaser" 8 | }, 9 | "description":"A VRChat system that will assign a unique object to every player in the world.", 10 | "infoLink":{ 11 | "url":"http://github.com/CyanLaser/CyanPlayerObjectPool", 12 | "text":"View on GitHub" 13 | }, 14 | "bannerUrl":"banner.png", 15 | "packages":[ 16 | { 17 | "name":"com.cyan.playerobjectpool", 18 | "releases":[ 19 | "https://github.com/CyanLaser/CyanPlayerObjectPool/releases/download/v1.1.2/com.cyan.playerobjectpool-1.1.2.zip", 20 | "https://github.com/CyanLaser/CyanPlayerObjectPool/releases/download/v1.1.1/com.cyan.playerobjectpool.zip" 21 | ] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.cyan.playerobjectpool", 3 | "displayName": "Cyan Player Object Pool", 4 | "version": "1.1.2", 5 | "unity": "2019.4", 6 | "description": "A VRChat system that will assign a unique object to every player in the world.", 7 | "author" : { 8 | "name" : "CyanLaser" 9 | }, 10 | "url" : "https://github.com/CyanLaser/CyanPlayerObjectPool", 11 | "vpmDependencies": { 12 | "com.vrchat.worlds": "^3.1.x", 13 | "com.vrchat.udonsharp": "^1.1.x" 14 | }, 15 | "samples" : [ 16 | { 17 | "displayName" : "UdonGraph Examples", 18 | "description" : "", 19 | "path" : "Examples~/UdonGraph" 20 | }, 21 | { 22 | "displayName" : "UdonSharp Examples", 23 | "description" : "", 24 | "path" : "Examples~/UdonSharp" 25 | }, 26 | { 27 | "displayName" : "CyanTrigger Examples", 28 | "description" : "", 29 | "path" : "Examples~/CyanTrigger" 30 | } 31 | ], 32 | "legacyFolders" : { 33 | "Assets\\Cyan\\PlayerObjectPool" : "b8de48290350821488f80da1d1c22556" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 CyanLaser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 CyanLaser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.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 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | # Unity3D generated file on crash reports 52 | sysinfo.txt 53 | 54 | # Builds 55 | *.apk 56 | *.unitypackage 57 | 58 | # Crashlytics generated file 59 | crashlytics-build.properties 60 | 61 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePoolEventListener.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} 13 | m_Name: TemplatePoolEventListener 14 | m_EditorClassIdentifier: 15 | serializedUdonProgramAsset: {fileID: 11400000, guid: 9f89d5bad0d37ec4a85dfffccbee4f37, 16 | type: 2} 17 | udonAssembly: 18 | assemblyError: 19 | sourceCsScript: {fileID: 11500000, guid: 04a144ac3f6dfc34d8f6ebdd09b77f19, type: 3} 20 | scriptVersion: 2 21 | compiledVersion: 2 22 | behaviourSyncMode: 0 23 | hasInteractEvent: 0 24 | scriptID: 1328042123363048056 25 | serializationData: 26 | SerializedFormat: 2 27 | SerializedBytes: 28 | ReferencedUnityObjects: [] 29 | SerializedBytesString: 30 | Prefab: {fileID: 0} 31 | PrefabModificationsReferencedUnityObjects: [] 32 | PrefabModifications: [] 33 | SerializationNodes: 34 | - Name: fieldDefinitions 35 | Entry: 7 36 | Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, 37 | UdonSharp.Editor]], mscorlib 38 | - Name: comparer 39 | Entry: 7 40 | Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, 41 | mscorlib]], mscorlib 42 | - Name: 43 | Entry: 8 44 | Data: 45 | - Name: 46 | Entry: 12 47 | Data: 0 48 | - Name: 49 | Entry: 13 50 | Data: 51 | - Name: 52 | Entry: 8 53 | Data: 54 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPoolEventListener.cs: -------------------------------------------------------------------------------- 1 | 2 | using UnityEngine; 3 | using VRC.SDKBase; 4 | using VRC.Udon; 5 | 6 | namespace Cyan.PlayerObjectPool 7 | { 8 | public class DemoPoolEventListener : CyanPlayerObjectPoolEventListener 9 | { 10 | public CyanPlayerObjectAssigner objectPool; 11 | private DemoPooledObject _localPoolObject; 12 | 13 | void Start() 14 | { 15 | DisableInteractive = true; 16 | } 17 | 18 | public override void Interact() 19 | { 20 | // Prevent interacting before local pool object has been assigned 21 | if (_localPoolObject == null) 22 | { 23 | return; 24 | } 25 | 26 | _localPoolObject._IncreaseValue(); 27 | } 28 | 29 | public override void _OnLocalPlayerAssigned() 30 | { 31 | Debug.Log("The local player has been assigned an object from the pool!"); 32 | 33 | // Get the local player's pool object so we can later perform operations on it. 34 | _localPoolObject = (DemoPooledObject)objectPool._GetPlayerPooledUdon(Networking.LocalPlayer); 35 | 36 | // Allow the user to interact with this object. 37 | DisableInteractive = false; 38 | } 39 | 40 | public override void _OnPlayerAssigned(VRCPlayerApi player, int poolIndex, UdonBehaviour poolObject) 41 | { 42 | Debug.Log($"Object {poolIndex} assigned to player {player.displayName} {player.playerId}"); 43 | } 44 | 45 | public override void _OnPlayerUnassigned(VRCPlayerApi player, int poolIndex, UdonBehaviour poolObject) 46 | { 47 | Debug.Log($"Object {poolIndex} unassigned from player {player.displayName} {player.playerId}"); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /.github/workflows/build-listing.yml: -------------------------------------------------------------------------------- 1 | name: Build Repo Listing 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: main 7 | paths: source.json 8 | 9 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 10 | permissions: 11 | contents: read 12 | pages: write 13 | id-token: write 14 | 15 | # Allow one concurrent deployment 16 | concurrency: 17 | group: "pages" 18 | cancel-in-progress: true 19 | 20 | env: 21 | listPublishDirectory: Website 22 | pathToCi: ci 23 | 24 | jobs: 25 | 26 | build-listing: 27 | name: build-listing 28 | environment: 29 | name: github-pages 30 | url: ${{ steps.deployment.outputs.page_url }} 31 | runs-on: ubuntu-latest 32 | steps: 33 | 34 | - uses: actions/checkout@v3 # check out this repo 35 | - uses: actions/checkout@v3 # check out automation repo 36 | with: 37 | repository: vrchat-community/package-list-action 38 | path: ${{env.pathToCi}} 39 | clean: false # otherwise the local repo will no longer be checked out 40 | 41 | - name: Restore Cache 42 | uses: actions/cache@v3 43 | with: 44 | path: | 45 | ${{env.pathToCi}}/.nuke/temp 46 | ~/.nuget/packages 47 | key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }} 48 | 49 | - name: Build Package Version Listing 50 | run: ${{env.pathToCi}}/build.cmd BuildMultiPackageListing --root ${{env.pathToCi}} --list-publish-directory $GITHUB_WORKSPACE/${{env.listPublishDirectory}} 51 | env: 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | 54 | - name: Setup Pages 55 | uses: actions/configure-pages@v3 56 | 57 | - name: Upload artifact 58 | uses: actions/upload-pages-artifact@v1 59 | with: 60 | path: ${{env.listPublishDirectory}} 61 | 62 | - name: Deploy to GitHub Pages 63 | id: deployment 64 | uses: actions/deploy-pages@v2 65 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/TemplatePooledObject.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} 13 | m_Name: TemplatePooledObject 14 | m_EditorClassIdentifier: 15 | serializedUdonProgramAsset: {fileID: 11400000, guid: 38a4ab4f63530d44c81c7aca81c421f5, 16 | type: 2} 17 | udonAssembly: 18 | assemblyError: 19 | sourceCsScript: {fileID: 11500000, guid: 711203916931a5742b74dec08331a5c8, type: 3} 20 | scriptVersion: 2 21 | compiledVersion: 2 22 | behaviourSyncMode: 0 23 | hasInteractEvent: 0 24 | scriptID: -678833640572851845 25 | serializationData: 26 | SerializedFormat: 2 27 | SerializedBytes: 28 | ReferencedUnityObjects: [] 29 | SerializedBytesString: 30 | Prefab: {fileID: 0} 31 | PrefabModificationsReferencedUnityObjects: [] 32 | PrefabModifications: [] 33 | SerializationNodes: 34 | - Name: fieldDefinitions 35 | Entry: 7 36 | Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, 37 | UdonSharp.Editor]], mscorlib 38 | - Name: comparer 39 | Entry: 7 40 | Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, 41 | mscorlib]], mscorlib 42 | - Name: 43 | Entry: 8 44 | Data: 45 | - Name: 46 | Entry: 12 47 | Data: 1 48 | - Name: 49 | Entry: 7 50 | Data: 51 | - Name: $k 52 | Entry: 1 53 | Data: Owner 54 | - Name: $v 55 | Entry: 7 56 | Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 57 | - Name: k__BackingField 58 | Entry: 1 59 | Data: Owner 60 | - Name: k__BackingField 61 | Entry: 7 62 | Data: 3|System.RuntimeType, mscorlib 63 | - Name: 64 | Entry: 1 65 | Data: VRC.SDKBase.VRCPlayerApi, VRCSDKBase 66 | - Name: 67 | Entry: 8 68 | Data: 69 | - Name: k__BackingField 70 | Entry: 9 71 | Data: 3 72 | - Name: k__BackingField 73 | Entry: 7 74 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 75 | - Name: 76 | Entry: 6 77 | Data: 78 | - Name: 79 | Entry: 8 80 | Data: 81 | - Name: k__BackingField 82 | Entry: 5 83 | Data: false 84 | - Name: _fieldAttributes 85 | Entry: 7 86 | Data: 4|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 87 | - Name: 88 | Entry: 12 89 | Data: 1 90 | - Name: 91 | Entry: 7 92 | Data: 5|System.NonSerializedAttribute, mscorlib 93 | - Name: 94 | Entry: 8 95 | Data: 96 | - Name: 97 | Entry: 13 98 | Data: 99 | - Name: 100 | Entry: 8 101 | Data: 102 | - Name: 103 | Entry: 8 104 | Data: 105 | - Name: 106 | Entry: 8 107 | Data: 108 | - Name: 109 | Entry: 13 110 | Data: 111 | - Name: 112 | Entry: 8 113 | Data: 114 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPooledObject.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | using UdonSharp; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | using VRC.SDKBase; 6 | using Random = UnityEngine.Random; 7 | 8 | namespace Cyan.PlayerObjectPool 9 | { 10 | [AddComponentMenu("")] 11 | [UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] 12 | public class DemoPooledObject : CyanPlayerObjectPoolObject 13 | { 14 | public Text text; 15 | 16 | [UdonSynced] 17 | public int value = -1; 18 | private int _prevValue = -1; 19 | 20 | private VRCPlayerApi _localPlayer; 21 | 22 | private void Start() 23 | { 24 | _localPlayer = Networking.LocalPlayer; 25 | } 26 | 27 | [PublicAPI] 28 | public override void _OnOwnerSet() 29 | { 30 | // Initialize the object here 31 | if (Owner.isLocal) 32 | { 33 | _SetValue(Random.Range(0, 100)); 34 | } 35 | 36 | // After assigning the owner, have everyone act as if the value has changed, as the owner has. 37 | // This is needed as an edge case when the synced value of this pool object is changed BEFORE 38 | // the owner has been assigned. See OnDeserialization as well. 39 | _UpdateDebugDisplay(); 40 | } 41 | 42 | [PublicAPI] 43 | public override void _OnCleanup() 44 | { 45 | // Cleanup the object here 46 | if (Networking.IsMaster) 47 | { 48 | _SetValue(-1); 49 | } 50 | transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); 51 | } 52 | 53 | public override void OnDeserialization() 54 | { 55 | // OnDeserialization happens when synced variable data has been changed. Note that this method may happen 56 | // before the owner has been assigned to this object. Be sure to check for that case and handle initial 57 | // variable updates both in OnDeserialization and in _OnOwnerSet. 58 | _OnValueChanged(); 59 | } 60 | 61 | [PublicAPI] 62 | public void _SetValue(int newValue) 63 | { 64 | value = newValue; 65 | RequestSerialization(); 66 | _OnValueChanged(); 67 | } 68 | 69 | private void _OnValueChanged() 70 | { 71 | if (_prevValue == value) 72 | { 73 | return; 74 | } 75 | 76 | _prevValue = value; 77 | 78 | _UpdateDebugDisplay(); 79 | } 80 | 81 | private void _UpdateDebugDisplay() 82 | { 83 | string ownerName = Utilities.IsValid(Owner) ? $"{Owner.displayName} {Owner.playerId}" : "Invalid"; 84 | text.text = $"{ownerName}\n{value}"; 85 | } 86 | 87 | private void Update() 88 | { 89 | if (!Utilities.IsValid(Owner) || value == -1) 90 | { 91 | return; 92 | } 93 | 94 | Vector3 pos = Owner.GetPosition(); 95 | transform.position = pos + Vector3.up * 2; 96 | 97 | pos = _localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position; 98 | transform.LookAt(pos); 99 | } 100 | 101 | public void _IncreaseValue() 102 | { 103 | if (Owner.isLocal) 104 | { 105 | _SetValue((value + 1) % 100); 106 | } 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/TemplateGraphPooledObject.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 4f11136daadff0b44ac2278a314682ab, type: 3} 13 | m_Name: TemplateGraphPooledObject 14 | m_EditorClassIdentifier: 15 | serializedUdonProgramAsset: {fileID: 11400000, guid: bd79ee398ae5bfa44b8599384415b08c, 16 | type: 2} 17 | udonAssembly: ".data_start\r\n\r\n .export Owner\r\n \r\n Owner: %VRCSDKBaseVRCPlayerApi, 18 | null\r\n\r\n.data_end\r\n\r\n.code_start\r\n\r\n\r\n.code_end\r\n" 19 | assemblyError: 20 | graphData: 21 | name: 22 | description: 23 | nodes: 24 | - fullName: Variable_VRCSDKBaseVRCPlayerApi 25 | uid: ac63edfb-69c5-4265-9144-1219a514b583 26 | position: {x: 0, y: 0} 27 | nodeUIDs: 28 | - 29 | - 30 | - 31 | - 32 | - 33 | flowUIDs: [] 34 | nodeValues: 35 | - unityObjectValue: {fileID: 0} 36 | stringValue: 37 | - unityObjectValue: {fileID: 0} 38 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|Owner 39 | - unityObjectValue: {fileID: 0} 40 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|True 41 | - unityObjectValue: {fileID: 0} 42 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 43 | - unityObjectValue: {fileID: 0} 44 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 45 | - fullName: Event_Custom 46 | uid: f0ff706e-eeaf-4530-a6ca-e42628b72049 47 | position: {x: 279, y: 265} 48 | nodeUIDs: 49 | - 50 | flowUIDs: [] 51 | nodeValues: 52 | - unityObjectValue: {fileID: 0} 53 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|_OnOwnerSet 54 | - fullName: Event_Custom 55 | uid: fe5b75d3-3818-4922-bf85-8d19f38a5175 56 | position: {x: 287.45923, y: 651.76025} 57 | nodeUIDs: 58 | - 59 | flowUIDs: [] 60 | nodeValues: 61 | - unityObjectValue: {fileID: 0} 62 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|_OnCleanup 63 | updateOrder: 0 64 | graphElementData: 65 | - type: 2 66 | uid: ccc64cfb-74d0-459f-a3ab-1fe9845fd710 67 | jsonData: '{"uid":"ccc64cfb-74d0-459f-a3ab-1fe9845fd710","layout":{"serializedVersion":"2","x":254.0,"y":70.0,"width":384.0,"height":303.0},"containedElements":["f0ff706e-eeaf-4530-a6ca-e42628b72049","13a8fb05-002e-4ecd-883c-05658eaea826"],"title":"On 68 | Owner Set","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 69 | - type: 3 70 | uid: 13a8fb05-002e-4ecd-883c-05658eaea826 71 | jsonData: '{"uid":"13a8fb05-002e-4ecd-883c-05658eaea826","layout":{"serializedVersion":"2","x":283.0,"y":134.0,"width":330.0,"height":127.0},"title":"This 72 | Event will be called on all clients when the object is enabled and the Owner 73 | has been assigned.","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 74 | - type: 2 75 | uid: b998856e-fee0-4d70-b091-7d1c06120f28 76 | jsonData: '{"uid":"b998856e-fee0-4d70-b091-7d1c06120f28","layout":{"serializedVersion":"2","x":259.36773681640627,"y":438.4656677246094,"width":376.0,"height":321.0},"containedElements":["fe5b75d3-3818-4922-bf85-8d19f38a5175","34eba742-ba91-4c02-9523-99af3cbcd499"],"title":"On 77 | Cleanup","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 78 | - type: 3 79 | uid: 34eba742-ba91-4c02-9523-99af3cbcd499 80 | jsonData: '{"uid":"34eba742-ba91-4c02-9523-99af3cbcd499","layout":{"serializedVersion":"2","x":284.36773681640627,"y":502.4656982421875,"width":325.7137451171875,"height":138.85687255859376},"title":"This 81 | Event will be called on all clients when the original owner has left and the 82 | object is about to be disabled.","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 83 | viewTransform: 84 | position: {x: 182.95952, y: 168.8643} 85 | scale: 0.375937 86 | version: 1.0.0 87 | showAssembly: 0 88 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/CyanPlayerObjectPoolEditorHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Cyan.PlayerObjectPool 6 | { 7 | public static class CyanPlayerObjectPoolEditorHelpers 8 | { 9 | private const string GITHUB_URL = "https://github.com/CyanLaser/CyanPlayerObjectPool"; 10 | private const string DISCORD_URL = "https://discord.gg/hEwb9eF"; 11 | private const string PATREON_URL = "https://www.patreon.com/CyanLaser"; 12 | private const string GITHUB_ISSUE_URL = "https://github.com/CyanLaser/CyanPlayerObjectPool/issues"; 13 | 14 | public static Color LineColorDark => EditorGUIUtility.isProSkin ? 15 | new Color(0, 0, 0, 0.5f) : 16 | new Color(0.5f, 0.5f, 0.5f, 0.5f); 17 | 18 | public static Color BackgroundColor => EditorGUIUtility.isProSkin ? 19 | new Color(0.25f, 0.25f, 0.25f, 0.5f) : 20 | #if UNITY_2019_3_OR_NEWER 21 | new Color(0.75f, 0.75f, 0.75f, 0.25f); 22 | #else 23 | new Color(1f, 1f, 1f, 0.25f); 24 | #endif 25 | 26 | private static int _indent = 1; 27 | 28 | public static void AddIndent() 29 | { 30 | ++_indent; 31 | EditorGUILayout.BeginHorizontal(); 32 | GUILayout.Space(_indent * 4 + 10); 33 | EditorGUILayout.BeginVertical(); 34 | } 35 | 36 | public static void RemoveIndent() 37 | { 38 | EditorGUILayout.EndVertical(); 39 | EditorGUILayout.EndHorizontal(); 40 | --_indent; 41 | } 42 | 43 | public static bool RenderFoldout(bool value, GUIContent content) 44 | { 45 | EditorGUILayout.BeginHorizontal(); 46 | 47 | GUILayout.Space(10); 48 | 49 | value = EditorGUILayout.Foldout(value, content, true); 50 | 51 | EditorGUILayout.EndHorizontal(); 52 | 53 | return value; 54 | } 55 | 56 | public static void RenderHeader(string title) 57 | { 58 | EditorGUILayout.BeginVertical(EditorStyles.helpBox); 59 | 60 | // Render title 61 | EditorGUILayout.BeginHorizontal(); 62 | GUILayout.FlexibleSpace(); 63 | GUILayout.Label(title, EditorStyles.boldLabel); 64 | GUILayout.FlexibleSpace(); 65 | EditorGUILayout.EndHorizontal(); 66 | 67 | GUILayout.Space(5); 68 | 69 | // Render buttons 70 | float width = EditorGUIUtility.currentViewWidth; 71 | float buttonWidth = Mathf.Max((width - 45) * 0.5f, 100); 72 | 73 | EditorGUILayout.BeginHorizontal(); 74 | GUILayout.Space(5); 75 | 76 | if (GUILayout.Button("Github Repo", GUILayout.Width(buttonWidth))) 77 | { 78 | Application.OpenURL(GITHUB_URL); 79 | } 80 | 81 | GUILayout.Space(5); 82 | 83 | if (GUILayout.Button("Report Bug", GUILayout.Width(buttonWidth))) 84 | { 85 | Application.OpenURL(GITHUB_ISSUE_URL); 86 | } 87 | 88 | GUILayout.Space(5); 89 | EditorGUILayout.EndHorizontal(); 90 | 91 | EditorGUILayout.BeginHorizontal(); 92 | GUILayout.Space(5); 93 | 94 | if (GUILayout.Button("Discord", GUILayout.Width(buttonWidth))) 95 | { 96 | Application.OpenURL(DISCORD_URL); 97 | } 98 | 99 | GUILayout.Space(5); 100 | 101 | if (GUILayout.Button("Patreon", GUILayout.Width(buttonWidth))) 102 | { 103 | Application.OpenURL(PATREON_URL); 104 | } 105 | 106 | GUILayout.Space(5); 107 | EditorGUILayout.EndHorizontal(); 108 | 109 | EditorGUILayout.EndVertical(); 110 | } 111 | 112 | public static Texture2D CreateTexture(int width, int height, Func getColor) 113 | { 114 | Texture2D ret = new Texture2D(width, height) 115 | { 116 | alphaIsTransparency = true, 117 | filterMode = FilterMode.Point 118 | }; 119 | for (int y = 0; y < ret.height; ++y) 120 | { 121 | for (int x = 0; x < ret.width; ++x) 122 | { 123 | ret.SetPixel(x, y, getColor(x, y)); 124 | } 125 | } 126 | ret.Apply(); 127 | return ret; 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPoolEventListener.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} 13 | m_Name: DemoPoolEventListener 14 | m_EditorClassIdentifier: 15 | serializedUdonProgramAsset: {fileID: 11400000, guid: afa65530642a24d43b42b3237491de80, 16 | type: 2} 17 | udonAssembly: 18 | assemblyError: 19 | sourceCsScript: {fileID: 11500000, guid: 174795531e5079b4e9018adf5e5fc6f8, type: 3} 20 | scriptVersion: 2 21 | compiledVersion: 2 22 | behaviourSyncMode: 0 23 | hasInteractEvent: 1 24 | scriptID: 8148159219206977808 25 | serializationData: 26 | SerializedFormat: 2 27 | SerializedBytes: 28 | ReferencedUnityObjects: [] 29 | SerializedBytesString: 30 | Prefab: {fileID: 0} 31 | PrefabModificationsReferencedUnityObjects: [] 32 | PrefabModifications: [] 33 | SerializationNodes: 34 | - Name: fieldDefinitions 35 | Entry: 7 36 | Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, 37 | UdonSharp.Editor]], mscorlib 38 | - Name: comparer 39 | Entry: 7 40 | Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, 41 | mscorlib]], mscorlib 42 | - Name: 43 | Entry: 8 44 | Data: 45 | - Name: 46 | Entry: 12 47 | Data: 2 48 | - Name: 49 | Entry: 7 50 | Data: 51 | - Name: $k 52 | Entry: 1 53 | Data: objectPool 54 | - Name: $v 55 | Entry: 7 56 | Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 57 | - Name: k__BackingField 58 | Entry: 1 59 | Data: objectPool 60 | - Name: k__BackingField 61 | Entry: 7 62 | Data: 3|System.RuntimeType, mscorlib 63 | - Name: 64 | Entry: 1 65 | Data: Cyan.PlayerObjectPool.CyanPlayerObjectAssigner, Cyan.PlayerObjectPool.UdonSharp 66 | - Name: 67 | Entry: 8 68 | Data: 69 | - Name: k__BackingField 70 | Entry: 7 71 | Data: 4|System.RuntimeType, mscorlib 72 | - Name: 73 | Entry: 1 74 | Data: VRC.Udon.UdonBehaviour, VRC.Udon 75 | - Name: 76 | Entry: 8 77 | Data: 78 | - Name: k__BackingField 79 | Entry: 7 80 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 81 | - Name: 82 | Entry: 6 83 | Data: 84 | - Name: 85 | Entry: 8 86 | Data: 87 | - Name: k__BackingField 88 | Entry: 5 89 | Data: true 90 | - Name: _fieldAttributes 91 | Entry: 7 92 | Data: 5|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 93 | - Name: 94 | Entry: 12 95 | Data: 0 96 | - Name: 97 | Entry: 13 98 | Data: 99 | - Name: 100 | Entry: 8 101 | Data: 102 | - Name: 103 | Entry: 8 104 | Data: 105 | - Name: 106 | Entry: 8 107 | Data: 108 | - Name: 109 | Entry: 7 110 | Data: 111 | - Name: $k 112 | Entry: 1 113 | Data: _localPoolObject 114 | - Name: $v 115 | Entry: 7 116 | Data: 6|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 117 | - Name: k__BackingField 118 | Entry: 1 119 | Data: _localPoolObject 120 | - Name: k__BackingField 121 | Entry: 7 122 | Data: 7|System.RuntimeType, mscorlib 123 | - Name: 124 | Entry: 1 125 | Data: Cyan.PlayerObjectPool.DemoPooledObject, Assembly-CSharp 126 | - Name: 127 | Entry: 8 128 | Data: 129 | - Name: k__BackingField 130 | Entry: 9 131 | Data: 4 132 | - Name: k__BackingField 133 | Entry: 7 134 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 135 | - Name: 136 | Entry: 6 137 | Data: 138 | - Name: 139 | Entry: 8 140 | Data: 141 | - Name: k__BackingField 142 | Entry: 5 143 | Data: false 144 | - Name: _fieldAttributes 145 | Entry: 7 146 | Data: 8|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 147 | - Name: 148 | Entry: 12 149 | Data: 0 150 | - Name: 151 | Entry: 13 152 | Data: 153 | - Name: 154 | Entry: 8 155 | Data: 156 | - Name: 157 | Entry: 8 158 | Data: 159 | - Name: 160 | Entry: 8 161 | Data: 162 | - Name: 163 | Entry: 13 164 | Data: 165 | - Name: 166 | Entry: 8 167 | Data: 168 | -------------------------------------------------------------------------------- /Website/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | color-scheme: light dark; 3 | } 4 | 5 | * { 6 | box-sizing: border-box; 7 | } 8 | 9 | body { 10 | padding: 0; 11 | margin: 0; 12 | min-width: 100vw; 13 | min-height: 100vh; 14 | display: flex; 15 | align-items: center; 16 | justify-content: center; 17 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 18 | color: var(--neutral-foreground-rest); 19 | } 20 | 21 | .hidden { 22 | display: none !important; 23 | } 24 | 25 | .row { 26 | display: flex; 27 | flex-direction: row; 28 | } 29 | 30 | .col { 31 | display: flex; 32 | flex-direction: column; 33 | } 34 | 35 | .content { 36 | max-width: 1000px; 37 | width: 100%; 38 | margin: 0 auto; 39 | } 40 | 41 | .align-items-center { 42 | align-items: center; 43 | } 44 | 45 | .justify-content-between { 46 | justify-content: space-between; 47 | } 48 | 49 | .justify-content-end { 50 | justify-content: flex-end; 51 | } 52 | 53 | h1 { 54 | margin-bottom: 0.5rem; 55 | } 56 | 57 | .caption1 { 58 | font-size: 1rem; 59 | color: var(--neutral-foreground-hover); 60 | } 61 | 62 | .caption2 { 63 | font-size: 0.8rem; 64 | margin-top: 0.25rem; 65 | color: var(--neutral-foreground-rest); 66 | } 67 | 68 | .packages { 69 | margin: 0.5rem 0 1rem 0; 70 | max-width: 90%; 71 | padding: 0.25rem; 72 | display: flex; 73 | flex: 1; 74 | } 75 | 76 | #packageGrid { 77 | overflow-y: auto; 78 | width: 100%; 79 | max-height: 40rem; 80 | } 81 | 82 | .packages .packageName { 83 | font-size: 1.1rem; 84 | font-weight: 600; 85 | margin: 0.25rem 0; 86 | } 87 | 88 | .searchBlock { 89 | margin-top: 1rem; 90 | width: 100%; 91 | max-width: 90%; 92 | } 93 | 94 | .searchBlock .root { 95 | width: 100%; 96 | } 97 | 98 | #searchInput { 99 | width: 100%; 100 | } 101 | 102 | .vccUrlField { 103 | min-width: 450px; 104 | max-width: 90%; 105 | flex-grow:1; 106 | } 107 | 108 | #addListingToVccHelp { 109 | z-index: 11; 110 | } 111 | 112 | #packageInfoModal { 113 | z-index: 10; 114 | } 115 | 116 | #rowMoreMenu { 117 | top: 0; 118 | left: 0; 119 | position: absolute; 120 | z-index: 10; 121 | } 122 | 123 | #rowMoreMenu a { 124 | display: block; 125 | text-decoration: none; 126 | color: var(--neutral-foreground-rest); 127 | } 128 | 129 | .bannerImage { 130 | aspect-ratio: 5 / 1; 131 | border-radius: 6px; 132 | max-width: 90%; 133 | width: 100%; 134 | background-size: cover; 135 | background-position: center; 136 | background-repeat: no-repeat; 137 | margin-bottom: 0.25rem; 138 | } 139 | 140 | .badge { 141 | border-radius: 4px; 142 | padding: 0.25rem 0.5rem; 143 | background-color: var(--neutral-fill-hover); 144 | } 145 | 146 | .m-0 { 147 | margin: 0; 148 | } 149 | 150 | .m-1 { 151 | margin: 0.25rem; 152 | } 153 | 154 | .m-2 { 155 | margin: 0.5rem; 156 | } 157 | 158 | .m-3 { 159 | margin: 0.75rem; 160 | } 161 | 162 | .m-4 { 163 | margin: 1rem; 164 | } 165 | 166 | .m-5 { 167 | margin: 2rem; 168 | } 169 | 170 | .mt-1 { 171 | margin-top: 0.25rem; 172 | } 173 | 174 | .mt-2 { 175 | margin-top: 0.5rem; 176 | } 177 | 178 | .mt-3 { 179 | margin-top: 0.75rem; 180 | } 181 | 182 | .mt-4 { 183 | margin-top: 1rem; 184 | } 185 | 186 | .mt-5 { 187 | margin-top: 2rem; 188 | } 189 | 190 | .mb-1 { 191 | margin-bottom: 0.25rem; 192 | } 193 | 194 | .mb-2 { 195 | margin-bottom: 0.5rem; 196 | } 197 | 198 | .mb-3 { 199 | margin-bottom: 0.75rem; 200 | } 201 | 202 | .mb-4 { 203 | margin-bottom: 1rem; 204 | } 205 | 206 | .mb-5 { 207 | margin-bottom: 2rem; 208 | } 209 | 210 | .ms-1 { 211 | margin-left: 0.25rem; 212 | } 213 | 214 | .ms-2 { 215 | margin-left: 0.5rem; 216 | } 217 | 218 | .ms-3 { 219 | margin-left: 0.75rem; 220 | } 221 | 222 | .ms-4 { 223 | margin-left: 1rem; 224 | } 225 | 226 | .ms-5 { 227 | margin-left: 2rem; 228 | } 229 | 230 | .me-1 { 231 | margin-right: 0.25rem; 232 | } 233 | 234 | .me-2 { 235 | margin-right: 0.5rem; 236 | } 237 | 238 | .me-3 { 239 | margin-right: 0.75rem; 240 | } 241 | 242 | .me-4 { 243 | margin-right: 1rem; 244 | } 245 | 246 | .me-5 { 247 | margin-right: 2rem; 248 | } 249 | 250 | .p-1 { 251 | padding: 0.25rem; 252 | } 253 | 254 | .p-2 { 255 | padding: 0.5rem; 256 | } 257 | 258 | .p-3 { 259 | padding: 0.75rem; 260 | } 261 | 262 | .p-4 { 263 | padding: 1rem; 264 | } 265 | 266 | .p-5 { 267 | padding: 2rem; 268 | } 269 | 270 | .pt-1 { 271 | padding-top: 0.25rem; 272 | } 273 | 274 | .pt-2 { 275 | padding-top: 0.5rem; 276 | } 277 | 278 | .pt-3 { 279 | padding-top: 0.75rem; 280 | } 281 | 282 | .pt-4 { 283 | padding-top: 1rem; 284 | } 285 | 286 | .pt-5 { 287 | padding-top: 2rem; 288 | } 289 | 290 | .pb-1 { 291 | padding-bottom: 0.25rem; 292 | } 293 | 294 | .pb-2 { 295 | padding-bottom: 0.5rem; 296 | } 297 | 298 | .pb-3 { 299 | padding-bottom: 0.75rem; 300 | } 301 | 302 | .pb-4 { 303 | padding-bottom: 1rem; 304 | } 305 | 306 | .pb-5 { 307 | padding-bottom: 2rem; 308 | } 309 | 310 | .ps-1 { 311 | padding-left: 0.25rem; 312 | } 313 | 314 | .ps-2 { 315 | padding-left: 0.5rem; 316 | } 317 | 318 | .ps-3 { 319 | padding-left: 0.75rem; 320 | } 321 | 322 | .ps-4 { 323 | padding-left: 1rem; 324 | } 325 | 326 | .ps-5 { 327 | padding-left: 2rem; 328 | } 329 | 330 | .pe-1 { 331 | padding-right: 0.25rem; 332 | } 333 | 334 | .pe-2 { 335 | padding-right: 0.5rem; 336 | } 337 | 338 | .pe-3 { 339 | padding-right: 0.75rem; 340 | } 341 | 342 | .pe-4 { 343 | padding-right: 1rem; 344 | } 345 | 346 | .pe-5 { 347 | padding-right: 2rem; 348 | } 349 | 350 | .w-100 { 351 | width: 100%; 352 | } 353 | 354 | .flex-1 { 355 | flex: 1; 356 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger/TemplatePooledObject.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &860394213257231625 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: 3145608065973377954} 12 | - component: {fileID: 2365246243032988683} 13 | - component: {fileID: 4248953960706351786} 14 | m_Layer: 0 15 | m_Name: TemplatePooledObject 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!4 &3145608065973377954 22 | Transform: 23 | m_ObjectHideFlags: 0 24 | m_CorrespondingSourceObject: {fileID: 0} 25 | m_PrefabInstance: {fileID: 0} 26 | m_PrefabAsset: {fileID: 0} 27 | m_GameObject: {fileID: 860394213257231625} 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_Children: [] 32 | m_Father: {fileID: 0} 33 | m_RootOrder: 0 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | --- !u!114 &2365246243032988683 36 | MonoBehaviour: 37 | m_ObjectHideFlags: 0 38 | m_CorrespondingSourceObject: {fileID: 0} 39 | m_PrefabInstance: {fileID: 0} 40 | m_PrefabAsset: {fileID: 0} 41 | m_GameObject: {fileID: 860394213257231625} 42 | m_Enabled: 1 43 | m_EditorHideFlags: 0 44 | m_Script: {fileID: 11500000, guid: 3dd4a7956009f7d429a09b8371329c82, type: 3} 45 | m_Name: 46 | m_EditorClassIdentifier: 47 | triggerInstance: 48 | proximity: 2 49 | interactText: Use 50 | triggerDataInstance: 51 | version: 6 52 | updateOrder: 0 53 | autoSetSyncMode: 1 54 | programSyncMode: 2 55 | programName: 56 | events: 57 | - name: _OnOwnerSet 58 | eventId: a7955659-c9c2-4a40-a112-7178c1df1dcf 59 | eventInstance: 60 | actionType: 61 | directEvent: Event_Custom 62 | guid: 63 | inputs: [] 64 | multiInput: [] 65 | expanded: 1 66 | comment: 67 | comment: "This method will be called on all clients when the object is 68 | enabled and the Owner has been assigned.\r" 69 | actionInstances: 70 | - actionType: 71 | directEvent: CyanTriggerSpecial_Comment 72 | guid: 73 | inputs: [] 74 | multiInput: [] 75 | expanded: 1 76 | comment: 77 | comment: Initialize the object here 78 | eventOptions: 79 | userGate: 0 80 | userGateExtraData: [] 81 | broadcast: 0 82 | delay: 0 83 | replay: 0 84 | expanded: 1 85 | - name: _OnCleanup 86 | eventId: 30cba9ab-2be6-428e-a027-b7780bb6192c 87 | eventInstance: 88 | actionType: 89 | directEvent: Event_Custom 90 | guid: 91 | inputs: [] 92 | multiInput: [] 93 | expanded: 1 94 | comment: 95 | comment: This method will be called on all clients when the original 96 | owner has left and the object is about to be disabled. 97 | actionInstances: 98 | - actionType: 99 | directEvent: CyanTriggerSpecial_Comment 100 | guid: 101 | inputs: [] 102 | multiInput: [] 103 | expanded: 1 104 | comment: 105 | comment: Cleanup the object here 106 | eventOptions: 107 | userGate: 0 108 | userGateExtraData: [] 109 | broadcast: 0 110 | delay: 0 111 | replay: 0 112 | expanded: 1 113 | variables: 114 | - isVariable: 0 115 | name: Owner 116 | variableID: fd50d655-bb9a-4d68-b91d-b418068c8399 117 | data: 118 | objEncoded: Lg== 119 | unityObjects: [] 120 | type: 121 | typeDef: VRC.SDKBase.VRCPlayerApi, VRCSDKBase, Version=0.0.0.0, Culture=neutral, 122 | PublicKeyToken=null 123 | sync: 0 124 | showInInspector: 1 125 | typeInfo: 0 126 | comment: 127 | comment: 128 | comment: 129 | comment: 130 | expandVariables: 0 131 | expandOtherSettings: 1 132 | expandSyncSection: 0 133 | ignoreEventWarnings: 0 134 | udonBehaviour: {fileID: 4248953960706351786} 135 | --- !u!114 &4248953960706351786 136 | MonoBehaviour: 137 | m_ObjectHideFlags: 0 138 | m_CorrespondingSourceObject: {fileID: 0} 139 | m_PrefabInstance: {fileID: 0} 140 | m_PrefabAsset: {fileID: 0} 141 | m_GameObject: {fileID: 860394213257231625} 142 | m_Enabled: 1 143 | m_EditorHideFlags: 0 144 | m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} 145 | m_Name: 146 | m_EditorClassIdentifier: 147 | interactTextPlacement: {fileID: 0} 148 | interactText: Use 149 | interactTextGO: {fileID: 0} 150 | proximity: 2 151 | SynchronizePosition: 0 152 | AllowCollisionOwnershipTransfer: 1 153 | Reliable: 1 154 | _syncMethod: 1 155 | serializedProgramAsset: {fileID: 0} 156 | programSource: {fileID: 11400000, guid: cc18f4b6c2dd8c74d9f7ce3362168f28, type: 2} 157 | serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgAAAAAAAAAABwUHBQ== 158 | publicVariablesUnityEngineObjects: [] 159 | publicVariablesSerializationDataFormat: 0 160 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/CyanPlayerObjectAssignerEditor.cs: -------------------------------------------------------------------------------- 1 | using UdonSharpEditor; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace Cyan.PlayerObjectPool 6 | { 7 | [CustomEditor(typeof(CyanPlayerObjectAssigner))] 8 | public class CyanPlayerObjectAssignerEditor : Editor 9 | { 10 | private readonly GUIContent _runtimeSettingsFoldoutGuiContent = new GUIContent("Pool Settings", ""); 11 | private readonly GUIContent _editorFoldoutGuiContent = new GUIContent("Editor Settings", ""); 12 | 13 | private SerializedProperty _ownershipProp; 14 | private SerializedProperty _disableProp; 15 | private SerializedProperty _eventListenerProp; 16 | private SerializedProperty _poolObjectParentProp; 17 | 18 | // CyanPoolSetupHelper properties 19 | private CyanPoolSetupHelper _setupHelper; 20 | private SerializedObject _setupHelperSerializedObject; 21 | private SerializedProperty _poolObjectProp; 22 | 23 | private bool _showSettings = true; 24 | private bool _showEditorSettings = true; 25 | 26 | private void Awake() 27 | { 28 | _ownershipProp = serializedObject.FindProperty(nameof(CyanPlayerObjectAssigner.setNetworkOwnershipForPoolObjects)); 29 | _disableProp = serializedObject.FindProperty(nameof(CyanPlayerObjectAssigner.disableUnassignedObjects)); 30 | _eventListenerProp = serializedObject.FindProperty(nameof(CyanPlayerObjectAssigner.poolEventListener)); 31 | _poolObjectParentProp = serializedObject.FindProperty(nameof(CyanPlayerObjectAssigner.poolObjectsParent)); 32 | 33 | _setupHelper = (target as CyanPlayerObjectAssigner).GetComponent(); 34 | if (_setupHelper != null) 35 | { 36 | _setupHelperSerializedObject = new SerializedObject(_setupHelper); 37 | _poolObjectProp = _setupHelperSerializedObject.FindProperty(nameof(CyanPoolSetupHelper.poolObjectPrefab)); 38 | 39 | _setupHelper.VerifyPoolSize(); 40 | } 41 | } 42 | 43 | public override void OnInspectorGUI() 44 | { 45 | if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return; 46 | if (!UdonSharpEditorUtility.IsProxyBehaviour((CyanPlayerObjectAssigner)target)) return; 47 | 48 | serializedObject.UpdateIfRequiredOrScript(); 49 | 50 | CyanPlayerObjectPoolEditorHelpers.RenderHeader("Cyan Player Object Assigner"); 51 | RenderSettings(); 52 | 53 | RenderHelperSettings(); 54 | 55 | serializedObject.ApplyModifiedProperties(); 56 | } 57 | 58 | private void RenderSettings() 59 | { 60 | GUILayout.Space(5); 61 | 62 | EditorGUILayout.BeginVertical(EditorStyles.helpBox); 63 | 64 | _showSettings = CyanPlayerObjectPoolEditorHelpers.RenderFoldout(_showSettings, _runtimeSettingsFoldoutGuiContent); 65 | 66 | if (_showSettings) 67 | { 68 | CyanPlayerObjectPoolEditorHelpers.AddIndent(); 69 | 70 | EditorGUILayout.PropertyField(_ownershipProp, new GUIContent("Assign Network Owner", _ownershipProp.tooltip)); 71 | EditorGUILayout.PropertyField(_disableProp); 72 | EditorGUILayout.PropertyField(_eventListenerProp); 73 | 74 | EditorGUI.BeginChangeCheck(); 75 | 76 | Transform prev = (Transform)_poolObjectParentProp.objectReferenceValue; 77 | 78 | EditorGUILayout.PropertyField(_poolObjectParentProp); 79 | 80 | if (_poolObjectParentProp.objectReferenceValue == null) 81 | { 82 | _poolObjectParentProp.objectReferenceValue = (target as CyanPlayerObjectAssigner).transform; 83 | } 84 | 85 | if (EditorGUI.EndChangeCheck() && prev != null) 86 | { 87 | Transform cur = (Transform)_poolObjectParentProp.objectReferenceValue; 88 | if (prev != cur) 89 | { 90 | while (prev.childCount != 0) 91 | { 92 | prev.GetChild(0).SetParent(cur, false); 93 | } 94 | } 95 | } 96 | 97 | CyanPlayerObjectPoolEditorHelpers.RemoveIndent(); 98 | } 99 | 100 | EditorGUILayout.EndVertical(); 101 | } 102 | 103 | private void RenderHelperSettings() 104 | { 105 | if (_setupHelper == null) 106 | { 107 | return; 108 | } 109 | 110 | bool shouldInitialize = _setupHelper.ShouldInitialize(); 111 | 112 | _setupHelperSerializedObject.UpdateIfRequiredOrScript(); 113 | 114 | GUILayout.Space(5); 115 | 116 | EditorGUILayout.BeginVertical(EditorStyles.helpBox); 117 | 118 | _showEditorSettings = CyanPlayerObjectPoolEditorHelpers.RenderFoldout(_showEditorSettings, _editorFoldoutGuiContent); 119 | 120 | if (_showEditorSettings) 121 | { 122 | CyanPlayerObjectPoolEditorHelpers.AddIndent(); 123 | 124 | int assignerSize = _setupHelper.GetObjectCount(); 125 | 126 | // Only show Pool options when in a valid scene and not a prefab editor. 127 | if (shouldInitialize) 128 | { 129 | int poolSize = _setupHelper.GetPoolSize(); 130 | 131 | EditorGUILayout.BeginHorizontal(); 132 | 133 | if (GUILayout.Button("Ping Object Pool")) 134 | { 135 | EditorGUIUtility.PingObject(_setupHelper.GetPoolUdon().gameObject); 136 | } 137 | 138 | GUILayout.Space(5); 139 | 140 | if (GUILayout.Button("Respawn All Pool Objects")) 141 | { 142 | _setupHelper.RespawnAllPoolObjects(); 143 | } 144 | 145 | EditorGUILayout.EndHorizontal(); 146 | 147 | EditorGUI.BeginDisabledGroup(true); 148 | 149 | EditorGUILayout.IntField("Pool Size", poolSize); 150 | 151 | EditorGUI.EndDisabledGroup(); 152 | 153 | if (poolSize != assignerSize && assignerSize > 0) 154 | { 155 | EditorGUILayout.HelpBox($"Pool Object count does not match Pool Size! This assigner has {assignerSize} objects when the pool is expecting {poolSize} objects.", MessageType.Error); 156 | } 157 | } 158 | 159 | EditorGUI.BeginChangeCheck(); 160 | 161 | EditorGUILayout.PropertyField(_poolObjectProp); 162 | 163 | bool changes = EditorGUI.EndChangeCheck(); 164 | 165 | _setupHelperSerializedObject.ApplyModifiedProperties(); 166 | 167 | if (_poolObjectProp.objectReferenceValue == null && assignerSize == 0) 168 | { 169 | GUILayout.Space(5); 170 | EditorGUILayout.HelpBox("Pool Object has not been assigned. Assignment and Unassignment events will still be sent to the Pool Event Listener but no object will be assigned.", MessageType.Warning); 171 | } 172 | 173 | // Only apply changes when the scene is valid and not in a prefab editor. 174 | if (changes && shouldInitialize) 175 | { 176 | _setupHelper.RespawnAllPoolObjects(); 177 | } 178 | 179 | CyanPlayerObjectPoolEditorHelpers.RemoveIndent(); 180 | } 181 | 182 | EditorGUILayout.EndVertical(); 183 | } 184 | } 185 | } -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Runtime/CyanPoolSetupHelper.cs: -------------------------------------------------------------------------------- 1 | 2 | using UnityEngine; 3 | 4 | #if UNITY_EDITOR 5 | using UnityEditor; 6 | using UnityEditor.SceneManagement; 7 | #endif 8 | 9 | namespace Cyan.PlayerObjectPool 10 | { 11 | [AddComponentMenu("")] 12 | [ExecuteInEditMode] 13 | public class CyanPoolSetupHelper : MonoBehaviour 14 | { 15 | public GameObject cyanPlayerObjectPoolPrefab; 16 | 17 | public GameObject poolObjectPrefab; 18 | 19 | [HideInInspector, SerializeField] 20 | private CyanPlayerObjectPool pool; 21 | [SerializeField] 22 | private CyanPlayerObjectAssigner assigner; 23 | 24 | #if UNITY_EDITOR 25 | // On dragging this as a prefab into the scene, create the necessary number of pool objects based on the 26 | // Object Pool's settings. If no Object Pool exists in the scene, add one. 27 | public void Awake() 28 | { 29 | if (!ShouldInitialize()) 30 | { 31 | return; 32 | } 33 | 34 | hideFlags = HideFlags.DontSaveInBuild; 35 | 36 | GetPoolUdon(); 37 | VerifyPoolSize(); 38 | } 39 | 40 | // Check if this object is in a valid scene and not in a prefab editor. 41 | public bool ShouldInitialize() 42 | { 43 | if (Application.isPlaying) 44 | { 45 | return false; 46 | } 47 | 48 | if (!gameObject.scene.isLoaded) 49 | { 50 | return false; 51 | } 52 | 53 | #if UNITY_EDITOR 54 | if (EditorSceneManager.IsPreviewSceneObject(this)) 55 | { 56 | return false; 57 | } 58 | #endif 59 | 60 | return true; 61 | } 62 | 63 | public CyanPlayerObjectPool GetPoolUdon() 64 | { 65 | // If this object shouldn't be initialized, always return null to prevent the scene from being edited. 66 | if (!ShouldInitialize()) 67 | { 68 | return null; 69 | } 70 | 71 | // If the udon behaviour has been cached, return it. 72 | if (pool != null) 73 | { 74 | return pool; 75 | } 76 | 77 | // Given an object, return the first UdonBehaviour that is of type CyanPlayerObjectPool contained in this 78 | // object's hierarchy. 79 | CyanPlayerObjectPool GetPoolUdon(GameObject obj) 80 | { 81 | CyanPlayerObjectPool[] pools = obj.GetComponentsInChildren(true); 82 | 83 | if (pools.Length == 0) 84 | { 85 | return null; 86 | } 87 | 88 | return pools[0]; 89 | } 90 | 91 | // Go through every object to find the Object pool 92 | foreach (var obj in gameObject.scene.GetRootGameObjects()) 93 | { 94 | pool = GetPoolUdon(obj); 95 | 96 | if (pool != null) 97 | { 98 | break; 99 | } 100 | } 101 | 102 | // Object pool does not currently exist in the scene. Spawn a new one. 103 | if (pool == null && cyanPlayerObjectPoolPrefab != null) 104 | { 105 | GameObject poolPrefab = PrefabUtility.InstantiatePrefab(cyanPlayerObjectPoolPrefab) as GameObject; 106 | Undo.RegisterCreatedObjectUndo(poolPrefab, "Create Object Pool Prefab"); 107 | 108 | pool = GetPoolUdon(poolPrefab); 109 | } 110 | 111 | return pool; 112 | } 113 | 114 | // Get the current size of the Object Pool. 115 | public int GetPoolSize() 116 | { 117 | return GetPoolUdon().poolSize; 118 | } 119 | 120 | public int GetObjectCount() 121 | { 122 | return GetPoolParentTransform().childCount; 123 | } 124 | 125 | public Transform GetPoolParentTransform() 126 | { 127 | if (assigner.poolObjectsParent) 128 | { 129 | return assigner.poolObjectsParent; 130 | } 131 | return assigner.transform; 132 | } 133 | 134 | // Update the number of pool objects for this assigner based on the current size of the Object pool. 135 | public void UpdatePoolSize() 136 | { 137 | UpdatePoolSize(GetPoolSize()); 138 | } 139 | 140 | // Delete all children under this Object Assigner. 141 | public void ClearChildren() 142 | { 143 | Transform poolTransform = GetPoolParentTransform(); 144 | while (GetObjectCount() > 0) 145 | { 146 | GameObject poolObject = poolTransform.GetChild(0).gameObject; 147 | Undo.DestroyObjectImmediate(poolObject); 148 | } 149 | } 150 | 151 | public void RespawnAllPoolObjects() 152 | { 153 | if (!ShouldInitialize()) 154 | { 155 | return; 156 | } 157 | 158 | // No pool object prefab to update size. 159 | if (poolObjectPrefab == null) 160 | { 161 | return; 162 | } 163 | 164 | ClearChildren(); 165 | UpdatePoolSize(); 166 | } 167 | 168 | // Verify that the pool's current size matches the Object Pool's size. 169 | public void VerifyPoolSize() 170 | { 171 | if (!ShouldInitialize()) 172 | { 173 | return; 174 | } 175 | 176 | int size = GetPoolSize(); 177 | if (GetObjectCount() != size) 178 | { 179 | UpdatePoolSize(size); 180 | } 181 | } 182 | 183 | // Given a size, spawn new pooled objects or delete old objects until this object assigner has the appropriate size. 184 | public void UpdatePoolSize(int size) 185 | { 186 | // No pool object prefab to update size. 187 | if (poolObjectPrefab == null) 188 | { 189 | return; 190 | } 191 | 192 | Transform poolTransform = GetPoolParentTransform(); 193 | // Too many children, delete the last items until size is met. 194 | while (GetObjectCount() > size) 195 | { 196 | GameObject poolObject = poolTransform.GetChild(GetObjectCount() - 1).gameObject; 197 | Undo.DestroyObjectImmediate(poolObject); 198 | } 199 | 200 | // Too few children, spawn new items until size is met. 201 | while (GetObjectCount() < size) 202 | { 203 | GameObject poolObject = null; 204 | // If pool object is a prefab, spawn as a prefab instance 205 | if (PrefabUtility.IsPartOfPrefabAsset(poolObjectPrefab)) 206 | { 207 | poolObject = (GameObject)PrefabUtility.InstantiatePrefab(poolObjectPrefab, poolTransform); 208 | } 209 | // If pool object is not a prefab, instantiate as normal gameobject. 210 | else 211 | { 212 | poolObject = Instantiate(poolObjectPrefab, poolTransform); 213 | poolObject.name = poolObjectPrefab.name; 214 | } 215 | 216 | // Ensure that no siblings have the same name. This adds the (#) to the end of the object. 217 | GameObjectUtility.EnsureUniqueNameForSibling(poolObject); 218 | 219 | // Register that the object has been created to ensure that undo deletes them properly. 220 | Undo.RegisterCreatedObjectUndo(poolObject, "Create Pool Object"); 221 | } 222 | } 223 | #endif 224 | } 225 | 226 | #if UNITY_EDITOR 227 | [CustomEditor(typeof(CyanPoolSetupHelper))] 228 | public class CyanPoolSetupHelperEditor : Editor 229 | { 230 | // Render nothing so that people use the CyanPlayerObjectAssigner inspector 231 | public override void OnInspectorGUI() { } 232 | } 233 | #endif 234 | } 235 | 236 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/PlayerObjectPool.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &8671630162616761239 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: 2389743308707461704} 12 | - component: {fileID: -1886765728581271151} 13 | - component: {fileID: 9026171130748990446} 14 | m_Layer: 0 15 | m_Name: PlayerObjectPool 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!4 &2389743308707461704 22 | Transform: 23 | m_ObjectHideFlags: 0 24 | m_CorrespondingSourceObject: {fileID: 0} 25 | m_PrefabInstance: {fileID: 0} 26 | m_PrefabAsset: {fileID: 0} 27 | m_GameObject: {fileID: 8671630162616761239} 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_Children: [] 32 | m_Father: {fileID: 0} 33 | m_RootOrder: 0 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | --- !u!114 &-1886765728581271151 36 | MonoBehaviour: 37 | m_ObjectHideFlags: 0 38 | m_CorrespondingSourceObject: {fileID: 0} 39 | m_PrefabInstance: {fileID: 0} 40 | m_PrefabAsset: {fileID: 0} 41 | m_GameObject: {fileID: 8671630162616761239} 42 | m_Enabled: 1 43 | m_EditorHideFlags: 0 44 | m_Script: {fileID: 11500000, guid: 6922f711e24eb38459bf73a5fd4eac34, type: 3} 45 | m_Name: 46 | m_EditorClassIdentifier: 47 | serializationData: 48 | SerializedFormat: 2 49 | SerializedBytes: 50 | ReferencedUnityObjects: [] 51 | SerializedBytesString: 52 | Prefab: {fileID: 0} 53 | PrefabModificationsReferencedUnityObjects: [] 54 | PrefabModifications: [] 55 | SerializationNodes: [] 56 | _udonSharpBackingUdonBehaviour: {fileID: 9026171130748990446} 57 | poolSize: 82 58 | printDebugLogs: 0 59 | --- !u!114 &9026171130748990446 60 | MonoBehaviour: 61 | m_ObjectHideFlags: 0 62 | m_CorrespondingSourceObject: {fileID: 0} 63 | m_PrefabInstance: {fileID: 0} 64 | m_PrefabAsset: {fileID: 0} 65 | m_GameObject: {fileID: 8671630162616761239} 66 | m_Enabled: 1 67 | m_EditorHideFlags: 0 68 | m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} 69 | m_Name: 70 | m_EditorClassIdentifier: 71 | interactTextPlacement: {fileID: 0} 72 | interactText: Use 73 | interactTextGO: {fileID: 0} 74 | proximity: 2 75 | SynchronizePosition: 0 76 | AllowCollisionOwnershipTransfer: 0 77 | Reliable: 1 78 | _syncMethod: 3 79 | serializedProgramAsset: {fileID: 11400000, guid: 7931a2e2cfe6c604db3e24f5a2895a58, 80 | type: 2} 81 | programSource: {fileID: 11400000, guid: a57243225bd6a94408379a754932c5b6, type: 2} 82 | serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgwAAAAAAAAAAi8CAAAAAWIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AQwBvAG0AcABvAG4AZQBuAHQAWwBdACwAIABVAG4AaQB0AHkARQBuAGcAaQBuAGUALgBDAG8AcgBlAE0AbwBkAHUAbABlAF0AXQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAgAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5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 83 | publicVariablesUnityEngineObjects: [] 84 | publicVariablesSerializationDataFormat: 0 85 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPooledObject.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} 13 | m_Name: DemoPooledObject 14 | m_EditorClassIdentifier: 15 | serializedUdonProgramAsset: {fileID: 11400000, guid: a567fa5250bc609409cbe68aa8e42c84, 16 | type: 2} 17 | udonAssembly: 18 | assemblyError: 19 | sourceCsScript: {fileID: 11500000, guid: f2969aff4accf794784b87096b734be0, type: 3} 20 | scriptVersion: 2 21 | compiledVersion: 2 22 | behaviourSyncMode: 4 23 | hasInteractEvent: 0 24 | scriptID: -4551627141202163093 25 | serializationData: 26 | SerializedFormat: 2 27 | SerializedBytes: 28 | ReferencedUnityObjects: [] 29 | SerializedBytesString: 30 | Prefab: {fileID: 0} 31 | PrefabModificationsReferencedUnityObjects: [] 32 | PrefabModifications: [] 33 | SerializationNodes: 34 | - Name: fieldDefinitions 35 | Entry: 7 36 | Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, 37 | UdonSharp.Editor]], mscorlib 38 | - Name: comparer 39 | Entry: 7 40 | Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, 41 | mscorlib]], mscorlib 42 | - Name: 43 | Entry: 8 44 | Data: 45 | - Name: 46 | Entry: 12 47 | Data: 5 48 | - Name: 49 | Entry: 7 50 | Data: 51 | - Name: $k 52 | Entry: 1 53 | Data: Owner 54 | - Name: $v 55 | Entry: 7 56 | Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 57 | - Name: k__BackingField 58 | Entry: 1 59 | Data: Owner 60 | - Name: k__BackingField 61 | Entry: 7 62 | Data: 3|System.RuntimeType, mscorlib 63 | - Name: 64 | Entry: 1 65 | Data: VRC.SDKBase.VRCPlayerApi, VRCSDKBase 66 | - Name: 67 | Entry: 8 68 | Data: 69 | - Name: k__BackingField 70 | Entry: 9 71 | Data: 3 72 | - Name: k__BackingField 73 | Entry: 7 74 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 75 | - Name: 76 | Entry: 6 77 | Data: 78 | - Name: 79 | Entry: 8 80 | Data: 81 | - Name: k__BackingField 82 | Entry: 5 83 | Data: false 84 | - Name: _fieldAttributes 85 | Entry: 7 86 | Data: 4|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 87 | - Name: 88 | Entry: 12 89 | Data: 1 90 | - Name: 91 | Entry: 7 92 | Data: 5|System.NonSerializedAttribute, mscorlib 93 | - Name: 94 | Entry: 8 95 | Data: 96 | - Name: 97 | Entry: 13 98 | Data: 99 | - Name: 100 | Entry: 8 101 | Data: 102 | - Name: 103 | Entry: 8 104 | Data: 105 | - Name: 106 | Entry: 8 107 | Data: 108 | - Name: 109 | Entry: 7 110 | Data: 111 | - Name: $k 112 | Entry: 1 113 | Data: text 114 | - Name: $v 115 | Entry: 7 116 | Data: 6|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 117 | - Name: k__BackingField 118 | Entry: 1 119 | Data: text 120 | - Name: k__BackingField 121 | Entry: 7 122 | Data: 7|System.RuntimeType, mscorlib 123 | - Name: 124 | Entry: 1 125 | Data: UnityEngine.UI.Text, UnityEngine.UI 126 | - Name: 127 | Entry: 8 128 | Data: 129 | - Name: k__BackingField 130 | Entry: 9 131 | Data: 7 132 | - Name: k__BackingField 133 | Entry: 7 134 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 135 | - Name: 136 | Entry: 6 137 | Data: 138 | - Name: 139 | Entry: 8 140 | Data: 141 | - Name: k__BackingField 142 | Entry: 5 143 | Data: true 144 | - Name: _fieldAttributes 145 | Entry: 7 146 | Data: 8|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 147 | - Name: 148 | Entry: 12 149 | Data: 0 150 | - Name: 151 | Entry: 13 152 | Data: 153 | - Name: 154 | Entry: 8 155 | Data: 156 | - Name: 157 | Entry: 8 158 | Data: 159 | - Name: 160 | Entry: 8 161 | Data: 162 | - Name: 163 | Entry: 7 164 | Data: 165 | - Name: $k 166 | Entry: 1 167 | Data: value 168 | - Name: $v 169 | Entry: 7 170 | Data: 9|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 171 | - Name: k__BackingField 172 | Entry: 1 173 | Data: value 174 | - Name: k__BackingField 175 | Entry: 7 176 | Data: 10|System.RuntimeType, mscorlib 177 | - Name: 178 | Entry: 1 179 | Data: System.Int32, mscorlib 180 | - Name: 181 | Entry: 8 182 | Data: 183 | - Name: k__BackingField 184 | Entry: 9 185 | Data: 10 186 | - Name: k__BackingField 187 | Entry: 7 188 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 189 | - Name: 190 | Entry: 3 191 | Data: 1 192 | - Name: 193 | Entry: 8 194 | Data: 195 | - Name: k__BackingField 196 | Entry: 5 197 | Data: true 198 | - Name: _fieldAttributes 199 | Entry: 7 200 | Data: 11|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 201 | - Name: 202 | Entry: 12 203 | Data: 1 204 | - Name: 205 | Entry: 7 206 | Data: 12|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime 207 | - Name: 208 | Entry: 8 209 | Data: 210 | - Name: 211 | Entry: 13 212 | Data: 213 | - Name: 214 | Entry: 8 215 | Data: 216 | - Name: 217 | Entry: 8 218 | Data: 219 | - Name: 220 | Entry: 8 221 | Data: 222 | - Name: 223 | Entry: 7 224 | Data: 225 | - Name: $k 226 | Entry: 1 227 | Data: _prevValue 228 | - Name: $v 229 | Entry: 7 230 | Data: 13|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 231 | - Name: k__BackingField 232 | Entry: 1 233 | Data: _prevValue 234 | - Name: k__BackingField 235 | Entry: 9 236 | Data: 10 237 | - Name: k__BackingField 238 | Entry: 9 239 | Data: 10 240 | - Name: k__BackingField 241 | Entry: 7 242 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 243 | - Name: 244 | Entry: 6 245 | Data: 246 | - Name: 247 | Entry: 8 248 | Data: 249 | - Name: k__BackingField 250 | Entry: 5 251 | Data: false 252 | - Name: _fieldAttributes 253 | Entry: 7 254 | Data: 14|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 255 | - Name: 256 | Entry: 12 257 | Data: 0 258 | - Name: 259 | Entry: 13 260 | Data: 261 | - Name: 262 | Entry: 8 263 | Data: 264 | - Name: 265 | Entry: 8 266 | Data: 267 | - Name: 268 | Entry: 8 269 | Data: 270 | - Name: 271 | Entry: 7 272 | Data: 273 | - Name: $k 274 | Entry: 1 275 | Data: _localPlayer 276 | - Name: $v 277 | Entry: 7 278 | Data: 15|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor 279 | - Name: k__BackingField 280 | Entry: 1 281 | Data: _localPlayer 282 | - Name: k__BackingField 283 | Entry: 9 284 | Data: 3 285 | - Name: k__BackingField 286 | Entry: 9 287 | Data: 3 288 | - Name: k__BackingField 289 | Entry: 7 290 | Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib 291 | - Name: 292 | Entry: 6 293 | Data: 294 | - Name: 295 | Entry: 8 296 | Data: 297 | - Name: k__BackingField 298 | Entry: 5 299 | Data: false 300 | - Name: _fieldAttributes 301 | Entry: 7 302 | Data: 16|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib 303 | - Name: 304 | Entry: 12 305 | Data: 0 306 | - Name: 307 | Entry: 13 308 | Data: 309 | - Name: 310 | Entry: 8 311 | Data: 312 | - Name: 313 | Entry: 8 314 | Data: 315 | - Name: 316 | Entry: 8 317 | Data: 318 | - Name: 319 | Entry: 13 320 | Data: 321 | - Name: 322 | Entry: 8 323 | Data: 324 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/CyanTrigger/TemplatePoolEventListener.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &6466507093370580791 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: 5454796645173130692} 12 | - component: {fileID: 1181118861461511621} 13 | - component: {fileID: 1267990233830225175} 14 | m_Layer: 0 15 | m_Name: TemplatePoolEventListener 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!4 &5454796645173130692 22 | Transform: 23 | m_ObjectHideFlags: 0 24 | m_CorrespondingSourceObject: {fileID: 0} 25 | m_PrefabInstance: {fileID: 0} 26 | m_PrefabAsset: {fileID: 0} 27 | m_GameObject: {fileID: 6466507093370580791} 28 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 29 | m_LocalPosition: {x: 0, y: 1, z: 0} 30 | m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} 31 | m_Children: [] 32 | m_Father: {fileID: 0} 33 | m_RootOrder: 0 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | --- !u!114 &1181118861461511621 36 | MonoBehaviour: 37 | m_ObjectHideFlags: 0 38 | m_CorrespondingSourceObject: {fileID: 0} 39 | m_PrefabInstance: {fileID: 0} 40 | m_PrefabAsset: {fileID: 0} 41 | m_GameObject: {fileID: 6466507093370580791} 42 | m_Enabled: 1 43 | m_EditorHideFlags: 0 44 | m_Script: {fileID: 11500000, guid: 3dd4a7956009f7d429a09b8371329c82, type: 3} 45 | m_Name: 46 | m_EditorClassIdentifier: 47 | triggerInstance: 48 | proximity: 2 49 | interactText: Use 50 | triggerDataInstance: 51 | version: 6 52 | updateOrder: 0 53 | autoSetSyncMode: 1 54 | programSyncMode: 2 55 | programName: 56 | events: 57 | - name: _OnLocalPlayerAssigned 58 | eventId: 9ba932f5-2f1b-4d50-b77d-1dc7e789aecc 59 | eventInstance: 60 | actionType: 61 | directEvent: Event_Custom 62 | guid: 63 | inputs: [] 64 | multiInput: [] 65 | expanded: 1 66 | comment: 67 | comment: This event is called when the local player's pool object has 68 | been assigned. 69 | actionInstances: [] 70 | eventOptions: 71 | userGate: 0 72 | userGateExtraData: [] 73 | broadcast: 0 74 | delay: 0 75 | replay: 0 76 | expanded: 1 77 | - name: _OnPlayerAssigned 78 | eventId: 1c84abdc-2b4b-49d9-b4c0-1c3bcdc9bff8 79 | eventInstance: 80 | actionType: 81 | directEvent: Event_Custom 82 | guid: 83 | inputs: [] 84 | multiInput: [] 85 | expanded: 1 86 | comment: 87 | comment: This event is called when any player is assigned a pool object. 88 | The playerAssignedId and playerAssignedPoolObject variables will be 89 | set before this event is called. 90 | actionInstances: [] 91 | eventOptions: 92 | userGate: 0 93 | userGateExtraData: [] 94 | broadcast: 0 95 | delay: 0 96 | replay: 0 97 | expanded: 1 98 | - name: _OnPlayerUnassigned 99 | eventId: 3c908768-6bcd-49e2-b23c-335790d974a0 100 | eventInstance: 101 | actionType: 102 | directEvent: Event_Custom 103 | guid: 104 | inputs: [] 105 | multiInput: [] 106 | expanded: 1 107 | comment: 108 | comment: This event is called when any player's object has been unassigned. 109 | The playerUnassignedId and playerUnassignedPoolObject variables will 110 | be set before this event is called. 111 | actionInstances: [] 112 | eventOptions: 113 | userGate: 0 114 | userGateExtraData: [] 115 | broadcast: 0 116 | delay: 0 117 | replay: 0 118 | expanded: 1 119 | variables: 120 | - isVariable: 0 121 | name: playerAssignedPlayer 122 | variableID: f12c3ee8-e181-499a-8bc7-45ea6a0c41ae 123 | data: 124 | objEncoded: Lg== 125 | unityObjects: [] 126 | type: 127 | typeDef: VRC.SDKBase.VRCPlayerApi, VRCSDKBase, Version=0.0.0.0, Culture=neutral, 128 | PublicKeyToken=null 129 | sync: 0 130 | showInInspector: 1 131 | typeInfo: 0 132 | comment: 133 | comment: 134 | - isVariable: 0 135 | name: playerAssignedPoolObject 136 | variableID: f1aa35c2-8603-48cc-a0fe-d76e26edc067 137 | data: 138 | objEncoded: Lg== 139 | unityObjects: [] 140 | type: 141 | typeDef: VRC.Udon.UdonBehaviour, VRC.Udon, Version=0.0.0.0, Culture=neutral, 142 | PublicKeyToken=null 143 | sync: 0 144 | showInInspector: 1 145 | typeInfo: 0 146 | comment: 147 | comment: 148 | - isVariable: 0 149 | name: playerAssignedIndex 150 | variableID: eb444b02-f2d8-4368-9d65-43cbb5202560 151 | data: 152 | objEncoded: Ai8AAAAAARYAAABTAHkAcwB0AGUAbQAuAEkAbgB0ADMAMgAsACAAbQBzAGMAbwByAGwAaQBiAAAAAAAYAAAAAAU= 153 | unityObjects: [] 154 | type: 155 | typeDef: System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 156 | sync: 0 157 | showInInspector: 1 158 | typeInfo: 0 159 | comment: 160 | comment: 161 | - isVariable: 0 162 | name: playerUnassignedPlayer 163 | variableID: d725719e-d2e4-424f-be05-f53f3c5dd488 164 | data: 165 | objEncoded: Lg== 166 | unityObjects: [] 167 | type: 168 | typeDef: VRC.SDKBase.VRCPlayerApi, VRCSDKBase, Version=0.0.0.0, Culture=neutral, 169 | PublicKeyToken=null 170 | sync: 0 171 | showInInspector: 1 172 | typeInfo: 0 173 | comment: 174 | comment: 175 | - isVariable: 0 176 | name: playerUnassignedPoolObject 177 | variableID: fd64ee2b-4c88-4aa9-b79d-ec71f6c7ae57 178 | data: 179 | objEncoded: Lg== 180 | unityObjects: [] 181 | type: 182 | typeDef: VRC.Udon.UdonBehaviour, VRC.Udon, Version=0.0.0.0, Culture=neutral, 183 | PublicKeyToken=null 184 | sync: 0 185 | showInInspector: 1 186 | typeInfo: 0 187 | comment: 188 | comment: 189 | - isVariable: 0 190 | name: playerUnassignedIndex 191 | variableID: 0502be4f-5e58-4c8b-8f81-6ef62aa3a8cc 192 | data: 193 | objEncoded: Ai8AAAAAARYAAABTAHkAcwB0AGUAbQAuAEkAbgB0ADMAMgAsACAAbQBzAGMAbwByAGwAaQBiAAAAAAAYAAAAAAU= 194 | unityObjects: [] 195 | type: 196 | typeDef: System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 197 | sync: 0 198 | showInInspector: 1 199 | typeInfo: 0 200 | comment: 201 | comment: 202 | comment: 203 | comment: 204 | expandVariables: 0 205 | expandOtherSettings: 1 206 | expandSyncSection: 0 207 | ignoreEventWarnings: 0 208 | udonBehaviour: {fileID: 1267990233830225175} 209 | --- !u!114 &1267990233830225175 210 | MonoBehaviour: 211 | m_ObjectHideFlags: 0 212 | m_CorrespondingSourceObject: {fileID: 0} 213 | m_PrefabInstance: {fileID: 0} 214 | m_PrefabAsset: {fileID: 0} 215 | m_GameObject: {fileID: 6466507093370580791} 216 | m_Enabled: 1 217 | m_EditorHideFlags: 0 218 | m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} 219 | m_Name: 220 | m_EditorClassIdentifier: 221 | interactTextPlacement: {fileID: 0} 222 | interactText: Use 223 | interactTextGO: {fileID: 0} 224 | proximity: 2 225 | SynchronizePosition: 0 226 | AllowCollisionOwnershipTransfer: 1 227 | Reliable: 1 228 | _syncMethod: 0 229 | serializedProgramAsset: {fileID: 0} 230 | programSource: {fileID: 11400000, guid: cc18f4b6c2dd8c74d9f7ce3362168f28, type: 2} 231 | serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgAAAAAAAAAABwUHBQ== 232 | publicVariablesUnityEngineObjects: [] 233 | publicVariablesSerializationDataFormat: 0 234 | -------------------------------------------------------------------------------- /Website/app.js: -------------------------------------------------------------------------------- 1 | import { baseLayerLuminance, StandardLuminance } from 'https://unpkg.com/@fluentui/web-components'; 2 | 3 | const LISTING_URL = "{{ listingInfo.Url }}"; 4 | 5 | const PACKAGES = { 6 | {{~ for package in packages ~}} 7 | "{{ package.Name }}": { 8 | name: "{{ package.Name }}", 9 | displayName: "{{ if package.DisplayName; package.DisplayName; end; }}", 10 | description: "{{ if package.Description; package.Description; end; }}", 11 | version: "{{ package.Version }}", 12 | author: { 13 | name: "{{ if package.Author.Name; package.Author.Name; end; }}", 14 | url: "{{ if package.Author.Url; package.Author.Url; end; }}", 15 | }, 16 | dependencies: { 17 | {{~ for dependency in package.Dependencies ~}} 18 | "{{ dependency.Name }}": "{{ dependency.Version }}", 19 | {{~ end ~}} 20 | }, 21 | keywords: [ 22 | {{~ for keyword in package.Keywords ~}} 23 | "{{ keyword }}", 24 | {{~ end ~}} 25 | ], 26 | license: "{{ package.License }}", 27 | licensesUrl: "{{ package.LicensesUrl }}", 28 | }, 29 | {{~ end ~}} 30 | }; 31 | 32 | const setTheme = () => { 33 | const isDarkTheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches; 34 | if (isDarkTheme()) { 35 | baseLayerLuminance.setValueFor(document.documentElement, StandardLuminance.DarkMode); 36 | } else { 37 | baseLayerLuminance.setValueFor(document.documentElement, StandardLuminance.LightMode); 38 | } 39 | } 40 | 41 | (() => { 42 | setTheme(); 43 | 44 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { 45 | setTheme(); 46 | }); 47 | 48 | const packageGrid = document.getElementById('packageGrid'); 49 | 50 | const searchInput = document.getElementById('searchInput'); 51 | searchInput.addEventListener('input', ({ target: { value = '' }}) => { 52 | const items = packageGrid.querySelectorAll('fluent-data-grid-row[row-type="default"]'); 53 | items.forEach(item => { 54 | if (value === '') { 55 | item.style.display = 'grid'; 56 | return; 57 | } 58 | if ( 59 | item.dataset?.packageName?.toLowerCase()?.includes(value.toLowerCase()) || 60 | item.dataset?.packageId?.toLowerCase()?.includes(value.toLowerCase()) 61 | ) { 62 | item.style.display = 'grid'; 63 | } else { 64 | item.style.display = 'none'; 65 | } 66 | }); 67 | }); 68 | 69 | const urlBarHelpButton = document.getElementById('urlBarHelp'); 70 | const addListingToVccHelp = document.getElementById('addListingToVccHelp'); 71 | urlBarHelpButton.addEventListener('click', () => { 72 | addListingToVccHelp.hidden = false; 73 | }); 74 | const addListingToVccHelpClose = document.getElementById('addListingToVccHelpClose'); 75 | addListingToVccHelpClose.addEventListener('click', () => { 76 | addListingToVccHelp.hidden = true; 77 | }); 78 | 79 | const vccListingInfoUrlFieldCopy = document.getElementById('vccListingInfoUrlFieldCopy'); 80 | vccListingInfoUrlFieldCopy.addEventListener('click', () => { 81 | const vccUrlField = document.getElementById('vccListingInfoUrlField'); 82 | vccUrlField.select(); 83 | navigator.clipboard.writeText(vccUrlField.value); 84 | vccUrlFieldCopy.appearance = 'accent'; 85 | setTimeout(() => { 86 | vccUrlFieldCopy.appearance = 'neutral'; 87 | }, 1000); 88 | }); 89 | 90 | const vccAddRepoButton = document.getElementById('vccAddRepoButton'); 91 | vccAddRepoButton.addEventListener('click', () => window.location.assign(`vcc://vpm/addRepo?url=${encodeURIComponent(LISTING_URL)}`)); 92 | 93 | const vccUrlFieldCopy = document.getElementById('vccUrlFieldCopy'); 94 | vccUrlFieldCopy.addEventListener('click', () => { 95 | const vccUrlField = document.getElementById('vccUrlField'); 96 | vccUrlField.select(); 97 | navigator.clipboard.writeText(vccUrlField.value); 98 | vccUrlFieldCopy.appearance = 'accent'; 99 | setTimeout(() => { 100 | vccUrlFieldCopy.appearance = 'neutral'; 101 | }, 1000); 102 | }); 103 | 104 | const rowMoreMenu = document.getElementById('rowMoreMenu'); 105 | const hideRowMoreMenu = e => { 106 | if (rowMoreMenu.contains(e.target)) return; 107 | document.removeEventListener('click', hideRowMoreMenu); 108 | rowMoreMenu.hidden = true; 109 | } 110 | 111 | const rowMenuButtons = document.querySelectorAll('.rowMenuButton'); 112 | rowMenuButtons.forEach(button => { 113 | button.addEventListener('click', e => { 114 | if (rowMoreMenu?.hidden) { 115 | rowMoreMenu.style.top = `${e.clientY + e.target.clientHeight}px`; 116 | rowMoreMenu.style.left = `${e.clientX - 120}px`; 117 | rowMoreMenu.hidden = false; 118 | 119 | const downloadLink = rowMoreMenu.querySelector('#rowMoreMenuDownload'); 120 | const downloadListener = () => { 121 | window.open(e?.target?.dataset?.packageUrl, '_blank'); 122 | } 123 | downloadLink.addEventListener('change', () => { 124 | downloadListener(); 125 | downloadLink.removeEventListener('change', downloadListener); 126 | }); 127 | 128 | setTimeout(() => { 129 | document.addEventListener('click', hideRowMoreMenu); 130 | }, 1); 131 | } 132 | }); 133 | }); 134 | 135 | const packageInfoModal = document.getElementById('packageInfoModal'); 136 | const packageInfoModalClose = document.getElementById('packageInfoModalClose'); 137 | packageInfoModalClose.addEventListener('click', () => { 138 | packageInfoModal.hidden = true; 139 | }); 140 | 141 | // Fluent dialogs use nested shadow-rooted elements, so we need to use JS to style them 142 | const modalControl = packageInfoModal.shadowRoot.querySelector('.control'); 143 | modalControl.style.maxHeight = "90%"; 144 | modalControl.style.transition = 'height 0.2s ease-in-out'; 145 | modalControl.style.overflowY = 'hidden'; 146 | 147 | const packageInfoName = document.getElementById('packageInfoName'); 148 | const packageInfoId = document.getElementById('packageInfoId'); 149 | const packageInfoVersion = document.getElementById('packageInfoVersion'); 150 | const packageInfoDescription = document.getElementById('packageInfoDescription'); 151 | const packageInfoAuthor = document.getElementById('packageInfoAuthor'); 152 | const packageInfoDependencies = document.getElementById('packageInfoDependencies'); 153 | const packageInfoKeywords = document.getElementById('packageInfoKeywords'); 154 | const packageInfoLicense = document.getElementById('packageInfoLicense'); 155 | 156 | const rowAddToVccButtons = document.querySelectorAll('.rowAddToVccButton'); 157 | rowAddToVccButtons.forEach((button) => { 158 | button.addEventListener('click', () => window.location.assign(`vcc://vpm/addRepo?url=${encodeURIComponent(LISTING_URL)}`)); 159 | }); 160 | 161 | const rowPackageInfoButton = document.querySelectorAll('.rowPackageInfoButton'); 162 | rowPackageInfoButton.forEach((button) => { 163 | button.addEventListener('click', e => { 164 | const packageId = e.target.dataset?.packageId; 165 | const packageInfo = PACKAGES?.[packageId]; 166 | if (!packageInfo) { 167 | console.error(`Did not find package ${packageId}. Packages available:`, PACKAGES); 168 | return; 169 | } 170 | 171 | packageInfoName.textContent = packageInfo.displayName; 172 | packageInfoId.textContent = packageId; 173 | packageInfoVersion.textContent = `v${packageInfo.version}`; 174 | packageInfoDescription.textContent = packageInfo.description; 175 | packageInfoAuthor.textContent = packageInfo.author.name; 176 | packageInfoAuthor.href = packageInfo.author.url; 177 | 178 | if ((packageInfo.keywords?.length ?? 0) === 0) { 179 | packageInfoKeywords.parentElement.classList.add('hidden'); 180 | } else { 181 | packageInfoKeywords.parentElement.classList.remove('hidden'); 182 | packageInfoKeywords.innerHTML = null; 183 | packageInfo.keywords.forEach(keyword => { 184 | const keywordDiv = document.createElement('div'); 185 | keywordDiv.classList.add('me-2', 'mb-2', 'badge'); 186 | keywordDiv.textContent = keyword; 187 | packageInfoKeywords.appendChild(keywordDiv); 188 | }); 189 | } 190 | 191 | if (!packageInfo.license?.length && !packageInfo.licensesUrl?.length) { 192 | packageInfoLicense.parentElement.classList.add('hidden'); 193 | } else { 194 | packageInfoLicense.parentElement.classList.remove('hidden'); 195 | packageInfoLicense.textContent = packageInfo.license ?? 'See License'; 196 | packageInfoLicense.href = packageInfo.licensesUrl ?? '#'; 197 | } 198 | 199 | packageInfoDependencies.innerHTML = null; 200 | Object.entries(packageInfo.dependencies).forEach(([name, version]) => { 201 | const depRow = document.createElement('li'); 202 | depRow.classList.add('mb-2'); 203 | depRow.textContent = `${name} @ v${version}`; 204 | packageInfoDependencies.appendChild(depRow); 205 | }); 206 | 207 | packageInfoModal.hidden = false; 208 | 209 | setTimeout(() => { 210 | const height = packageInfoModal.querySelector('.col').clientHeight; 211 | modalControl.style.setProperty('--dialog-height', `${height + 14}px`); 212 | }, 1); 213 | }); 214 | }); 215 | 216 | const packageInfoVccUrlFieldCopy = document.getElementById('packageInfoVccUrlFieldCopy'); 217 | packageInfoVccUrlFieldCopy.addEventListener('click', () => { 218 | const vccUrlField = document.getElementById('packageInfoVccUrlField'); 219 | vccUrlField.select(); 220 | navigator.clipboard.writeText(vccUrlField.value); 221 | vccUrlFieldCopy.appearance = 'accent'; 222 | setTimeout(() => { 223 | vccUrlFieldCopy.appearance = 'neutral'; 224 | }, 1000); 225 | }); 226 | 227 | const packageInfoListingHelp = document.getElementById('packageInfoListingHelp'); 228 | packageInfoListingHelp.addEventListener('click', () => { 229 | addListingToVccHelp.hidden = false; 230 | }); 231 | })(); -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/PlayerObjectAssigner.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &6666951785657947597 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: 3276687640108633848} 12 | - component: {fileID: 6984481130000384837} 13 | - component: {fileID: -3945521236885312116} 14 | - component: {fileID: 4488810526670663005} 15 | m_Layer: 0 16 | m_Name: PlayerObjectAssigner 17 | m_TagString: Untagged 18 | m_Icon: {fileID: 0} 19 | m_NavMeshLayer: 0 20 | m_StaticEditorFlags: 0 21 | m_IsActive: 1 22 | --- !u!4 &3276687640108633848 23 | Transform: 24 | m_ObjectHideFlags: 0 25 | m_CorrespondingSourceObject: {fileID: 0} 26 | m_PrefabInstance: {fileID: 0} 27 | m_PrefabAsset: {fileID: 0} 28 | m_GameObject: {fileID: 6666951785657947597} 29 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 30 | m_LocalPosition: {x: 0, y: 0, z: 0} 31 | m_LocalScale: {x: 1, y: 1, z: 1} 32 | m_Children: [] 33 | m_Father: {fileID: 0} 34 | m_RootOrder: 0 35 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 36 | --- !u!114 &6984481130000384837 37 | MonoBehaviour: 38 | m_ObjectHideFlags: 0 39 | m_CorrespondingSourceObject: {fileID: 0} 40 | m_PrefabInstance: {fileID: 0} 41 | m_PrefabAsset: {fileID: 0} 42 | m_GameObject: {fileID: 6666951785657947597} 43 | m_Enabled: 1 44 | m_EditorHideFlags: 0 45 | m_Script: {fileID: 11500000, guid: d9c0d913d6d4bd741aec5a89b8072b28, type: 3} 46 | m_Name: 47 | m_EditorClassIdentifier: 48 | cyanPlayerObjectPoolPrefab: {fileID: 8671630162616761239, guid: a35f2996ce6d14c4c854aba5420212ed, 49 | type: 3} 50 | poolObjectPrefab: {fileID: 0} 51 | pool: {fileID: 0} 52 | assigner: {fileID: -3945521236885312116} 53 | --- !u!114 &-3945521236885312116 54 | MonoBehaviour: 55 | m_ObjectHideFlags: 0 56 | m_CorrespondingSourceObject: {fileID: 0} 57 | m_PrefabInstance: {fileID: 0} 58 | m_PrefabAsset: {fileID: 0} 59 | m_GameObject: {fileID: 6666951785657947597} 60 | m_Enabled: 1 61 | m_EditorHideFlags: 0 62 | m_Script: {fileID: 11500000, guid: 511c88e9e2f5ef84aa091d7eca6eeb51, type: 3} 63 | m_Name: 64 | m_EditorClassIdentifier: 65 | serializationData: 66 | SerializedFormat: 2 67 | SerializedBytes: 68 | ReferencedUnityObjects: [] 69 | SerializedBytesString: 70 | Prefab: {fileID: 0} 71 | PrefabModificationsReferencedUnityObjects: [] 72 | PrefabModifications: [] 73 | SerializationNodes: [] 74 | _udonSharpBackingUdonBehaviour: {fileID: 4488810526670663005} 75 | setNetworkOwnershipForPoolObjects: 1 76 | disableUnassignedObjects: 1 77 | poolEventListener: {fileID: 0} 78 | poolObjectsParent: {fileID: 3276687640108633848} 79 | --- !u!114 &4488810526670663005 80 | MonoBehaviour: 81 | m_ObjectHideFlags: 0 82 | m_CorrespondingSourceObject: {fileID: 0} 83 | m_PrefabInstance: {fileID: 0} 84 | m_PrefabAsset: {fileID: 0} 85 | m_GameObject: {fileID: 6666951785657947597} 86 | m_Enabled: 1 87 | m_EditorHideFlags: 0 88 | m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} 89 | m_Name: 90 | m_EditorClassIdentifier: 91 | interactTextPlacement: {fileID: 0} 92 | interactText: Use 93 | interactTextGO: {fileID: 0} 94 | proximity: 2 95 | SynchronizePosition: 0 96 | AllowCollisionOwnershipTransfer: 0 97 | Reliable: 0 98 | _syncMethod: 0 99 | serializedProgramAsset: {fileID: 11400000, guid: 564c21d778bd54a409e87b08c86ca519, 100 | type: 2} 101 | programSource: {fileID: 11400000, guid: 2198d3daa09eca24186cd87102f01cb5, type: 2} 102 | serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABg0AAAAAAAAAAi8CAAAAAUsAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBCAG8AbwBsAGUAYQBuACwAIABtAHMAYwBvAHIAbABpAGIAXQBdACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgACAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAEhAAAAcwBlAHQATgBlAHQAdwBvAHIAawBPAHcAbgBlAHIAcwBoAGkAcABGAG8AcgBQAG8AbwBsAE8AYgBqAGUAYwB0AHMAJwEEAAAAdAB5AHAAZQABGAAAAFMAeQBzAHQAZQBtAC4AQgBvAG8AbABlAGEAbgAsACAAbQBzAGMAbwByAGwAaQBiACsBBQAAAFYAYQBsAHUAZQABBwUCLwMAAAABYgAAAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAC4AVQBkAG8AbgBWAGEAcgBpAGEAYgBsAGUAYAAxAFsAWwBVAG4AaQB0AHkARQBuAGcAaQBuAGUALgBDAG8AbQBwAG8AbgBlAG4AdABbAF0ALAAgAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAEMAbwByAGUATQBvAGQAdQBsAGUAXQBdACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgADAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAEKAAAAcABvAG8AbABlAGQAVQBkAG8AbgAnAQQAAAB0AHkAcABlAAEvAAAAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AQwBvAG0AcABvAG4AZQBuAHQAWwBdACwAIABVAG4AaQB0AHkARQBuAGcAaQBuAGUALgBDAG8AcgBlAE0AbwBkAHUAbABlAAEBBQAAAFYAYQBsAHUAZQAvBAAAAAEvAAAAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AQwBvAG0AcABvAG4AZQBuAHQAWwBdACwAIABVAG4AaQB0AHkARQBuAGcAaQBuAGUALgBDAG8AcgBlAE0AbwBkAHUAbABlAAQAAAAGAAAAAAAAAAAHBQcFAi8FAAAAAVcAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAVgBSAEMALgBTAEQASwBCAGEAcwBlAC4AVgBSAEMAUABsAGEAeQBlAHIAQQBwAGkALAAgAFYAUgBDAFMARABLAEIAYQBzAGUAXQBdACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAF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 103 | publicVariablesUnityEngineObjects: [] 104 | publicVariablesSerializationDataFormat: 0 105 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Readme.txt: -------------------------------------------------------------------------------- 1 | CyanPlayerObjectPool 2 | Created by CyanLaser#4695 3 | https://github.com/CyanLaser/CyanPlayerObjectPool 4 | 5 | Assigns a unique object to every player in the world. 6 | 7 | - Can be used with all Udon Compilers! - Includes examples for UdonGraph, UdonSharp, CyanTrigger 8 | - Network Race Condition Safe - Every player will get an object over time, even when multiple join at once. 9 | - Master Crash Verification - On master change, all players and all objects are verified to ensure that each pair is still valid. Old objects will be cleaned up and new players will be assigned an object. 10 | - Supports multiple object types - Prefabs created for this system can be used together without conflicting. 11 | 12 | 13 | --- General Use --- 14 | 15 | 16 | Dependencies 17 | 18 | UdonSharp 1.0 - https://github.com/vrchat-community/UdonSharp 19 | While UdonSharp is required to run, you may use UdonGraph or CyanTrigger to create your pooled object programs. 20 | 21 | 22 | Setup 23 | 24 | 1. Drag the PlayerObjectPool and PlayerObjectAssigner prefabs into your scene. 25 | 2. In the PlayerObjectPool prefab, set the pool size to double the world capacity. 26 | 3. Create an Udon program to be used for each pooled object, implementing the required items (see template UdonGraph, CyanTrigger, or UdonSharp script) 27 | 4. Create a new GameObject with this Udon program, make it a prefab, and drag the prefab into the "Pool Object Prefab" field in the PlayerObjectAssigner prefab. This will automatically create enough instances of the pool object for the current pool size. 28 | 29 | See the example scenes for more details on proper setup. 30 | 31 | 32 | Examples 33 | 34 | Samples for each compiler type can be imported through the Package Manager. Open the Package Manager through "Window/Package Manager". Once open, in the top right, click the drop down and select "In Project". Find "Cyan Player Object Pool" under the heading labeled "Custom". In the Samples section, you can then import examples using UdonGraph, UdonSharp, or CyanTrigger. Once impored, the examples can be found in in your assets folder under "Assets/Samples/CyanPlayerObjectPool/". 35 | 36 | 37 | Pooled Object Requirements 38 | 39 | When creating an Udon program to be used as a pooled object, it needs three things: 40 | 1. A public VRCPlayerApi variable named "Owner". This variable will store the current assigned owner for the object, or null if no owner has been assigned. 41 | 2. A public event named "_OnOwnerSet". This event will be called by everyone when the object is assigned a new owner. 42 | 3. A public event named "_OnCleanup". This event will be called by everyone when the object owner is leaving the world and the object is about to be unassigned. 43 | 44 | 45 | Known Potential Issues 46 | 47 | - When creating a pooled object with synced variables, be sure to check if the owner has been assigned when updating data based on those variables (OnVariableChanged and OnDesrialization). When a player joins and is receiving synced data, it is possible that the variable data for the pool object will be set before the object has been assigned. The solution to this is to verify the owner is valid before handing variable changes, and to handle variable changes in both _OnOwnerSet and in OnDeserialization. See example programs for more details. 48 | 49 | - When creating a pooled object with synced variables, synced values will not send when the object is disabled. When a player leaves the instance, all players will disable the pooled object, which prevents any cleanup code from syncing the last value assigned. One solution is to ensure that ALL players reset all variables, and not just the new owner. Another solution is to uncheck the option in the PlayerObjectAssigner "Disable Unassigned Objects". This will leave the objects enabled at all times, allowing you to manually disable them if needed. 50 | 51 | - When creating pooled objects with update order (Execution Order), there are known bugs that this order is inconsistent when nested under another UdonBehaviour with its own update order set. The PlayerObjectAssigner has this set, which will affect the pooled objects. The solution to this is to move the pooled objects under a different parent, and set the "Pool Objects Parent" value in the PlayerObjectAssigner. 52 | 53 | 54 | --- Advanced Use --- 55 | 56 | 57 | Setup for Prefab Authors 58 | 59 | 1. Right click on the PlayerObjectAssigner prefab and create a new Prefab Variant. 60 | 2. Create your Pool Object prefab and set it in the Variant's "Pool Object Prefab" field. 61 | 3. (Optional) If your system depends on objects outside of the Pool Object (Pool Event Listeners), create a new prefab for your system, have the prefab variant as a child. Add other systems dependent on your pool system as children. Ensure that the PlayerObjectAssigner prefab variant does not have any children as these will be created when dragged into the scene. 62 | 4. Create a Readme file for your prefab and tell users to drag your system prefab into the scene. When the prefab is added to the scene, it will auto link with the Object Pool system, or create a new one if one did not already exist. 63 | 64 | 65 | Pool Event Listener 66 | 67 | The PlayerObjectAssigner can send optional events to a listener UdonBehaviour so that you can handle different callbacks. 68 | - _OnLocalPlayerAssigned - This event is called whenever the local player has been assigned their object. Use this event to enable external features that require the local player to have an assigned object. 69 | - _OnPlayerAssigned - This event is called when any player is assigned a pool object. When using this event, if the program has a public VRCPlayerAPI variable named "playerAssignedPlayer", a public int variable named "playerAssignedIndex", or a public UdonBehaviour variable named "playerAssignedPoolObject", it will be set before the event is called. 70 | - _OnPlayerUnassigned - This event is called when any player's object has been unassigned. When using this event, if the program has a public VRCPlayerAPI variable named "playerUnassignedPlayer", a public int variable named "playerUnassignedIndex", or a public UdonBehaviour variable named "playerUnassignedPoolObject", it will be set before the event is called. 71 | 72 | 73 | UdonGraph and CyanTrigger Helper Methods 74 | 75 | The PlayerObjectAssigner script contains a few helper methods that can be used with UdonGraph and CyanTrigger. 76 | For these methods, you will need to use SetProgramVariable on the pool to set the required input and GetProgramVariable to get the output. See the example scenes for more details 77 | 78 | _GetPlayerPooledObjectEvent 79 | Input: VRCPlayerApi "playerInput" 80 | Output: GameObject "poolObjectOutput" 81 | Description: Given a player, get the GameObject that has been assigned to this player. 82 | 83 | _GetPlayerPooledObjectByIdEvent 84 | Input: int "playerIdInput" 85 | Output: GameObject "poolObjectOutput" 86 | Description: Given a player id, get the GameObject that has been assigned to this player. 87 | 88 | _GetPlayerPooledUdonEvent 89 | Input: VRCPlayerApi "playerInput" 90 | Output: UdonBehaviour "poolUdonOutput" 91 | Description: Given a player, get the UdonBehaviour that has been assigned to this player. 92 | 93 | _GetPlayerPooledUdonByIdEvent 94 | Input: int "playerIdInput" 95 | Output: UdonBehaviour "poolUdonOutput" 96 | Description: Given a player id, get the UdonBehaviour that has been assigned to this player. 97 | 98 | _GetOrderedPlayersEvent 99 | Input: Nothing 100 | Output: VRCPlayer[] "playerArrayOutput" 101 | Description: Get an ordered list of players based on the pool's assignment. This list will be the same order for all clients and is useful for randomization. 102 | 103 | _GetOrderedPlayersNoAllocEvent 104 | Input: VRCPlayer[] "playerArrayInput" 105 | Output: int "playerCountOutput" 106 | Description: Fill the input array in order with players based on the pool's assignment. The number of players will be stored in the output variable. This list will be the same order for all clients and is useful for randomization. 107 | 108 | _GetActivePoolObjectsEvent 109 | Input: Nothing 110 | Output: Component[] "poolObjectArrayOutput" 111 | Description: Get an array of active pool objects based on the current assignments. This list will be the same order for all clients and is useful for randomization. 112 | 113 | _GetActivePoolObjectsNoAllocEvent 114 | Input: Component[] "poolObjectArrayInput" 115 | Output: int "poolObjectCountOutput" 116 | Description: Fill the input array in order with active pool objects based on the current assignments. The number of pooled objects will be stored in the output variable. This list will be the same order for all clients and is useful for randomization. 117 | 118 | _GetPlayerPoolIndexEvent 119 | Input: VRCPlayerApi "playerInput" 120 | Output: int "playerIndexOutput" 121 | Description: Given a player, get the pool index for the given player. The pool index will be a value between 0 and the total number of objects in the pool. This is useful since Player Ids will continue to increase with no cap as the instance is alive. 122 | 123 | _GetPlayerPoolIndexByIdEvent 124 | Input: int "playerIdInput" 125 | Output: int "playerIndexOutput" 126 | Description: Given a player id, get the pool index for the given player. The pool index will be a value between 0 and the total number of objects in the pool. This is useful since Player Ids will continue to increase with no cap as the instance is alive. 127 | 128 | 129 | UdonSharp Helper Methods 130 | 131 | The PlayerObjectAssigner script contains a few helper methods that can be used with UdonSharp. 132 | 133 | GameObject _GetPlayerPooledObject(VRCPlayerApi player) 134 | GameObject _GetPlayerPooledObjectById(int playerId) 135 | Component _GetPlayerPooledUdon(VRCPlayerApi player) 136 | Component _GetPlayerPooledUdonById(int playerId) 137 | VRCPlayerApi[] _GetOrderedPlayers() 138 | int _GetOrderedPlayersNoAlloc(VRCPlayerApi[] players) 139 | Component[] _GetActivePoolObjects() 140 | int _GetActivePoolObjectsNoAlloc(Component[] pooledObjects) 141 | int _GetPlayerPoolIndex(VRCPlayerApi player) 142 | int _GetPlayerPoolIndexById(int playerId) 143 | 144 | Implementation Details 145 | 146 | This pool system works by having master do all the work. On player join, master will assign this player a free object and on player leave, master will remove assignment of this object. Assignment is handled through a synced int array. Whenever this array changes, all clients will read through the array to find out the changes and set the object state accordingly. The script also implements various error handling in case master crashes before assigning or removing assignments for various players. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CyanPlayerObjectPool 2 | A VRChat system that will assign a unique object to every player in the world. 3 | 4 | - Can be used with all Udon Compilers! 5 | - Includes examples for UdonGraph, UdonSharp, CyanTrigger 6 | - Network Race Condition Safe 7 | - Every player will get an object over time, even when multiple join at once. 8 | - Master Crash Verification 9 | - On master change, all players and all objects are verified to ensure that each pair is still valid. Old objects will be cleaned up and new players will be assigned an object. 10 | - Supports multiple object types 11 | - Prefabs created for this system can be used together without conflicting. 12 | 13 | 14 | # General Use 15 | 16 | 17 | ## Dependencies 18 | 19 | - UdonSharp 1.0 - https://github.com/vrchat-community/UdonSharp 20 | - While UdonSharp is required to run, you may use UdonGraph or CyanTrigger to create your pooled object programs. 21 | 22 | 23 | ## Installation 24 | 25 | - [Add through VCC](https://cyanlaser.github.io/CyanPlayerObjectPool/) 26 | 27 | 28 | ## Setup 29 | 30 | 1. Drag the PlayerObjectPool and PlayerObjectAssigner prefabs into your scene. 31 | 2. In the PlayerObjectPool prefab, set the pool size to double the world capacity. 32 | 3. Create an Udon program to be used for each pooled object, implementing the required items (see template UdonGraph, CyanTrigger, or UdonSharp script) 33 | 4. Create a new GameObject with this Udon program, make it a prefab, and drag the prefab into the "Pool Object Prefab" field in the PlayerObjectAssigner prefab. This will automatically create enough instances of the pool object for the current pool size. 34 | 35 | See the example scenes for more details on proper setup. 36 | 37 | 38 | ## Examples 39 | 40 | Samples for each compiler type can be imported through the Package Manager. Open the Package Manager through "Window/Package Manager". Once open, in the top right, click the drop down and select "In Project". Find "Cyan Player Object Pool" under the heading labeled "Custom". In the Samples section, you can then import examples using UdonGraph, UdonSharp, or CyanTrigger. Once impored, the examples can be found in in your assets folder under "Assets/Samples/CyanPlayerObjectPool/". 41 | 42 | 43 | ## Pooled Object Requirements 44 | 45 | When creating an Udon program to be used as a pooled object, it needs three things: 46 | 1. A public VRCPlayerApi variable named "Owner". This variable will store the current assigned owner for the object, or null if no owner has been assigned. 47 | 2. A public event named "_OnOwnerSet". This event will be called by everyone when the object is assigned a new owner. 48 | 3. A public event named "_OnCleanup". This event will be called by everyone when the object owner is leaving the world and the object is about to be unassigned. 49 | 50 | 51 | ## Known Potential Issues 52 | 53 | - When creating a pooled object with synced variables, be sure to check if the owner has been assigned when updating data based on those variables (OnVariableChanged and OnDesrialization). When a player joins and is receiving synced data, it is possible that the variable data for the pool object will be set before the object has been assigned. The solution to this is to verify the owner is valid before handing variable changes, and to handle variable changes in both _OnOwnerSet and in OnDeserialization. See example programs for more details. 54 | 55 | - When creating a pooled object with synced variables, synced values will not send when the object is disabled. When a player leaves the instance, all players will disable the pooled object, which prevents any cleanup code from syncing the last value assigned. One solution is to ensure that ALL players reset all variables, and not just the new owner. Another solution is to uncheck the option in the PlayerObjectAssigner "Disable Unassigned Objects". This will leave the objects enabled at all times, allowing you to manually disable them if needed. 56 | 57 | - When creating pooled objects with update order (Execution Order), there are known bugs that this order is inconsistent when nested under another UdonBehaviour with its own update order set. The PlayerObjectAssigner has this set, which will affect the pooled objects. The solution to this is to move the pooled objects under a different parent, and set the "Pool Objects Parent" value in the PlayerObjectAssigner. 58 | 59 | 60 | # Advanced Use 61 | 62 | 63 | ## Setup for Prefab Authors 64 | 65 | 1. Right click on the PlayerObjectAssigner prefab and create a new Prefab Variant. 66 | 2. Create your Pool Object prefab and set it in the Variant's "Pool Object Prefab" field. 67 | 3. (Optional) If your system depends on objects outside of the Pool Object (Pool Event Listeners), create a new prefab for your system, have the prefab variant as a child. Add other systems dependent on your pool system as children. Ensure that the PlayerObjectAssigner prefab variant does not have any children as these will be created when dragged into the scene. 68 | 4. Create a Readme file for your prefab and tell users to drag your system prefab into the scene. When the prefab is added to the scene, it will auto link with the Object Pool system, or create a new one if one did not already exist. 69 | 70 | 71 | ## Pool Event Listener 72 | 73 | The PlayerObjectAssigner can send optional events to a listener UdonBehaviour so that you can handle different callbacks. 74 | - _OnLocalPlayerAssigned - This event is called whenever the local player has been assigned their object. Use this event to enable external features that require the local player to have an assigned object. 75 | - _OnPlayerAssigned - This event is called when any player is assigned a pool object. When using this event, if the program has a public VRCPlayerAPI variable named "playerAssignedPlayer", a public int variable named "playerAssignedIndex", or a public UdonBehaviour variable named "playerAssignedPoolObject", it will be set before the event is called. 76 | - _OnPlayerUnassigned - This event is called when any player's object has been unassigned. When using this event, if the program has a public VRCPlayerAPI variable named "playerUnassignedPlayer", a public int variable named "playerUnassignedIndex", or a public UdonBehaviour variable named "playerUnassignedPoolObject", it will be set before the event is called. 77 | 78 | 79 | ## UdonGraph and CyanTrigger Helper Methods 80 | 81 | The PlayerObjectAssigner script contains a few helper methods that can be used with UdonGraph and CyanTrigger. 82 | For these methods, you will need to use SetProgramVariable on the pool to set the required input and GetProgramVariable to get the output. See the example scenes for more details 83 | 84 | - _GetPlayerPooledObjectEvent 85 | - Input: VRCPlayerApi "playerInput" 86 | - Output: GameObject "poolObjectOutput" 87 | - Description: Given a player, get the GameObject that has been assigned to this player. 88 | 89 | - _GetPlayerPooledObjectByIdEvent 90 | - Input: int "playerIdInput" 91 | - Output: GameObject "poolObjectOutput" 92 | - Description: Given a player id, get the GameObject that has been assigned to this player. 93 | 94 | - _GetPlayerPooledUdonEvent 95 | - Input: VRCPlayerApi "playerInput" 96 | - Output: UdonBehaviour "poolUdonOutput" 97 | - Description: Given a player, get the UdonBehaviour that has been assigned to this player. 98 | 99 | - _GetPlayerPooledUdonByIdEvent 100 | - Input: int "playerIdInput" 101 | - Output: UdonBehaviour "poolUdonOutput" 102 | - Description: Given a player id, get the UdonBehaviour that has been assigned to this player. 103 | 104 | - _GetOrderedPlayersEvent 105 | - Input: Nothing 106 | - Output: VRCPlayer[] "playerArrayOutput" 107 | - Description: Get an ordered list of players based on the pool's assignment. This list will be the same order for all clients and is useful for randomization. 108 | 109 | - _GetOrderedPlayersNoAllocEvent 110 | - Input: VRCPlayer[] "playerArrayInput" 111 | - Output: int "playerCountOutput" 112 | - Description: Fill the input array in order with players based on the pool's assignment. The number of players will be stored in the output variable. This list will be the same order for all clients and is useful for randomization. 113 | 114 | - _GetActivePoolObjectsEvent 115 | - Input: Nothing 116 | - Output: Component[] "poolObjectArrayOutput" 117 | - Description: Get an array of active pool objects based on the current assignments. This list will be the same order for all clients and is useful for randomization. 118 | 119 | - _GetActivePoolObjectsNoAllocEvent 120 | - Input: Component[] "poolObjectArrayInput" 121 | - Output: int "poolObjectCountOutput" 122 | - Description: Fill the input array in order with active pool objects based on the current assignments. The number of pooled objects will be stored in the output variable. This list will be the same order for all clients and is useful for randomization. 123 | 124 | - _GetPlayerPoolIndexEvent 125 | - Input: VRCPlayerApi "playerInput" 126 | - Output: int "playerIndexOutput" 127 | - Description: Given a player, get the pool index for the given player. The pool index will be a value between 0 and the total number of objects in the pool. This is useful since Player Ids will continue to increase with no cap as the instance is alive. 128 | 129 | _GetPlayerPoolIndexByIdEvent 130 | - Input: int "playerIdInput" 131 | - Output: int "playerIndexOutput" 132 | - Description: Given a player id, get the pool index for the given player. The pool index will be a value between 0 and the total number of objects in the pool. This is useful since Player Ids will continue to increase with no cap as the instance is alive. 133 | 134 | 135 | ## UdonSharp Helper Methods 136 | 137 | The PlayerObjectAssigner script contains a few helper methods that can be used with UdonSharp. 138 | 139 | - GameObject _GetPlayerPooledObject(VRCPlayerApi player) 140 | - GameObject _GetPlayerPooledObjectById(int playerId) 141 | - Component _GetPlayerPooledUdon(VRCPlayerApi player) 142 | - Component _GetPlayerPooledUdonById(int playerId) 143 | - VRCPlayerApi[] _GetOrderedPlayers() 144 | - int _GetOrderedPlayersNoAlloc(VRCPlayerApi[] players) 145 | - Component[] _GetActivePoolObjects() 146 | - int _GetActivePoolObjectsNoAlloc(Component[] pooledObjects) 147 | - int _GetPlayerPoolIndex(VRCPlayerApi player) 148 | - int _GetPlayerPoolIndexById(int playerId) 149 | 150 | 151 | ## Implementation Details 152 | 153 | This pool system works by having master do all the work. On player join, master will assign this player a free object and on player leave, master will remove assignment of this object. Assignment is handled through a synced int array. Whenever this array changes, all clients will read through the array to find out the changes and set the object state accordingly. The script also implements various error handling in case master crashes before assigning or removing assignments for various players. 154 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/TemplateGraphPoolEventListener.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 4f11136daadff0b44ac2278a314682ab, type: 3} 13 | m_Name: TemplateGraphPoolEventListener 14 | m_EditorClassIdentifier: 15 | serializedUdonProgramAsset: {fileID: 11400000, guid: 2a3ecfdca02478749addfa51489ed89d, 16 | type: 2} 17 | udonAssembly: ".data_start\r\n\r\n .export playerAssignedPoolObject\r\n .export 18 | playerUnassignedPoolObject\r\n .export playerAssignedIndex\r\n .export playerUnassignedIndex\r\n 19 | \ \r\n playerAssignedPoolObject: %VRCUdonUdonBehaviour, this\r\n playerUnassignedPoolObject: 20 | %VRCUdonUdonBehaviour, this\r\n playerAssignedPlayer: %VRCSDKBaseVRCPlayerApi, 21 | null\r\n playerUnassignedPlayer: %VRCSDKBaseVRCPlayerApi, null\r\n playerAssignedIndex: 22 | %SystemInt32, null\r\n playerUnassignedIndex: %SystemInt32, null\r\n\r\n.data_end\r\n\r\n.code_start\r\n\r\n\r\n.code_end\r\n" 23 | assemblyError: 24 | graphData: 25 | name: 26 | description: 27 | nodes: 28 | - fullName: Event_Custom 29 | uid: 610022c6-706f-4cc8-bcde-7d78b291ed08 30 | position: {x: 119.69787, y: 45.726433} 31 | nodeUIDs: 32 | - 33 | flowUIDs: 34 | - 35 | nodeValues: 36 | - unityObjectValue: {fileID: 0} 37 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|_OnLocalPlayerAssigned 38 | - fullName: Variable_VRCUdonCommonInterfacesIUdonEventReceiver 39 | uid: cdb0e080-a0b6-4a92-8eb3-f5d1bab63899 40 | position: {x: 0, y: 0} 41 | nodeUIDs: 42 | - 43 | - 44 | - 45 | - 46 | - 47 | flowUIDs: [] 48 | nodeValues: 49 | - unityObjectValue: {fileID: 0} 50 | stringValue: 51 | - unityObjectValue: {fileID: 0} 52 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|playerAssignedPoolObject 53 | - unityObjectValue: {fileID: 0} 54 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|True 55 | - unityObjectValue: {fileID: 0} 56 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 57 | - unityObjectValue: {fileID: 0} 58 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 59 | - fullName: Variable_VRCUdonCommonInterfacesIUdonEventReceiver 60 | uid: 001be5fd-4536-4740-aeac-1aae191b0318 61 | position: {x: 0, y: 0} 62 | nodeUIDs: 63 | - 64 | - 65 | - 66 | - 67 | - 68 | flowUIDs: [] 69 | nodeValues: 70 | - unityObjectValue: {fileID: 0} 71 | stringValue: 72 | - unityObjectValue: {fileID: 0} 73 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|playerUnassignedPoolObject 74 | - unityObjectValue: {fileID: 0} 75 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|True 76 | - unityObjectValue: {fileID: 0} 77 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 78 | - unityObjectValue: {fileID: 0} 79 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 80 | - fullName: Event_Custom 81 | uid: 5be367ed-8a39-443c-a215-2b27688d1d7d 82 | position: {x: 123.3339, y: 291.78568} 83 | nodeUIDs: 84 | - 85 | flowUIDs: 86 | - 87 | nodeValues: 88 | - unityObjectValue: {fileID: 0} 89 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|_OnPlayerAssigned 90 | - fullName: Event_Custom 91 | uid: 4df5fc42-45c0-4516-be27-79faa1c67196 92 | position: {x: 122.78149, y: 570.92474} 93 | nodeUIDs: 94 | - 95 | flowUIDs: 96 | - 97 | nodeValues: 98 | - unityObjectValue: {fileID: 0} 99 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|_OnPlayerUnassigned 100 | - fullName: Variable_VRCSDKBaseVRCPlayerApi 101 | uid: 4cad0fe2-02cf-464e-85fc-2d8adb10be5a 102 | position: {x: 0, y: 0} 103 | nodeUIDs: 104 | - 105 | - 106 | - 107 | - 108 | - 109 | flowUIDs: [] 110 | nodeValues: 111 | - unityObjectValue: {fileID: 0} 112 | stringValue: 113 | - unityObjectValue: {fileID: 0} 114 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|playerAssignedPlayer 115 | - unityObjectValue: {fileID: 0} 116 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 117 | - unityObjectValue: {fileID: 0} 118 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 119 | - unityObjectValue: {fileID: 0} 120 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 121 | - fullName: Variable_VRCSDKBaseVRCPlayerApi 122 | uid: d1bfa2f7-335f-481d-88af-1ea07e2da21a 123 | position: {x: 0, y: 0} 124 | nodeUIDs: 125 | - 126 | - 127 | - 128 | - 129 | - 130 | flowUIDs: [] 131 | nodeValues: 132 | - unityObjectValue: {fileID: 0} 133 | stringValue: 134 | - unityObjectValue: {fileID: 0} 135 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|playerUnassignedPlayer 136 | - unityObjectValue: {fileID: 0} 137 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 138 | - unityObjectValue: {fileID: 0} 139 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 140 | - unityObjectValue: {fileID: 0} 141 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 142 | - fullName: Variable_SystemInt32 143 | uid: 0f00236b-4755-4019-a88a-37346ab6c746 144 | position: {x: 0, y: 0} 145 | nodeUIDs: 146 | - 147 | - 148 | - 149 | - 150 | - 151 | flowUIDs: [] 152 | nodeValues: 153 | - unityObjectValue: {fileID: 0} 154 | stringValue: 155 | - unityObjectValue: {fileID: 0} 156 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|playerAssignedIndex 157 | - unityObjectValue: {fileID: 0} 158 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|True 159 | - unityObjectValue: {fileID: 0} 160 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 161 | - unityObjectValue: {fileID: 0} 162 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 163 | - fullName: Variable_SystemInt32 164 | uid: c21908db-adc6-4821-b455-f8914059c76a 165 | position: {x: 0, y: 0} 166 | nodeUIDs: 167 | - 168 | - 169 | - 170 | - 171 | - 172 | flowUIDs: [] 173 | nodeValues: 174 | - unityObjectValue: {fileID: 0} 175 | stringValue: 176 | - unityObjectValue: {fileID: 0} 177 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|playerUnassignedIndex 178 | - unityObjectValue: {fileID: 0} 179 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|True 180 | - unityObjectValue: {fileID: 0} 181 | stringValue: System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|False 182 | - unityObjectValue: {fileID: 0} 183 | stringValue: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|none 184 | updateOrder: 0 185 | graphElementData: 186 | - type: 2 187 | uid: fc8dd40f-3bcd-4486-beb6-3424edcbaa0b 188 | jsonData: '{"uid":"fc8dd40f-3bcd-4486-beb6-3424edcbaa0b","layout":{"serializedVersion":"2","x":94.69791412353516,"y":-19.27356719970703,"width":661.0,"height":173.0},"containedElements":["0ec21c7e-467f-4888-a267-afda60c7ceeb","610022c6-706f-4cc8-bcde-7d78b291ed08","14f8e559-ec93-4ed7-a81a-be76c9290846","485d7ef4-965e-4526-9576-cba7e7652d50","fc48f253-4338-4bba-b4fc-fb88bc58433c"],"title":"Event 189 | called when the local user has been assigned an object","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 190 | - type: 5 191 | uid: 5c806224-0aa1-4f09-b9b0-b5a669fe9339 192 | jsonData: '{"visible":true,"layout":{"serializedVersion":"2","x":10.0,"y":130.0,"width":274.0,"height":245.0}}' 193 | - type: 2 194 | uid: bf65cbe1-3458-4440-9b3f-b11edcdaf54b 195 | jsonData: '{"uid":"bf65cbe1-3458-4440-9b3f-b11edcdaf54b","layout":{"serializedVersion":"2","x":97.78155517578125,"y":505.92474365234377,"width":562.0,"height":173.0},"containedElements":["55e08cea-d1a3-4bbf-9d94-058d5dca7842","fd763f48-5577-418a-b438-8e85cb2ab0df","de57a5b5-e114-4d27-ac27-a2f494481641","e5b96a23-2fee-4ca8-b3d2-845fc204851b","de66bff5-5fef-4e5c-9b81-f931be8f3796","4df5fc42-45c0-4516-be27-79faa1c67196","9598725d-b6de-4e91-9713-fb8cdeaff80b","ada4fefa-ff29-4cd9-ab1a-02c67547975a","1138c372-b969-4aa1-a00b-f4b062e9c4c0","a91d2337-3ae1-4b2a-8f38-9fccb976187c","6894e799-ce77-456f-af9f-5567703053e5"],"title":"Event 196 | called when any player''s object is unassigned","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 197 | - type: 2 198 | uid: f98cfcc7-9920-442c-aa9b-58f2ee44955f 199 | jsonData: '{"uid":"f98cfcc7-9920-442c-aa9b-58f2ee44955f","layout":{"serializedVersion":"2","x":98.33394622802735,"y":226.78570556640626,"width":552.0,"height":173.0},"containedElements":["5be367ed-8a39-443c-a215-2b27688d1d7d","045103c1-3070-4792-a1ad-2e7701c66d01","3fcf8b35-8043-467f-86b6-20afe80bf3de","712c781a-c90f-466a-aa5c-0fb8eef291d0","02c58ad9-516f-4fda-8ffe-7bbdca95aa27","d3fc9399-aeef-4bcd-96cb-6ced3638cbe0"],"title":"Event 200 | called when any player is assigned an object","layer":0,"elementTypeColor":{"r":0.0,"g":0.0,"b":0.0,"a":0.0}}' 201 | viewTransform: 202 | position: {x: 253.2718, y: 62.73428} 203 | scale: 0.57175326 204 | version: 1.0.0 205 | showAssembly: 0 206 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonGraph/DemoGraphPooledObject (0).prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &7239175875574932085 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: 7239175875574932086} 12 | - component: {fileID: 7239175875574932082} 13 | - component: {fileID: 7239175875574932081} 14 | - component: {fileID: 7239175875574932080} 15 | - component: {fileID: 7239175875574932087} 16 | m_Layer: 5 17 | m_Name: Canvas 18 | m_TagString: Untagged 19 | m_Icon: {fileID: 0} 20 | m_NavMeshLayer: 0 21 | m_StaticEditorFlags: 0 22 | m_IsActive: 1 23 | --- !u!224 &7239175875574932086 24 | RectTransform: 25 | m_ObjectHideFlags: 0 26 | m_CorrespondingSourceObject: {fileID: 0} 27 | m_PrefabInstance: {fileID: 0} 28 | m_PrefabAsset: {fileID: 0} 29 | m_GameObject: {fileID: 7239175875574932085} 30 | m_LocalRotation: {x: -0, y: -1, z: -0, w: 0.0000014454126} 31 | m_LocalPosition: {x: 0, y: 0, z: 0} 32 | m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} 33 | m_Children: 34 | - {fileID: 7239175876222275330} 35 | m_Father: {fileID: 7239175876297497478} 36 | m_RootOrder: 0 37 | m_LocalEulerAnglesHint: {x: 0, y: -180.00002, z: 0} 38 | m_AnchorMin: {x: 0, y: 0} 39 | m_AnchorMax: {x: 0, y: 0} 40 | m_AnchoredPosition: {x: 0, y: 0} 41 | m_SizeDelta: {x: 100, y: 100} 42 | m_Pivot: {x: 0.5, y: 0.5} 43 | --- !u!223 &7239175875574932082 44 | Canvas: 45 | m_ObjectHideFlags: 0 46 | m_CorrespondingSourceObject: {fileID: 0} 47 | m_PrefabInstance: {fileID: 0} 48 | m_PrefabAsset: {fileID: 0} 49 | m_GameObject: {fileID: 7239175875574932085} 50 | m_Enabled: 1 51 | serializedVersion: 3 52 | m_RenderMode: 2 53 | m_Camera: {fileID: 0} 54 | m_PlaneDistance: 100 55 | m_PixelPerfect: 0 56 | m_ReceivesEvents: 1 57 | m_OverrideSorting: 0 58 | m_OverridePixelPerfect: 0 59 | m_SortingBucketNormalizedSize: 0 60 | m_AdditionalShaderChannelsFlag: 0 61 | m_SortingLayerID: 0 62 | m_SortingOrder: 0 63 | m_TargetDisplay: 0 64 | --- !u!114 &7239175875574932081 65 | MonoBehaviour: 66 | m_ObjectHideFlags: 0 67 | m_CorrespondingSourceObject: {fileID: 0} 68 | m_PrefabInstance: {fileID: 0} 69 | m_PrefabAsset: {fileID: 0} 70 | m_GameObject: {fileID: 7239175875574932085} 71 | m_Enabled: 1 72 | m_EditorHideFlags: 0 73 | m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} 74 | m_Name: 75 | m_EditorClassIdentifier: 76 | m_UiScaleMode: 0 77 | m_ReferencePixelsPerUnit: 100 78 | m_ScaleFactor: 1 79 | m_ReferenceResolution: {x: 800, y: 600} 80 | m_ScreenMatchMode: 0 81 | m_MatchWidthOrHeight: 0 82 | m_PhysicalUnit: 3 83 | m_FallbackScreenDPI: 96 84 | m_DefaultSpriteDPI: 96 85 | m_DynamicPixelsPerUnit: 3 86 | --- !u!114 &7239175875574932080 87 | MonoBehaviour: 88 | m_ObjectHideFlags: 0 89 | m_CorrespondingSourceObject: {fileID: 0} 90 | m_PrefabInstance: {fileID: 0} 91 | m_PrefabAsset: {fileID: 0} 92 | m_GameObject: {fileID: 7239175875574932085} 93 | m_Enabled: 1 94 | m_EditorHideFlags: 0 95 | m_Script: {fileID: -1533785930, guid: 661092b4961be7145bfbe56e1e62337b, type: 3} 96 | m_Name: 97 | m_EditorClassIdentifier: 98 | --- !u!65 &7239175875574932087 99 | BoxCollider: 100 | m_ObjectHideFlags: 0 101 | m_CorrespondingSourceObject: {fileID: 0} 102 | m_PrefabInstance: {fileID: 0} 103 | m_PrefabAsset: {fileID: 0} 104 | m_GameObject: {fileID: 7239175875574932085} 105 | m_Material: {fileID: 0} 106 | m_IsTrigger: 1 107 | m_Enabled: 0 108 | serializedVersion: 2 109 | m_Size: {x: 1, y: 1, z: 1} 110 | m_Center: {x: 0, y: 0, z: 0} 111 | --- !u!1 &7239175876222275329 112 | GameObject: 113 | m_ObjectHideFlags: 0 114 | m_CorrespondingSourceObject: {fileID: 0} 115 | m_PrefabInstance: {fileID: 0} 116 | m_PrefabAsset: {fileID: 0} 117 | serializedVersion: 6 118 | m_Component: 119 | - component: {fileID: 7239175876222275330} 120 | - component: {fileID: 7239175876222275452} 121 | - component: {fileID: 7239175876222275331} 122 | - component: {fileID: 1511748775479175093} 123 | m_Layer: 5 124 | m_Name: Text 125 | m_TagString: Untagged 126 | m_Icon: {fileID: 0} 127 | m_NavMeshLayer: 0 128 | m_StaticEditorFlags: 0 129 | m_IsActive: 1 130 | --- !u!224 &7239175876222275330 131 | RectTransform: 132 | m_ObjectHideFlags: 0 133 | m_CorrespondingSourceObject: {fileID: 0} 134 | m_PrefabInstance: {fileID: 0} 135 | m_PrefabAsset: {fileID: 0} 136 | m_GameObject: {fileID: 7239175876222275329} 137 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 138 | m_LocalPosition: {x: 0, y: 0, z: 0} 139 | m_LocalScale: {x: 1, y: 1, z: 1} 140 | m_Children: [] 141 | m_Father: {fileID: 7239175875574932086} 142 | m_RootOrder: 0 143 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 144 | m_AnchorMin: {x: 0, y: 0} 145 | m_AnchorMax: {x: 1, y: 1} 146 | m_AnchoredPosition: {x: 0, y: 0} 147 | m_SizeDelta: {x: 0, y: 0} 148 | m_Pivot: {x: 0.5, y: 0.5} 149 | --- !u!222 &7239175876222275452 150 | CanvasRenderer: 151 | m_ObjectHideFlags: 0 152 | m_CorrespondingSourceObject: {fileID: 0} 153 | m_PrefabInstance: {fileID: 0} 154 | m_PrefabAsset: {fileID: 0} 155 | m_GameObject: {fileID: 7239175876222275329} 156 | m_CullTransparentMesh: 0 157 | --- !u!114 &7239175876222275331 158 | MonoBehaviour: 159 | m_ObjectHideFlags: 0 160 | m_CorrespondingSourceObject: {fileID: 0} 161 | m_PrefabInstance: {fileID: 0} 162 | m_PrefabAsset: {fileID: 0} 163 | m_GameObject: {fileID: 7239175876222275329} 164 | m_Enabled: 1 165 | m_EditorHideFlags: 0 166 | m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 167 | m_Name: 168 | m_EditorClassIdentifier: 169 | m_Material: {fileID: 0} 170 | m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} 171 | m_RaycastTarget: 1 172 | m_Maskable: 1 173 | m_OnCullStateChanged: 174 | m_PersistentCalls: 175 | m_Calls: [] 176 | m_FontData: 177 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 178 | m_FontSize: 14 179 | m_FontStyle: 0 180 | m_BestFit: 0 181 | m_MinSize: 10 182 | m_MaxSize: 40 183 | m_Alignment: 4 184 | m_AlignByGeometry: 0 185 | m_RichText: 1 186 | m_HorizontalOverflow: 0 187 | m_VerticalOverflow: 0 188 | m_LineSpacing: 1 189 | m_Text: New Text 190 | --- !u!114 &1511748775479175093 191 | MonoBehaviour: 192 | m_ObjectHideFlags: 0 193 | m_CorrespondingSourceObject: {fileID: 0} 194 | m_PrefabInstance: {fileID: 0} 195 | m_PrefabAsset: {fileID: 0} 196 | m_GameObject: {fileID: 7239175876222275329} 197 | m_Enabled: 1 198 | m_EditorHideFlags: 0 199 | m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3} 200 | m_Name: 201 | m_EditorClassIdentifier: 202 | m_EffectColor: {r: 1, g: 1, b: 1, a: 0.5} 203 | m_EffectDistance: {x: 0.2, y: 0.2} 204 | m_UseGraphicAlpha: 1 205 | --- !u!1 &7239175876297497477 206 | GameObject: 207 | m_ObjectHideFlags: 0 208 | m_CorrespondingSourceObject: {fileID: 0} 209 | m_PrefabInstance: {fileID: 0} 210 | m_PrefabAsset: {fileID: 0} 211 | serializedVersion: 6 212 | m_Component: 213 | - component: {fileID: 7239175876297497478} 214 | - component: {fileID: 7239175876297497479} 215 | m_Layer: 0 216 | m_Name: DemoGraphPooledObject (0) 217 | m_TagString: Untagged 218 | m_Icon: {fileID: 0} 219 | m_NavMeshLayer: 0 220 | m_StaticEditorFlags: 0 221 | m_IsActive: 1 222 | --- !u!4 &7239175876297497478 223 | Transform: 224 | m_ObjectHideFlags: 0 225 | m_CorrespondingSourceObject: {fileID: 0} 226 | m_PrefabInstance: {fileID: 0} 227 | m_PrefabAsset: {fileID: 0} 228 | m_GameObject: {fileID: 7239175876297497477} 229 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 230 | m_LocalPosition: {x: 0, y: 0, z: 0} 231 | m_LocalScale: {x: 1, y: 1, z: 1} 232 | m_Children: 233 | - {fileID: 7239175875574932086} 234 | m_Father: {fileID: 0} 235 | m_RootOrder: 0 236 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 237 | --- !u!114 &7239175876297497479 238 | MonoBehaviour: 239 | m_ObjectHideFlags: 0 240 | m_CorrespondingSourceObject: {fileID: 0} 241 | m_PrefabInstance: {fileID: 0} 242 | m_PrefabAsset: {fileID: 0} 243 | m_GameObject: {fileID: 7239175876297497477} 244 | m_Enabled: 1 245 | m_EditorHideFlags: 0 246 | m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} 247 | m_Name: 248 | m_EditorClassIdentifier: 249 | interactTextPlacement: {fileID: 0} 250 | interactText: Use 251 | interactTextGO: {fileID: 0} 252 | proximity: 2 253 | SynchronizePosition: 0 254 | AllowCollisionOwnershipTransfer: 1 255 | Reliable: 1 256 | _syncMethod: 0 257 | serializedProgramAsset: {fileID: 11400000, guid: a9b839aa2cd31a0459c6510206acb7be, 258 | type: 2} 259 | programSource: {fileID: 11400000, guid: 50e62c03f5856904490c6643c4260ced, type: 2} 260 | serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgMAAAAAAAAAAi8CAAAAAVcAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAVgBSAEMALgBTAEQASwBCAGEAcwBlAC4AVgBSAEMAUABsAGEAeQBlAHIAQQBwAGkALAAgAFYAUgBDAFMARABLAEIAYQBzAGUAXQBdACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgACAAAABgIAAAAAAAAAJwEEAAAAdAB5AHAAZQABFwAAAFMAeQBzAHQAZQBtAC4AUwB0AHIAaQBuAGcALAAgAG0AcwBjAG8AcgBsAGkAYgAnAQoAAABTAHkAbQBiAG8AbABOAGEAbQBlAAEFAAAATwB3AG4AZQByACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAE8AYgBqAGUAYwB0ACwAIABtAHMAYwBvAHIAbABpAGIALQEFAAAAVgBhAGwAdQBlAAcFAi8DAAAAAVYAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AVQBJAC4AVABlAHgAdAAsACAAVQBuAGkAdAB5AEUAbgBnAGkAbgBlAC4AVQBJAF0AXQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAwAAAAYCAAAAAAAAACcBBAAAAHQAeQBwAGUAARcAAABTAHkAcwB0AGUAbQAuAFMAdAByAGkAbgBnACwAIABtAHMAYwBvAHIAbABpAGIAJwEKAAAAUwB5AG0AYgBvAGwATgBhAG0AZQABBAAAAHQAZQB4AHQAJwEEAAAAdAB5AHAAZQABIwAAAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAFUASQAuAFQAZQB4AHQALAAgAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAFUASQALAQUAAABWAGEAbAB1AGUAAAAAAAcFAi8EAAAAAUkAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgBdAF0ALAAgAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAAQAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAAQUAAAB2AGEAbAB1AGUAJwEEAAAAdAB5AHAAZQABFgAAAFMAeQBzAHQAZQBtAC4ASQBuAHQAMwAyACwAIABtAHMAYwBvAHIAbABpAGIAFwEFAAAAVgBhAGwAdQBlAP////8HBQcFBwU= 261 | publicVariablesUnityEngineObjects: 262 | - {fileID: 7239175876222275331} 263 | publicVariablesSerializationDataFormat: 0 264 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Examples~/UdonSharp/DemoPooledObject (0).prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &7239175875574932085 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: 7239175875574932086} 12 | - component: {fileID: 7239175875574932082} 13 | - component: {fileID: 7239175875574932081} 14 | - component: {fileID: 7239175875574932080} 15 | - component: {fileID: 7239175875574932087} 16 | m_Layer: 5 17 | m_Name: Canvas 18 | m_TagString: Untagged 19 | m_Icon: {fileID: 0} 20 | m_NavMeshLayer: 0 21 | m_StaticEditorFlags: 0 22 | m_IsActive: 1 23 | --- !u!224 &7239175875574932086 24 | RectTransform: 25 | m_ObjectHideFlags: 0 26 | m_CorrespondingSourceObject: {fileID: 0} 27 | m_PrefabInstance: {fileID: 0} 28 | m_PrefabAsset: {fileID: 0} 29 | m_GameObject: {fileID: 7239175875574932085} 30 | m_LocalRotation: {x: -0, y: -1, z: -0, w: 0.0000014454126} 31 | m_LocalPosition: {x: 0, y: 0, z: 0} 32 | m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} 33 | m_Children: 34 | - {fileID: 7239175876222275330} 35 | m_Father: {fileID: 7239175876297497478} 36 | m_RootOrder: 0 37 | m_LocalEulerAnglesHint: {x: 0, y: -180.00002, z: 0} 38 | m_AnchorMin: {x: 0, y: 0} 39 | m_AnchorMax: {x: 0, y: 0} 40 | m_AnchoredPosition: {x: 0, y: 0} 41 | m_SizeDelta: {x: 100, y: 100} 42 | m_Pivot: {x: 0.5, y: 0.5} 43 | --- !u!223 &7239175875574932082 44 | Canvas: 45 | m_ObjectHideFlags: 0 46 | m_CorrespondingSourceObject: {fileID: 0} 47 | m_PrefabInstance: {fileID: 0} 48 | m_PrefabAsset: {fileID: 0} 49 | m_GameObject: {fileID: 7239175875574932085} 50 | m_Enabled: 1 51 | serializedVersion: 3 52 | m_RenderMode: 2 53 | m_Camera: {fileID: 0} 54 | m_PlaneDistance: 100 55 | m_PixelPerfect: 0 56 | m_ReceivesEvents: 1 57 | m_OverrideSorting: 0 58 | m_OverridePixelPerfect: 0 59 | m_SortingBucketNormalizedSize: 0 60 | m_AdditionalShaderChannelsFlag: 0 61 | m_SortingLayerID: 0 62 | m_SortingOrder: 0 63 | m_TargetDisplay: 0 64 | --- !u!114 &7239175875574932081 65 | MonoBehaviour: 66 | m_ObjectHideFlags: 0 67 | m_CorrespondingSourceObject: {fileID: 0} 68 | m_PrefabInstance: {fileID: 0} 69 | m_PrefabAsset: {fileID: 0} 70 | m_GameObject: {fileID: 7239175875574932085} 71 | m_Enabled: 1 72 | m_EditorHideFlags: 0 73 | m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} 74 | m_Name: 75 | m_EditorClassIdentifier: 76 | m_UiScaleMode: 0 77 | m_ReferencePixelsPerUnit: 100 78 | m_ScaleFactor: 1 79 | m_ReferenceResolution: {x: 800, y: 600} 80 | m_ScreenMatchMode: 0 81 | m_MatchWidthOrHeight: 0 82 | m_PhysicalUnit: 3 83 | m_FallbackScreenDPI: 96 84 | m_DefaultSpriteDPI: 96 85 | m_DynamicPixelsPerUnit: 3 86 | --- !u!114 &7239175875574932080 87 | MonoBehaviour: 88 | m_ObjectHideFlags: 0 89 | m_CorrespondingSourceObject: {fileID: 0} 90 | m_PrefabInstance: {fileID: 0} 91 | m_PrefabAsset: {fileID: 0} 92 | m_GameObject: {fileID: 7239175875574932085} 93 | m_Enabled: 1 94 | m_EditorHideFlags: 0 95 | m_Script: {fileID: -1533785930, guid: 661092b4961be7145bfbe56e1e62337b, type: 3} 96 | m_Name: 97 | m_EditorClassIdentifier: 98 | --- !u!65 &7239175875574932087 99 | BoxCollider: 100 | m_ObjectHideFlags: 0 101 | m_CorrespondingSourceObject: {fileID: 0} 102 | m_PrefabInstance: {fileID: 0} 103 | m_PrefabAsset: {fileID: 0} 104 | m_GameObject: {fileID: 7239175875574932085} 105 | m_Material: {fileID: 0} 106 | m_IsTrigger: 1 107 | m_Enabled: 0 108 | serializedVersion: 2 109 | m_Size: {x: 1, y: 1, z: 1} 110 | m_Center: {x: 0, y: 0, z: 0} 111 | --- !u!1 &7239175876222275329 112 | GameObject: 113 | m_ObjectHideFlags: 0 114 | m_CorrespondingSourceObject: {fileID: 0} 115 | m_PrefabInstance: {fileID: 0} 116 | m_PrefabAsset: {fileID: 0} 117 | serializedVersion: 6 118 | m_Component: 119 | - component: {fileID: 7239175876222275330} 120 | - component: {fileID: 7239175876222275452} 121 | - component: {fileID: 7239175876222275331} 122 | m_Layer: 5 123 | m_Name: Text 124 | m_TagString: Untagged 125 | m_Icon: {fileID: 0} 126 | m_NavMeshLayer: 0 127 | m_StaticEditorFlags: 0 128 | m_IsActive: 1 129 | --- !u!224 &7239175876222275330 130 | RectTransform: 131 | m_ObjectHideFlags: 0 132 | m_CorrespondingSourceObject: {fileID: 0} 133 | m_PrefabInstance: {fileID: 0} 134 | m_PrefabAsset: {fileID: 0} 135 | m_GameObject: {fileID: 7239175876222275329} 136 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 137 | m_LocalPosition: {x: 0, y: 0, z: 0} 138 | m_LocalScale: {x: 1, y: 1, z: 1} 139 | m_Children: [] 140 | m_Father: {fileID: 7239175875574932086} 141 | m_RootOrder: 0 142 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 143 | m_AnchorMin: {x: 0, y: 0} 144 | m_AnchorMax: {x: 1, y: 1} 145 | m_AnchoredPosition: {x: 0, y: 0} 146 | m_SizeDelta: {x: 0, y: 0} 147 | m_Pivot: {x: 0.5, y: 0.5} 148 | --- !u!222 &7239175876222275452 149 | CanvasRenderer: 150 | m_ObjectHideFlags: 0 151 | m_CorrespondingSourceObject: {fileID: 0} 152 | m_PrefabInstance: {fileID: 0} 153 | m_PrefabAsset: {fileID: 0} 154 | m_GameObject: {fileID: 7239175876222275329} 155 | m_CullTransparentMesh: 0 156 | --- !u!114 &7239175876222275331 157 | MonoBehaviour: 158 | m_ObjectHideFlags: 0 159 | m_CorrespondingSourceObject: {fileID: 0} 160 | m_PrefabInstance: {fileID: 0} 161 | m_PrefabAsset: {fileID: 0} 162 | m_GameObject: {fileID: 7239175876222275329} 163 | m_Enabled: 1 164 | m_EditorHideFlags: 0 165 | m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 166 | m_Name: 167 | m_EditorClassIdentifier: 168 | m_Material: {fileID: 0} 169 | m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} 170 | m_RaycastTarget: 1 171 | m_Maskable: 1 172 | m_OnCullStateChanged: 173 | m_PersistentCalls: 174 | m_Calls: [] 175 | m_FontData: 176 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 177 | m_FontSize: 14 178 | m_FontStyle: 0 179 | m_BestFit: 0 180 | m_MinSize: 10 181 | m_MaxSize: 40 182 | m_Alignment: 4 183 | m_AlignByGeometry: 0 184 | m_RichText: 1 185 | m_HorizontalOverflow: 0 186 | m_VerticalOverflow: 0 187 | m_LineSpacing: 1 188 | m_Text: New Text 189 | --- !u!1 &7239175876297497477 190 | GameObject: 191 | m_ObjectHideFlags: 0 192 | m_CorrespondingSourceObject: {fileID: 0} 193 | m_PrefabInstance: {fileID: 0} 194 | m_PrefabAsset: {fileID: 0} 195 | serializedVersion: 6 196 | m_Component: 197 | - component: {fileID: 7239175876297497478} 198 | - component: {fileID: -653023529802255540} 199 | - component: {fileID: 7239175876297497479} 200 | m_Layer: 0 201 | m_Name: DemoPooledObject (0) 202 | m_TagString: Untagged 203 | m_Icon: {fileID: 0} 204 | m_NavMeshLayer: 0 205 | m_StaticEditorFlags: 0 206 | m_IsActive: 1 207 | --- !u!4 &7239175876297497478 208 | Transform: 209 | m_ObjectHideFlags: 0 210 | m_CorrespondingSourceObject: {fileID: 0} 211 | m_PrefabInstance: {fileID: 0} 212 | m_PrefabAsset: {fileID: 0} 213 | m_GameObject: {fileID: 7239175876297497477} 214 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 215 | m_LocalPosition: {x: 0, y: 0, z: 0} 216 | m_LocalScale: {x: 1, y: 1, z: 1} 217 | m_Children: 218 | - {fileID: 7239175875574932086} 219 | m_Father: {fileID: 0} 220 | m_RootOrder: 0 221 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 222 | --- !u!114 &-653023529802255540 223 | MonoBehaviour: 224 | m_ObjectHideFlags: 0 225 | m_CorrespondingSourceObject: {fileID: 0} 226 | m_PrefabInstance: {fileID: 0} 227 | m_PrefabAsset: {fileID: 0} 228 | m_GameObject: {fileID: 7239175876297497477} 229 | m_Enabled: 1 230 | m_EditorHideFlags: 0 231 | m_Script: {fileID: 11500000, guid: f2969aff4accf794784b87096b734be0, type: 3} 232 | m_Name: 233 | m_EditorClassIdentifier: 234 | serializationData: 235 | SerializedFormat: 2 236 | SerializedBytes: 237 | ReferencedUnityObjects: [] 238 | SerializedBytesString: 239 | Prefab: {fileID: 0} 240 | PrefabModificationsReferencedUnityObjects: [] 241 | PrefabModifications: [] 242 | SerializationNodes: [] 243 | _udonSharpBackingUdonBehaviour: {fileID: 7239175876297497479} 244 | text: {fileID: 7239175876222275331} 245 | value: -1 246 | --- !u!114 &7239175876297497479 247 | MonoBehaviour: 248 | m_ObjectHideFlags: 0 249 | m_CorrespondingSourceObject: {fileID: 0} 250 | m_PrefabInstance: {fileID: 0} 251 | m_PrefabAsset: {fileID: 0} 252 | m_GameObject: {fileID: 7239175876297497477} 253 | m_Enabled: 1 254 | m_EditorHideFlags: 0 255 | m_Script: {fileID: 11500000, guid: 45115577ef41a5b4ca741ed302693907, type: 3} 256 | m_Name: 257 | m_EditorClassIdentifier: 258 | interactTextPlacement: {fileID: 0} 259 | interactText: Use 260 | interactTextGO: {fileID: 0} 261 | proximity: 2 262 | SynchronizePosition: 0 263 | AllowCollisionOwnershipTransfer: 0 264 | Reliable: 1 265 | _syncMethod: 3 266 | serializedProgramAsset: {fileID: 11400000, guid: a567fa5250bc609409cbe68aa8e42c84, 267 | type: 2} 268 | programSource: {fileID: 11400000, guid: f2cca2eb14c80914ea60dcdbe25e0416, type: 2} 269 | serializedPublicVariablesBytesString: Ai8AAAAAATIAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAFQAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AAAAAAAYBAAAAAAAAACcBBAAAAHQAeQBwAGUAAWgAAABTAHkAcwB0AGUAbQAuAEMAbwBsAGwAZQBjAHQAaQBvAG4AcwAuAEcAZQBuAGUAcgBpAGMALgBMAGkAcwB0AGAAMQBbAFsAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBJAG4AdABlAHIAZgBhAGMAZQBzAC4ASQBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQAsACAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4AXQBdACwAIABtAHMAYwBvAHIAbABpAGIAAQEJAAAAVgBhAHIAaQBhAGIAbABlAHMALwEAAAABaAAAAFMAeQBzAHQAZQBtAC4AQwBvAGwAbABlAGMAdABpAG8AbgBzAC4ARwBlAG4AZQByAGkAYwAuAEwAaQBzAHQAYAAxAFsAWwBWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAEkAbgB0AGUAcgBmAGEAYwBlAHMALgBJAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlACwAIABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgBdAF0ALAAgAG0AcwBjAG8AcgBsAGkAYgABAAAABgQAAAAAAAAAAi8CAAAAAUkAAABWAFIAQwAuAFUAZABvAG4ALgBDAG8AbQBtAG8AbgAuAFUAZABvAG4AVgBhAHIAaQBhAGIAbABlAGAAMQBbAFsAUwB5AHMAdABlAG0ALgBJAG4AdAAzADIALAAgAG0AcwBjAG8AcgBsAGkAYgBdAF0ALAAgAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAAIAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAAQUAAAB2AGEAbAB1AGUAJwEEAAAAdAB5AHAAZQABFgAAAFMAeQBzAHQAZQBtAC4ASQBuAHQAMwAyACwAIABtAHMAYwBvAHIAbABpAGIAFwEFAAAAVgBhAGwAdQBlAP////8HBQIvAwAAAAFWAAAAVgBSAEMALgBVAGQAbwBuAC4AQwBvAG0AbQBvAG4ALgBVAGQAbwBuAFYAYQByAGkAYQBiAGwAZQBgADEAWwBbAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAFUASQAuAFQAZQB4AHQALAAgAFUAbgBpAHQAeQBFAG4AZwBpAG4AZQAuAFUASQBdAF0ALAAgAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAAMAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAAQQAAAB0AGUAeAB0ACcBBAAAAHQAeQBwAGUAASMAAABVAG4AaQB0AHkARQBuAGcAaQBuAGUALgBVAEkALgBUAGUAeAB0ACwAIABVAG4AaQB0AHkARQBuAGcAaQBuAGUALgBVAEkACwEFAAAAVgBhAGwAdQBlAAAAAAAHBQIwAgAAAAQAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAAR8AAABfAF8AXwBVAGQAbwBuAFMAaABhAHIAcABCAGUAaABhAHYAaQBvAHUAcgBWAGUAcgBzAGkAbwBuAF8AXwBfACcBBAAAAHQAeQBwAGUAARYAAABTAHkAcwB0AGUAbQAuAEkAbgB0ADMAMgAsACAAbQBzAGMAbwByAGwAaQBiABcBBQAAAFYAYQBsAHUAZQACAAAABwUCLwQAAAABSwAAAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAC4AVQBkAG8AbgBWAGEAcgBpAGEAYgBsAGUAYAAxAFsAWwBTAHkAcwB0AGUAbQAuAEIAbwBvAGwAZQBhAG4ALAAgAG0AcwBjAG8AcgBsAGkAYgBdAF0ALAAgAFYAUgBDAC4AVQBkAG8AbgAuAEMAbwBtAG0AbwBuAAUAAAAGAgAAAAAAAAAnAQQAAAB0AHkAcABlAAEXAAAAUwB5AHMAdABlAG0ALgBTAHQAcgBpAG4AZwAsACAAbQBzAGMAbwByAGwAaQBiACcBCgAAAFMAeQBtAGIAbwBsAE4AYQBtAGUAAS4AAABfAF8AXwBVAGQAbwBuAFMAaABhAHIAcABCAGUAaABhAHYAaQBvAHUAcgBQAGUAcgBzAGkAcwB0AEQAYQB0AGEARgByAG8AbQBVAHAAZwByAGEAZABlAF8AXwBfACcBBAAAAHQAeQBwAGUAARgAAABTAHkAcwB0AGUAbQAuAEIAbwBvAGwAZQBhAG4ALAAgAG0AcwBjAG8AcgBsAGkAYgArAQUAAABWAGEAbAB1AGUAAQcFBwUHBQ== 270 | publicVariablesUnityEngineObjects: 271 | - {fileID: 7239175876222275331} 272 | publicVariablesSerializationDataFormat: 0 273 | -------------------------------------------------------------------------------- /com.cyan.playerobjectpool/Editor/CyanPlayerObjectPoolEditor.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Collections.Generic; 3 | using UdonSharpEditor; 4 | using UnityEditor; 5 | using UnityEditor.SceneManagement; 6 | using UnityEngine; 7 | using VRC.Udon; 8 | 9 | namespace Cyan.PlayerObjectPool 10 | { 11 | [CustomEditor(typeof(CyanPlayerObjectPool))] 12 | public class CyanPlayerObjectPoolEditor : Editor 13 | { 14 | private readonly GUIContent _settingsFoldoutGuiContent = new GUIContent("Pool Settings", ""); 15 | private readonly GUIContent _poolAssignersFoldoutGuiContent = new GUIContent("Pool Types", ""); 16 | 17 | // Minimum world capacity is 1. 18 | private const int MinPoolObjects = 1; 19 | // Maximum world capacity is ~82, but allowing more since it doesn't break the system. 20 | private const int MaxPoolObjects = 100; 21 | 22 | private Texture2D _typesBackgroundTexture; 23 | 24 | private CyanPlayerObjectPool _instance; 25 | private UdonBehaviour _udon; 26 | 27 | private int _poolSize; 28 | private bool _multiplePools; 29 | 30 | private SerializedProperty _sizeProp; 31 | private SerializedProperty _debugProp; 32 | 33 | private bool _showSettings = true; 34 | private bool _showPoolAssigners = true; 35 | 36 | 37 | private void Awake() 38 | { 39 | _instance = (CyanPlayerObjectPool) target; 40 | _udon = UdonSharpEditorUtility.GetBackingUdonBehaviour(_instance); 41 | _poolSize = _instance.poolSize; 42 | 43 | _sizeProp = serializedObject.FindProperty(nameof(CyanPlayerObjectPool.poolSize)); 44 | _debugProp = serializedObject.FindProperty(nameof(CyanPlayerObjectPool.printDebugLogs)); 45 | 46 | _typesBackgroundTexture = CyanPlayerObjectPoolEditorHelpers.CreateTexture(3, 3, 47 | (x, y) => x == 1 && y == 1 48 | ? CyanPlayerObjectPoolEditorHelpers.BackgroundColor 49 | : CyanPlayerObjectPoolEditorHelpers.LineColorDark); 50 | 51 | _multiplePools = false; 52 | if (ShouldCheckScene()) 53 | { 54 | // Go through all objects to find if there are multiple Object Pool scripts. 55 | int count = 0; 56 | foreach (var obj in _instance.gameObject.scene.GetRootGameObjects()) 57 | { 58 | CyanPlayerObjectPool[] pools = obj.GetComponentsInChildren(true); 59 | count += pools.Length; 60 | } 61 | 62 | _multiplePools = count > 1; 63 | 64 | // Go through each setup helper and verify their pool size. 65 | foreach (var helper in FindObjectsOfType()) 66 | { 67 | helper.VerifyPoolSize(); 68 | } 69 | } 70 | } 71 | 72 | private bool ShouldCheckScene() 73 | { 74 | return _udon != null 75 | && _udon.gameObject.scene.isLoaded 76 | && !EditorSceneManager.IsPreviewSceneObject(_udon); 77 | } 78 | 79 | public override void OnInspectorGUI() 80 | { 81 | if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return; 82 | if (!UdonSharpEditorUtility.IsProxyBehaviour(_instance)) return; 83 | 84 | CyanPlayerObjectPoolEditorHelpers.RenderHeader("Cyan Player Object Pool"); 85 | 86 | if (_multiplePools) 87 | { 88 | GUILayout.Space(5); 89 | EditorGUILayout.HelpBox("Multiple Object Pools exist in the scene! Please only have one Object Pool!", MessageType.Error); 90 | // TODO list all object pools 91 | return; 92 | } 93 | 94 | serializedObject.UpdateIfRequiredOrScript(); 95 | 96 | RenderSettings(); 97 | 98 | serializedObject.ApplyModifiedProperties(); 99 | 100 | // Prevent modifying the scene if this is part of a prefab editor. 101 | if (!ShouldCheckScene()) 102 | { 103 | return; 104 | } 105 | 106 | List helpers = new List(FindObjectsOfType()); 107 | // Sort based on name 108 | helpers.Sort((h1, h2) => h1.name.CompareTo(h2.name)); 109 | 110 | UpdateHelpers(helpers); 111 | RenderObjectAssigners(helpers); 112 | } 113 | 114 | private void RenderSettings() 115 | { 116 | GUILayout.Space(5); 117 | 118 | EditorGUILayout.BeginVertical(EditorStyles.helpBox); 119 | 120 | _showSettings = CyanPlayerObjectPoolEditorHelpers.RenderFoldout(_showSettings, _settingsFoldoutGuiContent); 121 | 122 | if (_showSettings) 123 | { 124 | CyanPlayerObjectPoolEditorHelpers.AddIndent(); 125 | 126 | EditorGUILayout.PropertyField(_sizeProp); 127 | EditorGUILayout.PropertyField(_debugProp); 128 | 129 | // Hard-cap the min and max size of the object pool. 130 | int value = _sizeProp.intValue; 131 | if (value < MinPoolObjects || value > MaxPoolObjects) 132 | { 133 | _sizeProp.intValue = Mathf.Clamp(value, MinPoolObjects, MaxPoolObjects); 134 | } 135 | 136 | // Only display button to respawn objects if the scene can be edited. 137 | if (ShouldCheckScene() && GUILayout.Button("Respawn All Pool Objects")) 138 | { 139 | foreach (var helper in FindObjectsOfType()) 140 | { 141 | helper.RespawnAllPoolObjects(); 142 | } 143 | } 144 | 145 | CyanPlayerObjectPoolEditorHelpers.RemoveIndent(); 146 | } 147 | 148 | EditorGUILayout.EndVertical(); 149 | } 150 | 151 | private void UpdateHelpers(List helpers) 152 | { 153 | // If the size has changed, notify all helpers to update the spawned number of pool objects. 154 | int newSize = _sizeProp.intValue; 155 | if (_poolSize != newSize) 156 | { 157 | _poolSize = newSize; 158 | foreach (var helper in helpers) 159 | { 160 | helper.UpdatePoolSize(_poolSize); 161 | } 162 | } 163 | } 164 | 165 | private void RenderObjectAssigners(List helpers) 166 | { 167 | GUILayout.Space(5); 168 | EditorGUILayout.BeginVertical(EditorStyles.helpBox); 169 | 170 | _showPoolAssigners = CyanPlayerObjectPoolEditorHelpers.RenderFoldout(_showPoolAssigners, _poolAssignersFoldoutGuiContent); 171 | 172 | if (_showPoolAssigners) 173 | { 174 | GUIContent errorIcon = EditorGUIUtility.TrIconContent("console.erroricon", "This pool type does not have the correct number of objects!"); 175 | GUIContent warningIcon = EditorGUIUtility.TrIconContent("console.warnicon", "This pool type does not have any objects."); 176 | 177 | GUILayout.Space(5); 178 | 179 | var boxStyle = new GUIStyle 180 | { 181 | border = new RectOffset(1, 1, 1, 1), 182 | normal = 183 | { 184 | background = _typesBackgroundTexture 185 | } 186 | }; 187 | 188 | Rect rect = EditorGUILayout.BeginVertical(boxStyle); 189 | float width = rect.width; 190 | float height = rect.height - 1; 191 | float xStart = rect.x; 192 | float sectionHeight = 24; 193 | float buttonHeight = 18; 194 | float labelHeight = EditorGUIUtility.singleLineHeight; 195 | 196 | float between = 9; 197 | float betweenHalf = Mathf.Floor(between / 2f); 198 | float indexLabelWidth = 20; 199 | float pingWidth = 40; 200 | float iconWidth = 25; 201 | 202 | // Create vertical bars separating the sections 203 | GUI.Box(new Rect(rect.x + indexLabelWidth + between, rect.y + 1, 1, height), GUIContent.none, boxStyle); 204 | GUI.Box(new Rect(rect.x + indexLabelWidth + pingWidth + between * 2, rect.y + 1, 1, height), GUIContent.none, boxStyle); 205 | 206 | if (helpers.Count == 0) 207 | { 208 | GUILayout.Space(sectionHeight); 209 | } 210 | 211 | for (int cur = 0; cur < helpers.Count; ++cur) 212 | { 213 | var helper = helpers[cur]; 214 | 215 | rect = EditorGUILayout.BeginHorizontal(GUILayout.Height(sectionHeight)); 216 | 217 | if (cur + 1 < helpers.Count) 218 | { 219 | // Create horizontal bar separating the sections 220 | GUI.Box(new Rect(rect.x, rect.yMax, width, 1), GUIContent.none, boxStyle); 221 | } 222 | 223 | float textY = rect.y + Mathf.Ceil((rect.height - labelHeight) / 2f); 224 | float buttonY = rect.y + Mathf.Ceil((rect.height - buttonHeight) / 2f); 225 | 226 | float indexLabelStartX = xStart + betweenHalf; 227 | float pingStart = indexLabelStartX + indexLabelWidth + between; 228 | float objectLabelStartX = pingStart + pingWidth + between; 229 | float objectLabelWidth = width - objectLabelStartX - betweenHalf; 230 | 231 | Rect indexRect = new Rect(indexLabelStartX, textY, indexLabelWidth, labelHeight); 232 | Rect pingRect = new Rect(pingStart, buttonY, pingWidth, buttonHeight); 233 | Rect objectLabelRect = new Rect(objectLabelStartX, textY, objectLabelWidth, labelHeight); 234 | 235 | GUI.Label(indexRect, (1 + cur).ToString().PadLeft(2)); 236 | 237 | if (GUI.Button(pingRect, "Ping")) 238 | { 239 | EditorGUIUtility.PingObject(helper); 240 | } 241 | 242 | GUIContent objectContent = 243 | new GUIContent(helper.name, VRC.Tools.GetGameObjectPath(helper.gameObject)); 244 | GUI.Label(objectLabelRect, objectContent); 245 | 246 | int objCount = helper.GetObjectCount(); 247 | if (objCount != _poolSize) 248 | { 249 | GUIContent content = null; 250 | if (objCount == 0) 251 | { 252 | // Display warning saying no objects 253 | content = warningIcon; 254 | } 255 | else 256 | { 257 | // Display error saying object count does not match 258 | content = errorIcon; 259 | } 260 | 261 | Rect iconRect = new Rect(objectLabelRect.xMax, buttonY, iconWidth, buttonHeight); 262 | GUI.Label(iconRect, content); 263 | } 264 | 265 | GUILayout.Space(1); 266 | EditorGUILayout.EndHorizontal(); 267 | } 268 | 269 | EditorGUILayout.EndVertical(); 270 | GUILayout.Space(5); 271 | } 272 | 273 | EditorGUILayout.EndVertical(); 274 | } 275 | } 276 | } 277 | 278 | -------------------------------------------------------------------------------- /Website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | VCC Listing 7 | 8 | 9 | 10 | 11 |
12 |
13 | {{~ if listingInfo.BannerImage; ~}} 14 |
15 | {{~ end; ~}} 16 |

17 | {{~ listingInfo.Name ~}} 18 |

19 | {{~ if listingInfo.Description; ~}} 20 |
{{ listingInfo.Description }}
21 | {{~ end; ~}} 22 |
23 | {{~ if listingInfo.Author.Email; ~}} 24 | 25 | {{ listingInfo.Author.Email }} 26 | 27 | {{~ end; ~}} 28 | 29 | {{~ if listingInfo.InfoLink.Url ~}} 30 | 33 | {{~ end; ~}} 34 |
35 |
36 |
37 | 38 | 39 | Add to VCC 40 | 41 | 42 | 43 | 44 | Copy 45 | 46 | 47 | How to add a listing to your VCC 48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 | 96 |
97 | 98 |
99 | 109 | 171 | 172 | 173 | 174 | 175 | Name 176 | 177 | 178 | Type 179 | 180 | 181 | 182 | 183 | {{~ for package in packages ~}} 184 | 185 | 186 |
187 |
{{ package.DisplayName }}
188 |
{{ package.Description }}
189 |
{{ package.Name }}
190 |
191 |
192 | 193 | {{ package.Type }} 194 | 195 | 196 | Add to VCC 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 |
209 | {{~ end ~}} 210 |
211 |
212 | {{~ if listingInfo.InfoLink.Url ~}} 213 | 216 | {{~ end; ~}} 217 |
218 | 219 | 220 | --------------------------------------------------------------------------------