Scriptable Data & Events

This commit is contained in:
max 2021-12-22 12:53:49 +01:00
parent be3af5cba7
commit 10d751c21e
57 changed files with 746 additions and 146 deletions

View File

@ -1,6 +1,5 @@
# Change Log:
## 0.1.0
## 1.0.0
- Start Project:
- ...
- Base project.

7
CHANGELOG.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3d077b5779f81994097715ac0982a56e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,16 +0,0 @@
{
"name": "COMPANYNAME.PACKAGENAME.Editor",
"references": [
"COMPANYNAME.PACKAGENAME"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
}

View File

@ -1,6 +0,0 @@
using UnityEngine;
using UnityEditor;
namespace COMPANYNAME.PACKAGENAME.Editor
{
}

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 COMPANYNAME
Copyright (c) 2021 Max Kruf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

7
LICENSE.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3f1cf957ba3177244ae054de6f577495
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,14 +1,43 @@
# [COMPANYNAME]() - PACKAGENAME
Description.
# ScriptableData
## Data
ScriptableData stores runtime data to be accessed by scripts that reference the ScriptableObject. It has a OnValueChangedEvent to subscribe when data changes.
With this workflow you can remove dependencies and increase flexibility.
### Extendable Data:
```C#
public class ScriptableData<T0> : ScriptableObject {}
public class ScriptableData<T0, T1> : ScriptableObject {}
public class ScriptableData<T0, T1, T2> : ScriptableObject {}
public class ScriptableData<T0, T1, T2, T3> : ScriptableObject {}
```
### Example:
```C#
[CreateAssetMenu(menuName = "ScriptableData/Data/Vector3", order = 147)]
public class SDVector3 : ScriptableData<Vector3> {}
```
## Events
ScriptableEvent does not contain any runtime data but can be used to send events (with data) around.
### Base Event
```C#
[CreateAssetMenu(menuName = "ScriptableData/Event/Event", order = 147)]
public class ScriptableEvent : ScriptableObject {}
```
### Extendable Events:
```C#
public class ScriptableEvent<T0> : ScriptableObject {}
public class ScriptableEvent<T0, T1> : ScriptableObject {}
public class ScriptableEvent<T0, T1, T2> : ScriptableObject {}
public class ScriptableEvent<T0, T1, T2, T3> : ScriptableObject {}
```
### Example:
```C#
[CreateAssetMenu(menuName = "ScriptableData/Event/Vector3", order = 147)]
public class SEVector3 : ScriptableEvent<Vector3> {}
```
## Install
[Installing from a Git URL](https://docs.unity3d.com/Manual/upm-ui-giturl.html)
[Unitypackage](https://github.com/COMPANYNAME/PACKAGENAME/releases)
[Unitypackage](https://github.com/maxartz15/ScriptableData/releases)
## LICENSE
Overall package is licensed under [MIT](/LICENSE.md), unless otherwise noted in the [3rd party licenses](/THIRD%20PARTY%20NOTICES.md) file and/or source code.

7
README.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8d70691f088be874a969b026fa3eb74b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime.meta Normal file
View File

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

View File

@ -1,5 +0,0 @@
using UnityEngine;
namespace COMPANYNAME.PACKAGENAME
{
}

255
Runtime/ScriptableData.cs Normal file
View File

@ -0,0 +1,255 @@
using System;
using UnityEngine;
namespace ScriptableData
{
public class ScriptableData<T0> : ScriptableObject
{
public event Action<T0> OnValueChangedEvent;
private T0 _value;
public T0 Value
{
get
{
return _value;
}
set
{
_value = value;
OnValueChangedEvent?.Invoke(_value);
}
}
public void SetWithoutNotify(T0 value)
{
_value = value;
}
public void Invoke(T0 value)
{
_value = value;
OnValueChangedEvent?.Invoke(value);
}
}
public class ScriptableData<T0, T1> : ScriptableObject
{
public event Action<T0, T1> OnValueChangedEvent;
private T0 _value;
public T0 Value
{
get
{
return _value;
}
set
{
_value = value;
OnValueChangedEvent?.Invoke(_value, _value1);
}
}
private T1 _value1;
public T1 Value1
{
get
{
return _value1;
}
set
{
_value1 = value;
OnValueChangedEvent?.Invoke(_value, _value1);
}
}
public void SetWithoutNotify(T0 value)
{
_value = value;
}
public void SetWithoutNotify(T0 value, T1 value1)
{
_value = value;
_value1 = value1;
}
public void Invoke(T0 value, T1 value1)
{
Value = value;
Value1 = value1;
OnValueChangedEvent?.Invoke(value, value1);
}
}
public class ScriptableData<T0, T1, T2> : ScriptableObject
{
public event Action<T0, T1, T2> OnValueChangedEvent;
private T0 _value;
public T0 Value
{
get
{
return _value;
}
set
{
_value = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2);
}
}
private T1 _value1;
public T1 Value1
{
get
{
return _value1;
}
set
{
_value1 = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2);
}
}
private T2 _value2;
public T2 Value2
{
get
{
return _value2;
}
set
{
_value2 = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2);
}
}
public void SetWithoutNotify(T0 value)
{
_value = value;
}
public void SetWithoutNotify(T0 value, T1 value1)
{
_value = value;
_value1 = value1;
}
public void SetWithoutNotify(T0 value, T1 value1, T2 value2)
{
_value = value;
_value1 = value1;
_value2 = value2;
}
public void Invoke(T0 value, T1 value1, T2 value2)
{
Value = value;
Value1 = value1;
Value2 = value2;
OnValueChangedEvent?.Invoke(value, value1, value2);
}
}
public class ScriptableData<T0, T1, T2, T3> : ScriptableObject
{
public event Action<T0, T1, T2, T3> OnValueChangedEvent;
private T0 _value;
public T0 Value
{
get
{
return _value;
}
set
{
_value = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2, _value3);
}
}
private T1 _value1;
public T1 Value1
{
get
{
return _value1;
}
set
{
_value1 = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2, _value3);
}
}
private T2 _value2;
public T2 Value2
{
get
{
return _value2;
}
set
{
_value2 = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2, _value3);
}
}
private T3 _value3;
public T3 Value3
{
get
{
return _value3;
}
set
{
_value3 = value;
OnValueChangedEvent?.Invoke(_value, _value1, _value2, _value3);
}
}
public void SetWithoutNotify(T0 value)
{
_value = value;
}
public void SetWithoutNotify(T0 value, T1 value1)
{
_value = value;
_value1 = value1;
}
public void SetWithoutNotify(T0 value, T1 value1, T2 value2)
{
_value = value;
_value1 = value1;
_value2 = value2;
}
public void SetWithoutNotify(T0 value, T1 value1, T2 value2, T3 value3)
{
_value = value;
_value1 = value1;
_value2 = value2;
_value3 = value3;
}
public void Invoke(T0 value, T1 value1, T2 value2, T3 value3)
{
Value = value;
Value1 = value1;
Value2 = value2;
Value3 = value3;
OnValueChangedEvent?.Invoke(value, value1, value2, value3);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db3264973431f63458697af52994bf57
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,56 @@
using System;
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Event", order = 147)]
public class ScriptableEvent : ScriptableObject
{
public event Action OnScriptableEvent;
public void Invoke()
{
OnScriptableEvent?.Invoke();
}
}
public class ScriptableEvent<T0> : ScriptableObject
{
public event Action<T0> OnScriptableEvent;
public void Invoke(T0 value)
{
OnScriptableEvent?.Invoke(value);
}
}
public class ScriptableEvent<T0, T1> : ScriptableObject
{
public event Action<T0, T1> OnScriptableEvent;
public void Invoke(T0 value, T1 value1)
{
OnScriptableEvent?.Invoke(value, value1);
}
}
public class ScriptableEvent<T0, T1, T2> : ScriptableObject
{
public event Action<T0, T1, T2> OnScriptableEvent;
public void Invoke(T0 value, T1 value1, T2 value2)
{
OnScriptableEvent?.Invoke(value, value1, value2);
}
}
public class ScriptableEvent<T0, T1, T2, T3> : ScriptableObject
{
public event Action<T0, T1, T2, T3> OnScriptableEvent;
public void Invoke(T0 value, T1 value1, T2 value2, T3 value3)
{
OnScriptableEvent?.Invoke(value, value1, value2, value3);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19a385034782e5145827449109c29d63
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,6 @@
{
"name": "COMPANYNAME.PACKAGENAME",
"name": "VertexColor.ScriptableData",
"rootNamespace": "ScriptableData",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
@ -8,5 +9,6 @@
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: bd2fa452e376b7e4e8356eed741e5eea
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Samples~/BaseTypes.meta Normal file
View File

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

View File

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

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/Bool", order = 146)]
public class SDBool : ScriptableData<bool> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ead1cfb6b7922e40b6a4caa0efbae67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/Float", order = 146)]
public class SDFloat : ScriptableData<float> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 917e540fe8be80f4f9274e1e998d9329
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/GameObject", order = 146)]
public class SDGameObject : ScriptableData<GameObject> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6dc28fb2198d394fa5a174cfba52560
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/Int", order = 146)]
public class SDInt : ScriptableData<int> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a77d994ca5c579449ba30e60316b47e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/Quaternion", order = 146)]
public class SDQuaternion : ScriptableData<Quaternion> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e9a8c28baf804d34195d0c31032dbabd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/Transform", order = 146)]
public class SDQTransform : ScriptableData<Transform> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8ff1e93cfb8df9443806844756073a85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/SDVector3", order = 146)]
public class SDVector3 : ScriptableData<Vector3> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 136f21e7e95b1e342aa7fbf8570b4fd0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Bool", order = 147)]
public class SEBool : ScriptableEvent<bool> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4aec005e72ed5c4ea8a5fd1e56d47da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Float", order = 147)]
public class SEFloat : ScriptableEvent<float> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d1ce65d6edd49e4c994ca41da2916c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/GameObject", order = 147)]
public class SEGameObject : ScriptableEvent<GameObject> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 727a58c71e459eb42b6acd8b499b05d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Int", order = 147)]
public class SEInt : ScriptableEvent<int> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a0c983892a2cdb4393e8b8ba67b458e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Quaternion", order = 147)]
public class SEQuaternion : ScriptableEvent<Quaternion> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7493b17fc08fc674d904c9cfc5370e7e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Transform", order = 147)]
public class SETransform : ScriptableEvent<Transform> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8945c026d7d76de4892a766db77a4b6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/Vector3", order = 147)]
public class SEVector3 : ScriptableEvent<Vector3> { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53c4d0f2b581bcd4aad2fd9f5dbb05d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
Types can be anything: classes, structs etc.
Replace {TYPE} with your type.
Data:
```C#
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Data/{TYPE}", order = 146)]
public class SD{TYPE} : ScriptableData<{TYPE}> { }
}
```
Events:
```C#
using UnityEngine;
namespace ScriptableData
{
[CreateAssetMenu(menuName = "ScriptableData/Event/{TYPE}", order = 147)]
public class SE{TYPE} : ScriptableEvent<{TYPE}> {}
}
```

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f5d5f3d545025a4479b8026b61e29c3e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,2 +0,0 @@
This is just a template package with a template sample folder structure.
Import of this example file is successful!

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 79a45fd43a13f2b4e9e0bf907986bdb6
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,20 +0,0 @@
{
"name": "COMPANYNAME.PACKAGENAME.Editor.Tests",
"references": [
"COMPANYNAME.PACKAGENAME",
"COMPANYNAME.PACKAGENAME.Editor"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"optionalUnityReferences": [
"TestAssemblies"
]
}

View File

@ -1,26 +0,0 @@
using UnityEngine;
using UnityEngine.TestTools;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
namespace COMPANYNAME.PACKAGENAME.Editor.Tests
{
public class TestEditorExample
{
[Test]
public void TestEditorExampleSimplePasses()
{
// Use the Assert class to test conditions
}
[UnityTest]
public IEnumerator TestEditorExampleWithEnumeratorPasses()
{
// Use the Assert class to test conditions.
// Use yield to skip a frame.
yield return null;
}
}
}

View File

@ -1,17 +0,0 @@
{
"name": "COMPANYNAME.PACKAGENAME.Tests",
"references": [
"COMPANYNAME.PACKAGENAME"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"optionalUnityReferences": [
"TestAssemblies"
]
}

View File

@ -1,25 +0,0 @@
using UnityEngine;
using UnityEngine.TestTools;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
namespace COMPANYNAME.PACKAGENAME.Tests
{
public class TestRuntimeExample
{
[Test]
public void TestRuntimeExampleSimplePasses()
{
// Use the Assert class to test conditions
}
[UnityTest]
public IEnumerator TestRuntimeExampleEnumeratorPasses()
{
// Use the Assert class to test conditions.
// Use yield to skip a frame.
yield return null;
}
}
}

View File

@ -1,30 +1,27 @@
{
"name": "com.COMPANYNAME.PACKAGENAME",
"displayName": "Template Unity Package",
"version": "0.1.0",
"unity": "2019.3",
"unityRelease": "7f1",
"description": "This is a template package, used as a basis to build a bigger one.",
"name": "com.vertexcolor.scriptabledata",
"displayName": "ScriptableData",
"version": "1.0.0",
"unity": "2019.1",
"description": "ScriptableData code base for ScriptableObject workflow.",
"category": "Tool",
"type": "tool",
"type": "library",
"license": "MIT",
"author": {
"name": "Max Kruf",
"email": "info@maxartz15.com",
"url": "https://www.maxartz15.com"
},
"dependencies": {
"com.maxartz15.package1": "0.1.0"
},
"keywords": [
"COMPANYNAME",
"PACKAGENAME"
"ScriptableObject",
"ScriptableData",
"ScriptableEvent"
],
"samples": [
{
"displayName": "Example 1",
"description": "This sample is just an example",
"path": "Samples~/Example1"
"displayName": "BaseTypes",
"description": "ScriptableData base types",
"path": "Samples~/BaseTypes"
}
]
}
}

7
package.json.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f48ddd375aee7dd459a643aed1951997
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: