├── Examples ├── Prefabs.meta ├── Prefabs │ ├── ChildItem.prefab │ └── ChildItem.prefab.meta ├── Scenes.meta ├── Scenes │ ├── RecyclingList.unity │ └── RecyclingList.unity.meta ├── Scripts.meta └── Scripts │ ├── TestChildItem.cs │ ├── TestChildItem.cs.meta │ ├── TestPanel.cs │ └── TestPanel.cs.meta ├── LICENSE ├── ReadMe.md ├── Source ├── RecyclingListView.cs ├── RecyclingListView.cs.meta ├── RecyclingListViewItem.cs └── RecyclingListViewItem.cs.meta └── demo.gif /Examples/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80c77e76cd3e4964a9925a221cce184c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Examples/Prefabs/ChildItem.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &628231073078430941 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: 7808332169243586686} 12 | - component: {fileID: 4973743338571479962} 13 | - component: {fileID: 5698122441288927554} 14 | m_Layer: 5 15 | m_Name: RightFixed1 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!224 &7808332169243586686 22 | RectTransform: 23 | m_ObjectHideFlags: 0 24 | m_CorrespondingSourceObject: {fileID: 0} 25 | m_PrefabInstance: {fileID: 0} 26 | m_PrefabAsset: {fileID: 0} 27 | m_GameObject: {fileID: 628231073078430941} 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: 8699625926193876490} 33 | m_RootOrder: 2 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | m_AnchorMin: {x: 1, y: 0.5} 36 | m_AnchorMax: {x: 1, y: 0.5} 37 | m_AnchoredPosition: {x: -15, y: -9.2} 38 | m_SizeDelta: {x: 80, y: 18} 39 | m_Pivot: {x: 1, y: 0.5} 40 | --- !u!222 &4973743338571479962 41 | CanvasRenderer: 42 | m_ObjectHideFlags: 0 43 | m_CorrespondingSourceObject: {fileID: 0} 44 | m_PrefabInstance: {fileID: 0} 45 | m_PrefabAsset: {fileID: 0} 46 | m_GameObject: {fileID: 628231073078430941} 47 | m_CullTransparentMesh: 0 48 | --- !u!114 &5698122441288927554 49 | MonoBehaviour: 50 | m_ObjectHideFlags: 0 51 | m_CorrespondingSourceObject: {fileID: 0} 52 | m_PrefabInstance: {fileID: 0} 53 | m_PrefabAsset: {fileID: 0} 54 | m_GameObject: {fileID: 628231073078430941} 55 | m_Enabled: 1 56 | m_EditorHideFlags: 0 57 | m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 58 | m_Name: 59 | m_EditorClassIdentifier: 60 | m_Material: {fileID: 0} 61 | m_Color: {r: 0.8679245, g: 0.5585936, b: 0.3520826, a: 1} 62 | m_RaycastTarget: 1 63 | m_OnCullStateChanged: 64 | m_PersistentCalls: 65 | m_Calls: [] 66 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 67 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 68 | m_FontData: 69 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 70 | m_FontSize: 12 71 | m_FontStyle: 2 72 | m_BestFit: 0 73 | m_MinSize: 1 74 | m_MaxSize: 40 75 | m_Alignment: 5 76 | m_AlignByGeometry: 0 77 | m_RichText: 1 78 | m_HorizontalOverflow: 0 79 | m_VerticalOverflow: 0 80 | m_LineSpacing: 1 81 | m_Text: New Text 82 | --- !u!1 &1887378022519194077 83 | GameObject: 84 | m_ObjectHideFlags: 0 85 | m_CorrespondingSourceObject: {fileID: 0} 86 | m_PrefabInstance: {fileID: 0} 87 | m_PrefabAsset: {fileID: 0} 88 | serializedVersion: 6 89 | m_Component: 90 | - component: {fileID: 2288791036235580468} 91 | - component: {fileID: 1237414540409905619} 92 | - component: {fileID: 5471987907530298521} 93 | m_Layer: 5 94 | m_Name: Image 95 | m_TagString: Untagged 96 | m_Icon: {fileID: 0} 97 | m_NavMeshLayer: 0 98 | m_StaticEditorFlags: 0 99 | m_IsActive: 1 100 | --- !u!224 &2288791036235580468 101 | RectTransform: 102 | m_ObjectHideFlags: 0 103 | m_CorrespondingSourceObject: {fileID: 0} 104 | m_PrefabInstance: {fileID: 0} 105 | m_PrefabAsset: {fileID: 0} 106 | m_GameObject: {fileID: 1887378022519194077} 107 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 108 | m_LocalPosition: {x: 0, y: 0, z: 0} 109 | m_LocalScale: {x: 1, y: 1, z: 1} 110 | m_Children: [] 111 | m_Father: {fileID: 8699625926193876490} 112 | m_RootOrder: 0 113 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 114 | m_AnchorMin: {x: 0, y: 0.5} 115 | m_AnchorMax: {x: 0, y: 0.5} 116 | m_AnchoredPosition: {x: 10, y: 0} 117 | m_SizeDelta: {x: 30, y: 30} 118 | m_Pivot: {x: 0, y: 0.5} 119 | --- !u!222 &1237414540409905619 120 | CanvasRenderer: 121 | m_ObjectHideFlags: 0 122 | m_CorrespondingSourceObject: {fileID: 0} 123 | m_PrefabInstance: {fileID: 0} 124 | m_PrefabAsset: {fileID: 0} 125 | m_GameObject: {fileID: 1887378022519194077} 126 | m_CullTransparentMesh: 0 127 | --- !u!114 &5471987907530298521 128 | MonoBehaviour: 129 | m_ObjectHideFlags: 0 130 | m_CorrespondingSourceObject: {fileID: 0} 131 | m_PrefabInstance: {fileID: 0} 132 | m_PrefabAsset: {fileID: 0} 133 | m_GameObject: {fileID: 1887378022519194077} 134 | m_Enabled: 1 135 | m_EditorHideFlags: 0 136 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 137 | m_Name: 138 | m_EditorClassIdentifier: 139 | m_Material: {fileID: 0} 140 | m_Color: {r: 1, g: 1, b: 1, a: 1} 141 | m_RaycastTarget: 1 142 | m_OnCullStateChanged: 143 | m_PersistentCalls: 144 | m_Calls: [] 145 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 146 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 147 | m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0} 148 | m_Type: 0 149 | m_PreserveAspect: 0 150 | m_FillCenter: 1 151 | m_FillMethod: 4 152 | m_FillAmount: 1 153 | m_FillClockwise: 1 154 | m_FillOrigin: 0 155 | m_UseSpriteMesh: 0 156 | m_PixelsPerUnitMultiplier: 1 157 | --- !u!1 &3546619229314839408 158 | GameObject: 159 | m_ObjectHideFlags: 0 160 | m_CorrespondingSourceObject: {fileID: 0} 161 | m_PrefabInstance: {fileID: 0} 162 | m_PrefabAsset: {fileID: 0} 163 | serializedVersion: 6 164 | m_Component: 165 | - component: {fileID: 8699625926193876490} 166 | - component: {fileID: 2757982202855801997} 167 | - component: {fileID: 9138159912152891133} 168 | - component: {fileID: -4295012922733440193} 169 | m_Layer: 5 170 | m_Name: ChildItem 171 | m_TagString: Untagged 172 | m_Icon: {fileID: 0} 173 | m_NavMeshLayer: 0 174 | m_StaticEditorFlags: 0 175 | m_IsActive: 1 176 | --- !u!224 &8699625926193876490 177 | RectTransform: 178 | m_ObjectHideFlags: 0 179 | m_CorrespondingSourceObject: {fileID: 0} 180 | m_PrefabInstance: {fileID: 0} 181 | m_PrefabAsset: {fileID: 0} 182 | m_GameObject: {fileID: 3546619229314839408} 183 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 184 | m_LocalPosition: {x: 0, y: 0, z: 0} 185 | m_LocalScale: {x: 1, y: 1, z: 1} 186 | m_Children: 187 | - {fileID: 2288791036235580468} 188 | - {fileID: 2895037214348498999} 189 | - {fileID: 7808332169243586686} 190 | - {fileID: 6656934231110490123} 191 | m_Father: {fileID: 0} 192 | m_RootOrder: 0 193 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 194 | m_AnchorMin: {x: 0, y: 1} 195 | m_AnchorMax: {x: 1, y: 1} 196 | m_AnchoredPosition: {x: 0, y: 0} 197 | m_SizeDelta: {x: 0, y: 45} 198 | m_Pivot: {x: 0.5, y: 1} 199 | --- !u!222 &2757982202855801997 200 | CanvasRenderer: 201 | m_ObjectHideFlags: 0 202 | m_CorrespondingSourceObject: {fileID: 0} 203 | m_PrefabInstance: {fileID: 0} 204 | m_PrefabAsset: {fileID: 0} 205 | m_GameObject: {fileID: 3546619229314839408} 206 | m_CullTransparentMesh: 0 207 | --- !u!114 &9138159912152891133 208 | MonoBehaviour: 209 | m_ObjectHideFlags: 0 210 | m_CorrespondingSourceObject: {fileID: 0} 211 | m_PrefabInstance: {fileID: 0} 212 | m_PrefabAsset: {fileID: 0} 213 | m_GameObject: {fileID: 3546619229314839408} 214 | m_Enabled: 1 215 | m_EditorHideFlags: 0 216 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 217 | m_Name: 218 | m_EditorClassIdentifier: 219 | m_Material: {fileID: 0} 220 | m_Color: {r: 0, g: 0, b: 0, a: 0.21568628} 221 | m_RaycastTarget: 1 222 | m_OnCullStateChanged: 223 | m_PersistentCalls: 224 | m_Calls: [] 225 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 226 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 227 | m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} 228 | m_Type: 1 229 | m_PreserveAspect: 0 230 | m_FillCenter: 1 231 | m_FillMethod: 4 232 | m_FillAmount: 1 233 | m_FillClockwise: 1 234 | m_FillOrigin: 0 235 | m_UseSpriteMesh: 0 236 | m_PixelsPerUnitMultiplier: 1 237 | --- !u!114 &-4295012922733440193 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: 3546619229314839408} 244 | m_Enabled: 1 245 | m_EditorHideFlags: 0 246 | m_Script: {fileID: 11500000, guid: fcf4560bf40f78c478e0c716c320daaa, type: 3} 247 | m_Name: 248 | m_EditorClassIdentifier: 249 | leftText: {fileID: 5198050249495137039} 250 | rightText1: {fileID: 5698122441288927554} 251 | rightText2: {fileID: 2320007929958512595} 252 | --- !u!1 &4991227333897739239 253 | GameObject: 254 | m_ObjectHideFlags: 0 255 | m_CorrespondingSourceObject: {fileID: 0} 256 | m_PrefabInstance: {fileID: 0} 257 | m_PrefabAsset: {fileID: 0} 258 | serializedVersion: 6 259 | m_Component: 260 | - component: {fileID: 2895037214348498999} 261 | - component: {fileID: 4915673223779312823} 262 | - component: {fileID: 5198050249495137039} 263 | m_Layer: 5 264 | m_Name: LeftStretchedText 265 | m_TagString: Untagged 266 | m_Icon: {fileID: 0} 267 | m_NavMeshLayer: 0 268 | m_StaticEditorFlags: 0 269 | m_IsActive: 1 270 | --- !u!224 &2895037214348498999 271 | RectTransform: 272 | m_ObjectHideFlags: 0 273 | m_CorrespondingSourceObject: {fileID: 0} 274 | m_PrefabInstance: {fileID: 0} 275 | m_PrefabAsset: {fileID: 0} 276 | m_GameObject: {fileID: 4991227333897739239} 277 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 278 | m_LocalPosition: {x: 0, y: 0, z: 0} 279 | m_LocalScale: {x: 1, y: 1, z: 1} 280 | m_Children: [] 281 | m_Father: {fileID: 8699625926193876490} 282 | m_RootOrder: 1 283 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 284 | m_AnchorMin: {x: 0, y: 1} 285 | m_AnchorMax: {x: 1, y: 1} 286 | m_AnchoredPosition: {x: -33.31996, y: -7.5} 287 | m_SizeDelta: {x: -153.35992, y: 30} 288 | m_Pivot: {x: 0.5, y: 1} 289 | --- !u!222 &4915673223779312823 290 | CanvasRenderer: 291 | m_ObjectHideFlags: 0 292 | m_CorrespondingSourceObject: {fileID: 0} 293 | m_PrefabInstance: {fileID: 0} 294 | m_PrefabAsset: {fileID: 0} 295 | m_GameObject: {fileID: 4991227333897739239} 296 | m_CullTransparentMesh: 0 297 | --- !u!114 &5198050249495137039 298 | MonoBehaviour: 299 | m_ObjectHideFlags: 0 300 | m_CorrespondingSourceObject: {fileID: 0} 301 | m_PrefabInstance: {fileID: 0} 302 | m_PrefabAsset: {fileID: 0} 303 | m_GameObject: {fileID: 4991227333897739239} 304 | m_Enabled: 1 305 | m_EditorHideFlags: 0 306 | m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 307 | m_Name: 308 | m_EditorClassIdentifier: 309 | m_Material: {fileID: 0} 310 | m_Color: {r: 0.9245283, g: 0.9245283, b: 0.9245283, a: 1} 311 | m_RaycastTarget: 1 312 | m_OnCullStateChanged: 313 | m_PersistentCalls: 314 | m_Calls: [] 315 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 316 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 317 | m_FontData: 318 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 319 | m_FontSize: 14 320 | m_FontStyle: 0 321 | m_BestFit: 0 322 | m_MinSize: 10 323 | m_MaxSize: 40 324 | m_Alignment: 3 325 | m_AlignByGeometry: 0 326 | m_RichText: 1 327 | m_HorizontalOverflow: 0 328 | m_VerticalOverflow: 0 329 | m_LineSpacing: 1 330 | m_Text: New Text 331 | --- !u!1 &5650287049948130283 332 | GameObject: 333 | m_ObjectHideFlags: 0 334 | m_CorrespondingSourceObject: {fileID: 0} 335 | m_PrefabInstance: {fileID: 0} 336 | m_PrefabAsset: {fileID: 0} 337 | serializedVersion: 6 338 | m_Component: 339 | - component: {fileID: 6656934231110490123} 340 | - component: {fileID: 7793133864675314396} 341 | - component: {fileID: 2320007929958512595} 342 | m_Layer: 5 343 | m_Name: RightFixed2 344 | m_TagString: Untagged 345 | m_Icon: {fileID: 0} 346 | m_NavMeshLayer: 0 347 | m_StaticEditorFlags: 0 348 | m_IsActive: 1 349 | --- !u!224 &6656934231110490123 350 | RectTransform: 351 | m_ObjectHideFlags: 0 352 | m_CorrespondingSourceObject: {fileID: 0} 353 | m_PrefabInstance: {fileID: 0} 354 | m_PrefabAsset: {fileID: 0} 355 | m_GameObject: {fileID: 5650287049948130283} 356 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 357 | m_LocalPosition: {x: 0, y: 0, z: 0} 358 | m_LocalScale: {x: 1, y: 1, z: 1} 359 | m_Children: [] 360 | m_Father: {fileID: 8699625926193876490} 361 | m_RootOrder: 3 362 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 363 | m_AnchorMin: {x: 1, y: 0.5} 364 | m_AnchorMax: {x: 1, y: 0.5} 365 | m_AnchoredPosition: {x: -15, y: 9.2} 366 | m_SizeDelta: {x: 80, y: 18} 367 | m_Pivot: {x: 1, y: 0.5} 368 | --- !u!222 &7793133864675314396 369 | CanvasRenderer: 370 | m_ObjectHideFlags: 0 371 | m_CorrespondingSourceObject: {fileID: 0} 372 | m_PrefabInstance: {fileID: 0} 373 | m_PrefabAsset: {fileID: 0} 374 | m_GameObject: {fileID: 5650287049948130283} 375 | m_CullTransparentMesh: 0 376 | --- !u!114 &2320007929958512595 377 | MonoBehaviour: 378 | m_ObjectHideFlags: 0 379 | m_CorrespondingSourceObject: {fileID: 0} 380 | m_PrefabInstance: {fileID: 0} 381 | m_PrefabAsset: {fileID: 0} 382 | m_GameObject: {fileID: 5650287049948130283} 383 | m_Enabled: 1 384 | m_EditorHideFlags: 0 385 | m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 386 | m_Name: 387 | m_EditorClassIdentifier: 388 | m_Material: {fileID: 0} 389 | m_Color: {r: 0.81594056, g: 0.8666667, b: 0.35294116, a: 1} 390 | m_RaycastTarget: 1 391 | m_OnCullStateChanged: 392 | m_PersistentCalls: 393 | m_Calls: [] 394 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 395 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 396 | m_FontData: 397 | m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} 398 | m_FontSize: 12 399 | m_FontStyle: 2 400 | m_BestFit: 0 401 | m_MinSize: 1 402 | m_MaxSize: 40 403 | m_Alignment: 5 404 | m_AlignByGeometry: 0 405 | m_RichText: 1 406 | m_HorizontalOverflow: 0 407 | m_VerticalOverflow: 0 408 | m_LineSpacing: 1 409 | m_Text: New Text 410 | -------------------------------------------------------------------------------- /Examples/Prefabs/ChildItem.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 113d11a263242a84bb061a25d1876dc9 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Examples/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c99e620987794ac43a3742585a86e331 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Examples/Scenes/RecyclingList.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 705507994} 41 | m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 1 56 | m_LightmapEditorSettings: 57 | serializedVersion: 12 58 | m_Resolution: 2 59 | m_BakeResolution: 40 60 | m_AtlasSize: 1024 61 | m_AO: 0 62 | m_AOMaxDistance: 1 63 | m_CompAOExponent: 1 64 | m_CompAOExponentDirect: 0 65 | m_ExtractAmbientOcclusion: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVREnvironmentSampleCount: 500 81 | m_PVREnvironmentReferencePointCount: 2048 82 | m_PVRFilteringMode: 2 83 | m_PVRDenoiserTypeDirect: 0 84 | m_PVRDenoiserTypeIndirect: 0 85 | m_PVRDenoiserTypeAO: 0 86 | m_PVRFilterTypeDirect: 0 87 | m_PVRFilterTypeIndirect: 0 88 | m_PVRFilterTypeAO: 0 89 | m_PVREnvironmentMIS: 0 90 | m_PVRCulling: 1 91 | m_PVRFilteringGaussRadiusDirect: 1 92 | m_PVRFilteringGaussRadiusIndirect: 5 93 | m_PVRFilteringGaussRadiusAO: 2 94 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 95 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 96 | m_PVRFilteringAtrousPositionSigmaAO: 1 97 | m_ExportTrainingData: 0 98 | m_TrainingDataDestination: TrainingData 99 | m_LightingDataAsset: {fileID: 0} 100 | m_UseShadowmask: 1 101 | --- !u!196 &4 102 | NavMeshSettings: 103 | serializedVersion: 2 104 | m_ObjectHideFlags: 0 105 | m_BuildSettings: 106 | serializedVersion: 2 107 | agentTypeID: 0 108 | agentRadius: 0.5 109 | agentHeight: 2 110 | agentSlope: 45 111 | agentClimb: 0.4 112 | ledgeDropHeight: 0 113 | maxJumpAcrossDistance: 0 114 | minRegionArea: 2 115 | manualCellSize: 0 116 | cellSize: 0.16666667 117 | manualTileSize: 0 118 | tileSize: 256 119 | accuratePlacement: 0 120 | debug: 121 | m_Flags: 0 122 | m_NavMeshData: {fileID: 0} 123 | --- !u!1 &705507993 124 | GameObject: 125 | m_ObjectHideFlags: 0 126 | m_CorrespondingSourceObject: {fileID: 0} 127 | m_PrefabInstance: {fileID: 0} 128 | m_PrefabAsset: {fileID: 0} 129 | serializedVersion: 6 130 | m_Component: 131 | - component: {fileID: 705507995} 132 | - component: {fileID: 705507994} 133 | m_Layer: 0 134 | m_Name: Directional Light 135 | m_TagString: Untagged 136 | m_Icon: {fileID: 0} 137 | m_NavMeshLayer: 0 138 | m_StaticEditorFlags: 0 139 | m_IsActive: 1 140 | --- !u!108 &705507994 141 | Light: 142 | m_ObjectHideFlags: 0 143 | m_CorrespondingSourceObject: {fileID: 0} 144 | m_PrefabInstance: {fileID: 0} 145 | m_PrefabAsset: {fileID: 0} 146 | m_GameObject: {fileID: 705507993} 147 | m_Enabled: 1 148 | serializedVersion: 9 149 | m_Type: 1 150 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 151 | m_Intensity: 1 152 | m_Range: 10 153 | m_SpotAngle: 30 154 | m_InnerSpotAngle: 21.80208 155 | m_CookieSize: 10 156 | m_Shadows: 157 | m_Type: 2 158 | m_Resolution: -1 159 | m_CustomResolution: -1 160 | m_Strength: 1 161 | m_Bias: 0.05 162 | m_NormalBias: 0.4 163 | m_NearPlane: 0.2 164 | m_CullingMatrixOverride: 165 | e00: 1 166 | e01: 0 167 | e02: 0 168 | e03: 0 169 | e10: 0 170 | e11: 1 171 | e12: 0 172 | e13: 0 173 | e20: 0 174 | e21: 0 175 | e22: 1 176 | e23: 0 177 | e30: 0 178 | e31: 0 179 | e32: 0 180 | e33: 1 181 | m_UseCullingMatrixOverride: 0 182 | m_Cookie: {fileID: 0} 183 | m_DrawHalo: 0 184 | m_Flare: {fileID: 0} 185 | m_RenderMode: 0 186 | m_CullingMask: 187 | serializedVersion: 2 188 | m_Bits: 4294967295 189 | m_RenderingLayerMask: 1 190 | m_Lightmapping: 1 191 | m_LightShadowCasterMode: 0 192 | m_AreaSize: {x: 1, y: 1} 193 | m_BounceIntensity: 1 194 | m_ColorTemperature: 6570 195 | m_UseColorTemperature: 0 196 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 197 | m_UseBoundingSphereOverride: 0 198 | m_ShadowRadius: 0 199 | m_ShadowAngle: 0 200 | --- !u!4 &705507995 201 | Transform: 202 | m_ObjectHideFlags: 0 203 | m_CorrespondingSourceObject: {fileID: 0} 204 | m_PrefabInstance: {fileID: 0} 205 | m_PrefabAsset: {fileID: 0} 206 | m_GameObject: {fileID: 705507993} 207 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 208 | m_LocalPosition: {x: 0, y: 3, z: 0} 209 | m_LocalScale: {x: 1, y: 1, z: 1} 210 | m_Children: [] 211 | m_Father: {fileID: 0} 212 | m_RootOrder: 1 213 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 214 | --- !u!1 &813572925 215 | GameObject: 216 | m_ObjectHideFlags: 0 217 | m_CorrespondingSourceObject: {fileID: 0} 218 | m_PrefabInstance: {fileID: 0} 219 | m_PrefabAsset: {fileID: 0} 220 | serializedVersion: 6 221 | m_Component: 222 | - component: {fileID: 813572926} 223 | - component: {fileID: 813572929} 224 | - component: {fileID: 813572927} 225 | - component: {fileID: 813572928} 226 | m_Layer: 5 227 | m_Name: Scroll View 228 | m_TagString: Untagged 229 | m_Icon: {fileID: 0} 230 | m_NavMeshLayer: 0 231 | m_StaticEditorFlags: 0 232 | m_IsActive: 1 233 | --- !u!224 &813572926 234 | RectTransform: 235 | m_ObjectHideFlags: 0 236 | m_CorrespondingSourceObject: {fileID: 0} 237 | m_PrefabInstance: {fileID: 0} 238 | m_PrefabAsset: {fileID: 0} 239 | m_GameObject: {fileID: 813572925} 240 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 241 | m_LocalPosition: {x: 0, y: 0, z: 0} 242 | m_LocalScale: {x: 1, y: 1, z: 1} 243 | m_Children: 244 | - {fileID: 1533726423} 245 | - {fileID: 1306076439} 246 | - {fileID: 828812289} 247 | m_Father: {fileID: 1630477740} 248 | m_RootOrder: 0 249 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 250 | m_AnchorMin: {x: 0, y: 0} 251 | m_AnchorMax: {x: 1, y: 1} 252 | m_AnchoredPosition: {x: 0, y: -5} 253 | m_SizeDelta: {x: -40, y: -30} 254 | m_Pivot: {x: 0.5, y: 0.5} 255 | --- !u!114 &813572927 256 | MonoBehaviour: 257 | m_ObjectHideFlags: 0 258 | m_CorrespondingSourceObject: {fileID: 0} 259 | m_PrefabInstance: {fileID: 0} 260 | m_PrefabAsset: {fileID: 0} 261 | m_GameObject: {fileID: 813572925} 262 | m_Enabled: 1 263 | m_EditorHideFlags: 0 264 | m_Script: {fileID: 11500000, guid: 1aa08ab6e0800fa44ae55d278d1423e3, type: 3} 265 | m_Name: 266 | m_EditorClassIdentifier: 267 | m_Content: {fileID: 1554804300} 268 | m_Horizontal: 0 269 | m_Vertical: 1 270 | m_MovementType: 1 271 | m_Elasticity: 0.1 272 | m_Inertia: 1 273 | m_DecelerationRate: 0.135 274 | m_ScrollSensitivity: 1 275 | m_Viewport: {fileID: 1533726423} 276 | m_HorizontalScrollbar: {fileID: 1306076440} 277 | m_VerticalScrollbar: {fileID: 828812290} 278 | m_HorizontalScrollbarVisibility: 1 279 | m_VerticalScrollbarVisibility: 2 280 | m_HorizontalScrollbarSpacing: -3 281 | m_VerticalScrollbarSpacing: 0 282 | m_OnValueChanged: 283 | m_PersistentCalls: 284 | m_Calls: [] 285 | m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, 286 | Culture=neutral, PublicKeyToken=null 287 | --- !u!114 &813572928 288 | MonoBehaviour: 289 | m_ObjectHideFlags: 0 290 | m_CorrespondingSourceObject: {fileID: 0} 291 | m_PrefabInstance: {fileID: 0} 292 | m_PrefabAsset: {fileID: 0} 293 | m_GameObject: {fileID: 813572925} 294 | m_Enabled: 1 295 | m_EditorHideFlags: 0 296 | m_Script: {fileID: 11500000, guid: 3994d7f124d44369a0dc83c6951888e5, type: 3} 297 | m_Name: 298 | m_EditorClassIdentifier: 299 | ChildPrefab: {fileID: -4295012922733440193, guid: 113d11a263242a84bb061a25d1876dc9, 300 | type: 3} 301 | RowPadding: 5 302 | PreAllocHeight: 0 303 | --- !u!222 &813572929 304 | CanvasRenderer: 305 | m_ObjectHideFlags: 0 306 | m_CorrespondingSourceObject: {fileID: 0} 307 | m_PrefabInstance: {fileID: 0} 308 | m_PrefabAsset: {fileID: 0} 309 | m_GameObject: {fileID: 813572925} 310 | m_CullTransparentMesh: 0 311 | --- !u!1 &828812288 312 | GameObject: 313 | m_ObjectHideFlags: 0 314 | m_CorrespondingSourceObject: {fileID: 0} 315 | m_PrefabInstance: {fileID: 0} 316 | m_PrefabAsset: {fileID: 0} 317 | serializedVersion: 6 318 | m_Component: 319 | - component: {fileID: 828812289} 320 | - component: {fileID: 828812292} 321 | - component: {fileID: 828812291} 322 | - component: {fileID: 828812290} 323 | m_Layer: 5 324 | m_Name: Scrollbar Vertical 325 | m_TagString: Untagged 326 | m_Icon: {fileID: 0} 327 | m_NavMeshLayer: 0 328 | m_StaticEditorFlags: 0 329 | m_IsActive: 1 330 | --- !u!224 &828812289 331 | RectTransform: 332 | m_ObjectHideFlags: 0 333 | m_CorrespondingSourceObject: {fileID: 0} 334 | m_PrefabInstance: {fileID: 0} 335 | m_PrefabAsset: {fileID: 0} 336 | m_GameObject: {fileID: 828812288} 337 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 338 | m_LocalPosition: {x: 0, y: 0, z: 0} 339 | m_LocalScale: {x: 1, y: 1, z: 1} 340 | m_Children: 341 | - {fileID: 1930312828} 342 | m_Father: {fileID: 813572926} 343 | m_RootOrder: 2 344 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 345 | m_AnchorMin: {x: 1, y: 0} 346 | m_AnchorMax: {x: 1, y: 1} 347 | m_AnchoredPosition: {x: 0, y: 0} 348 | m_SizeDelta: {x: 20, y: 0} 349 | m_Pivot: {x: 1, y: 1} 350 | --- !u!114 &828812290 351 | MonoBehaviour: 352 | m_ObjectHideFlags: 0 353 | m_CorrespondingSourceObject: {fileID: 0} 354 | m_PrefabInstance: {fileID: 0} 355 | m_PrefabAsset: {fileID: 0} 356 | m_GameObject: {fileID: 828812288} 357 | m_Enabled: 1 358 | m_EditorHideFlags: 0 359 | m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, type: 3} 360 | m_Name: 361 | m_EditorClassIdentifier: 362 | m_Navigation: 363 | m_Mode: 3 364 | m_SelectOnUp: {fileID: 0} 365 | m_SelectOnDown: {fileID: 0} 366 | m_SelectOnLeft: {fileID: 0} 367 | m_SelectOnRight: {fileID: 0} 368 | m_Transition: 1 369 | m_Colors: 370 | m_NormalColor: {r: 0.8113208, g: 0.92655486, b: 1, a: 1} 371 | m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} 372 | m_PressedColor: {r: 0.8117648, g: 0.92549026, b: 1, a: 1} 373 | m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} 374 | m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} 375 | m_ColorMultiplier: 1 376 | m_FadeDuration: 0.1 377 | m_SpriteState: 378 | m_HighlightedSprite: {fileID: 0} 379 | m_PressedSprite: {fileID: 0} 380 | m_SelectedSprite: {fileID: 0} 381 | m_DisabledSprite: {fileID: 0} 382 | m_AnimationTriggers: 383 | m_NormalTrigger: Normal 384 | m_HighlightedTrigger: Highlighted 385 | m_PressedTrigger: Pressed 386 | m_SelectedTrigger: Selected 387 | m_DisabledTrigger: Disabled 388 | m_Interactable: 1 389 | m_TargetGraphic: {fileID: 874150242} 390 | m_HandleRect: {fileID: 874150241} 391 | m_Direction: 2 392 | m_Value: 1 393 | m_Size: 1 394 | m_NumberOfSteps: 0 395 | m_OnValueChanged: 396 | m_PersistentCalls: 397 | m_Calls: [] 398 | m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, 399 | Culture=neutral, PublicKeyToken=null 400 | --- !u!114 &828812291 401 | MonoBehaviour: 402 | m_ObjectHideFlags: 0 403 | m_CorrespondingSourceObject: {fileID: 0} 404 | m_PrefabInstance: {fileID: 0} 405 | m_PrefabAsset: {fileID: 0} 406 | m_GameObject: {fileID: 828812288} 407 | m_Enabled: 1 408 | m_EditorHideFlags: 0 409 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 410 | m_Name: 411 | m_EditorClassIdentifier: 412 | m_Material: {fileID: 0} 413 | m_Color: {r: 0, g: 0, b: 0, a: 0.27058825} 414 | m_RaycastTarget: 1 415 | m_OnCullStateChanged: 416 | m_PersistentCalls: 417 | m_Calls: [] 418 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 419 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 420 | m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} 421 | m_Type: 1 422 | m_PreserveAspect: 0 423 | m_FillCenter: 1 424 | m_FillMethod: 4 425 | m_FillAmount: 1 426 | m_FillClockwise: 1 427 | m_FillOrigin: 0 428 | m_UseSpriteMesh: 0 429 | m_PixelsPerUnitMultiplier: 1 430 | --- !u!222 &828812292 431 | CanvasRenderer: 432 | m_ObjectHideFlags: 0 433 | m_CorrespondingSourceObject: {fileID: 0} 434 | m_PrefabInstance: {fileID: 0} 435 | m_PrefabAsset: {fileID: 0} 436 | m_GameObject: {fileID: 828812288} 437 | m_CullTransparentMesh: 0 438 | --- !u!1 &874150240 439 | GameObject: 440 | m_ObjectHideFlags: 0 441 | m_CorrespondingSourceObject: {fileID: 0} 442 | m_PrefabInstance: {fileID: 0} 443 | m_PrefabAsset: {fileID: 0} 444 | serializedVersion: 6 445 | m_Component: 446 | - component: {fileID: 874150241} 447 | - component: {fileID: 874150243} 448 | - component: {fileID: 874150242} 449 | m_Layer: 5 450 | m_Name: Handle 451 | m_TagString: Untagged 452 | m_Icon: {fileID: 0} 453 | m_NavMeshLayer: 0 454 | m_StaticEditorFlags: 0 455 | m_IsActive: 1 456 | --- !u!224 &874150241 457 | RectTransform: 458 | m_ObjectHideFlags: 0 459 | m_CorrespondingSourceObject: {fileID: 0} 460 | m_PrefabInstance: {fileID: 0} 461 | m_PrefabAsset: {fileID: 0} 462 | m_GameObject: {fileID: 874150240} 463 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 464 | m_LocalPosition: {x: 0, y: 0, z: 0} 465 | m_LocalScale: {x: 1, y: 1, z: 1} 466 | m_Children: [] 467 | m_Father: {fileID: 1930312828} 468 | m_RootOrder: 0 469 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 470 | m_AnchorMin: {x: 0, y: 0} 471 | m_AnchorMax: {x: 0, y: 0} 472 | m_AnchoredPosition: {x: 0, y: 0} 473 | m_SizeDelta: {x: 20, y: 20} 474 | m_Pivot: {x: 0.5, y: 0.5} 475 | --- !u!114 &874150242 476 | MonoBehaviour: 477 | m_ObjectHideFlags: 0 478 | m_CorrespondingSourceObject: {fileID: 0} 479 | m_PrefabInstance: {fileID: 0} 480 | m_PrefabAsset: {fileID: 0} 481 | m_GameObject: {fileID: 874150240} 482 | m_Enabled: 1 483 | m_EditorHideFlags: 0 484 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 485 | m_Name: 486 | m_EditorClassIdentifier: 487 | m_Material: {fileID: 0} 488 | m_Color: {r: 1, g: 1, b: 1, a: 1} 489 | m_RaycastTarget: 1 490 | m_OnCullStateChanged: 491 | m_PersistentCalls: 492 | m_Calls: [] 493 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 494 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 495 | m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} 496 | m_Type: 1 497 | m_PreserveAspect: 0 498 | m_FillCenter: 1 499 | m_FillMethod: 4 500 | m_FillAmount: 1 501 | m_FillClockwise: 1 502 | m_FillOrigin: 0 503 | m_UseSpriteMesh: 0 504 | m_PixelsPerUnitMultiplier: 1 505 | --- !u!222 &874150243 506 | CanvasRenderer: 507 | m_ObjectHideFlags: 0 508 | m_CorrespondingSourceObject: {fileID: 0} 509 | m_PrefabInstance: {fileID: 0} 510 | m_PrefabAsset: {fileID: 0} 511 | m_GameObject: {fileID: 874150240} 512 | m_CullTransparentMesh: 0 513 | --- !u!1 &917752014 514 | GameObject: 515 | m_ObjectHideFlags: 0 516 | m_CorrespondingSourceObject: {fileID: 0} 517 | m_PrefabInstance: {fileID: 0} 518 | m_PrefabAsset: {fileID: 0} 519 | serializedVersion: 6 520 | m_Component: 521 | - component: {fileID: 917752017} 522 | - component: {fileID: 917752016} 523 | - component: {fileID: 917752015} 524 | m_Layer: 0 525 | m_Name: EventSystem 526 | m_TagString: Untagged 527 | m_Icon: {fileID: 0} 528 | m_NavMeshLayer: 0 529 | m_StaticEditorFlags: 0 530 | m_IsActive: 1 531 | --- !u!114 &917752015 532 | MonoBehaviour: 533 | m_ObjectHideFlags: 0 534 | m_CorrespondingSourceObject: {fileID: 0} 535 | m_PrefabInstance: {fileID: 0} 536 | m_PrefabAsset: {fileID: 0} 537 | m_GameObject: {fileID: 917752014} 538 | m_Enabled: 1 539 | m_EditorHideFlags: 0 540 | m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} 541 | m_Name: 542 | m_EditorClassIdentifier: 543 | m_HorizontalAxis: Horizontal 544 | m_VerticalAxis: Vertical 545 | m_SubmitButton: Submit 546 | m_CancelButton: Cancel 547 | m_InputActionsPerSecond: 10 548 | m_RepeatDelay: 0.5 549 | m_ForceModuleActive: 0 550 | --- !u!114 &917752016 551 | MonoBehaviour: 552 | m_ObjectHideFlags: 0 553 | m_CorrespondingSourceObject: {fileID: 0} 554 | m_PrefabInstance: {fileID: 0} 555 | m_PrefabAsset: {fileID: 0} 556 | m_GameObject: {fileID: 917752014} 557 | m_Enabled: 1 558 | m_EditorHideFlags: 0 559 | m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} 560 | m_Name: 561 | m_EditorClassIdentifier: 562 | m_FirstSelected: {fileID: 0} 563 | m_sendNavigationEvents: 1 564 | m_DragThreshold: 10 565 | --- !u!4 &917752017 566 | Transform: 567 | m_ObjectHideFlags: 0 568 | m_CorrespondingSourceObject: {fileID: 0} 569 | m_PrefabInstance: {fileID: 0} 570 | m_PrefabAsset: {fileID: 0} 571 | m_GameObject: {fileID: 917752014} 572 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 573 | m_LocalPosition: {x: 0, y: 0, z: 0} 574 | m_LocalScale: {x: 1, y: 1, z: 1} 575 | m_Children: [] 576 | m_Father: {fileID: 0} 577 | m_RootOrder: 3 578 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 579 | --- !u!1 &937915133 580 | GameObject: 581 | m_ObjectHideFlags: 0 582 | m_CorrespondingSourceObject: {fileID: 0} 583 | m_PrefabInstance: {fileID: 0} 584 | m_PrefabAsset: {fileID: 0} 585 | serializedVersion: 6 586 | m_Component: 587 | - component: {fileID: 937915134} 588 | m_Layer: 5 589 | m_Name: Sliding Area 590 | m_TagString: Untagged 591 | m_Icon: {fileID: 0} 592 | m_NavMeshLayer: 0 593 | m_StaticEditorFlags: 0 594 | m_IsActive: 1 595 | --- !u!224 &937915134 596 | RectTransform: 597 | m_ObjectHideFlags: 0 598 | m_CorrespondingSourceObject: {fileID: 0} 599 | m_PrefabInstance: {fileID: 0} 600 | m_PrefabAsset: {fileID: 0} 601 | m_GameObject: {fileID: 937915133} 602 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 603 | m_LocalPosition: {x: 0, y: 0, z: 0} 604 | m_LocalScale: {x: 1, y: 1, z: 1} 605 | m_Children: 606 | - {fileID: 1695937243} 607 | m_Father: {fileID: 1306076439} 608 | m_RootOrder: 0 609 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 610 | m_AnchorMin: {x: 0, y: 0} 611 | m_AnchorMax: {x: 1, y: 1} 612 | m_AnchoredPosition: {x: 0, y: 0} 613 | m_SizeDelta: {x: -20, y: -20} 614 | m_Pivot: {x: 0.5, y: 0.5} 615 | --- !u!1 &963194225 616 | GameObject: 617 | m_ObjectHideFlags: 0 618 | m_CorrespondingSourceObject: {fileID: 0} 619 | m_PrefabInstance: {fileID: 0} 620 | m_PrefabAsset: {fileID: 0} 621 | serializedVersion: 6 622 | m_Component: 623 | - component: {fileID: 963194228} 624 | - component: {fileID: 963194227} 625 | - component: {fileID: 963194226} 626 | m_Layer: 0 627 | m_Name: Main Camera 628 | m_TagString: MainCamera 629 | m_Icon: {fileID: 0} 630 | m_NavMeshLayer: 0 631 | m_StaticEditorFlags: 0 632 | m_IsActive: 1 633 | --- !u!81 &963194226 634 | AudioListener: 635 | m_ObjectHideFlags: 0 636 | m_CorrespondingSourceObject: {fileID: 0} 637 | m_PrefabInstance: {fileID: 0} 638 | m_PrefabAsset: {fileID: 0} 639 | m_GameObject: {fileID: 963194225} 640 | m_Enabled: 1 641 | --- !u!20 &963194227 642 | Camera: 643 | m_ObjectHideFlags: 0 644 | m_CorrespondingSourceObject: {fileID: 0} 645 | m_PrefabInstance: {fileID: 0} 646 | m_PrefabAsset: {fileID: 0} 647 | m_GameObject: {fileID: 963194225} 648 | m_Enabled: 1 649 | serializedVersion: 2 650 | m_ClearFlags: 2 651 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 652 | m_projectionMatrixMode: 1 653 | m_GateFitMode: 2 654 | m_FOVAxisMode: 0 655 | m_SensorSize: {x: 36, y: 24} 656 | m_LensShift: {x: 0, y: 0} 657 | m_FocalLength: 50 658 | m_NormalizedViewPortRect: 659 | serializedVersion: 2 660 | x: 0 661 | y: 0 662 | width: 1 663 | height: 1 664 | near clip plane: 0.3 665 | far clip plane: 1000 666 | field of view: 60 667 | orthographic: 0 668 | orthographic size: 5 669 | m_Depth: -1 670 | m_CullingMask: 671 | serializedVersion: 2 672 | m_Bits: 4294967295 673 | m_RenderingPath: -1 674 | m_TargetTexture: {fileID: 0} 675 | m_TargetDisplay: 0 676 | m_TargetEye: 3 677 | m_HDR: 1 678 | m_AllowMSAA: 1 679 | m_AllowDynamicResolution: 0 680 | m_ForceIntoRT: 0 681 | m_OcclusionCulling: 1 682 | m_StereoConvergence: 10 683 | m_StereoSeparation: 0.022 684 | --- !u!4 &963194228 685 | Transform: 686 | m_ObjectHideFlags: 0 687 | m_CorrespondingSourceObject: {fileID: 0} 688 | m_PrefabInstance: {fileID: 0} 689 | m_PrefabAsset: {fileID: 0} 690 | m_GameObject: {fileID: 963194225} 691 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 692 | m_LocalPosition: {x: 0, y: 1, z: -10} 693 | m_LocalScale: {x: 1, y: 1, z: 1} 694 | m_Children: [] 695 | m_Father: {fileID: 0} 696 | m_RootOrder: 0 697 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 698 | --- !u!1 &1306076438 699 | GameObject: 700 | m_ObjectHideFlags: 0 701 | m_CorrespondingSourceObject: {fileID: 0} 702 | m_PrefabInstance: {fileID: 0} 703 | m_PrefabAsset: {fileID: 0} 704 | serializedVersion: 6 705 | m_Component: 706 | - component: {fileID: 1306076439} 707 | - component: {fileID: 1306076442} 708 | - component: {fileID: 1306076441} 709 | - component: {fileID: 1306076440} 710 | m_Layer: 5 711 | m_Name: Scrollbar Horizontal 712 | m_TagString: Untagged 713 | m_Icon: {fileID: 0} 714 | m_NavMeshLayer: 0 715 | m_StaticEditorFlags: 0 716 | m_IsActive: 1 717 | --- !u!224 &1306076439 718 | RectTransform: 719 | m_ObjectHideFlags: 0 720 | m_CorrespondingSourceObject: {fileID: 0} 721 | m_PrefabInstance: {fileID: 0} 722 | m_PrefabAsset: {fileID: 0} 723 | m_GameObject: {fileID: 1306076438} 724 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 725 | m_LocalPosition: {x: 0, y: 0, z: 0} 726 | m_LocalScale: {x: 1, y: 1, z: 1} 727 | m_Children: 728 | - {fileID: 937915134} 729 | m_Father: {fileID: 813572926} 730 | m_RootOrder: 1 731 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 732 | m_AnchorMin: {x: 0, y: 0} 733 | m_AnchorMax: {x: 0, y: 0} 734 | m_AnchoredPosition: {x: 0, y: 0} 735 | m_SizeDelta: {x: 0, y: 20} 736 | m_Pivot: {x: 0, y: 0} 737 | --- !u!114 &1306076440 738 | MonoBehaviour: 739 | m_ObjectHideFlags: 0 740 | m_CorrespondingSourceObject: {fileID: 0} 741 | m_PrefabInstance: {fileID: 0} 742 | m_PrefabAsset: {fileID: 0} 743 | m_GameObject: {fileID: 1306076438} 744 | m_Enabled: 1 745 | m_EditorHideFlags: 0 746 | m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, type: 3} 747 | m_Name: 748 | m_EditorClassIdentifier: 749 | m_Navigation: 750 | m_Mode: 3 751 | m_SelectOnUp: {fileID: 0} 752 | m_SelectOnDown: {fileID: 0} 753 | m_SelectOnLeft: {fileID: 0} 754 | m_SelectOnRight: {fileID: 0} 755 | m_Transition: 1 756 | m_Colors: 757 | m_NormalColor: {r: 1, g: 1, b: 1, a: 1} 758 | m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} 759 | m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} 760 | m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} 761 | m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} 762 | m_ColorMultiplier: 1 763 | m_FadeDuration: 0.1 764 | m_SpriteState: 765 | m_HighlightedSprite: {fileID: 0} 766 | m_PressedSprite: {fileID: 0} 767 | m_SelectedSprite: {fileID: 0} 768 | m_DisabledSprite: {fileID: 0} 769 | m_AnimationTriggers: 770 | m_NormalTrigger: Normal 771 | m_HighlightedTrigger: Highlighted 772 | m_PressedTrigger: Pressed 773 | m_SelectedTrigger: Selected 774 | m_DisabledTrigger: Disabled 775 | m_Interactable: 1 776 | m_TargetGraphic: {fileID: 1695937244} 777 | m_HandleRect: {fileID: 1695937243} 778 | m_Direction: 0 779 | m_Value: 0 780 | m_Size: 1 781 | m_NumberOfSteps: 0 782 | m_OnValueChanged: 783 | m_PersistentCalls: 784 | m_Calls: [] 785 | m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, 786 | Culture=neutral, PublicKeyToken=null 787 | --- !u!114 &1306076441 788 | MonoBehaviour: 789 | m_ObjectHideFlags: 0 790 | m_CorrespondingSourceObject: {fileID: 0} 791 | m_PrefabInstance: {fileID: 0} 792 | m_PrefabAsset: {fileID: 0} 793 | m_GameObject: {fileID: 1306076438} 794 | m_Enabled: 1 795 | m_EditorHideFlags: 0 796 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 797 | m_Name: 798 | m_EditorClassIdentifier: 799 | m_Material: {fileID: 0} 800 | m_Color: {r: 1, g: 1, b: 1, a: 1} 801 | m_RaycastTarget: 1 802 | m_OnCullStateChanged: 803 | m_PersistentCalls: 804 | m_Calls: [] 805 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 806 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 807 | m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} 808 | m_Type: 1 809 | m_PreserveAspect: 0 810 | m_FillCenter: 1 811 | m_FillMethod: 4 812 | m_FillAmount: 1 813 | m_FillClockwise: 1 814 | m_FillOrigin: 0 815 | m_UseSpriteMesh: 0 816 | m_PixelsPerUnitMultiplier: 1 817 | --- !u!222 &1306076442 818 | CanvasRenderer: 819 | m_ObjectHideFlags: 0 820 | m_CorrespondingSourceObject: {fileID: 0} 821 | m_PrefabInstance: {fileID: 0} 822 | m_PrefabAsset: {fileID: 0} 823 | m_GameObject: {fileID: 1306076438} 824 | m_CullTransparentMesh: 0 825 | --- !u!1 &1533726422 826 | GameObject: 827 | m_ObjectHideFlags: 0 828 | m_CorrespondingSourceObject: {fileID: 0} 829 | m_PrefabInstance: {fileID: 0} 830 | m_PrefabAsset: {fileID: 0} 831 | serializedVersion: 6 832 | m_Component: 833 | - component: {fileID: 1533726423} 834 | - component: {fileID: 1533726426} 835 | - component: {fileID: 1533726425} 836 | - component: {fileID: 1533726424} 837 | m_Layer: 5 838 | m_Name: Viewport 839 | m_TagString: Untagged 840 | m_Icon: {fileID: 0} 841 | m_NavMeshLayer: 0 842 | m_StaticEditorFlags: 0 843 | m_IsActive: 1 844 | --- !u!224 &1533726423 845 | RectTransform: 846 | m_ObjectHideFlags: 0 847 | m_CorrespondingSourceObject: {fileID: 0} 848 | m_PrefabInstance: {fileID: 0} 849 | m_PrefabAsset: {fileID: 0} 850 | m_GameObject: {fileID: 1533726422} 851 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 852 | m_LocalPosition: {x: 0, y: 0, z: 0} 853 | m_LocalScale: {x: 1, y: 1, z: 1} 854 | m_Children: 855 | - {fileID: 1554804300} 856 | m_Father: {fileID: 813572926} 857 | m_RootOrder: 0 858 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 859 | m_AnchorMin: {x: 0, y: 0} 860 | m_AnchorMax: {x: 0, y: 0} 861 | m_AnchoredPosition: {x: 0, y: 0} 862 | m_SizeDelta: {x: 0, y: 0} 863 | m_Pivot: {x: 0, y: 1} 864 | --- !u!114 &1533726424 865 | MonoBehaviour: 866 | m_ObjectHideFlags: 0 867 | m_CorrespondingSourceObject: {fileID: 0} 868 | m_PrefabInstance: {fileID: 0} 869 | m_PrefabAsset: {fileID: 0} 870 | m_GameObject: {fileID: 1533726422} 871 | m_Enabled: 1 872 | m_EditorHideFlags: 0 873 | m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3} 874 | m_Name: 875 | m_EditorClassIdentifier: 876 | m_ShowMaskGraphic: 0 877 | --- !u!114 &1533726425 878 | MonoBehaviour: 879 | m_ObjectHideFlags: 0 880 | m_CorrespondingSourceObject: {fileID: 0} 881 | m_PrefabInstance: {fileID: 0} 882 | m_PrefabAsset: {fileID: 0} 883 | m_GameObject: {fileID: 1533726422} 884 | m_Enabled: 1 885 | m_EditorHideFlags: 0 886 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 887 | m_Name: 888 | m_EditorClassIdentifier: 889 | m_Material: {fileID: 0} 890 | m_Color: {r: 1, g: 1, b: 1, a: 1} 891 | m_RaycastTarget: 1 892 | m_OnCullStateChanged: 893 | m_PersistentCalls: 894 | m_Calls: [] 895 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 896 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 897 | m_Sprite: {fileID: 10917, guid: 0000000000000000f000000000000000, type: 0} 898 | m_Type: 1 899 | m_PreserveAspect: 0 900 | m_FillCenter: 1 901 | m_FillMethod: 4 902 | m_FillAmount: 1 903 | m_FillClockwise: 1 904 | m_FillOrigin: 0 905 | m_UseSpriteMesh: 0 906 | m_PixelsPerUnitMultiplier: 1 907 | --- !u!222 &1533726426 908 | CanvasRenderer: 909 | m_ObjectHideFlags: 0 910 | m_CorrespondingSourceObject: {fileID: 0} 911 | m_PrefabInstance: {fileID: 0} 912 | m_PrefabAsset: {fileID: 0} 913 | m_GameObject: {fileID: 1533726422} 914 | m_CullTransparentMesh: 0 915 | --- !u!1 &1554804299 916 | GameObject: 917 | m_ObjectHideFlags: 0 918 | m_CorrespondingSourceObject: {fileID: 0} 919 | m_PrefabInstance: {fileID: 0} 920 | m_PrefabAsset: {fileID: 0} 921 | serializedVersion: 6 922 | m_Component: 923 | - component: {fileID: 1554804300} 924 | m_Layer: 5 925 | m_Name: Content 926 | m_TagString: Untagged 927 | m_Icon: {fileID: 0} 928 | m_NavMeshLayer: 0 929 | m_StaticEditorFlags: 0 930 | m_IsActive: 1 931 | --- !u!224 &1554804300 932 | RectTransform: 933 | m_ObjectHideFlags: 0 934 | m_CorrespondingSourceObject: {fileID: 0} 935 | m_PrefabInstance: {fileID: 0} 936 | m_PrefabAsset: {fileID: 0} 937 | m_GameObject: {fileID: 1554804299} 938 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 939 | m_LocalPosition: {x: 0, y: 0, z: 0} 940 | m_LocalScale: {x: 1, y: 1, z: 1} 941 | m_Children: [] 942 | m_Father: {fileID: 1533726423} 943 | m_RootOrder: 0 944 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 945 | m_AnchorMin: {x: 0, y: 1} 946 | m_AnchorMax: {x: 1, y: 1} 947 | m_AnchoredPosition: {x: 0, y: 0} 948 | m_SizeDelta: {x: 0, y: 300} 949 | m_Pivot: {x: 0, y: 1} 950 | --- !u!1 &1630477739 951 | GameObject: 952 | m_ObjectHideFlags: 0 953 | m_CorrespondingSourceObject: {fileID: 0} 954 | m_PrefabInstance: {fileID: 0} 955 | m_PrefabAsset: {fileID: 0} 956 | serializedVersion: 6 957 | m_Component: 958 | - component: {fileID: 1630477740} 959 | - component: {fileID: 1630477742} 960 | - component: {fileID: 1630477741} 961 | - component: {fileID: 1630477743} 962 | m_Layer: 5 963 | m_Name: TestPanel 964 | m_TagString: Untagged 965 | m_Icon: {fileID: 0} 966 | m_NavMeshLayer: 0 967 | m_StaticEditorFlags: 0 968 | m_IsActive: 1 969 | --- !u!224 &1630477740 970 | RectTransform: 971 | m_ObjectHideFlags: 0 972 | m_CorrespondingSourceObject: {fileID: 0} 973 | m_PrefabInstance: {fileID: 0} 974 | m_PrefabAsset: {fileID: 0} 975 | m_GameObject: {fileID: 1630477739} 976 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 977 | m_LocalPosition: {x: 0, y: 0, z: 0} 978 | m_LocalScale: {x: 1, y: 1, z: 1} 979 | m_Children: 980 | - {fileID: 813572926} 981 | m_Father: {fileID: 2050582174} 982 | m_RootOrder: 0 983 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 984 | m_AnchorMin: {x: 0, y: 0} 985 | m_AnchorMax: {x: 1, y: 1} 986 | m_AnchoredPosition: {x: 0, y: 5} 987 | m_SizeDelta: {x: -360, y: -70} 988 | m_Pivot: {x: 0.5, y: 0.5} 989 | --- !u!114 &1630477741 990 | MonoBehaviour: 991 | m_ObjectHideFlags: 0 992 | m_CorrespondingSourceObject: {fileID: 0} 993 | m_PrefabInstance: {fileID: 0} 994 | m_PrefabAsset: {fileID: 0} 995 | m_GameObject: {fileID: 1630477739} 996 | m_Enabled: 1 997 | m_EditorHideFlags: 0 998 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 999 | m_Name: 1000 | m_EditorClassIdentifier: 1001 | m_Material: {fileID: 0} 1002 | m_Color: {r: 0.35973808, g: 0.37214285, b: 0.52099997, a: 1} 1003 | m_RaycastTarget: 1 1004 | m_OnCullStateChanged: 1005 | m_PersistentCalls: 1006 | m_Calls: [] 1007 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 1008 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 1009 | m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} 1010 | m_Type: 1 1011 | m_PreserveAspect: 0 1012 | m_FillCenter: 1 1013 | m_FillMethod: 4 1014 | m_FillAmount: 1 1015 | m_FillClockwise: 1 1016 | m_FillOrigin: 0 1017 | m_UseSpriteMesh: 0 1018 | m_PixelsPerUnitMultiplier: 1 1019 | --- !u!222 &1630477742 1020 | CanvasRenderer: 1021 | m_ObjectHideFlags: 0 1022 | m_CorrespondingSourceObject: {fileID: 0} 1023 | m_PrefabInstance: {fileID: 0} 1024 | m_PrefabAsset: {fileID: 0} 1025 | m_GameObject: {fileID: 1630477739} 1026 | m_CullTransparentMesh: 0 1027 | --- !u!114 &1630477743 1028 | MonoBehaviour: 1029 | m_ObjectHideFlags: 0 1030 | m_CorrespondingSourceObject: {fileID: 0} 1031 | m_PrefabInstance: {fileID: 0} 1032 | m_PrefabAsset: {fileID: 0} 1033 | m_GameObject: {fileID: 1630477739} 1034 | m_Enabled: 1 1035 | m_EditorHideFlags: 0 1036 | m_Script: {fileID: 11500000, guid: 3c4625d22f0dab74ca1855a738040c8d, type: 3} 1037 | m_Name: 1038 | m_EditorClassIdentifier: 1039 | theList: {fileID: 813572928} 1040 | --- !u!1 &1695937242 1041 | GameObject: 1042 | m_ObjectHideFlags: 0 1043 | m_CorrespondingSourceObject: {fileID: 0} 1044 | m_PrefabInstance: {fileID: 0} 1045 | m_PrefabAsset: {fileID: 0} 1046 | serializedVersion: 6 1047 | m_Component: 1048 | - component: {fileID: 1695937243} 1049 | - component: {fileID: 1695937245} 1050 | - component: {fileID: 1695937244} 1051 | m_Layer: 5 1052 | m_Name: Handle 1053 | m_TagString: Untagged 1054 | m_Icon: {fileID: 0} 1055 | m_NavMeshLayer: 0 1056 | m_StaticEditorFlags: 0 1057 | m_IsActive: 1 1058 | --- !u!224 &1695937243 1059 | RectTransform: 1060 | m_ObjectHideFlags: 0 1061 | m_CorrespondingSourceObject: {fileID: 0} 1062 | m_PrefabInstance: {fileID: 0} 1063 | m_PrefabAsset: {fileID: 0} 1064 | m_GameObject: {fileID: 1695937242} 1065 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 1066 | m_LocalPosition: {x: 0, y: 0, z: 0} 1067 | m_LocalScale: {x: 1, y: 1, z: 1} 1068 | m_Children: [] 1069 | m_Father: {fileID: 937915134} 1070 | m_RootOrder: 0 1071 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 1072 | m_AnchorMin: {x: 0, y: 0} 1073 | m_AnchorMax: {x: 0, y: 0} 1074 | m_AnchoredPosition: {x: 0, y: 0} 1075 | m_SizeDelta: {x: 20, y: 20} 1076 | m_Pivot: {x: 0.5, y: 0.5} 1077 | --- !u!114 &1695937244 1078 | MonoBehaviour: 1079 | m_ObjectHideFlags: 0 1080 | m_CorrespondingSourceObject: {fileID: 0} 1081 | m_PrefabInstance: {fileID: 0} 1082 | m_PrefabAsset: {fileID: 0} 1083 | m_GameObject: {fileID: 1695937242} 1084 | m_Enabled: 1 1085 | m_EditorHideFlags: 0 1086 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 1087 | m_Name: 1088 | m_EditorClassIdentifier: 1089 | m_Material: {fileID: 0} 1090 | m_Color: {r: 1, g: 1, b: 1, a: 1} 1091 | m_RaycastTarget: 1 1092 | m_OnCullStateChanged: 1093 | m_PersistentCalls: 1094 | m_Calls: [] 1095 | m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, 1096 | Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 1097 | m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} 1098 | m_Type: 1 1099 | m_PreserveAspect: 0 1100 | m_FillCenter: 1 1101 | m_FillMethod: 4 1102 | m_FillAmount: 1 1103 | m_FillClockwise: 1 1104 | m_FillOrigin: 0 1105 | m_UseSpriteMesh: 0 1106 | m_PixelsPerUnitMultiplier: 1 1107 | --- !u!222 &1695937245 1108 | CanvasRenderer: 1109 | m_ObjectHideFlags: 0 1110 | m_CorrespondingSourceObject: {fileID: 0} 1111 | m_PrefabInstance: {fileID: 0} 1112 | m_PrefabAsset: {fileID: 0} 1113 | m_GameObject: {fileID: 1695937242} 1114 | m_CullTransparentMesh: 0 1115 | --- !u!1 &1930312827 1116 | GameObject: 1117 | m_ObjectHideFlags: 0 1118 | m_CorrespondingSourceObject: {fileID: 0} 1119 | m_PrefabInstance: {fileID: 0} 1120 | m_PrefabAsset: {fileID: 0} 1121 | serializedVersion: 6 1122 | m_Component: 1123 | - component: {fileID: 1930312828} 1124 | m_Layer: 5 1125 | m_Name: Sliding Area 1126 | m_TagString: Untagged 1127 | m_Icon: {fileID: 0} 1128 | m_NavMeshLayer: 0 1129 | m_StaticEditorFlags: 0 1130 | m_IsActive: 1 1131 | --- !u!224 &1930312828 1132 | RectTransform: 1133 | m_ObjectHideFlags: 0 1134 | m_CorrespondingSourceObject: {fileID: 0} 1135 | m_PrefabInstance: {fileID: 0} 1136 | m_PrefabAsset: {fileID: 0} 1137 | m_GameObject: {fileID: 1930312827} 1138 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 1139 | m_LocalPosition: {x: 0, y: 0, z: 0} 1140 | m_LocalScale: {x: 1, y: 1, z: 1} 1141 | m_Children: 1142 | - {fileID: 874150241} 1143 | m_Father: {fileID: 828812289} 1144 | m_RootOrder: 0 1145 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 1146 | m_AnchorMin: {x: 0, y: 0} 1147 | m_AnchorMax: {x: 1, y: 1} 1148 | m_AnchoredPosition: {x: 0, y: 0} 1149 | m_SizeDelta: {x: -20, y: -20} 1150 | m_Pivot: {x: 0.5, y: 0.5} 1151 | --- !u!1 &2050582170 1152 | GameObject: 1153 | m_ObjectHideFlags: 0 1154 | m_CorrespondingSourceObject: {fileID: 0} 1155 | m_PrefabInstance: {fileID: 0} 1156 | m_PrefabAsset: {fileID: 0} 1157 | serializedVersion: 6 1158 | m_Component: 1159 | - component: {fileID: 2050582174} 1160 | - component: {fileID: 2050582173} 1161 | - component: {fileID: 2050582172} 1162 | - component: {fileID: 2050582171} 1163 | m_Layer: 5 1164 | m_Name: Canvas 1165 | m_TagString: Untagged 1166 | m_Icon: {fileID: 0} 1167 | m_NavMeshLayer: 0 1168 | m_StaticEditorFlags: 0 1169 | m_IsActive: 1 1170 | --- !u!114 &2050582171 1171 | MonoBehaviour: 1172 | m_ObjectHideFlags: 0 1173 | m_CorrespondingSourceObject: {fileID: 0} 1174 | m_PrefabInstance: {fileID: 0} 1175 | m_PrefabAsset: {fileID: 0} 1176 | m_GameObject: {fileID: 2050582170} 1177 | m_Enabled: 1 1178 | m_EditorHideFlags: 0 1179 | m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} 1180 | m_Name: 1181 | m_EditorClassIdentifier: 1182 | m_IgnoreReversedGraphics: 1 1183 | m_BlockingObjects: 0 1184 | m_BlockingMask: 1185 | serializedVersion: 2 1186 | m_Bits: 4294967295 1187 | --- !u!114 &2050582172 1188 | MonoBehaviour: 1189 | m_ObjectHideFlags: 0 1190 | m_CorrespondingSourceObject: {fileID: 0} 1191 | m_PrefabInstance: {fileID: 0} 1192 | m_PrefabAsset: {fileID: 0} 1193 | m_GameObject: {fileID: 2050582170} 1194 | m_Enabled: 1 1195 | m_EditorHideFlags: 0 1196 | m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} 1197 | m_Name: 1198 | m_EditorClassIdentifier: 1199 | m_UiScaleMode: 1 1200 | m_ReferencePixelsPerUnit: 100 1201 | m_ScaleFactor: 1 1202 | m_ReferenceResolution: {x: 800, y: 600} 1203 | m_ScreenMatchMode: 0 1204 | m_MatchWidthOrHeight: 0 1205 | m_PhysicalUnit: 3 1206 | m_FallbackScreenDPI: 96 1207 | m_DefaultSpriteDPI: 96 1208 | m_DynamicPixelsPerUnit: 1 1209 | --- !u!223 &2050582173 1210 | Canvas: 1211 | m_ObjectHideFlags: 0 1212 | m_CorrespondingSourceObject: {fileID: 0} 1213 | m_PrefabInstance: {fileID: 0} 1214 | m_PrefabAsset: {fileID: 0} 1215 | m_GameObject: {fileID: 2050582170} 1216 | m_Enabled: 1 1217 | serializedVersion: 3 1218 | m_RenderMode: 0 1219 | m_Camera: {fileID: 0} 1220 | m_PlaneDistance: 100 1221 | m_PixelPerfect: 0 1222 | m_ReceivesEvents: 1 1223 | m_OverrideSorting: 0 1224 | m_OverridePixelPerfect: 0 1225 | m_SortingBucketNormalizedSize: 0 1226 | m_AdditionalShaderChannelsFlag: 0 1227 | m_SortingLayerID: 0 1228 | m_SortingOrder: 0 1229 | m_TargetDisplay: 0 1230 | --- !u!224 &2050582174 1231 | RectTransform: 1232 | m_ObjectHideFlags: 0 1233 | m_CorrespondingSourceObject: {fileID: 0} 1234 | m_PrefabInstance: {fileID: 0} 1235 | m_PrefabAsset: {fileID: 0} 1236 | m_GameObject: {fileID: 2050582170} 1237 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 1238 | m_LocalPosition: {x: 0, y: 0, z: 0} 1239 | m_LocalScale: {x: 0, y: 0, z: 0} 1240 | m_Children: 1241 | - {fileID: 1630477740} 1242 | m_Father: {fileID: 0} 1243 | m_RootOrder: 2 1244 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 1245 | m_AnchorMin: {x: 0, y: 0} 1246 | m_AnchorMax: {x: 0, y: 0} 1247 | m_AnchoredPosition: {x: 0, y: 0} 1248 | m_SizeDelta: {x: 0, y: 0} 1249 | m_Pivot: {x: 0, y: 0} 1250 | -------------------------------------------------------------------------------- /Examples/Scenes/RecyclingList.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9fc0d4010bbf28b4594072e72b8655ab 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Examples/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f4fe53df5bf9a64fac98205e2233b88 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Examples/Scripts/TestChildItem.cs: -------------------------------------------------------------------------------- 1 | using TMPro; 2 | using UnityEngine; 3 | using UnityEngine.UI; 4 | 5 | public class TestChildItem : RecyclingListViewItem { 6 | public Text leftText; 7 | public Text rightText1; 8 | public Text rightText2; 9 | 10 | private TestChildData childData; 11 | public TestChildData ChildData { 12 | get { return childData; } 13 | set { 14 | childData = value; 15 | leftText.text = childData.Title; 16 | rightText1.text = childData.Note1; 17 | rightText2.text = childData.Note2; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Scripts/TestChildItem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fcf4560bf40f78c478e0c716c320daaa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Examples/Scripts/TestPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEngine.UI; 6 | using Random = UnityEngine.Random; 7 | 8 | public struct TestChildData { 9 | public string Title; 10 | public string Note1; 11 | public string Note2; 12 | 13 | public TestChildData(string t, string n1, string n2) { 14 | Title = t; 15 | Note1 = n1; 16 | Note2 = n2; 17 | } 18 | } 19 | 20 | public class TestPanel : MonoBehaviour { 21 | public RecyclingListView theList; 22 | private List data = new List(); 23 | 24 | private void Start() { 25 | theList.ItemCallback = PopulateItem; 26 | 27 | RetrieveData(); 28 | 29 | // This will resize the list and cause callbacks to PopulateItem for 30 | // items that are needed for the view 31 | theList.RowCount = data.Count; 32 | } 33 | 34 | private void RetrieveData() { 35 | data.Clear(); 36 | int row = 0; 37 | 38 | // You'd obviously load real data here 39 | string[] randomTitles = new[] { 40 | "Hello World", 41 | "This is fine", 42 | "You look nice today", 43 | "Recycling is good", 44 | "Why not", 45 | "Go outside", 46 | "And do something", 47 | "Less boring instead" 48 | }; 49 | for (int i = 0; i < 200; ++i) { 50 | data.Add(new TestChildData(randomTitles[Random.Range(0, randomTitles.Length)], $"Row {row++}", Random.Range(0, 256).ToString())); 51 | } 52 | } 53 | 54 | private void PopulateItem(RecyclingListViewItem item, int rowIndex) { 55 | var child = item as TestChildItem; 56 | child.ChildData = data[rowIndex]; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /Examples/Scripts/TestPanel.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c4625d22f0dab74ca1855a738040c8d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Steve Streeting 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | 2 | # RecyclingListView for Unity 3 | 4 | > #### Note: I have stopped using Unity and so am not maintaining this library any more. 5 | 6 | ## What is this for? 7 | 8 | One way of making a list is simply to create every item in the list and add it to 9 | the content view of a Unity ScrollRect, perhaps with a ContentFitter to automatically 10 | expand it, and a VerticalLayoutGroup to position them. There's one problem with 11 | this: it gets *really* slow at high volumes. 12 | 13 | Most UI systems don't do this under the hood; instead they only allocate just enough 14 | visual resources to cover the visible area (plus a safety area), and then 15 | recycle the child views as you scroll - views which drop out of view are re-used 16 | for the parts that are just coming into view. This way you have a fixed amount 17 | of overheads regardless of how big your list is. 18 | 19 | This repo contains a smallest-possible implementation of this concept, sometimes 20 | called "virtualising" a list or just "recycling". Basically you keep the 21 | "model" which contains all of the data, and the list calls you back to ask you 22 | to provide details of a specific element when it needs it, because it's coming 23 | into view. 24 | 25 | ![Example Image](demo.gif) 26 | 27 | ## How to use it 28 | 29 | 30 | ### The Demo 31 | 32 | You can drag this whole repo into Unity Assets to provide a 33 | quick demo of this so you can pick it apart yourself, just load *Scenes/RecyclingList*. 34 | 35 | ### How it works 36 | 37 | * You have a list of items (just data, no view), this is your Model. This can be on any class. 38 | * You create a ScrollRect (Scroll View in the menu) and add a RecyclingListView to it 39 | * You create a prefab which is a child item in your list (the View item). It must have a component of RecyclingListViewItem on it. 40 | * You give the RecyclingListView a reference to that prefab; it pre-allocates them and keeps them in a pool 41 | * You set a delegate on RecyclingListView which is the method it calls when one of these 42 | items needs populating with data 43 | * You simply tell the RecyclingListView the RowCount of your Model. It then calls the delegate for any of those items in view, giving you a row index to refer to. 44 | * You can tell the view that the model has been updated (without changing its size) via Refresh if need be (either completely or for a subset) 45 | 46 | 47 | ### Step by step 48 | 49 | 1. Create a Canvas 50 | 2. Create a Scroll View underneath 51 | 3. Tune how you like (I removed the horizontal scroll bar) 52 | 4. Add RecyclingListView component to the scroll view 53 | 5. Create a child panel which will go inside the scroll view, temporarily inside Content of scroll view (just so you can get it looking like you want) 54 | 6. Create a subclass of RecyclingListViewItem to hold whatever data you need for this view 55 | 6. Add your RecyclingListViewItem subclass as a component to the root of the child 56 | 7. Make a prefab out of this child panel, then delete it from content 57 | 8. Select the scroll view and set the Child Prefab on RecyclingListView to your prefab 58 | 9. Create your component which will contain the model, somewhere. It doesn't matter where, so long as it has a reference to the RecyclingListView 59 | 10. Your model component should set RecyclingListView.ItemCallback, and set RecyclingListView.RowCount. The rest will happen mostly automatically as "How it works" above. 60 | 11. Change RowCount when you alter the length of the list, or Clear() and Refresh() to 61 | empty or update content in-place. 62 | 63 | 64 | ## Limitations 65 | 66 | This is not a general purpose grid view like you'll find in the Asset Store, it's just 67 | for lists. Specifically: 68 | 69 | * Only one type of child panel is supported 70 | * The child panel has to be a fixed height 71 | * Horizontal scrolling can still be used, but virtualisation is only done vertically 72 | 73 | ## Tips 74 | 75 | ### Pre-Allocate More Items 76 | 77 | The list handles dynamic resizing, but if you know the max height your content 78 | view can ever be, and that's likely to be bigger than the default size, you can 79 | avoid some reallocation by specifying that height in the "Pre Alloc Height" 80 | property on the list view component. 81 | 82 | ## License (MIT) 83 | 84 | Copyright (c) 2019 Steve Streeting 85 | 86 | Permission is hereby granted, free of charge, to any person obtaining a copy 87 | of this software and associated documentation files (the "Software"), to deal 88 | in the Software without restriction, including without limitation the rights 89 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 90 | copies of the Software, and to permit persons to whom the Software is 91 | furnished to do so, subject to the following conditions: 92 | 93 | The above copyright notice and this permission notice shall be included in all 94 | copies or substantial portions of the Software. 95 | 96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 97 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 98 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 99 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 100 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 101 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 102 | SOFTWARE. 103 | -------------------------------------------------------------------------------- /Source/RecyclingListView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEngine.UI; 4 | 5 | /// 6 | /// RecyclingListView uses a Unity UI ScrollRect to provide an efficiently scrolling list. 7 | /// The key feature is that it only allocates just enough child items needed for the 8 | /// visible part of the view, and recycles them as the list is scrolled, saving memory 9 | /// and layout cost. 10 | /// 11 | /// There are limitations: 12 | /// * Child items must be a fixed height 13 | /// * Only one type of child item is supported 14 | /// * Only vertical scrolling is virtualised. Horizontal scrolling is still supported but 15 | /// there is no support for grid view style layouts 16 | /// 17 | [RequireComponent(typeof(ScrollRect))] 18 | public class RecyclingListView : MonoBehaviour { 19 | [Tooltip("Prefab for all the child view objects in the list")] 20 | public RecyclingListViewItem ChildPrefab; 21 | [Tooltip("The amount of vertical padding to add between items")] 22 | public float RowPadding = 15f; 23 | [Tooltip("Minimum height to pre-allocate list items for. Use to prevent allocations on resizing.")] 24 | public float PreAllocHeight = 0; 25 | 26 | 27 | /// 28 | /// Set the vertical normalized scroll position. 0 is bottom, 1 is top (as with ScrollRect) 29 | /// 30 | public float VerticalNormalizedPosition { 31 | get => scrollRect.verticalNormalizedPosition; 32 | set => scrollRect.verticalNormalizedPosition = value; 33 | } 34 | 35 | protected int rowCount; 36 | /// 37 | /// Get / set the number of rows in the list. If changed, will cause a rebuild of 38 | /// the contents of the list. Call Refresh() instead to update contents without changing 39 | /// length. 40 | /// 41 | public int RowCount { 42 | get => rowCount; 43 | set { 44 | if (rowCount != value) { 45 | rowCount = value; 46 | // avoid triggering double refresh due to scroll change from height change 47 | ignoreScrollChange = true; 48 | UpdateContentHeight(); 49 | ignoreScrollChange = false; 50 | ReorganiseContent(true); 51 | } 52 | } 53 | } 54 | 55 | /// 56 | /// Delegate which users should implement to populate their custom RecyclingListViewItem 57 | /// instances when they're needed by the list. 58 | /// 59 | /// The child item being populated. These are recycled as the list scrolls. 60 | /// The overall row index of the list item being populated 61 | public delegate void ItemDelegate(RecyclingListViewItem item, int rowIndex); 62 | 63 | /// 64 | /// Set the delegate which will be called back to populate items. You must provide this at runtime. 65 | /// 66 | public ItemDelegate ItemCallback; 67 | 68 | protected ScrollRect scrollRect; 69 | // circular buffer of child items which are reused 70 | protected RecyclingListViewItem[] childItems; 71 | // the current start index of the circular buffer 72 | protected int childBufferStart = 0; 73 | // the index into source data which childBufferStart refers to 74 | protected int sourceDataRowStart; 75 | 76 | protected bool ignoreScrollChange = false; 77 | protected float previousBuildHeight = 0; 78 | protected const int rowsAboveBelow = 1; 79 | 80 | /// 81 | /// Trigger the refreshing of the list content (e.g. if you've changed some values). 82 | /// Use this if the number of rows hasn't changed but you want to update the contents 83 | /// for some other reason. All active items will have the ItemCallback invoked. 84 | /// 85 | public virtual void Refresh() { 86 | ReorganiseContent(true); 87 | } 88 | 89 | /// 90 | /// Refresh a subset of the list content. Any rows which currently have data populated in the view 91 | /// will cause a call to ItemCallback. The size of the list or positions won't change. 92 | /// 93 | /// 94 | /// 95 | public virtual void Refresh(int rowStart, int count) { 96 | // only refresh the overlap 97 | int sourceDataLimit = sourceDataRowStart + childItems.Length; 98 | for (int i = 0; i < count; ++i) { 99 | int row = rowStart + i; 100 | if (row < sourceDataRowStart || row >= sourceDataLimit) 101 | continue; 102 | 103 | int bufIdx = WrapChildIndex(childBufferStart + row - sourceDataRowStart); 104 | if (childItems[bufIdx] != null) { 105 | UpdateChild(childItems[bufIdx], row); 106 | } 107 | } 108 | } 109 | 110 | /// 111 | /// Refresh a single row based on its reference. 112 | /// 113 | /// 114 | public virtual void Refresh(RecyclingListViewItem item) { 115 | for (int i = 0; i < childItems.Length; ++i) { 116 | int idx = WrapChildIndex(childBufferStart + i); 117 | if (childItems[idx] != null && childItems[idx] == item) { 118 | UpdateChild(childItems[i], sourceDataRowStart + i); 119 | break; 120 | } 121 | } 122 | } 123 | 124 | /// 125 | /// Quick way of clearing all the content from the list (alias for RowCount = 0) 126 | /// 127 | public virtual void Clear() { 128 | RowCount = 0; 129 | } 130 | 131 | /// 132 | /// Scroll the viewport so that a given row is in view, preferably centred vertically. 133 | /// 134 | /// 135 | public virtual void ScrollToRow(int row) { 136 | scrollRect.verticalNormalizedPosition = GetRowScrollPosition(row); 137 | } 138 | 139 | /// 140 | /// Get the normalised vertical scroll position which would centre the given row in the view, 141 | /// as best as possible without scrolling outside the bounds of the content. 142 | /// Use this instead of ScrollToRow if you want to control the actual scrolling yourself. 143 | /// 144 | /// 145 | /// 146 | public float GetRowScrollPosition(int row) { 147 | float rowCentre = (row + 0.5f) * RowHeight(); 148 | float vpHeight = ViewportHeight(); 149 | float halfVpHeight = vpHeight * 0.5f; 150 | // Clamp to top of content 151 | float vpTop = Mathf.Max(0, rowCentre - halfVpHeight); 152 | float vpBottom = vpTop + vpHeight; 153 | float contentHeight = scrollRect.content.sizeDelta.y; 154 | // clamp to bottom of content 155 | if (vpBottom > contentHeight) // if content is shorter than vp always stop at 0 156 | vpTop = Mathf.Max(0, vpTop - (vpBottom - contentHeight)); 157 | 158 | // Range for our purposes is between top (0) and top of vp when scrolled to bottom (contentHeight - vpHeight) 159 | // ScrollRect normalised position is 0 at bottom, 1 at top 160 | // so inverted range because 0 is bottom and our calc is top-down 161 | return Mathf.InverseLerp(contentHeight - vpHeight, 0, vpTop); 162 | } 163 | 164 | /// 165 | /// Retrieve the item instance for a given row, IF it is currently allocated for the view. 166 | /// Because these items are recycled as the view moves, you should not hold on to this item beyond 167 | /// the site of the call to this method. 168 | /// 169 | /// The row number 170 | /// The list view item assigned to this row IF it's within the window the list currently has 171 | /// allocated for viewing. If row is outside this range, returns null. 172 | public RecyclingListViewItem GetRowItem(int row) { 173 | if (childItems != null && 174 | row >= sourceDataRowStart && row < sourceDataRowStart + childItems.Length && // within window 175 | row < rowCount) { // within overall range 176 | 177 | return childItems[WrapChildIndex(childBufferStart + row - sourceDataRowStart)]; 178 | } 179 | 180 | return null; 181 | } 182 | 183 | protected virtual void Awake() { 184 | scrollRect = GetComponent(); 185 | } 186 | 187 | protected virtual bool CheckChildItems() { 188 | float vpHeight = ViewportHeight(); 189 | float buildHeight = Mathf.Max(vpHeight, PreAllocHeight); 190 | bool rebuild = childItems == null || buildHeight > previousBuildHeight; 191 | if (rebuild) { 192 | // create a fixed number of children, we'll re-use them when scrolling 193 | // figure out how many we need, round up 194 | int childCount = Mathf.RoundToInt(0.5f + buildHeight / RowHeight()); 195 | childCount += rowsAboveBelow * 2; // X before, X after 196 | 197 | if (childItems == null) 198 | childItems = new RecyclingListViewItem[childCount]; 199 | else if (childCount > childItems.Length) 200 | Array.Resize(ref childItems, childCount); 201 | 202 | for (int i = 0; i < childItems.Length; ++i) { 203 | if (childItems[i] == null) { 204 | childItems[i] = Instantiate(ChildPrefab); 205 | } 206 | childItems[i].RectTransform.SetParent(scrollRect.content, false); 207 | childItems[i].gameObject.SetActive(false); 208 | } 209 | 210 | previousBuildHeight = buildHeight; 211 | } 212 | 213 | return rebuild; 214 | } 215 | 216 | 217 | protected virtual void OnEnable() { 218 | scrollRect.onValueChanged.AddListener(OnScrollChanged); 219 | ignoreScrollChange = false; 220 | } 221 | 222 | protected virtual void OnDisable() { 223 | scrollRect.onValueChanged.RemoveListener(OnScrollChanged); 224 | } 225 | 226 | protected virtual void OnScrollChanged(Vector2 normalisedPos) { 227 | // This is called when scroll bar is moved *and* when viewport changes size 228 | if (!ignoreScrollChange) { 229 | ReorganiseContent(false); 230 | } 231 | } 232 | 233 | protected virtual void ReorganiseContent(bool clearContents) { 234 | 235 | if (clearContents) { 236 | scrollRect.StopMovement(); 237 | scrollRect.verticalNormalizedPosition = 1; // 1 == top 238 | } 239 | 240 | bool childrenChanged = CheckChildItems(); 241 | bool populateAll = childrenChanged || clearContents; 242 | 243 | // Figure out which is the first virtual slot visible 244 | float ymin = scrollRect.content.localPosition.y; 245 | 246 | // round down to find first visible 247 | int firstVisibleIndex = (int)(ymin / RowHeight()); 248 | 249 | // we always want to start our buffer before 250 | int newRowStart = firstVisibleIndex - rowsAboveBelow; 251 | 252 | // If we've moved too far to be able to reuse anything, same as init case 253 | int diff = newRowStart - sourceDataRowStart; 254 | if (populateAll || Mathf.Abs(diff) >= childItems.Length) { 255 | 256 | sourceDataRowStart = newRowStart; 257 | childBufferStart = 0; 258 | int rowIdx = newRowStart; 259 | foreach (var item in childItems) { 260 | UpdateChild(item, rowIdx++); 261 | } 262 | 263 | } else if (diff != 0) { 264 | // we scrolled forwards or backwards within the tolerance that we can re-use some of what we have 265 | // Move our window so that we just re-use from back and place in front 266 | // children which were already there and contain correct data won't need changing 267 | int newBufferStart = (childBufferStart + diff) % childItems.Length; 268 | 269 | if (diff < 0) { 270 | // window moved backwards 271 | for (int i = 1; i <= -diff; ++i) { 272 | int bufi = WrapChildIndex(childBufferStart - i); 273 | int rowIdx = sourceDataRowStart - i; 274 | UpdateChild(childItems[bufi], rowIdx); 275 | } 276 | } else { 277 | // window moved forwards 278 | int prevLastBufIdx = childBufferStart + childItems.Length - 1; 279 | int prevLastRowIdx = sourceDataRowStart + childItems.Length - 1; 280 | for (int i = 1; i <= diff; ++i) { 281 | int bufi = WrapChildIndex(prevLastBufIdx + i); 282 | int rowIdx = prevLastRowIdx + i; 283 | UpdateChild(childItems[bufi], rowIdx); 284 | } 285 | } 286 | 287 | sourceDataRowStart = newRowStart; 288 | childBufferStart = newBufferStart; 289 | } 290 | 291 | } 292 | 293 | private int WrapChildIndex(int idx) { 294 | while (idx < 0) 295 | idx += childItems.Length; 296 | 297 | return idx % childItems.Length; 298 | } 299 | 300 | private float RowHeight() { 301 | return RowPadding + ChildPrefab.RectTransform.rect.height; 302 | } 303 | 304 | private float ViewportHeight() { 305 | return scrollRect.viewport.rect.height; 306 | } 307 | 308 | protected virtual void UpdateChild(RecyclingListViewItem child, int rowIdx) { 309 | if (rowIdx < 0 || rowIdx >= rowCount) { 310 | // Out of range of data, can happen 311 | child.gameObject.SetActive(false); 312 | } else { 313 | if (ItemCallback == null) { 314 | Debug.Log("RecyclingListView is missing an ItemCallback, cannot function", this); 315 | return; 316 | } 317 | 318 | // Move to correct location 319 | var childRect = ChildPrefab.RectTransform.rect; 320 | Vector2 pivot = ChildPrefab.RectTransform.pivot; 321 | float ytoppos = RowHeight() * rowIdx; 322 | float ypos = ytoppos + (1f - pivot.y) * childRect.height; 323 | float xpos = 0 + pivot.x * childRect.width; 324 | child.RectTransform.anchoredPosition = new Vector2(xpos, -ypos); 325 | child.NotifyCurrentAssignment(this, rowIdx); 326 | 327 | // Populate data 328 | ItemCallback(child, rowIdx); 329 | 330 | child.gameObject.SetActive(true); 331 | } 332 | } 333 | 334 | protected virtual void UpdateContentHeight() { 335 | float height = ChildPrefab.RectTransform.rect.height * rowCount + (rowCount-1) * RowPadding; 336 | // apparently 'sizeDelta' is the way to set w / h 337 | var sz = scrollRect.content.sizeDelta; 338 | scrollRect.content.sizeDelta = new Vector2(sz.x, height); 339 | } 340 | 341 | protected virtual void DisableAllChildren() { 342 | if (childItems != null) { 343 | for (int i = 0; i < childItems.Length; ++i) { 344 | childItems[i].gameObject.SetActive(false); 345 | } 346 | } 347 | } 348 | 349 | 350 | } 351 | -------------------------------------------------------------------------------- /Source/RecyclingListView.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3994d7f124d44369a0dc83c6951888e5 3 | timeCreated: 1570013482 -------------------------------------------------------------------------------- /Source/RecyclingListViewItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | /// 5 | /// You should subclass this to provide fast access to any data you need to populate 6 | /// this item on demand. 7 | /// 8 | [RequireComponent(typeof(RectTransform))] 9 | public class RecyclingListViewItem : MonoBehaviour { 10 | 11 | private RecyclingListView parentList; 12 | public RecyclingListView ParentList { 13 | get => parentList; 14 | } 15 | 16 | private int currentRow; 17 | public int CurrentRow { 18 | get => currentRow; 19 | } 20 | 21 | private RectTransform rectTransform; 22 | public RectTransform RectTransform { 23 | get { 24 | if (rectTransform == null) 25 | rectTransform = GetComponent(); 26 | return rectTransform; 27 | } 28 | } 29 | 30 | private void Awake() { 31 | rectTransform = GetComponent(); 32 | } 33 | 34 | public void NotifyCurrentAssignment(RecyclingListView v, int row) { 35 | parentList = v; 36 | currentRow = row; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Source/RecyclingListViewItem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 336f7191f0ed4820a1844d9c3c253a37 3 | timeCreated: 1570014067 -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sinbad/UnityRecyclingListView/82b491219cb35b3c24dee486285a74e1512706a9/demo.gif --------------------------------------------------------------------------------