当前提交
b5f3779d
共有 167 个文件被更改,包括 3542 次插入 和 0 次删除
-
8Assets/Scenes.meta
-
206Assets/Scenes/SampleScene.unity
-
7Assets/Scenes/SampleScene.unity.meta
-
8Assets/Scripts.meta
-
8Assets/Scripts/Utilities.meta
-
242LocalPackages/com.unity.services.rooms/.README - External.md
-
610LocalPackages/com.unity.services.rooms/.README-PACKAGE.md
-
2LocalPackages/com.unity.services.rooms/.github/CODEOWNERS
-
12LocalPackages/com.unity.services.rooms/.gitignore
-
19LocalPackages/com.unity.services.rooms/.npmignore
-
13LocalPackages/com.unity.services.rooms/.yamato/package-pack.yml
-
66LocalPackages/com.unity.services.rooms/.yamato/package-promotion.yml
-
40LocalPackages/com.unity.services.rooms/.yamato/package-publish.yml
-
82LocalPackages/com.unity.services.rooms/.yamato/package-test.yml
-
11LocalPackages/com.unity.services.rooms/CHANGELOG.md
-
7LocalPackages/com.unity.services.rooms/CHANGELOG.md.meta
-
9LocalPackages/com.unity.services.rooms/CONTRIBUTING.md
-
7LocalPackages/com.unity.services.rooms/CONTRIBUTING.md.meta
-
33LocalPackages/com.unity.services.rooms/Documentation~/com.unity.services.rooms.md
-
8LocalPackages/com.unity.services.rooms/Editor.meta
-
6LocalPackages/com.unity.services.rooms/LICENSE.md
-
7LocalPackages/com.unity.services.rooms/LICENSE.md.meta
-
26LocalPackages/com.unity.services.rooms/QAReport.md
-
7LocalPackages/com.unity.services.rooms/QAReport.md.meta
-
46LocalPackages/com.unity.services.rooms/README.md
-
7LocalPackages/com.unity.services.rooms/README.md.meta
-
8LocalPackages/com.unity.services.rooms/Runtime.meta
-
8LocalPackages/com.unity.services.rooms/Runtime/Apis.meta
-
70LocalPackages/com.unity.services.rooms/Runtime/Apis/RoomsApi.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Apis/RoomsApi.cs.meta
-
697LocalPackages/com.unity.services.rooms/Runtime/Apis/RoomsApiRequests.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Apis/RoomsApiRequests.cs.meta
-
8LocalPackages/com.unity.services.rooms/Runtime/Configuration.meta
-
13LocalPackages/com.unity.services.rooms/Runtime/Configuration/Configuration.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Configuration/Configuration.cs.meta
-
8LocalPackages/com.unity.services.rooms/Runtime/Http.meta
-
109LocalPackages/com.unity.services.rooms/Runtime/Http/AsyncOpRetry.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/AsyncOpRetry.cs.meta
-
15LocalPackages/com.unity.services.rooms/Runtime/Http/BaseApiClient.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/BaseApiClient.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Http/BasicError.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/BasicError.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Http/CommonErrors.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/CommonErrors.cs.meta
-
28LocalPackages/com.unity.services.rooms/Runtime/Http/DeserializationException.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/DeserializationException.cs.meta
-
184LocalPackages/com.unity.services.rooms/Runtime/Http/HttpClient.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/HttpClient.cs.meta
-
26LocalPackages/com.unity.services.rooms/Runtime/Http/HttpClientResponse.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/HttpClientResponse.cs.meta
-
28LocalPackages/com.unity.services.rooms/Runtime/Http/HttpException.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/HttpException.cs.meta
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/IError.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/IError.cs.meta
-
16LocalPackages/com.unity.services.rooms/Runtime/Http/IHttpClient.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/IHttpClient.cs.meta
-
23LocalPackages/com.unity.services.rooms/Runtime/Http/JsonHelpers.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/JsonHelpers.cs.meta
-
58LocalPackages/com.unity.services.rooms/Runtime/Http/ResponseHandler.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/ResponseHandler.cs.meta
-
27LocalPackages/com.unity.services.rooms/Runtime/Http/Responses.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/Responses.cs.meta
-
34LocalPackages/com.unity.services.rooms/Runtime/Http/UnityWebRequestHelpers.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Http/UnityWebRequestHelpers.cs.meta
-
8LocalPackages/com.unity.services.rooms/Runtime/Models.meta
-
45LocalPackages/com.unity.services.rooms/Runtime/Models/CreateRequest.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/CreateRequest.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Models/DataObject.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/DataObject.cs.meta
-
30LocalPackages/com.unity.services.rooms/Runtime/Models/Detail.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/Detail.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Models/ErrorStatus.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/ErrorStatus.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Models/JoinRequest.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/JoinRequest.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Models/Player.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/Player.cs.meta
-
30LocalPackages/com.unity.services.rooms/Runtime/Models/PlayerUpdateRequest.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/PlayerUpdateRequest.cs.meta
-
35LocalPackages/com.unity.services.rooms/Runtime/Models/QueryFilter.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/QueryFilter.cs.meta
-
30LocalPackages/com.unity.services.rooms/Runtime/Models/QueryRequest.cs
-
11LocalPackages/com.unity.services.rooms/Runtime/Models/QueryRequest.cs.meta
|
|||
fileFormatVersion: 2 |
|||
guid: 192ec0d70e2350c40aeba7d72c1b4081 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!29 &1 |
|||
OcclusionCullingSettings: |
|||
m_ObjectHideFlags: 0 |
|||
serializedVersion: 2 |
|||
m_OcclusionBakeSettings: |
|||
smallestOccluder: 5 |
|||
smallestHole: 0.25 |
|||
backfaceThreshold: 100 |
|||
m_SceneGUID: 00000000000000000000000000000000 |
|||
m_OcclusionCullingData: {fileID: 0} |
|||
--- !u!104 &2 |
|||
RenderSettings: |
|||
m_ObjectHideFlags: 0 |
|||
serializedVersion: 9 |
|||
m_Fog: 0 |
|||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} |
|||
m_FogMode: 3 |
|||
m_FogDensity: 0.01 |
|||
m_LinearFogStart: 0 |
|||
m_LinearFogEnd: 300 |
|||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} |
|||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} |
|||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} |
|||
m_AmbientIntensity: 1 |
|||
m_AmbientMode: 3 |
|||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} |
|||
m_SkyboxMaterial: {fileID: 0} |
|||
m_HaloStrength: 0.5 |
|||
m_FlareStrength: 1 |
|||
m_FlareFadeSpeed: 3 |
|||
m_HaloTexture: {fileID: 0} |
|||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} |
|||
m_DefaultReflectionMode: 0 |
|||
m_DefaultReflectionResolution: 128 |
|||
m_ReflectionBounces: 1 |
|||
m_ReflectionIntensity: 1 |
|||
m_CustomReflection: {fileID: 0} |
|||
m_Sun: {fileID: 0} |
|||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} |
|||
m_UseRadianceAmbientProbe: 0 |
|||
--- !u!157 &3 |
|||
LightmapSettings: |
|||
m_ObjectHideFlags: 0 |
|||
serializedVersion: 12 |
|||
m_GIWorkflowMode: 1 |
|||
m_GISettings: |
|||
serializedVersion: 2 |
|||
m_BounceScale: 1 |
|||
m_IndirectOutputScale: 1 |
|||
m_AlbedoBoost: 1 |
|||
m_EnvironmentLightingMode: 0 |
|||
m_EnableBakedLightmaps: 0 |
|||
m_EnableRealtimeLightmaps: 0 |
|||
m_LightmapEditorSettings: |
|||
serializedVersion: 12 |
|||
m_Resolution: 2 |
|||
m_BakeResolution: 40 |
|||
m_AtlasSize: 1024 |
|||
m_AO: 0 |
|||
m_AOMaxDistance: 1 |
|||
m_CompAOExponent: 1 |
|||
m_CompAOExponentDirect: 0 |
|||
m_ExtractAmbientOcclusion: 0 |
|||
m_Padding: 2 |
|||
m_LightmapParameters: {fileID: 0} |
|||
m_LightmapsBakeMode: 1 |
|||
m_TextureCompression: 1 |
|||
m_FinalGather: 0 |
|||
m_FinalGatherFiltering: 1 |
|||
m_FinalGatherRayCount: 256 |
|||
m_ReflectionCompression: 2 |
|||
m_MixedBakeMode: 2 |
|||
m_BakeBackend: 0 |
|||
m_PVRSampling: 1 |
|||
m_PVRDirectSampleCount: 32 |
|||
m_PVRSampleCount: 500 |
|||
m_PVRBounces: 2 |
|||
m_PVREnvironmentSampleCount: 500 |
|||
m_PVREnvironmentReferencePointCount: 2048 |
|||
m_PVRFilteringMode: 2 |
|||
m_PVRDenoiserTypeDirect: 0 |
|||
m_PVRDenoiserTypeIndirect: 0 |
|||
m_PVRDenoiserTypeAO: 0 |
|||
m_PVRFilterTypeDirect: 0 |
|||
m_PVRFilterTypeIndirect: 0 |
|||
m_PVRFilterTypeAO: 0 |
|||
m_PVREnvironmentMIS: 0 |
|||
m_PVRCulling: 1 |
|||
m_PVRFilteringGaussRadiusDirect: 1 |
|||
m_PVRFilteringGaussRadiusIndirect: 5 |
|||
m_PVRFilteringGaussRadiusAO: 2 |
|||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5 |
|||
m_PVRFilteringAtrousPositionSigmaIndirect: 2 |
|||
m_PVRFilteringAtrousPositionSigmaAO: 1 |
|||
m_ExportTrainingData: 0 |
|||
m_TrainingDataDestination: TrainingData |
|||
m_LightProbeSampleCountMultiplier: 4 |
|||
m_LightingDataAsset: {fileID: 0} |
|||
m_LightingSettings: {fileID: 0} |
|||
--- !u!196 &4 |
|||
NavMeshSettings: |
|||
serializedVersion: 2 |
|||
m_ObjectHideFlags: 0 |
|||
m_BuildSettings: |
|||
serializedVersion: 2 |
|||
agentTypeID: 0 |
|||
agentRadius: 0.5 |
|||
agentHeight: 2 |
|||
agentSlope: 45 |
|||
agentClimb: 0.4 |
|||
ledgeDropHeight: 0 |
|||
maxJumpAcrossDistance: 0 |
|||
minRegionArea: 2 |
|||
manualCellSize: 0 |
|||
cellSize: 0.16666667 |
|||
manualTileSize: 0 |
|||
tileSize: 256 |
|||
accuratePlacement: 0 |
|||
debug: |
|||
m_Flags: 0 |
|||
m_NavMeshData: {fileID: 0} |
|||
--- !u!1 &519420028 |
|||
GameObject: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
serializedVersion: 6 |
|||
m_Component: |
|||
- component: {fileID: 519420032} |
|||
- component: {fileID: 519420031} |
|||
- component: {fileID: 519420029} |
|||
m_Layer: 0 |
|||
m_Name: Main Camera |
|||
m_TagString: MainCamera |
|||
m_Icon: {fileID: 0} |
|||
m_NavMeshLayer: 0 |
|||
m_StaticEditorFlags: 0 |
|||
m_IsActive: 1 |
|||
--- !u!81 &519420029 |
|||
AudioListener: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 519420028} |
|||
m_Enabled: 1 |
|||
--- !u!20 &519420031 |
|||
Camera: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 519420028} |
|||
m_Enabled: 1 |
|||
serializedVersion: 2 |
|||
m_ClearFlags: 2 |
|||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} |
|||
m_projectionMatrixMode: 1 |
|||
m_GateFitMode: 2 |
|||
m_FOVAxisMode: 0 |
|||
m_SensorSize: {x: 36, y: 24} |
|||
m_LensShift: {x: 0, y: 0} |
|||
m_FocalLength: 50 |
|||
m_NormalizedViewPortRect: |
|||
serializedVersion: 2 |
|||
x: 0 |
|||
y: 0 |
|||
width: 1 |
|||
height: 1 |
|||
near clip plane: 0.3 |
|||
far clip plane: 1000 |
|||
field of view: 60 |
|||
orthographic: 1 |
|||
orthographic size: 5 |
|||
m_Depth: -1 |
|||
m_CullingMask: |
|||
serializedVersion: 2 |
|||
m_Bits: 4294967295 |
|||
m_RenderingPath: -1 |
|||
m_TargetTexture: {fileID: 0} |
|||
m_TargetDisplay: 0 |
|||
m_TargetEye: 0 |
|||
m_HDR: 1 |
|||
m_AllowMSAA: 0 |
|||
m_AllowDynamicResolution: 0 |
|||
m_ForceIntoRT: 0 |
|||
m_OcclusionCulling: 0 |
|||
m_StereoConvergence: 10 |
|||
m_StereoSeparation: 0.022 |
|||
--- !u!4 &519420032 |
|||
Transform: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 519420028} |
|||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |
|||
m_LocalPosition: {x: 0, y: 0, z: -10} |
|||
m_LocalScale: {x: 1, y: 1, z: 1} |
|||
m_Children: [] |
|||
m_Father: {fileID: 0} |
|||
m_RootOrder: 0 |
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2cda990e2423bbf4892e6590ba056729 |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: ed8aede70f63ef4468f734db0471ed1b |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 4e59a0c0ec4227344bcc4a4f79c8ac31 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# UPM Package Starter Kit |
|||
|
|||
The purpose of this starter kit is to provide the data structure and development guidelines for new packages meant for the **Unity Package Manager (UPM)**. |
|||
|
|||
## Are you ready to become a package? |
|||
The Package Manager is a work-in-progress for Unity and, in that sense, there are a few criteria that must be met for your package to be considered on the package list at this time: |
|||
- **Your code accesses public Unity C# APIs only.** If you have a native code component, it will need to ship with an official editor release. Internal API access might eventually be possible for Unity made packages, but not at this time. |
|||
- **Your code doesn't require security, obfuscation, or conditional access control.** Anyone should be able to download your package and access the source code. |
|||
|
|||
|
|||
## Package structure |
|||
|
|||
```none |
|||
<root> |
|||
├── package.json |
|||
├── README.md |
|||
├── CHANGELOG.md |
|||
├── LICENSE.md |
|||
├── Third Party Notices.md |
|||
├── QAReport.md |
|||
├── Editor |
|||
│ ├── Unity.[YourPackageName].Editor.asmdef |
|||
│ └── EditorExample.cs |
|||
├── Runtime |
|||
│ ├── Unity.[YourPackageName].asmdef |
|||
│ └── RuntimeExample.cs |
|||
├── Tests |
|||
│ ├── .tests.json |
|||
│ ├── Editor |
|||
│ │ ├── Unity.[YourPackageName].Editor.Tests.asmdef |
|||
│ │ └── EditorExampleTest.cs |
|||
│ └── Runtime |
|||
│ ├── Unity.[YourPackageName].Tests.asmdef |
|||
│ └── RuntimeExampleTest.cs |
|||
├── Samples |
|||
│ └── Example |
|||
│ ├── .sample.json |
|||
│ └── SampleExample.cs |
|||
└── Documentation~ |
|||
├── your-package-name.md |
|||
└── Images |
|||
``` |
|||
|
|||
## Develop your package |
|||
Package development works best within the Unity Editor. Here's how to set that up: |
|||
|
|||
1. Start **Unity**, create a local empty project. |
|||
|
|||
1. In a console (or terminal) application, go to the newly created project folder, then copy the contents of this starter kit into the packages directory. |
|||
__Note:__ Your directory name must be the name of your package (Example: `"com.unity.terrain-builder"`) |
|||
|
|||
1. ##### Fill in your package information |
|||
|
|||
Update the following required fields in file **package.json**: |
|||
- `"name"`: Package name, it should follow this naming convention: `"com.[YourCompanyName].[sub-group].[your-package-name]"` |
|||
(Example: `"com.unity.2d.animation"`, where `sub-group` should match the sub-group you selected in Gitlab) |
|||
- `"displayName"`: Package user friendly display name. (Example: `"Terrain Builder SDK"`). <br>__Note:__ Use a display name that will help users understand what your package is intended for. |
|||
- `"version"`: Package version `"X.Y.Z"`, your project **must** adhere to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). |
|||
Follow this guideline: |
|||
- To introduce a new feature or bug fix, increment the minor version (X.**Y**.Z) |
|||
- To introduce a breaking API change, increment the major version (**X**.Y.Z) |
|||
- The patch version (X.Y.**Z**), is reserved for sustainable engineering use only. |
|||
- `"unity"`: Unity Version your package is compatible with. (Example: `"2018.1"`) |
|||
- `"description"`: This description appears in the Package Manager window when the user selects this package from the list. For best results, use this text to summarize what the package does and how it can benefit the user.<br>__Note:__ Special formatting characters are supported, including line breaks (`\n`) and unicode characters such as bullets (`\u25AA`).<br> |
|||
|
|||
Update the following recommended fields in file **package.json**: |
|||
- `"dependencies"`: List of packages this package depends on. All dependencies will also be downloaded and loaded in a project with your package. Here's an example: |
|||
``` |
|||
dependencies: { |
|||
"com.unity.ads": "1.0.0" |
|||
"com.unity.analytics": "2.0.0" |
|||
} |
|||
``` |
|||
- `"keywords"`: List of words that will be indexed by the package manager search engine to facilitate discovery. |
|||
|
|||
Update the following field in file **Tests/.tests.json**: |
|||
- `"createSeparatePackage"`: If this is set to true, the CI will create a separate package for these tests. If you leave it set to false, the tests will remain part of the published package. If you set it to true, the tests in your package will automatically be moved to a separate package, and metadata will be added at publish time to link the packages together. This allows you to have a large number of tests, or assets, etc. that you don't want to include in your main package, while making it easy to test your package with those tests & fixtures. |
|||
|
|||
1. You should now see your package in the Project Window, along with all other available packages for your project. |
|||
|
|||
1. ##### Rename and update assembly definition files. |
|||
|
|||
Assembly definition files are used to generate C# assemblies during compilation. Package code must include asmdef files to ensure package code isolation. You can read up on assembly definition files [here](https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html). |
|||
|
|||
If your package contains Editor code, rename and modify [Editor/Unity.YourPackageName.Editor.asmdef](Editor/Unity.YourPackageName.Editor.asmdef). Otherwise, delete the Editor directory. |
|||
* Name **must** match your package name, suffixed by `.Editor` (i.e `Unity.[YourPackageName].Editor`) |
|||
* Assembly **must** reference `Unity.[YourPackageName]` (if you have any Runtime) |
|||
* Platforms **must** include `"Editor"` |
|||
|
|||
If your package contains code that needs to be included in Unity runtime builds, rename and modify [Runtime/Unity.YourPackageName.asmdef](Runtime/Unity.YourPackageName.asmdef). Otherwise, delete the Runtime directory. |
|||
* Name **must** match your package name (i.e `Unity.[YourPackageName]`) |
|||
|
|||
If your package has Editor code, you **must** include Editor Tests in your package. In that case, rename and modify [Tests/Editor/Unity.YourPackageName.Editor.Tests.asmdef](Tests/Editor/Unity.YourPackageName.Editor.Tests.asmdef). |
|||
* Name **must** match your package name, suffixed by `.Editor.Tests` (i.e `Unity.[YourPackageName].Editor.Tests`) |
|||
* Assembly **must** reference `Unity.[YourPackageName].Editor` and `Unity.[YourPackageName]` (if you have any Runtime) |
|||
* Platforms **must** include `"Editor"` |
|||
* Optional Unity references **must** include `"TestAssemblies"` to allow your Editor Tests to show up in the Test Runner/run on Katana when your package is listed in project manifest `testables` |
|||
|
|||
If your package has Runtime code, you **must** include Playmode Tests in your package. In that case, rename and modify [Tests/Runtime/Unity.YourPackageName.Tests.asmdef](Tests/Runtime/Unity.YourPackageName.Tests.asmdef). |
|||
* Name **must** match your package name, suffixed by `.Tests` (i.e `Unity.[YourPackageName].Tests`) |
|||
* Assembly **must** reference `Unity.[YourPackageName]` |
|||
* Optional Unity references **must** include `"TestAssemblies"` to allow your Playmode Tests to show up in the Test Runner/run on Katana when your package is listed in project manifest `testables` |
|||
|
|||
> |
|||
> The reason for choosing such name schema is to ensure that the name of the assembly built based on *assembly definition file* (_a.k.a .asmdef_) will follow the .Net [Framework Design Guidelines](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/index) |
|||
|
|||
1. ##### Document your package. |
|||
|
|||
Rename and update **your-package-name.md** documentation file. Use this documentation template file to create preliminary, high-level documentation. This document is meant to introduce users to the features and sample files included in your package. Your package documentation files will be used to generate online and local docs, available from the package manager UI. |
|||
|
|||
**Document your public APIs** |
|||
* All public APIs need to be documented with XmlDoc. If you don't need an API to be accessed by clients, mark it as internal instead. |
|||
* API documentation is generated from [XmlDoc tags](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments) included with all public APIs found in the package. See [Editor/EditorExample.cs](Editor/EditorExample.cs) for an example. |
|||
|
|||
**Documentation flow** |
|||
* Documentation needs to be ready when a publish request is sent to Release Management, as they will ask the documentation team to review it. |
|||
* The package will remain in `preview` mode until the final documentation is completed. Users will have access to the developer-generated documentation only in preview packages. |
|||
* When the documentation is completed, the documentation team will update the package git repo with the updates and they will publish it on the web. |
|||
* The package's development team will then need to submit a new package version with updated docs. |
|||
* The starting page in the user manual that links to package documentation is [Here](https://docs.unity3d.com/Manual/PackagesList.html). |
|||
* The `Documentation~` folder is suffixed with `~` so that its content does not get loaded in the editor, which is the recommended behavior. If this is problematic, you can still name it `Documentation` and all tools will still work correctly. `.Documentation` is also supported. |
|||
|
|||
**Test your documentation locally** |
|||
As you are developing your documentation, you can see what your documentation will look like by using the DocTools extension (optional). |
|||
Once the DocTools package is installed, it will add a `Generate Documentation` button in the Package Manager UI's details of your installed packages. To install the extension, follow these steps: |
|||
|
|||
1. Make sure you have `Package Manager UI v1.9.6` or above. |
|||
1. Your project manifest will need to point to a staging registry for this, which you can do by adding this line to it: `"registry": "https://staging-packages.unity.com"` |
|||
1. Install `Package Manager DocTools v1.0.0-preview.6` or above from the `Package Manager UI` (in the `All Packages` section). |
|||
1. After installation, you will see a `Generate Documentation` button which will generate the documentation locally, and open a web browser to a locally served version of your documentation so you can preview it. |
|||
1. (optional) If your package documentation contains multiple `.md` files for the user manual, see [this page](https://docs.unity3d.com/Packages/com.unity.package-manager-doctools@1.0/manual/index.html#table-of-content) to add a table of content to your documentation. |
|||
|
|||
The DocTools extension is still in preview, if you come across arguable results, please discuss them on #docs-packman. |
|||
|
|||
1. ##### Add samples to your package (code & assets). |
|||
If your package contains a sample, rename the `Samples/Example` folder, and update the `.sample.json` file in it. |
|||
|
|||
In the case where your package contains multiple samples, you can make a copy of the `Samples/Example` folder for each sample, and update the `.sample.json` file accordingly. |
|||
|
|||
Similar to `.tests.json` file, there is a `"createSeparatePackage"` field in `.sample.json`.If set to true, the CI will create an separate package for the sample.. |
|||
|
|||
Delete the `Samples` folder altogether if your package does not need samples. |
|||
|
|||
As of Unity release 2019.1, the /Samples directory of a package will be recognized by the package manager. Samples will not be imported to Unity when the package is added to a project, but will instead be offered to users of the package as an optional import, which can be added to their "/Assets" directory through a UI option. |
|||
|
|||
1. ##### Validate your package. |
|||
|
|||
Before you publish your package, you need to make sure that it passes all the necessary validation checks by using the Package Validation Suite extension (optional). |
|||
Once the Validation Suite package is installed, it will add a `Validate` button in the Package Manager UI's details of your installed packages. To install the extension, follow these steps: |
|||
|
|||
1. Make sure you have `Package Manager UI v1.9.6` or above. |
|||
1. Your project manifest will need to point to a staging registry for this, which you can do by adding this line to it: `"registry": "https://staging-packages.unity.com"` |
|||
1. Install `Package Validation Suite v0.3.0-preview.13` or above from the `Package Manager UI` in the `All Packages` section. If you can't find it there, try turning on `Show preview packages` in the `Advanced` menu. |
|||
1. After installation, you will see a `Validate` button show up in the Package Manager UI, which, when pressed, will run a series of tests and expose a `See Results` button for additional explanation. |
|||
1. If it succeeds, you will see a green bar with a `Success` message. |
|||
1. If it fails, you will see a red bar with a `Failed` message. |
|||
|
|||
The validation suite is still in preview, if you come across arguable results, please discuss them on #release-management. |
|||
|
|||
1. ##### Add tests to your package. |
|||
|
|||
All packages must contain tests. Tests are essential for Unity to ensure that the package works as expected in different scenarios. |
|||
|
|||
**Editor tests** |
|||
* Write all your Editor Tests in `Tests/Editor` |
|||
|
|||
**Playmode Tests** |
|||
* Write all your Playmode Tests in `Tests/Runtime`. |
|||
|
|||
1. ##### Update **CHANGELOG.md**. |
|||
|
|||
Every new feature or bug fix should have a trace in this file. For more details on the chosen changelog format, see [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). |
|||
|
|||
## Create a Pre-Release Package |
|||
Pre-Release Packages are a great way of getting your features in front of Unity Developers in order to get early feedback on functionality and UI designs. Pre-Release packages need to go through the publishing to production flow, as would any other package, but with diminished requirements. Here are the supported Pre-Release tags (to be used in package.json,`version` field), along with the requirements for each one: |
|||
|
|||
**Preview** - ex: `"version" : "1.2.0-preview"` |
|||
* Expected Package structure respected |
|||
* Package loads in Unity Editor without errors |
|||
* License file present - With third party notices file if necessary |
|||
* Test coverage is good - Optional but preferred |
|||
* Public APIs documented, minimal feature docs exists- Optional but preferred |
|||
|
|||
## Make sure your package meets all legal requirements |
|||
|
|||
##### Update **Third Party Notices.md** & **License.md** |
|||
|
|||
1. If your package has third-party elements and its licenses are approved, then all the licenses must be added to the `Third Party Notices.md` file. Simply duplicate the `Component Name/License Type/Provide License Details` section if you have more then one licenes. |
|||
|
|||
a. Concerning `[Provide License Details]` in the `Third Party Notices.md`, a URL can work as long as it actually points to the reproduced license and the copyright information _(if applicable)_. |
|||
|
|||
1. If your package does not have third party elements, you can remove the `Third Party Notices.md` file from your package. |
|||
|
|||
## Preparing your package for Staging |
|||
|
|||
Before publishing your package to production, you must send your package on the Package Manager's **staging** repository. The staging repository is monitored by QA and release management, and is where package validation will take place before it is accepted in production. |
|||
## *** IMPORTANT: The staging repository is publicly accessible, do not publish any packages with sensitive material you aren't ready to share with the public *** |
|||
|
|||
|
|||
1. Publishing your changes to the package manager's **staging** repository happens from Gitlab. To do so, simply setup your project's Continuous integration, which will be triggered by "Tags" on your branches. |
|||
* Join the **#devs-packman** channel on Slack, and request a staging **USERNAME** and **API_KEY**. |
|||
* In Gitlab, under the **Settings-> CI/CD -> Secret Variables** section, setup the following 2 project variables: |
|||
* API_KEY = [your API KEY] |
|||
* USER_NAME = [your USER NAME@unity] |
|||
* You're almost done! To publish a version of your package, make sure all your changes are checked into Gitlab, then create a new tag to reflect the version you are publishing (ex. "v1.2.2"), **the tag will trigger a publish to Staging**. You can view progress you the publish request by switch over to the "CI / CD" part of your project. |
|||
|
|||
1. Do it yourself CI |
|||
|
|||
If you are using your own CI, it is still recommended that you use the `build.sh` wrapper script that comes with the starter kit, as it handle the installation of the actual CI build scripts for you. |
|||
|
|||
Instead of calling `npm pack` and `npm publish` in the package root folder in your CI, use |
|||
``` |
|||
./build.sh package-ci pack --git-head $CI_COMMIT_SHA --git-url $CI_REPOSITORY_URL |
|||
``` |
|||
and |
|||
``` |
|||
./build.sh package-ci publish --git-head $CI_COMMIT_SHA --git-url $CI_REPOSITORY_URL |
|||
``` |
|||
respectively. |
|||
|
|||
1. Test your package locally |
|||
|
|||
Now that your package is published on the package manager's **staging** repository, you can test your package in the editor by creating a new project, and editing the project's `manifest.json` file to point to your staging package, as such: |
|||
``` |
|||
dependencies: { |
|||
"com.[YourCompanyName].[sub-group].[your-package-name]": "0.1.0" |
|||
}, |
|||
"registry": "https://staging-packages.unity.com" |
|||
``` |
|||
|
|||
## Get your package published to Production |
|||
|
|||
Packages are promoted to the **production** repository from **staging**, described above. |
|||
|
|||
Once you feel comfortable that your package is ready for prime time, and passes validation (Validation Suite), reach out to Unity so your package can be passed along to Release Management, for evaluation. |
|||
|
|||
**Release management will validate your package content, and check that the editor/playmode tests are passed before promoting the package to production. You will receive a confirmation email once the package is in production.** |
|||
|
|||
**You're almost done!** |
|||
At this point, your package is available on the cloud, but not discoverable through the editor: |
|||
|
|||
1. Contact the Package Manager team to ask them to add your package to the list of discoverable package for the Unity Editor. All you need to provide is the package name (com.[YourCompanyName].[sub-group].[your-package-name]) |
|
|||
# UPM Package Starter Kit |
|||
|
|||
The purpose of this package starter kit is to provide the data structure and development guidelines for new packages meant for the **Unity Package Manager (UPM)**. |
|||
|
|||
This is the first of many steps towards an automated package publishing experience within Unity. This package starter kit is merely a fraction of the creation, edition, validation, and publishing tools that we will end up with. |
|||
|
|||
> **Note:** With 2021.1 and package lifecycle V2 we introduced [Unity Standards](https://github.cds.internal.unity3d.com/unity/standards/tree/2021.2), an initiative to help us build quality and consistency into our products from the start. This README contains cross-references to Unity Standards, which apply from 2021.1 and up. For more information, see the Scholar course [Working with Unity Standards](https://scholar.internal.unity3d.com/course/working-with-unity-standards). |
|||
|
|||
We hope you enjoy your experience. You can use **#devs-packman-tooling** and **#devs-packman-client** on Slack to provide feedback or ask questions regarding your package development efforts. |
|||
|
|||
|
|||
## Are you ready to become a package? |
|||
|
|||
The Package Manager is a work-in-progress for Unity and, in that sense, there are a few criteria that must be met for your package to be considered on the package list at this time: |
|||
|
|||
- **Your code accesses public Unity C# APIs only.** If you have a native code component, it will need to ship with an official editor release. Internal API access might eventually be possible for Unity made packages, but not at this time. |
|||
|
|||
- **Your code doesn't require security, obfuscation, or conditional access control.** Anyone should be able to download your package and access the source code. |
|||
|
|||
|
|||
## Package structure |
|||
|
|||
```none |
|||
<root> |
|||
├── package.json |
|||
├── README.md |
|||
├── CHANGELOG.md |
|||
├── LICENSE.md |
|||
├── Third Party Notices.md |
|||
├── QAReport.md |
|||
├── Editor |
|||
│ ├── Unity.[YourPackageName].Editor.asmdef |
|||
│ └── EditorExample.cs |
|||
├── Runtime |
|||
│ ├── Unity.[YourPackageName].asmdef |
|||
│ └── RuntimeExample.cs |
|||
├── Tests |
|||
│ ├── .tests.json |
|||
│ ├── Editor |
|||
│ │ ├── Unity.[YourPackageName].Editor.Tests.asmdef |
|||
│ │ └── EditorExampleTest.cs |
|||
│ └── Runtime |
|||
│ ├── Unity.[YourPackageName].Tests.asmdef |
|||
│ └── RuntimeExampleTest.cs |
|||
├── Samples |
|||
│ └── Example |
|||
│ ├── .sample.json |
|||
│ └── SampleExample.cs |
|||
└── Documentation~ |
|||
├── your-package-name.md |
|||
└── Images |
|||
``` |
|||
|
|||
## Develop your package |
|||
|
|||
Package development works best within the Unity Editor. Here's how to set that up: |
|||
|
|||
1. Clone the Package Starter Kit repository locally. |
|||
|
|||
- In a console (or terminal) application, choose a place to clone the repository and enter the following: |
|||
|
|||
``` |
|||
git clone git@github.cds.internal.unity3d.com:unity/com.unity.package-starter-kit.git |
|||
``` |
|||
|
|||
2. Create a new repository for your package and clone to your desktop. |
|||
|
|||
- On Github.cds create a new repository with the name of your package (Example: `"com.unity.terrain-builder"`). |
|||
|
|||
- In a console (or terminal) application, choose a place to clone the repository and perform the following: |
|||
|
|||
``` |
|||
git clone git@github.cds.internal.unity3d.com:unity/com.unity.[sub-group].[your-package-name] |
|||
``` |
|||
|
|||
__Note:__ `sub-group` here means product area (if possible; ex: xr, rendering, ui) and not org/dept within the company (i.e. don't [ship the org chart](https://en.wikipedia.org/wiki/Conway%27s_law)) |
|||
|
|||
> **Applicable Unity Standards:** |
|||
> [US-0002](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0002/US-0002.md), |
|||
> [US-0003](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0003/US-0003.md), |
|||
> [US-0005](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0005/US-0005.md), |
|||
> [US-0006](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0006/US-0006.md), |
|||
> [US-0017](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0017/US-0017.md) |
|||
|
|||
3. Copy the contents of the Package Starter Kit folder to your new package. Be careful not to copy the Package Starter Kit *.git* folder over. |
|||
|
|||
4. **Fill in your package information.** |
|||
|
|||
Follow the instructions for [filling out your package manifest](#fill-out-your-package-manifest) (*package.json*). |
|||
|
|||
> **Applicable Unity Standard:** [US-0007](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0007/US-0007.md) |
|||
|
|||
Then update the `"createSeparatePackage"` field in the *Tests/.tests.json* file to set up testing for Continuous Integration (CI): |
|||
|
|||
* Set it to **false** if you want the tests to remain part of the published package. This is the default value. |
|||
|
|||
* Set it to **true** if you want the CI to create a separate package for these tests, and add the metadata at publish time to link the packages together. This allows you to have a large number of tests, or assets, etc. that you don't want to include in your main package, while making it easy to test your package with those tests & fixtures. |
|||
|
|||
1. Start **Unity**, create a local empty project and import your package into the project. |
|||
|
|||
1. In a console (or terminal) application, push the package starter kit files you copied in your new package repository to its remote. |
|||
- Add them to your repository's list to version |
|||
```git add .``` |
|||
- Commit to your new package's remote master |
|||
```git commit``` |
|||
- Push to your new package's remote master |
|||
```git push``` |
|||
|
|||
1. **Update the *README.md* file.** |
|||
|
|||
It should contain all pertinent information for developers using your package, such as: |
|||
|
|||
* Prerequistes |
|||
* External tools or development libraries |
|||
* Required installed Software |
|||
* Command line examples to build, test, and run your package. |
|||
|
|||
> **Applicable Unity Standard:** [US-0023](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0023/US-0023.md) |
|||
|
|||
|
|||
1. **Rename and update your documentation file(s).** |
|||
|
|||
Use the samples included in this starter kit to create preliminary, high-level documentation. Your documentation should introduce users to the features and sample files included in your package. For more information, see [Document your package](#document-your-package). |
|||
|
|||
> **Applicable Unity Standards:** |
|||
> [US-0013](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0013/US-0013.md), |
|||
> [US-0040](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0040/US-0040.md), |
|||
> [US-0041](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0041/US-0041.md), |
|||
> [US-0042](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0042/US-0042.md), |
|||
> [US-0044](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0044/US-0044.md), |
|||
> [US-0045](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0045/US-0045.md), |
|||
> [US-0046](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0046/US-0046.md), |
|||
> [US-0053](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0053/US-0053.md), |
|||
> [US-0062](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0062/US-0062.md), |
|||
> [US-0143](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0143/US-0143.md), |
|||
> [US-0168](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0168/US-0168.md) |
|||
|
|||
2. **Rename and update assembly definition files.** |
|||
|
|||
Choose a name schema to ensure that the name of the assembly built from the assembly definition file (_.asmdef_) will follow the .Net [Framework Design Guidelines](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/index). For more information, see [Name your assembly definition files](#name-your-assembly-definition-files). |
|||
|
|||
3. **Add samples to your package (code & assets).** |
|||
|
|||
The Package Manager recognizes the *Samples* directory in a package but does not import samples into Unity when the package is added to a project by default. Users can import samples into their */Assets* directory by clicking the **Import in project** button from the [Details view](https://docs.unity3d.com/Manual/upm-ui-details.html) of your package in the Package Manager window. |
|||
|
|||
If your package contains a sample: |
|||
|
|||
* Rename the *Samples/Example* folder, and update the *.sample.json* file in it. |
|||
|
|||
* If your package contains multiple samples, make a copy of the *Samples/Example* folder for each sample, and update each *.sample.json* file accordingly. |
|||
|
|||
Delete the *Samples* folder altogether if your package does not need samples. |
|||
|
|||
4. **Validate your package using the Validation Suite.** |
|||
|
|||
Before you publish your package, you need to make sure that it passes all the necessary validation checks by using the Package Validation Suite. The Validation Suite will ensure that your package comforms to Unity's established package standards. This is *required*. |
|||
|
|||
For more information, see [Validate your package](#validate-your-package). |
|||
|
|||
> **Applicable Unity Standard:** |
|||
> [US-0019](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0019/US-0019.md) |
|||
|
|||
|
|||
1. **Follow our design guidelines** |
|||
|
|||
Follow these design guidelines when creating your package: |
|||
|
|||
|
|||
* The [design checklist](https://unitytech.github.io/unityeditor-hig/topics/checklist.html) from Unity's Human Interface Guidelines. |
|||
|
|||
> **Applicable Unity Standard:** [US-0060](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0060/US-0060.md) |
|||
|
|||
* The namespace for code in the asmdef *must* match the asmdef name, except the initial `Unity`, which should be replaced with `UnityEngine` or `UnityEditor`. |
|||
|
|||
* For **Runtime code**, only use the `Unity` namespace for code that has no dependency on anything in `UnityEngine` or `UnityEditor` and instead uses `ECS` and other `Unity`-namespace systems. |
|||
|
|||
1. **Add tests to your package.** |
|||
|
|||
For **Editor tests**: |
|||
|
|||
* Write all your Editor Tests in *Tests/Editor* |
|||
* If your tests require access to internal methods, add an *AssemblyInfo.cs* file to your Editor code and use `[assembly: InternalsVisibleTo("Unity.[YourPackageName].Editor.Tests")]`. |
|||
|
|||
For **Playmode Tests**: |
|||
|
|||
* Write all your Playmode Tests in *Tests/Runtime*. |
|||
* If your tests require access to internal methods, add an *AssemblyInfo.cs* file to your Runtime code and use `[assembly: InternalsVisibleTo("Unity.[YourPackageName].Tests")]`. |
|||
|
|||
> **Applicable Unity Standards:** |
|||
> [US-0018](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0018/US-0018.md), |
|||
> [US-0020](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0020/US-0020.md) |
|||
|
|||
2. **Setup your package CI.** |
|||
|
|||
Make sure your package continues to work against trunk or any other branch by setting up automated testing on every commit. See the [Confluence page](https://confluence.hq.unity3d.com/display/PAK/Setting+up+your+package+CI) that explains how to set up your package CI. |
|||
|
|||
You can find the CI configuration templates at https://github.cds.internal.unity3d.com/unity/upm-ci-yamato-templates/tree/master/.yamato. The specific configuration files relevant for single package development are named `package-*.yml` and they cover all functions from `pack`, to `test`, `publish` and `promote`. |
|||
|
|||
3. **Update *CHANGELOG.md*.** |
|||
|
|||
Every new feature or bug fix should have a trace in this file. For more details on the chosen changelog format, see [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). |
|||
|
|||
> **Applicable Unity Standard:** |
|||
> [US-0039](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0039/US-0039.md) |
|||
|
|||
4. **Validate your package against Unity Standards.** |
|||
|
|||
From 2021.1, **all** packages we ship must be compliant with Unity Standards. It is up to you to track and record compliance against the standards, but at certain critical milestones Release Management will check that compliance. |
|||
|
|||
For more information, see [Using the Unity Standards checklist](#Using-the-Unity-Standards-checklist). |
|||
|
|||
|
|||
### Fill out your package manifest |
|||
|
|||
1. Update the following required fields in file *package.json* (see [Confluence](https://confluence.hq.unity3d.com/pages/viewpage.action?pageId=39065257) for more information): |
|||
|
|||
| **Attribute name** | **Description** | |
|||
| :----------------- | :----------------------------------------------------------- | |
|||
| `"name"` | Set the package name, following this naming convention: `"com.unity.[your-package-name]"`, without capital letters. For example, `"com.unity.2d.animation"`. | |
|||
| `"displayName"` | Set the package's user-friendly display name. For example, `"Terrain Builder SDK"`. <br><br>__Note:__ Use a display name that will help users understand what your package is intended for. | |
|||
| `"version"` | Set the package version in `"X.Y.Z"` format, following these [Semantic Versioning](http://semver.org/spec/v2.0.0.html) guidelines:<br>- To introduce a breaking API change, increment the major version (**X**.Y.Z).<br>- To introduce a new feature, increment the minor version (X.**Y**.Z).<br>- To introduce a bug fix, increment the patch version (X.Y.**Z**) | |
|||
| `"unity"` | Set the Unity version your package is compatible with. For example: `"2018.1"`. | |
|||
| `"unityRelease"` | Specify the Unity patch release your package is compatible with. For example: `"0a8"`.<br/><br/>__Note:__ This field is only required when the specific Unity version has a patch release. | |
|||
| `"description"` | This description appears in the Package Manager window when the user selects this package from the list. For best results, use this text to summarize what the package does and how it can benefit the user.<br><br>Special formatting characters are supported, including line breaks (`\n`) and unicode characters such as bullets (`\u25AA`). For more information, see the [Package summaries](https://confluence.unity3d.com/x/oyuFAw) page in Confluence. | |
|||
|
|||
|
|||
1. Update the following recommended fields in file **package.json**: |
|||
|
|||
| **Attribute name** | **Description** | |
|||
| :----------------- | :----------------------------------------------------------- | |
|||
| `"dependencies"` | List of packages this package depends on. All dependencies will also be downloaded and loaded in a project with your package. Here's an example:<br/><br/>`dependencies: {`<br/> `"com.unity.ads": "1.0.0",`<br/> `"com.unity.analytics": "2.0.0"`<br/>`}` | |
|||
| `"keywords"` | An array of keywords related to the package. This field is currently purely informational. | |
|||
| `"type"` | The type of your package. This is used to determine the visibility of your package in the Project Browser and the visibility of its Assets in the Object Picker. The `"tool"` and `"library"` types are used to set your package and its Assets as hidden by default. If not present or set to another value, your package and its Assets are visible by default. | |
|||
| `"hideInEditor"` | A boolean value that overrides the package visibility set by the package type. If set to `false`, the default value, your package and its Assets are **always** visible by default; if set to `true`, your package and its Assets are **always** hidden by default. | |
|||
|
|||
**Notes**: |
|||
|
|||
- For packages in development, neither `"type"` nor `"hideInEditor"` are used. The package is **always** visible in the Project Browser and its Assets are **always** visible in the Object Picker. |
|||
- The user is **always** able to toggle the package visibility in the Project Browser, as well as their Assets visibility in the Object Picker. |
|||
|
|||
> **Applicable Unity Standard:** |
|||
> [US-0007](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0007/US-0007.md) |
|||
|
|||
### Document your package |
|||
|
|||
To complete your package documentation, you need to complete the following: |
|||
|
|||
1. Document all of [your public APIs](#document-your-public-apis) and [your features](#document-features-in-the-user-manual). |
|||
2. [Test your documentation locally](#test-your-documentation-locally). |
|||
3. [Get your documentation published](#get-your-documentation-published). |
|||
|
|||
Package documentation must comply with [Unity documentation standards](https://confluence.unity3d.com/display/DOCS/Documentation+Standards). There are different standards based on whether your package is unsupported (experimental) or supported (pre-release, release candidate or released). |
|||
|
|||
One of the most important differences is that when a package is unsupported, you can write the User Manual and API documentation yourself. When a package is supported, this documentation must go through the Documentation team's editorial process. |
|||
|
|||
#### Working with the Documentation team |
|||
|
|||
Contact the Documentation team as early in the development process as possible, so that they can assess your documentation needs and provide guidance and resources. They might not be able to assign a writer to your package until it approaches supported status, but they can help you to comply with documentation standards, plan for the future, and make the transition between statuses as smooth as possible. |
|||
|
|||
To do this, contact the [Docs lead for your area of development](https://confluence.unity3d.com/display/DOCS/Meet+the+Documentation+team). |
|||
|
|||
For help or clarification, see the **#devs-documentation** Slack channel. |
|||
|
|||
#### Getting started with package documentation |
|||
|
|||
When your package approaches supported status, you should work with the Documentation team to ensure that your documentation complies with documentation standards. |
|||
|
|||
When your package is still in an experimental state, you can work on the documentation yourself. Your documentation needs to meet the [Unity documentation standards for packages](https://github.cds.internal.unity3d.com/unity/standards/blob/master/categories/documentationForPackages.md). See guidance on [Reviewing packages against documentation standards](https://confluence.unity3d.com/display/DOCS/Reviewing+packages+against+documentation+standards) using the STAR Docs Review dashboard. |
|||
|
|||
Your package should include only the documentation source, not the generated HTML. |
|||
|
|||
#### Document your public APIs |
|||
You must document all public APIs using Unity's standard API docs formatting. If you don't need an API to be public, mark it internal or exclude it using a filter. |
|||
|
|||
The following resources can help you writing Scripting API content: |
|||
* For step by step guidance on creating or updating API documentation, see [API documentation](https://confluence.unity3d.com/display/DOCS/API+documentation). |
|||
* For API documentation templates, guidance on excluding APIs from documentation, examples API documentation and * formatting information, see [API docs content and formatting](https://confluence.unity3d.com/display/DOCS/API+docs+content+and+formatting). |
|||
* For an example of a .cs file with XmlDoc comments, see the [Editor/EditorExample.cs](https://github.cds.internal.unity3d.com/unity/com.unity.package-starter-kit/blob/master/Editor/EditorExample.cs) file in this package. |
|||
|
|||
#### Document features in the User Manual |
|||
|
|||
If you are not yet working with a writer and you want to create early documentation for your experimental package, use one of the example guides under the Documentation~ folder: |
|||
|
|||
* [tools-package-guide.md](https://github.cds.internal.unity3d.com/unity/com.unity.package-starter-kit/blob/master/Documentation~/tools-package-guide.md ) for a package that includes features that augment the Unity Editor or Runtime (modules, tools, and libraries) |
|||
* [sample-package-guide.md](https://github.cds.internal.unity3d.com/unity/com.unity.package-starter-kit/blob/master/Documentation~/sample-package-guide.md) for a package that includes sample files |
|||
* [test-package-guide.md](https://github.cds.internal.unity3d.com/unity/com.unity.package-starter-kit/blob/master/Documentation~/test-package-guide.md ) for a package that provides tests |
|||
|
|||
For instructions on using these examples, see [Package documentation guides](https://github.cds.internal.unity3d.com/unity/com.unity.package-starter-kit/blob/master/Documentation~/index.md). |
|||
|
|||
The following resources can help you writing User Manual content: |
|||
* For step-by-step instructions on editing and testing User Manual content, see [User Manual documentation](https://confluence.unity3d.com/display/DOCS/User+Manual+documentation). |
|||
* For information on how to structure User Manual content in a clear and usable way, see [Content templates and guidelines](https://confluence.unity3d.com/display/DOCS/Content+templates+and+guidelines). |
|||
* For information on how to format User Manual pages, see [User Manual formatting: packages](https://confluence.unity3d.com/display/DOCS/User+Manual+formatting%3A+packages). |
|||
|
|||
When your package is more mature and ready for more in-depth documentation, or if you are approaching supported status, contact the Documentation team to arrange a writer to work with you. |
|||
|
|||
|
|||
#### Test your documentation locally |
|||
|
|||
As you are developing your documentation, you can see what your documentation will look like by using the DocTools package: [**com.unity.package-manager-doctools**](https://github.cds.internal.unity3d.com/unity/com.unity.package-manager-doctools). |
|||
|
|||
For instructions on using the DocTools package and interpreting the results, see [Validating Package Documentation](https://confluence.unity3d.com/pages/viewpage.action?spaceKey=DOCS&title=Validating+Package+Documentation). |
|||
|
|||
The DocTools extension is an internal, unreleased package. If you come across arguable results, please discuss them on #docs-packman. |
|||
|
|||
#### Get your documentation published |
|||
|
|||
If your package is unsupported, the documentation doesn’t need to be reviewed by a technical writer. |
|||
|
|||
> **Note:** Unsupported packages are published the just like supported packages, but their documentation doesn’t appear in the manual. |
|||
|
|||
If your package is supported (pre-release, release-candidate or released) and you’ve written your documentation, notify the technical writer assigned to your team or project. If you don’t have a technical writer at this stage, see [Working with the Documentation team](https://docs.google.com/document/d/1Hq_Lt7y_C4h4HgwddF7yLC7i2QFwxiH1U-4GVV50M7M/edit#heading=h.mii66g6vd1zt). |
|||
|
|||
|
|||
After the technical writer reviews the documentation, they create a pull request in the package git repository. The package's development team then needs to submit a new package version with the updated docs. |
|||
|
|||
Once you’ve [published your package to the candidates registry](#preparing-your-package-for-the-candidates-registry), and had it [published to production](#get-your-package-published-to-production), the **@docs-publish** group validates and then publishes the documentation. |
|||
|
|||
If you manually post a publish request in #devs-pkg-promotion (rather than using CI), the docs publisher will reply in the thread of your message with a link to the changelog of the newly published documentation. |
|||
|
|||
### Name your assembly definition files |
|||
|
|||
If your package contains Editor code, rename and modify [Editor/Unity.SubGroup.YourPackageName.Editor.asmdef](Editor/Unity.SubGroup.YourPackageName.Editor.asmdef). Otherwise, delete the *Editor* directory. |
|||
|
|||
* Name **must** match your package name, suffixed by `.Editor` (for example, `Unity.[YourPackageName].Editor`). |
|||
* Assembly **must** reference `Unity.[YourPackageName]` (if you have any runtime code). |
|||
* Platforms **must** include `"Editor"`. |
|||
|
|||
If your package contains code that needs to be included in Unity runtime builds, rename and modify [Runtime/Unity.SubGroup.YourPackageName.asmdef](Runtime/Unity.SubGroup.YourPackageName.asmdef). Otherwise, delete the *Runtime* directory. |
|||
|
|||
* Name **must** match your package name (for example,`Unity.[YourPackageName]`) |
|||
|
|||
If your package has Editor code, you **must** have Editor Tests. In that case, rename and modify [Tests/Editor/Unity.SubGroup.YourPackageName.EditorTests.asmdef](Tests/Editor/Unity.SubGroup.YourPackageName.EditorTests.asmdef). |
|||
|
|||
* Name **must** match your package name, suffixed by `.Editor.Tests` (for example, `Unity.[YourPackageName].Editor.Tests`) |
|||
* Assembly **must** reference `Unity.[YourPackageName].Editor` and `Unity.[YourPackageName]` (if you have any Runtime code). |
|||
* Platforms **must** include `"Editor"`. |
|||
* Optional Unity references **must** include `"TestAssemblies"` to allow your Editor Tests to show up in the Test Runner or run on Katana when your package is listed in the project manifest's `testables` field. |
|||
|
|||
If your package has Runtime code, you **must** have Playmode Tests. In that case, rename and modify [Tests/Runtime/Unity.SubGroup.YourPackageName.Tests.asmdef](Tests/Runtime/Unity.SubGroup.YourPackageName.Tests.asmdef). |
|||
|
|||
* Name **must** match your package name, suffixed by `.Tests` (for example, `Unity.[YourPackageName].Tests`) |
|||
* Assembly **must** reference `Unity.[YourPackageName]`. |
|||
* Optional Unity references **must** include `"TestAssemblies"` to allow your Playmode Tests to show up in the Test Runner or run on Katana when your package is listed in the project manifest's `testables` field. |
|||
|
|||
### Validate your package |
|||
|
|||
To validate your package, you must install the validation suite package into your project. To do so, follow these steps: |
|||
|
|||
1. Make sure you have `Unity 2019.2` or above. |
|||
|
|||
2. From the Package Manager window, install the latest version of the **Package Validation Suite** with the context set to **Unity Registry**. If you don't see it in the list, make sure the [Enable Preview Packages](https://docs.unity3d.com/Documentation/Manual/class-PackageManager.html) project setting is enabled. |
|||
**Note**: For releases prior to 2020.1, enable **Advanced** > **Show preview packages** instead. |
|||
|
|||
Once the Validation Suite package is installed, a **Validate** button appears in the details pane when you select your installed package from the Package Manager window. |
|||
|
|||
To run the tests: |
|||
|
|||
1. Click the **Validate** button to run a series of tests. A **See Results** button appears after the test run. |
|||
2. Click the **See Results** button for additional explanation: |
|||
* If it succeeds, a green bar displays a **Success** message. |
|||
* If it fails, a red bar displays a **Failed** message. |
|||
|
|||
The validation suite is still under development, so if you come across arguable results, please discuss them on **#devs-packman-tooling**. |
|||
|
|||
> **Applicable Unity Standard:** |
|||
> [US-0019](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0019/US-0019.md) |
|||
|
|||
|
|||
## Create an Experimental Package |
|||
|
|||
Experimental Packages are a great way of getting your features in front of Unity Developers in order to get early feedback on functionality and UI designs. Experimental packages need to go through the publishing to production flow, as would any other package, but with diminished requirements: |
|||
|
|||
* Expected Package structure respected |
|||
* Package loads in Unity Editor without errors |
|||
* License file present - With third-party notices file if necessary |
|||
* Test coverage is good - Optional but preferred |
|||
* Public APIs documented, minimal feature docs exists- Optional but preferred |
|||
|
|||
To mark your package as **Experimental**, set the package version in your `package.json` file to use either `0` for the **MAJOR** portion of the version, or suffix the `-exp` tag after the **PATCH** portion of the version. For example: |
|||
|
|||
```json |
|||
"version" : "0.1.0" |
|||
|
|||
OR |
|||
|
|||
"version" : "1.2.0-exp" |
|||
``` |
|||
|
|||
For more information on the Experimental cycle, see the [Experimental](https://confluence.unity3d.com/display/PAK/Experimental) Confluence page. |
|||
|
|||
For an overview of the entire lifecycle of packages, see the [Lifecycle V2](https://confluence.unity3d.com/display/PAK/Lifecycle+V2) Confluence page. |
|||
|
|||
## Register your package |
|||
|
|||
If you think you are working on a feature that is a good package candidate, please take a minute to advise the Package Review Board in the **#package-review-board** channel. Please make sure that your repo is private until the review board has approved the content of your package (NDA, Platforms, Product Management, etc). |
|||
|
|||
Working with the board of dev directors and with product management, we will schedule the entry of the candidates in the ecosystem, based on technical challenges and on our feature roadmap. |
|||
|
|||
|
|||
> **Applicable Unity Standard:** |
|||
> [US-0067](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0067/US-0067.md) |
|||
|
|||
|
|||
## Share your package |
|||
|
|||
If you want to share your project with other developers, the steps are similar to what's presented above. On the other developer's machine: |
|||
|
|||
1. Start **Unity** and create a local empty project. |
|||
|
|||
2. Launch the console (or terminal) application, navigate to the newly created project folder, and then clone your repository in the `Packages` directory: |
|||
|
|||
```shell |
|||
cd <YourProjectPath>/Packages |
|||
git clone https://github.cdsinternal.unity3d.com/unity/[your-package-name].git com.unity.[sub-group].[your-package-name] |
|||
``` |
|||
|
|||
> __Note:__ Your directory name must be the name of your package (Example: `"com.unity.terrain-builder"`). |
|||
|
|||
## Make sure your package meets all legal and security requirements |
|||
|
|||
|
|||
> **Applicable Unity Standards:** |
|||
> [US-0026](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0026/US-0026.md), |
|||
> [US-0027](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0027/US-0027.md), |
|||
> [US-0028](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0028/US-0028.md), |
|||
> [US-0031](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0031/US-0031.md), |
|||
> [US-0032](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0032/US-0032.md), |
|||
> [US-0033](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0033/US-0033.md), |
|||
> [US-0034](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0034/US-0034.md), |
|||
> [US-0037](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0037/US-0037.md), and for packages with third-party elements: |
|||
> [US-0065](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0065/US-0065.md) |
|||
|
|||
|
|||
## Preparing your package for the Candidates registry |
|||
|
|||
Before publishing your package to production, you must send your package on the Package Manager's internal **candidates** repository. The candidates repository is monitored by QA and release management, and is where package validation will take place before it is accepted in production. |
|||
|
|||
1. Publishing your changes to the Package Manager's **Candidates** registry happens from Github.cds. To do so, set up your project's Continuous integration (CI), which will be triggered by "Tags" on your branches. |
|||
|
|||
For information see [the Confluence page](https://confluence.hq.unity3d.com/display/PAK/Setting+up+your+package+CI) that describes how to set up CI for your package. |
|||
|
|||
2. Test your package locally. Once your package is published on the **Candidates** registry, you can test your package in the editor by creating a new project, and editing the project's *manifest.json* file to point to your candidate package: |
|||
|
|||
```json |
|||
dependencies: { |
|||
"com.unity.[sub-group].[your-package-name]": "0.1.0" |
|||
}, |
|||
"registry": "https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-candidates" |
|||
``` |
|||
|
|||
> **Applicable Unity Standards:** |
|||
> [US-0018](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0018/US-0018.md), |
|||
> [US-0019](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0019/US-0019.md), |
|||
> [US-0020](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0020/US-0020.md), |
|||
> [US-0021](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0021/US-0021.md), |
|||
> [US-0022](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0022/US-0022.md) |
|||
|
|||
## Using the Unity Standards checklist |
|||
|
|||
The Standards team provides a verification checklist for you to copy and use. Use this to view all the standards that are mandatory or recommended for your package or template. |
|||
The checklist is used for: |
|||
|
|||
- Experimental (unsupported) packages. Note that some standards for experimental packages are recommended, becoming mandatory when you move to a supported package phase. |
|||
- Supported (pre-release, release-candidate) packages (including entitled packages) |
|||
- Core packages |
|||
- Dynamic templates |
|||
|
|||
To get a copy of the checklist: |
|||
|
|||
1. Open the template preview: [Unity Standards checklist](https://docs.google.com/spreadsheets/d/1xeuDhFaQhhRApuZzZWREQS1SvxifU60ZYZVZf2gcm1E/template/preview). |
|||
|
|||
2. Click the **USE TEMPLATE** button to create a copy of the template for you to complete. |
|||
|
|||
3. Rename your copy of the checklist to match your package name and version. For example, name the checklist `com.unity.mypackage-0.0.1-pre.1`. |
|||
|
|||
4. Save (move) and maintain your copy of the checklist in Release Management’s [Package Standards Checklists folder](https://drive.google.com/drive/u/0/folders/14-oCWTptVpvHz09Rza0Q0iuUgqUvMEwG) in Google Drive. |
|||
|
|||
For more information, see [How to validate your package against Unity Standards](https://scholar.internal.unity3d.com/reader/course/working-with-unity-standards/article/how-to-validate-your-package-against-unity-standards-1). |
|||
|
|||
|
|||
## Get your package published to Production |
|||
|
|||
The process to promote packages to the **Production** registry changes depending on what phase your package is in: |
|||
|
|||
* First time **Experimental** and **Prerelease** packages are promoted by Release Management from the **Candidates** registry. After the first version is released, you can promote subsequent versions on your own. |
|||
* Release Candidates and Released packages are promoted to the **Production** registry by Release Management along with every Unity release. |
|||
|
|||
When your package meets the Release Management Criteria, the promotion process can be started by contacting Release Management in **#devs-pkg-promotion**. |
|||
|
|||
**Note:** Release management validates your package content, and checks that the editor/playmode tests pass before promoting the package to production. |
|||
|
|||
> **Applicable Unity Standards:** |
|||
> [US-0004](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0004/US-0004.md), |
|||
> [US-0014](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0014/US-0014.md), |
|||
> [US-0015](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0015/US-0015.md), |
|||
> [US-0016](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0016/US-0016.md), |
|||
> [US-0018](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0018/US-0018.md), |
|||
> [US-0021](https://github.cds.internal.unity3d.com/unity/standards/blob/2021.2/definitions/US-0021/US-0021.md) |
|||
|
|||
### Verified status and bundled packages |
|||
|
|||
If your package is meant to ship with a release of the editor (**Verified Packages** and **Bundled Packages**), follow these steps: |
|||
|
|||
1. To be marked as verified, in trunk, modify the editor manifest (*[root]\External\PackageManager\Editor\manifest.json*) to include your package in the **verified** list. |
|||
|
|||
2. If your package is not verified, but only bundled with the editor, submit one or more Test Project(s) in Ono, so that your new package can be tested in all ABVs moving forward. |
|||
|
|||
The following steps will create a test project that will run in ABVs, load your package into the project, and run all the tests found in your package. The better your test coverage, the more confident you'll be that your package works with trunk. |
|||
|
|||
* Create a branch in Ono, based on the latest branch this package must be compatible with (trunk, or release branch). |
|||
|
|||
* If your package contains **Editor Tests**: |
|||
|
|||
* In *[root]\Tests\Editor.Tests*, create a new EditorTest Project (for new packages use **YourPackageName**) or use an existing project (for new versions of existing package). |
|||
|
|||
To get a bare package for an EditorTest Project, click [here](https://oc.unity3d.com/index.php/s/Cldvuy6NpxqYy8y). |
|||
|
|||
* Modify the project’s *manifest.json* file to include the production version of the package (`name@version`). |
|||
|
|||
* Your project's *manifest.json* file should contain the following line: |
|||
|
|||
```json |
|||
"testables" : [ "com.unity.[sub-group].[your-package-name]" ] |
|||
``` |
|||
|
|||
* If your package contains **PlaymodeTests**: |
|||
|
|||
* In *[root]\Tests\PlaymodeTests*, create a new PlaymodeTest Project (for new packages use **YourPackageName**) or use an existing project (for new versions of existing package). |
|||
|
|||
* Modify the project’s *manifest.json* file to include the candidate version of the package (`name@version`). |
|||
|
|||
* Your project's manifest.json file should contain the following line: |
|||
|
|||
```json |
|||
"testables" : [ "com.unity.[sub-group].[your-package-name]" ] |
|||
``` |
|||
|
|||
* Commit your branch changes to Ono, and run all Windows & Mac Editor/PlayMode tests (not full ABV) in Katana. |
|||
|
|||
3. Once the tests are green on Katana, create your PR, add both **Latest Release Manager** and **Trunk Merge Queue** as reviewers. |
|||
|
|||
|
|||
## FAQ |
|||
|
|||
**What’s the difference between a core package and a default package?** |
|||
|
|||
A core package is a package that has its code included with the Editor’s core code. This is interesting for packages that plan to change enormously in parallel to editor APIs. By moving package code to the editor’s repo, both core API\functionality changes can be made along with required packages changes in the same PR. |
|||
https://docs.google.com/document/d/1CMoanjR3KAdew-6n39JdCFmHkTp1oshs3vkpejapf4Q/edit |
|||
|
|||
A default package is a verified package that gets installed with every new project users create, regardless of the template they use. We should limit the number of default packages we support, as each default package adds to the project loading time. The list of default packages can be found in the editor manifest (https://ono.unity3d.com/unity/unity/files/de904b9ed9b44580ecd1e883f510daaa08182cc5/External/PackageManager/Editor/manifest.json). |
|||
|
|||
**What are the requirements for me to publish an experimental package?** |
|||
|
|||
* [How to validate your package against Unity Standards](https://scholar.internal.unity3d.com/reader/course/working-with-unity-standards/article/how-to-validate-your-package-against-unity-standards-1) |
|||
|
|||
**What are the requirements for me to get my package verified for a version of unity?** |
|||
|
|||
https://docs.google.com/document/d/1oWC9XArVfkGMnqN9azR4hW4Pcd7-kQQw8Oy7ckP43JE/ |
|||
|
|||
**How is my verified package tested in Katana?** |
|||
|
|||
https://docs.google.com/document/d/1jwTh71ZGtB2vF0SsHEwivt2FunaJWMGDdQJTpYRj3EE/edit |
|||
|
|||
**How is my template tested in Katana?** |
|||
|
|||
Templates are no longer tested in Katana. Instead, you should enable CI on your repository to test any template package you have with the editor version(s) you want to be compatible with. |
|||
|
|||
In addition, Release Management uses Working Sets to track the status of packages and templates that will go into the next Unity Releases, making this the perfect place to set up the product. |
|||
|
|||
**How do I add samples to my package?** |
|||
|
|||
https://docs.google.com/document/d/1rmxGh6Z9gtbQlGUKCsVBaR0RyHvzq_gsWoYs6sttzYA/edit#heading=h.fg1e3sz56048 |
|||
|
|||
**How do I setup CI or publishing options for my package?** |
|||
https://confluence.hq.unity3d.com/display/PAK/Setting+up+your+package+CI |
|||
|
|||
**How can I add tests to my package?** |
|||
|
|||
There’s a “Tests” directory in the package starter kit. If you add editor and playmode tests in that directory, they will make up the list of tests for your package. |
|||
|
|||
**The tests in my package bloat my package too much, what are my options?** |
|||
|
|||
https://docs.google.com/document/d/19kKIGFetde5ES-gKXQp_P7bxQ9UgBnBUu58-y7c1rTA/edit |
|||
|
|||
**Can I automate my package publishing yet?** |
|||
|
|||
Automated publishing to the **Candidates** registry is enabled, but promotion to the **Production** registry is restricted depending on the phase your package is in: |
|||
|
|||
* **Experimental** can be promoted to **Production** automatically after the first version has been published by Release Management |
|||
* **Prerelease** can be promoted to **Production** automatically after the first version has been published by Release Management |
|||
* **Release Candidates** can only be promoted to **Production** by Release Management |
|||
* **Released** can only be promoted to **Production** by Release Management |
|||
|
|||
**How do I get a template package started?** |
|||
|
|||
Start with the Project Template Starter Kit (you can request access in **#devs-packman**). |
|||
https://github.cds.internal.unity3d.com/unity/com.unity.template-starter-kit |
|||
|
|||
**How do I get my package included in a template?** |
|||
|
|||
First and foremost, your package needs to be on the verified list of packages. Only verified packages can get added to templates we ship with the editor. Then reach out to the templates community in **#devs-template** to open discussions on adding your package to one or more of our existing templates. |
|||
|
|||
**How can I test my package locally, as a user would?** |
|||
|
|||
https://confluence.hq.unity3d.com/display/PAK/How+to+add+a+git+package+to+your+project |
|||
|
|||
**What tests are included by the validation suite?** |
|||
|
|||
https://docs.google.com/spreadsheets/d/1CdO7D0WSirbZhjnVsdJxJwOPK4UdUDxSRBIqwyjm70w/edit#gid=0 |
|
|||
# see https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners for more information |
|||
* @wess @andrewdu @ben-randall @james-lao |
|
|||
artifacts/** |
|||
build/** |
|||
.build_script/** |
|||
node_modules/** |
|||
.DS_Store |
|||
.npmrc |
|||
!Documentation~ |
|||
!.Documentation |
|||
npm-debug.log |
|||
build.sh.meta |
|||
build.bat.meta |
|||
.idea/ |
|
|||
artifacts/** |
|||
build/** |
|||
.build_script/** |
|||
node_modules/** |
|||
Documentation/ApiDocs/** |
|||
Documentation~/ApiDocs/** |
|||
.DS_Store |
|||
.npmrc |
|||
.npmignore |
|||
.gitignore |
|||
CONTRIBUTING.md |
|||
CONTRIBUTING.md.meta |
|||
QAReport.md |
|||
QAReport.md.meta |
|||
.gitlab-ci.yml |
|||
build.sh |
|||
build.sh.meta |
|||
build.bat |
|||
build.bat.meta |
|
|||
pack: |
|||
name: Pack |
|||
agent: |
|||
type: Unity::VM |
|||
image: package-ci/ubuntu:stable |
|||
flavor: b1.large |
|||
commands: |
|||
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm |
|||
- upm-ci package pack |
|||
artifacts: |
|||
packages: |
|||
paths: |
|||
- "upm-ci~/packages/**/*" |
|
|||
test_editors: |
|||
- version: 2021.2 |
|||
test_platforms: |
|||
- name: win |
|||
type: Unity::VM |
|||
image: package-ci/win10:stable |
|||
flavor: b1.large |
|||
--- |
|||
|
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
promotion_test_{{ platform.name }}_{{ editor.version }}: |
|||
name : Promotion Test {{ editor.version }} on {{ platform.name }} |
|||
agent: |
|||
type: {{ platform.type }} |
|||
image: {{ platform.image }} |
|||
flavor: {{ platform.flavor}} |
|||
variables: |
|||
UPMCI_PROMOTION: 1 |
|||
commands: |
|||
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm |
|||
- upm-ci package test --unity-version {{ editor.version }} --extra-create-project-arg=-upmNoDefaultPackages |
|||
artifacts: |
|||
logs: |
|||
paths: |
|||
- "upm-ci~/test-results/**/*" |
|||
dependencies: |
|||
- .yamato/package-pack.yml#pack |
|||
{% endfor %} |
|||
{% endfor %} |
|||
|
|||
promotion_test_trigger: |
|||
name: Promotion Tests Trigger |
|||
dependencies: |
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
- .yamato/package-promotion.yml#promotion_test_{{platform.name}}_{{editor.version}} |
|||
{% endfor %} |
|||
{% endfor %} |
|||
|
|||
promote: |
|||
name: Promote to Production |
|||
agent: |
|||
type: Unity::VM |
|||
image: package-ci/win10:stable |
|||
flavor: b1.large |
|||
variables: |
|||
UPMCI_PROMOTION: 1 |
|||
commands: |
|||
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm |
|||
- upm-ci package promote --dry-run |
|||
triggers: |
|||
tags: |
|||
only: |
|||
- /^[Rr]elease-(0\.\d+\.\d+|[1-9]\d*\.\d+\.\d+(-preview(\.\d+)?|-exp(\.\d+|-\w+\.\d+)|-pre\.\d+))$/ |
|||
artifacts: |
|||
artifacts: |
|||
paths: |
|||
- "upm-ci~/packages/*.tgz" |
|||
dependencies: |
|||
- .yamato/package-pack.yml#pack |
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
- .yamato/package-promotion.yml#promotion_test_{{ platform.name }}_{{ editor.version }} |
|||
{% endfor %} |
|||
{% endfor %} |
|
|||
test_editors: |
|||
- version: 2021.2 |
|||
- version: trunk |
|||
test_platforms: |
|||
- name: win |
|||
type: Unity::VM |
|||
image: package-ci/win10:stable |
|||
flavor: b1.large |
|||
- name: mac |
|||
type: Unity::VM::osx |
|||
image: package-ci/mac:stable |
|||
flavor: m1.mac |
|||
--- |
|||
|
|||
publish: |
|||
name: Publish to Internal Registry |
|||
agent: |
|||
type: Unity::VM |
|||
image: package-ci/win10:stable |
|||
flavor: b1.large |
|||
commands: |
|||
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm |
|||
# Please remove the dry-run option once your CI pipeline is in place ant that you're ready to publish for real |
|||
- upm-ci package publish --dry-run |
|||
triggers: |
|||
tags: |
|||
only: |
|||
- /^[Rr][Cc]-(0\.\d+\.\d+|[1-9]\d*\.\d+\.\d+(-preview(\.\d+)?|-exp(\.\d+|-\w+\.\d+)|-pre\.\d+)?)$/ |
|||
artifacts: |
|||
artifacts: |
|||
paths: |
|||
- "upm-ci~/packages/*.tgz" |
|||
dependencies: |
|||
- .yamato/package-pack.yml#pack |
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
- .yamato/package-test.yml#test_{{ platform.name }}_{{ editor.version }} |
|||
- .yamato/package-test.yml#validate_{{ platform.name }}_{{ editor.version }} |
|||
{% endfor %} |
|||
{% endfor %} |
|
|||
test_editors: |
|||
- version: 2021.2 |
|||
- version: trunk |
|||
test_platforms: |
|||
- name: win |
|||
type: Unity::VM |
|||
image: package-ci/win10:stable |
|||
flavor: b1.large |
|||
- name: mac |
|||
type: Unity::VM::osx |
|||
image: package-ci/mac:stable |
|||
flavor: m1.mac |
|||
- name: ubuntu |
|||
type: Unity::VM |
|||
image: package-ci/ubuntu:stable |
|||
flavor: b1.large |
|||
- name: centos |
|||
type: Unity::VM::GPU |
|||
image: package-ci/centos:stable |
|||
flavor: b1.large |
|||
--- |
|||
|
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
test_{{ platform.name }}_{{ editor.version }}: |
|||
name : Test {{ editor.version }} on {{ platform.name }} |
|||
agent: |
|||
type: {{ platform.type }} |
|||
image: {{ platform.image }} |
|||
flavor: {{ platform.flavor}} |
|||
commands: |
|||
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm |
|||
- {% if platform.name == "centos" %}DISPLAY=:0 {% endif %}upm-ci package test -u {{ editor.version }} --type package-tests --extra-create-project-arg=-upmNoDefaultPackages |
|||
artifacts: |
|||
logs: |
|||
paths: |
|||
- "upm-ci~/test-results/**/*" |
|||
dependencies: |
|||
- .yamato/package-pack.yml#pack |
|||
{% endfor %} |
|||
{% endfor %} |
|||
|
|||
# Validate the package on each editor version and each platform |
|||
# Validation only occurs in editmode. |
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
validate_{{ platform.name }}_{{ editor.version }}: |
|||
name : Validate {{ editor.version }} on {{ platform.name }} |
|||
agent: |
|||
type: {{ platform.type }} |
|||
image: {{ platform.image }} |
|||
flavor: {{ platform.flavor}} |
|||
commands: |
|||
- npm install upm-ci-utils@stable -g --registry https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-npm |
|||
- {% if platform.name == "centos" %}DISPLAY=:0 {% endif %}upm-ci package test -u {{ editor.version }} --type vetting-tests --platform editmode --extra-create-project-arg=-upmNoDefaultPackages |
|||
artifacts: |
|||
logs: |
|||
paths: |
|||
- "upm-ci~/test-results/**/*" |
|||
dependencies: |
|||
- .yamato/package-pack.yml#pack |
|||
{% endfor %} |
|||
{% endfor %} |
|||
|
|||
test_trigger: |
|||
name: Package Tests Trigger |
|||
triggers: |
|||
branches: |
|||
only: |
|||
- "master" |
|||
pull_requests: |
|||
- targets: |
|||
only: |
|||
- "/.*/" |
|||
dependencies: |
|||
- .yamato/package-pack.yml#pack |
|||
{% for editor in test_editors %} |
|||
{% for platform in test_platforms %} |
|||
- .yamato/package-test.yml#test_{{platform.name}}_{{editor.version}} |
|||
- .yamato/package-test.yml#validate_{{platform.name}}_{{editor.version}} |
|||
{% endfor %} |
|||
{% endfor %} |
|
|||
# Changelog |
|||
All notable changes to this package will be documented in this file. |
|||
|
|||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) |
|||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). |
|||
|
|||
## [0.1.0] - 2021-04-15 |
|||
|
|||
### This is the first release of *Unity Package Rooms*. |
|||
|
|||
This package implements the client API for the Unity Rooms service. |
|
|||
fileFormatVersion: 2 |
|||
guid: e26dfa7639a6ff24aa4dbf32ad49ee03 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Contributing |
|||
|
|||
## If you are interested in contributing, here are some ground rules: |
|||
* ... Define guidelines & rules for what contributors need to know to successfully make Pull requests against your repo ... |
|||
|
|||
## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement) |
|||
By making a pull request, you are confirming agreement to the terms and conditions of the UCA, including that your Contributions are your original creation and that you have complete right and authority to make your Contributions. |
|||
|
|||
## Once you have a change ready following these ground rules. Simply make a pull request |
|
|||
fileFormatVersion: 2 |
|||
guid: b6ce05c2339c8a34f87d7268fa2ac559 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Documentation for Unity Rooms |
|||
<a name="documentation-for-api-endpoints"></a> |
|||
## Documentation for API Endpoints |
|||
All URIs are relative to *https://rooms.cloud.unity3d.com/api/v1/rooms* |
|||
Class | Method | HTTP request | Description |
|||
------------ | ------------- | ------------- | ------------- |
|||
*RoomsApi* | [**CreateRoom**](Apis/RoomsApi.md#createroom) | **POST** /create | Creates a new Room. |
|||
*RoomsApi* | [**DeleteRoom**](Apis/RoomsApi.md#deleteroom) | **DELETE** /{roomId} | Remove a room. |
|||
*RoomsApi* | [**GetRoom**](Apis/RoomsApi.md#getroom) | **GET** /{roomId} | Get the details for a room |
|||
*RoomsApi* | [**JoinRoom**](Apis/RoomsApi.md#joinroom) | **POST** /join | Join a room. |
|||
*RoomsApi* | [**QueryRooms**](Apis/RoomsApi.md#queryrooms) | **POST** /query | Query available rooms. |
|||
*RoomsApi* | [**RemovePlayer**](Apis/RoomsApi.md#removeplayer) | **DELETE** /{roomId}/players/{playerId} | Remove a player |
|||
*RoomsApi* | [**UpdatePlayer**](Apis/RoomsApi.md#updateplayer) | **POST** /{roomId}/players/{playerId} | Update player data. |
|||
*RoomsApi* | [**UpdateRoom**](Apis/RoomsApi.md#updateroom) | **POST** /{roomId} | Update the data for a room. |
|||
|
|||
<a name="documentation-for-models"></a> |
|||
## Documentation for Models |
|||
- [Models.CreateRequest](Models/CreateRequest.md) |
|||
- [Models.DataObject](Models/DataObject.md) |
|||
- [Models.Detail](Models/Detail.md) |
|||
- [Models.ErrorStatus](Models/ErrorStatus.md) |
|||
- [Models.JoinRequest](Models/JoinRequest.md) |
|||
- [Models.Player](Models/Player.md) |
|||
- [Models.PlayerUpdateRequest](Models/PlayerUpdateRequest.md) |
|||
- [Models.QueryFilter](Models/QueryFilter.md) |
|||
- [Models.QueryRequest](Models/QueryRequest.md) |
|||
- [Models.QueryResponse](Models/QueryResponse.md) |
|||
- [Models.Room](Models/Room.md) |
|||
- [Models.UpdateRequest](Models/UpdateRequest.md) |
|||
|
|||
<a name="documentation-for-authorization"></a> |
|||
## Documentation for Authorization |
|||
All endpoints do not require authorization. |
|
|||
fileFormatVersion: 2 |
|||
guid: 7a02eb023d6782a40a2a5fef1778f0c9 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Unity Rooms copyright © 2021 Unity Technologies |
|||
|
|||
This software is subject to, and made available under, the terms of service for [name of Unity service] (see **TODO: link to the terms of service for Unity Rooms Service**). |
|||
|
|||
Unless expressly provided otherwise, the software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the terms of service for details on these and other terms and conditions. |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 8bf914b887aa15d499a5575ddde074a0 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Quality Report |
|||
Use this file to outline the test strategy for this package. |
|||
|
|||
## Version tested: [*package version*] |
|||
|
|||
## QA Owner: [*Add Name*] |
|||
## UX Owner: [*Add Name*] |
|||
|
|||
## Test strategy |
|||
*Use this section to describe how this feature was tested.* |
|||
* A link to the Test Plan (Test Rails, other) |
|||
* Results from the package's editor and runtime test suite. |
|||
* Link to automated test results (if any) |
|||
* Manual test Results, [here's an example](https://docs.google.com/spreadsheets/d/12A76U5Gf969w10KL4Ik0wC1oFIBDUoRrqIvQgD18TFo/edit#gid=0) |
|||
* Scenario test week outcome |
|||
* etc. |
|||
|
|||
## Package Status |
|||
Use this section to describe: |
|||
* UX status/evaluation results |
|||
* package stability |
|||
* known bugs, issues |
|||
* performance metrics, |
|||
* etc |
|||
|
|||
In other words, a general feeling on the health of this package. |
|
|||
fileFormatVersion: 2 |
|||
guid: 65e119d071e2c1c4f8da700c4a68a5de |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# How to install Unity Rooms into your Unity project |
|||
|
|||
## Open The package manager |
|||
|
|||
Window > Package Manager |
|||
|
|||
## Install Unity Rooms |
|||
|
|||
In the Package Manager Click on the "+" sign in the top left corner then select "Add Package From Disk" then browse to |
|||
`com.unity.services.rooms` and select package.json > open |
|||
|
|||
|
|||
## To install the Identity SDK |
|||
Modify the Unity projects manifest to contain: |
|||
```json |
|||
"dependencies": { |
|||
"com.unity.services.identity": "0.2.1-preview" |
|||
}, |
|||
"scopedRegistries": [ |
|||
{ |
|||
"name": "Internal Candidates Registry", |
|||
"url": "https://artifactory.prd.it.unity3d.com/artifactory/api/npm/upm-candidates", |
|||
"scopes": [ |
|||
"com.unity.services" |
|||
] |
|||
} |
|||
] |
|||
``` |
|||
To use the Identity SDK to retrieve the Player ID and Access Token: |
|||
|
|||
```csharp |
|||
void Start() |
|||
{ |
|||
Identity.SignInAnonymously(); |
|||
Identity.OnSignedIn += () => |
|||
{ |
|||
playerId = Identity.PlayerId; |
|||
Unity.Services.Rooms.JWT = Identity.AccessToken; |
|||
}; |
|||
Identity.OnSignInFailed += s => |
|||
{ |
|||
Debug.Log(s); |
|||
}; |
|||
} |
|||
``` |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 79f6de2b83890a74589ca44c894560c5 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 725a698d709ab654dbfb56421c843571 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: df17b74a1cde25b40a9bb0c979460ff8 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using System.Collections.Generic; |
|||
using Unity.Services.Rooms.Models; |
|||
using Unity.Services.Rooms.Http; |
|||
using TaskScheduler = Unity.Services.Rooms.Scheduler.TaskScheduler; |
|||
using Unity.Services.Rooms.Rooms; |
|||
|
|||
namespace Unity.Services.Rooms.Apis.Rooms |
|||
{ |
|||
public interface IRoomsApiClient |
|||
{ |
|||
Task<Response<Room>> CreateRoomAsync(CreateRoomRequest request); |
|||
Task<Response> DeleteRoomAsync(DeleteRoomRequest request); |
|||
Task<Response<Room>> GetRoomAsync(GetRoomRequest request); |
|||
Task<Response<Room>> JoinRoomAsync(JoinRoomRequest request); |
|||
Task<Response<QueryResponse>> QueryRoomsAsync(QueryRoomsRequest request); |
|||
Task<Response> RemovePlayerAsync(RemovePlayerRequest request); |
|||
Task<Response<Room>> UpdatePlayerAsync(UpdatePlayerRequest request); |
|||
Task<Response<Room>> UpdateRoomAsync(UpdateRoomRequest request); |
|||
} |
|||
|
|||
internal class RoomsApiClient : BaseApiClient, IRoomsApiClient |
|||
{ |
|||
internal RoomsApiClient(IHttpClient httpClient, TaskScheduler taskScheduler) : base(httpClient, taskScheduler) |
|||
{ |
|||
} |
|||
|
|||
public async Task<Response<Room>> CreateRoomAsync(CreateRoomRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response<Room>(response, ResponseHandler.HandleAsyncResponse<Room>(response)); |
|||
} |
|||
public async Task<Response> DeleteRoomAsync(DeleteRoomRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("DELETE", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response(response); |
|||
} |
|||
public async Task<Response<Room>> GetRoomAsync(GetRoomRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("GET", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response<Room>(response, ResponseHandler.HandleAsyncResponse<Room>(response)); |
|||
} |
|||
public async Task<Response<Room>> JoinRoomAsync(JoinRoomRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response<Room>(response, ResponseHandler.HandleAsyncResponse<Room>(response)); |
|||
} |
|||
public async Task<Response<QueryResponse>> QueryRoomsAsync(QueryRoomsRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response<QueryResponse>(response, ResponseHandler.HandleAsyncResponse<QueryResponse>(response)); |
|||
} |
|||
public async Task<Response> RemovePlayerAsync(RemovePlayerRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("DELETE", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response(response); |
|||
} |
|||
public async Task<Response<Room>> UpdatePlayerAsync(UpdatePlayerRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response<Room>(response, ResponseHandler.HandleAsyncResponse<Room>(response)); |
|||
} |
|||
public async Task<Response<Room>> UpdateRoomAsync(UpdateRoomRequest request) |
|||
{ |
|||
var response = await HttpClient.MakeRequestAsync("POST", request.ConstructUrl(), request.ConstructBody(), request.ConstructHeaders()); |
|||
return new Response<Room>(response, ResponseHandler.HandleAsyncResponse<Room>(response)); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 45c50a82b530ec348879befff45f9353 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Text; |
|||
using System.Text.RegularExpressions; |
|||
using Newtonsoft.Json; |
|||
using UnityEngine; |
|||
using UnityEngine.Networking; |
|||
using Unity.Services.Rooms.Models; |
|||
|
|||
namespace Unity.Services.Rooms.Rooms |
|||
{ |
|||
internal static class JsonSerialization |
|||
{ |
|||
public static byte[] Serialize<T>(T obj) |
|||
{ |
|||
return Encoding.UTF8.GetBytes(SerializeToString(obj)); |
|||
} |
|||
|
|||
public static string SerializeToString<T>(T obj) |
|||
{ |
|||
return JsonConvert.SerializeObject(obj); |
|||
} |
|||
} |
|||
[Preserve] |
|||
public class RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public List<string> AddParamsToQueryParams(List<string> queryParams, string key, string value) |
|||
{ |
|||
key = UnityWebRequest.EscapeURL(key); |
|||
value = UnityWebRequest.EscapeURL(value); |
|||
queryParams.Add($"{key}={value}"); |
|||
return queryParams; |
|||
} |
|||
|
|||
[Preserve] |
|||
public List<string> AddParamsToQueryParams(List<string> queryParams, string key, List<string> values) |
|||
{ |
|||
foreach(var value in values) |
|||
{ |
|||
string escapedValue = UnityWebRequest.EscapeURL(value); |
|||
queryParams.Add($"{UnityWebRequest.EscapeURL(key)}[]={escapedValue}"); |
|||
} |
|||
return queryParams; |
|||
} |
|||
|
|||
[Preserve] |
|||
public List<string> AddParamsToQueryParams<T>(List<string> queryParams, string key, T value) |
|||
{ |
|||
key = UnityWebRequest.EscapeURL(key); |
|||
string valueString = UnityWebRequest.EscapeURL(value.ToString()); |
|||
queryParams.Add($"{key}={valueString}"); |
|||
return queryParams; |
|||
} |
|||
|
|||
public string GenerateAcceptHeader(String[] accepts) |
|||
{ |
|||
if (accepts.Length == 0) |
|||
{ |
|||
return null; |
|||
} |
|||
for (int i = 0; i < accepts.Length; ++i) |
|||
{ |
|||
if (String.Equals(accepts[i], "application/json", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return "application/json"; |
|||
} |
|||
} |
|||
return String.Join(", ", accepts); |
|||
} |
|||
|
|||
private static readonly Regex JsonRegex = new Regex(@"application\/json(;\s)?((charset=utf8|q=[0-1]\.\d)(\s)?)*"); |
|||
|
|||
public string GenerateContentTypeHeader(String[] contentTypes) |
|||
{ |
|||
if (contentTypes.Length == 0) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
for(int i = 0; i < contentTypes.Length; ++i) |
|||
{ |
|||
if (!String.IsNullOrWhiteSpace(contentTypes[i]) && JsonRegex.IsMatch(contentTypes[i])) |
|||
{ |
|||
return contentTypes[i]; |
|||
} |
|||
} |
|||
return contentTypes[0]; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class CreateRoomRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public CreateRequest Body { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public CreateRoomRequest(string upid = default(string), string uasid = default(string), CreateRequest body = default(CreateRequest)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
Body = body; |
|||
PathAndQueryParams = $"/create"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return JsonSerialization.Serialize(Body); |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
"application/json" |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class DeleteRoomRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public string RoomId { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public DeleteRoomRequest(string upid = default(string), string uasid = default(string), string roomId = default(string)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
RoomId = roomId; |
|||
PathAndQueryParams = $"/{roomId}"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class GetRoomRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public string RoomId { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public GetRoomRequest(string upid = default(string), string uasid = default(string), string roomId = default(string)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
RoomId = roomId; |
|||
PathAndQueryParams = $"/{roomId}"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class JoinRoomRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public JoinRequest Body { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public JoinRoomRequest(string upid = default(string), string uasid = default(string), JoinRequest body = default(JoinRequest)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
Body = body; |
|||
PathAndQueryParams = $"/join"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return JsonSerialization.Serialize(Body); |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
"application/json" |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class QueryRoomsRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public QueryRequest Body { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public QueryRoomsRequest(string upid = default(string), string uasid = default(string), QueryRequest body = default(QueryRequest)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
Body = body; |
|||
PathAndQueryParams = $"/query"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return JsonSerialization.Serialize(Body); |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
"application/json" |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class RemovePlayerRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public string RoomId { get; } |
|||
[Preserve] |
|||
public string PlayerId { get; } |
|||
[Preserve] |
|||
public string Body { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public RemovePlayerRequest(string upid = default(string), string uasid = default(string), string roomId = default(string), string playerId = default(string), string body = default(string)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
RoomId = roomId; |
|||
PlayerId = playerId; |
|||
Body = body; |
|||
PathAndQueryParams = $"/{roomId}/players/{playerId}"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return JsonSerialization.Serialize(Body); |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
"application/json" |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class UpdatePlayerRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public string RoomId { get; } |
|||
[Preserve] |
|||
public string PlayerId { get; } |
|||
[Preserve] |
|||
public PlayerUpdateRequest Body { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public UpdatePlayerRequest(string upid = default(string), string uasid = default(string), string roomId = default(string), string playerId = default(string), PlayerUpdateRequest body = default(PlayerUpdateRequest)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
RoomId = roomId; |
|||
PlayerId = playerId; |
|||
Body = body; |
|||
PathAndQueryParams = $"/{roomId}/players/{playerId}"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return JsonSerialization.Serialize(Body); |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
"application/json" |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
|
|||
[Preserve] |
|||
public class UpdateRoomRequest : RoomsApiBaseRequest |
|||
{ |
|||
[Preserve] |
|||
public string Upid { get; } |
|||
[Preserve] |
|||
public string Uasid { get; } |
|||
[Preserve] |
|||
public string RoomId { get; } |
|||
[Preserve] |
|||
public UpdateRequest Body { get; } |
|||
string PathAndQueryParams; |
|||
|
|||
[Preserve] |
|||
public UpdateRoomRequest(string upid = default(string), string uasid = default(string), string roomId = default(string), UpdateRequest body = default(UpdateRequest)) |
|||
{ |
|||
Upid = upid; |
|||
Uasid = uasid; |
|||
RoomId = roomId; |
|||
Body = body; |
|||
PathAndQueryParams = $"/{roomId}"; |
|||
|
|||
List<string> queryParams = new List<string>(); |
|||
|
|||
if (queryParams.Count > 0) |
|||
{ |
|||
PathAndQueryParams = $"{PathAndQueryParams}?{string.Join("&", queryParams)}"; |
|||
} |
|||
} |
|||
|
|||
public string ConstructUrl() |
|||
{ |
|||
return Unity.Services.Rooms.Configuration.BasePath + PathAndQueryParams; |
|||
} |
|||
|
|||
public byte[] ConstructBody() |
|||
{ |
|||
return JsonSerialization.Serialize(Body); |
|||
} |
|||
|
|||
public Dictionary<string, string> ConstructHeaders() |
|||
{ |
|||
var headers = new Dictionary<string, string>(); |
|||
|
|||
String[] contentTypes = { |
|||
"application/json" |
|||
}; |
|||
|
|||
String[] accepts = { |
|||
"application/json" |
|||
}; |
|||
|
|||
var acceptHeader = GenerateAcceptHeader(accepts); |
|||
if (!string.IsNullOrEmpty(acceptHeader)) |
|||
{ |
|||
headers.Add("Accept", acceptHeader); |
|||
} |
|||
|
|||
var contentTypeHeader = GenerateContentTypeHeader(contentTypes); |
|||
if (!string.IsNullOrEmpty(contentTypeHeader)) |
|||
{ |
|||
headers.Add("Content-Type", contentTypeHeader); |
|||
} |
|||
|
|||
if(!string.IsNullOrEmpty(Upid)) |
|||
{ |
|||
headers.Add("Upid", Upid); |
|||
} |
|||
if(!string.IsNullOrEmpty(Uasid)) |
|||
{ |
|||
headers.Add("Uasid", Uasid); |
|||
} |
|||
|
|||
return headers; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b30de53e3444aae4daa5df617afbe4cf |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 40c186e87df4b364da9727e3ece4f5b8 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.Services.Rooms |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a set of configuration settings
|
|||
/// </summary>
|
|||
public class Configuration |
|||
{ |
|||
public const string RUNTIME_RESOURCE_PATH = "com.unity.services.rooms.config"; |
|||
public const string BasePath = "https://rooms.cloud.unity3d.com/api/v1/rooms"; |
|||
#region authdata
|
|||
#endregion
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1209e302f0eeb004099bb065321b1f34 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 95f2447a2a9c9054e826f8349bae1829 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.Services.Rooms.Helpers |
|||
{ |
|||
internal static class AsyncOpRetry |
|||
{ |
|||
public static AsyncOpRetry<T> FromCreateAsync<T>(Func<int, T> op) |
|||
{ |
|||
return AsyncOpRetry<T>.FromCreateAsync(op); |
|||
} |
|||
} |
|||
|
|||
internal class AsyncOpRetry<T> |
|||
{ |
|||
private uint MaxRetries { get; set; } = 4; |
|||
private float JitterMagnitude { get; set; } = 1.0f; |
|||
private float DelayScale { get; set; } = 1.0f; |
|||
private float MaxDelayTime { get; set; } = 8.0f; |
|||
private Func<int, T> CreateOperation { get; set; } |
|||
private Func<T, bool> RetryCondition { get; set; } |
|||
private Action<T> OnComplete { get; set; } |
|||
|
|||
private AsyncOpRetry(Func<int, T> createAsyncOp) |
|||
{ |
|||
CreateOperation = createAsyncOp; |
|||
} |
|||
|
|||
private static float AddJitter(float number, float magnitude) |
|||
{ |
|||
return number + (UnityEngine.Random.value * magnitude); |
|||
} |
|||
|
|||
private static float Pow2(float exponent, float scale) |
|||
{ |
|||
return (float) (Math.Pow(2.0f, exponent) * scale); |
|||
} |
|||
|
|||
private static float CalculateDelay(int attemptNumber, float maxDelayTime, float delayScale, |
|||
float jitterMagnitude) |
|||
{ |
|||
float delayTime = Pow2(attemptNumber, delayScale); |
|||
delayTime = AddJitter(delayTime, jitterMagnitude); |
|||
delayTime = Math.Min(delayTime, maxDelayTime); |
|||
return delayTime; |
|||
} |
|||
|
|||
public AsyncOpRetry<T> WithJitterMagnitude(float magnitude) |
|||
{ |
|||
JitterMagnitude = Mathf.Clamp(magnitude, 0.001f, 1.0f); |
|||
return this; |
|||
} |
|||
|
|||
public AsyncOpRetry<T> WithDelayScale(float scale) |
|||
{ |
|||
DelayScale = Mathf.Clamp(scale, 0.05f, 1.0f); |
|||
return this; |
|||
} |
|||
|
|||
public AsyncOpRetry<T> WithMaxDelayTime(float time) |
|||
{ |
|||
MaxDelayTime = Mathf.Clamp(time, 0.1f, 60.0f); |
|||
return this; |
|||
} |
|||
|
|||
public static AsyncOpRetry<T> FromCreateAsync(Func<int, T> op) |
|||
{ |
|||
return new AsyncOpRetry<T>(op); |
|||
} |
|||
|
|||
public AsyncOpRetry<T> WithRetryCondition(Func<T, bool> shouldRetry) |
|||
{ |
|||
RetryCondition = shouldRetry; |
|||
return this; |
|||
} |
|||
|
|||
public AsyncOpRetry<T> WhenComplete(Action<T> onComplete) |
|||
{ |
|||
OnComplete = onComplete; |
|||
return this; |
|||
} |
|||
|
|||
public AsyncOpRetry<T> UptoMaximumRetries(uint amount) |
|||
{ |
|||
MaxRetries = amount; |
|||
return this; |
|||
} |
|||
|
|||
public IEnumerator Run() |
|||
{ |
|||
T asyncOp = default; |
|||
for (var attempt = 0; attempt <= MaxRetries; ++attempt) |
|||
{ |
|||
asyncOp = CreateOperation(attempt + 1); |
|||
yield return asyncOp; |
|||
|
|||
if ((!RetryCondition?.Invoke(asyncOp) ?? false)) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
var delayTime = CalculateDelay(attempt, MaxDelayTime, DelayScale, JitterMagnitude); |
|||
yield return new WaitForSecondsRealtime(delayTime); |
|||
} |
|||
OnComplete?.Invoke(asyncOp); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e03f5ccd0203fce4fb6aa81987ec6f70 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.Services.Rooms.Scheduler; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public abstract class BaseApiClient |
|||
{ |
|||
protected readonly IHttpClient HttpClient; |
|||
|
|||
public BaseApiClient(IHttpClient httpClient, TaskScheduler scheduler) |
|||
{ |
|||
HttpClient = httpClient ?? new HttpClient(scheduler); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5cd4be7c1e186f9449b14ea0acbbea34 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Newtonsoft.Json; |
|||
using UnityEngine.Scripting; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
[Preserve] |
|||
public class BasicError: IError |
|||
{ |
|||
[Preserve] |
|||
public string Type { get; } |
|||
[Preserve] |
|||
public string Title { get; } |
|||
[Preserve] |
|||
public int? Status { get; } |
|||
[Preserve] |
|||
public int Code { get; } |
|||
[Preserve] |
|||
public string Detail { get; } |
|||
|
|||
[Preserve] |
|||
public BasicError(string type, string title, int? status, int code, string detail) |
|||
{ |
|||
Type = type; |
|||
Title = title; |
|||
Status = status; |
|||
Code = code; |
|||
Detail = detail; |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return JsonConvert.SerializeObject(this); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2646aadb29ec4a940a9c00d81284ce8e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
static internal class CommonErrors |
|||
{ |
|||
private const string ErrorPrefix = "com.unity.services.rooms"; |
|||
|
|||
public static IError CreateUnspecifiedHttpError(string details) |
|||
{ |
|||
return new BasicError( |
|||
$"{ErrorPrefix}http.httperror", |
|||
"Unspecified HTTP error", |
|||
null, |
|||
0, |
|||
details |
|||
); |
|||
} |
|||
|
|||
public static IError RequestOnSuccessNull => new BasicError( |
|||
$"{ErrorPrefix}onsuccessnullerror", |
|||
"Request must have an onSuccess callback", |
|||
null, |
|||
0, //TODO: define a code space for SDK side errors so all errors can be identified by a code
|
|||
""); |
|||
|
|||
|
|||
public static IError HttpNetworkError => new BasicError( |
|||
$"{ErrorPrefix}httpclient.networkerror", |
|||
"Network Error", |
|||
null, |
|||
0, |
|||
"" |
|||
); |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9fbc5aa0cdbc9aa4f8a9e5ee3f695e35 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
[Serializable] |
|||
public class DeserializationException : Exception |
|||
{ |
|||
public HttpClientResponse response; |
|||
|
|||
public DeserializationException() : base() |
|||
{ |
|||
} |
|||
|
|||
DeserializationException(string message) : base(message) |
|||
{ |
|||
} |
|||
|
|||
DeserializationException(string message, Exception inner) : base(message, inner) |
|||
{ |
|||
} |
|||
|
|||
public DeserializationException(HttpClientResponse httpClientResponse) : base( |
|||
"Unable to Deserialize Http Client Response") |
|||
{ |
|||
response = httpClientResponse; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8824ad88a91ef014d84ef9a88d56a1bd |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using UnityEngine.Networking; |
|||
using System.Threading.Tasks; |
|||
using Unity.Services.Rooms.Helpers; |
|||
using Unity.Services.Rooms.Scheduler; |
|||
using TaskScheduler = Unity.Services.Rooms.Scheduler.TaskScheduler; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public class HttpClient : IHttpClient |
|||
{ |
|||
private static readonly HashSet<string> DisallowedHeaders = new HashSet<string> |
|||
{ |
|||
"accept-charset", "access-control-request-headers", "access-control-request-method", "connection", "date", |
|||
"dnt", "expect", "host", "keep-alive", "origin", "referer", "te", "trailer", "transfer-encoding", "upgrade", |
|||
"via", "content-length", "x-unity-version", "user-agent", "cookie", "cookie2" |
|||
}; |
|||
|
|||
private static readonly List<int> ErrorCodes = new List<int> {408, 500, 502, 503, 504}; |
|||
private TaskScheduler _scheduler; |
|||
|
|||
public HttpClient(TaskScheduler scheduler) |
|||
{ |
|||
_scheduler = scheduler; |
|||
} |
|||
|
|||
public void Get(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, |
|||
int requestTimeout = 10) |
|||
{ |
|||
_scheduler.ScheduleMainThreadTask(() => |
|||
{ |
|||
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbGET, url, headers, null, |
|||
requestTimeout, onCompleted)); |
|||
}); |
|||
} |
|||
|
|||
public void Delete(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, |
|||
int requestTimeout = 10) |
|||
{ |
|||
_scheduler.ScheduleMainThreadTask(() => |
|||
{ |
|||
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbDELETE, url, headers, null, |
|||
requestTimeout, onCompleted)); |
|||
}); |
|||
} |
|||
|
|||
public void Post(string url, byte[] body, Dictionary<string, string> headers, |
|||
Action<HttpClientResponse> onCompleted, int requestTimeout = 10) |
|||
{ |
|||
_scheduler.ScheduleMainThreadTask(() => |
|||
{ |
|||
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbPOST, url, headers, body, |
|||
requestTimeout, onCompleted)); |
|||
}); |
|||
} |
|||
|
|||
public void Put(string url, byte[] body, Dictionary<string, string> headers, |
|||
Action<HttpClientResponse> onCompleted, int requestTimeout = 10) |
|||
{ |
|||
_scheduler.ScheduleMainThreadTask(() => |
|||
{ |
|||
_scheduler.StartCoroutine(ProcessRequest(UnityWebRequest.kHttpVerbPUT, url, headers, body, |
|||
requestTimeout, onCompleted)); |
|||
}); |
|||
} |
|||
|
|||
public void MakeRequest(string method, string url, byte[] body, Dictionary<string, string> headers, |
|||
Action<HttpClientResponse> onCompleted, int requestTimeout = 10) |
|||
{ |
|||
_scheduler.ScheduleMainThreadTask(() => |
|||
{ |
|||
_scheduler.StartCoroutine(ProcessRequest(method.ToUpper(), url, headers, body, requestTimeout, |
|||
onCompleted)); |
|||
}); |
|||
} |
|||
|
|||
public async Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, |
|||
Dictionary<string, string> headers, int requestTimeout = 10) |
|||
{ |
|||
return await CreateWebRequestAsync(method.ToUpper(), url, body, headers); |
|||
} |
|||
|
|||
private IEnumerator ProcessRequest(string method, string url, IDictionary<string, string> headers, byte[] body, |
|||
int requestTimeout, Action<HttpClientResponse> onCompleted) |
|||
{ |
|||
UnityWebRequestAsyncOperation SetupRequest(int attempt) |
|||
{ |
|||
// if (attempt > 1)
|
|||
// {
|
|||
// headers.Remove("X-Unity-CloudSave-Retry");
|
|||
// headers.Add("X-Unity-CloudSave-Retry", attempt.ToString());
|
|||
// }
|
|||
|
|||
var webRequest = CreateWebRequest(method, url, body, headers, requestTimeout); |
|||
return webRequest.SendWebRequest(); |
|||
} |
|||
|
|||
bool ShouldRetry(UnityWebRequestAsyncOperation request) |
|||
{ |
|||
var responseCode = (int) request.webRequest.responseCode; |
|||
return ErrorCodes.Contains(responseCode); |
|||
} |
|||
|
|||
void AsyncOpCompleted(UnityWebRequestAsyncOperation request) |
|||
{ |
|||
var internalResponse = UnityWebRequestHelpers.CreateHttpClientResponse(request); |
|||
onCompleted(internalResponse); |
|||
} |
|||
|
|||
yield return AsyncOpRetry.FromCreateAsync(SetupRequest) |
|||
.WithRetryCondition(ShouldRetry) |
|||
.WhenComplete(AsyncOpCompleted) |
|||
.Run(); |
|||
} |
|||
|
|||
private UnityWebRequest CreateWebRequest(string method, string url, byte[] body, |
|||
IDictionary<string, string> headers, int requestTimeout = 10) |
|||
{ |
|||
var request = new UnityWebRequest(url, method); |
|||
foreach (var header in headers) |
|||
{ |
|||
if (DisallowedHeaders.Contains(header.Key.ToLower())) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
|
|||
request.SetRequestHeader(header.Key, header.Value); |
|||
} |
|||
|
|||
request.timeout = requestTimeout; |
|||
if (body != null && (method == UnityWebRequest.kHttpVerbPOST || method == UnityWebRequest.kHttpVerbPUT || method == "PATCH")) |
|||
{ |
|||
request.uploadHandler = new UploadHandlerRaw(body); |
|||
} |
|||
|
|||
request.downloadHandler = new DownloadHandlerBuffer(); |
|||
return request; |
|||
} |
|||
|
|||
private async Task<HttpClientResponse> CreateWebRequestAsync(string method, string url, byte[] body, |
|||
IDictionary<string, string> headers, int requestTimeout = 10) |
|||
{ |
|||
var result = await await Task.Factory.StartNew(async () => |
|||
{ |
|||
var request = new UnityWebRequest(url, method); |
|||
foreach (var header in headers) |
|||
{ |
|||
request.SetRequestHeader(header.Key, header.Value); |
|||
} |
|||
|
|||
request.timeout = 10; |
|||
if (body != null && (method == UnityWebRequest.kHttpVerbPOST || |
|||
method == UnityWebRequest.kHttpVerbPUT || |
|||
method == "PATCH")) |
|||
{ |
|||
request.uploadHandler = new UploadHandlerRaw(body); |
|||
} |
|||
|
|||
request.downloadHandler = new DownloadHandlerBuffer(); |
|||
|
|||
return await request.SendWebRequest(); |
|||
}, CancellationToken.None, TaskCreationOptions.None, |
|||
Scheduler.ThreadHelper.TaskScheduler); |
|||
return result; |
|||
} |
|||
|
|||
internal static HttpClientResponse CreateHttpClientResponse(UnityWebRequestAsyncOperation unityResponse) |
|||
{ |
|||
var response = unityResponse.webRequest; |
|||
var result = new HttpClientResponse( |
|||
response.GetResponseHeaders(), |
|||
response.responseCode, |
|||
response.isHttpError, |
|||
response.isNetworkError, |
|||
response.downloadHandler.data, |
|||
response.error); |
|||
return result; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fd42941bf28cf604fbdf576e45c1f61d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public class HttpClientResponse |
|||
{ |
|||
public HttpClientResponse(Dictionary<string, string> headers, long responseCode, bool isHttpError, bool isNetworkError, byte[] data, string errorMessage) |
|||
{ |
|||
Headers = headers; |
|||
ResponseCode = responseCode; |
|||
IsHttpError = isHttpError; |
|||
IsNetworkError = isNetworkError; |
|||
Data = data; |
|||
ErrorMessage = errorMessage; |
|||
} |
|||
|
|||
public Dictionary<string, string> Headers { get; } |
|||
public long ResponseCode { get; } |
|||
public bool IsHttpError { get; } |
|||
public bool IsNetworkError { get; } |
|||
public byte[] Data { get;} |
|||
public string ErrorMessage { get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: babb58553f6f5ef4299a8ac5da3773d1 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.Services.Rooms; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
[Serializable] |
|||
public class HttpException : Exception |
|||
{ |
|||
public HttpClientResponse Response; |
|||
|
|||
public HttpException() : base() |
|||
{ |
|||
} |
|||
|
|||
public HttpException(string message) : base(message) |
|||
{ |
|||
} |
|||
|
|||
public HttpException(string message, Exception inner) : base(message, inner) |
|||
{ |
|||
} |
|||
|
|||
public HttpException(HttpClientResponse response) : base(response.ErrorMessage) |
|||
{ |
|||
Response = response; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c3b8677749a4bb747b327dd2d524d0a8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public interface IError |
|||
{ |
|||
string Type { get; } |
|||
string Title { get; } |
|||
int? Status { get; } |
|||
int Code { get; } |
|||
string Detail { get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 414d5d3ade9ba6143b2ca4a54063bf9b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public interface IHttpClient |
|||
{ |
|||
void Get(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10); |
|||
void Delete(string url, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10); |
|||
void Post(string url, byte[] body, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10); |
|||
void Put(string url, byte[] body, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10); |
|||
void MakeRequest(string method, string url, byte[] body, Dictionary<string, string> headers, Action<HttpClientResponse> onCompleted, int requestTimeout = 10); |
|||
Task<HttpClientResponse> MakeRequestAsync(string method, string url, byte[] body, Dictionary<string, string> headers, int requestTimeout = 10); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8f919508e7564414c940b5128357ad1c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
internal static class JsonHelpers |
|||
{ |
|||
internal static bool TryParseJson<T>(this string @this, out T result) |
|||
{ |
|||
var success = true; |
|||
var settings = new JsonSerializerSettings |
|||
{ |
|||
Error = (sender, args) => |
|||
{ |
|||
success = false; |
|||
args.ErrorContext.Handled = true; |
|||
}, |
|||
MissingMemberHandling = MissingMemberHandling.Ignore |
|||
}; |
|||
result = JsonConvert.DeserializeObject<T>(@this, settings); |
|||
return success; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2b7fe3f2f8426d7429a591dd03638ce8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Text; |
|||
using Unity.Services.Rooms.Http; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public static class ResponseHandler |
|||
{ |
|||
public static bool TryDeserializeResponse<T>(HttpClientResponse response, out string decodedJsonString, |
|||
out T dataObject) |
|||
{ |
|||
var data = response.Data; |
|||
decodedJsonString = Encoding.UTF8.GetString(data); |
|||
var didDecodeSuccessfully = decodedJsonString.TryParseJson(out dataObject); |
|||
return didDecodeSuccessfully; |
|||
} |
|||
|
|||
public static IError DeserializeError(HttpClientResponse response) |
|||
{ |
|||
var data = response.Data; |
|||
var decodedJsonString = Encoding.UTF8.GetString(data); |
|||
|
|||
if (!decodedJsonString.TryParseJson(out BasicError error)) |
|||
{ |
|||
return CommonErrors.CreateUnspecifiedHttpError(decodedJsonString); |
|||
} |
|||
|
|||
switch (error.Type) |
|||
{ |
|||
case "problems/basic": |
|||
return error; |
|||
default: |
|||
return CommonErrors.CreateUnspecifiedHttpError(decodedJsonString); |
|||
} |
|||
} |
|||
|
|||
public static void HandleAsyncResponse(HttpClientResponse response) |
|||
{ |
|||
if (response.IsHttpError || response.IsNetworkError) |
|||
{ |
|||
throw new HttpException(response); |
|||
} |
|||
} |
|||
|
|||
public static T HandleAsyncResponse<T>(HttpClientResponse response) where T : class |
|||
{ |
|||
HandleAsyncResponse(response); |
|||
|
|||
var couldDeserialize = ResponseHandler.TryDeserializeResponse(response, out var decodedJson, out T result); |
|||
if (!couldDeserialize) |
|||
{ |
|||
throw new DeserializationException(response); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fec10e52f76cd8a46b35432fecc9f246 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Unity.Services.Rooms.Http; |
|||
|
|||
namespace Unity.Services.Rooms |
|||
{ |
|||
public class Response { |
|||
public Dictionary<string, string> Headers { get; } |
|||
public long Status { get; set; } |
|||
|
|||
public Response(HttpClientResponse httpResponse) |
|||
{ |
|||
this.Headers = httpResponse.Headers; |
|||
this.Status = httpResponse.ResponseCode; |
|||
} |
|||
} |
|||
|
|||
public class Response<T> : Response |
|||
{ |
|||
public T Result { get; } |
|||
|
|||
public Response(HttpClientResponse httpResponse, T result): base(httpResponse) |
|||
{ |
|||
this.Result = result; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e0d3b4e8d1a9fb74b8c73ba34dd5be2e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Threading.Tasks; |
|||
using UnityEngine.Networking; |
|||
|
|||
namespace Unity.Services.Rooms.Http |
|||
{ |
|||
public static class UnityWebRequestHelpers |
|||
{ |
|||
public static TaskAwaiter<HttpClientResponse> GetAwaiter(this UnityWebRequestAsyncOperation asyncOp) |
|||
{ |
|||
var tcs = new TaskCompletionSource<HttpClientResponse>(); |
|||
|
|||
asyncOp.completed += obj => |
|||
{ |
|||
var result = CreateHttpClientResponse((UnityWebRequestAsyncOperation) obj); |
|||
tcs.SetResult(result); |
|||
}; |
|||
return tcs.Task.GetAwaiter(); |
|||
} |
|||
|
|||
internal static HttpClientResponse CreateHttpClientResponse(UnityWebRequestAsyncOperation unityResponse) |
|||
{ |
|||
var response = unityResponse.webRequest; |
|||
var result = new HttpClientResponse( |
|||
response.GetResponseHeaders(), |
|||
response.responseCode, |
|||
response.isHttpError, |
|||
response.isNetworkError, |
|||
response.downloadHandler.data, |
|||
response.error); |
|||
return result; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 91fa5984aa9808642be77d45b49b248b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 5090daa904f04fa44bf3e529ccbc4f13 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "CreateRequest")] |
|||
public class CreateRequest |
|||
{ |
|||
[Preserve] |
|||
public CreateRequest(string name, Player player, Dictionary<string, DataObject> data = default(Dictionary<string, DataObject>), bool? isPrivate = false, int? maxPlayers = default(int?)) |
|||
{ |
|||
Name = name; |
|||
Player = player; |
|||
Data = data; |
|||
IsPrivate = isPrivate; |
|||
MaxPlayers = maxPlayers; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "name", IsRequired = true, EmitDefaultValue = false)] |
|||
public string Name{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "player", IsRequired = true, EmitDefaultValue = false)] |
|||
public Player Player{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "data", EmitDefaultValue = false)] |
|||
public Dictionary<string, DataObject> Data{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "isPrivate", EmitDefaultValue = true)] |
|||
public bool? IsPrivate{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "maxPlayers", EmitDefaultValue = false)] |
|||
public int? MaxPlayers{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: cf497c409c924cc40add89affaad2bd3 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "DataObject")] |
|||
public class DataObject |
|||
{ |
|||
[Preserve] |
|||
public DataObject(string index = default(string), string value = default(string), string visibility = default(string)) |
|||
{ |
|||
Index = index; |
|||
Value = value; |
|||
Visibility = visibility; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "index", EmitDefaultValue = false)] |
|||
public string Index{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "value", EmitDefaultValue = false)] |
|||
public string Value{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "visibility", EmitDefaultValue = false)] |
|||
public string Visibility{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 567a8c599bc028f4e855bfe580efda37 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "Detail")] |
|||
public class Detail |
|||
{ |
|||
[Preserve] |
|||
public Detail(string errorType = default(string), string message = default(string)) |
|||
{ |
|||
ErrorType = errorType; |
|||
Message = message; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "errorType", EmitDefaultValue = false)] |
|||
public string ErrorType{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "message", EmitDefaultValue = false)] |
|||
public string Message{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 0c825d7b574aad247b6c528d89da0ca6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "ErrorStatus")] |
|||
public class ErrorStatus |
|||
{ |
|||
[Preserve] |
|||
public ErrorStatus(List<Detail> details = default(List<Detail>), int status = default(int), string title = default(string)) |
|||
{ |
|||
Details = details; |
|||
Status = status; |
|||
Title = title; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "details", EmitDefaultValue = false)] |
|||
public List<Detail> Details{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "status", EmitDefaultValue = false)] |
|||
public int Status{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "title", EmitDefaultValue = false)] |
|||
public string Title{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6b4ea526eef30a5459448bea29514d74 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "JoinRequest")] |
|||
public class JoinRequest |
|||
{ |
|||
[Preserve] |
|||
public JoinRequest(string id = default(string), Player player = default(Player), string roomCode = default(string)) |
|||
{ |
|||
Id = id; |
|||
Player = player; |
|||
RoomCode = roomCode; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "id", EmitDefaultValue = false)] |
|||
public string Id{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "player", EmitDefaultValue = false)] |
|||
public Player Player{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "roomCode", EmitDefaultValue = false)] |
|||
public string RoomCode{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b9a0d1263bcbc4f47a0f82e74ba0853f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "Player")] |
|||
public class Player |
|||
{ |
|||
[Preserve] |
|||
public Player(string id, string connectionInfo = default(string), Dictionary<string, DataObject> data = default(Dictionary<string, DataObject>)) |
|||
{ |
|||
Id = id; |
|||
ConnectionInfo = connectionInfo; |
|||
Data = data; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "id", IsRequired = true, EmitDefaultValue = false)] |
|||
public string Id{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "connectionInfo", EmitDefaultValue = false)] |
|||
public string ConnectionInfo{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "data", EmitDefaultValue = false)] |
|||
public Dictionary<string, DataObject> Data{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 885e9582c1c04fa489ca4be60f734da6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "PlayerUpdateRequest")] |
|||
public class PlayerUpdateRequest |
|||
{ |
|||
[Preserve] |
|||
public PlayerUpdateRequest(string connectionInfo = default(string), Dictionary<string, DataObject> data = default(Dictionary<string, DataObject>)) |
|||
{ |
|||
ConnectionInfo = connectionInfo; |
|||
Data = data; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "connectionInfo", EmitDefaultValue = false)] |
|||
public string ConnectionInfo{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "data", EmitDefaultValue = false)] |
|||
public Dictionary<string, DataObject> Data{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: daa1bf4a1727aa64599fdcd5d5be588b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "QueryFilter")] |
|||
public class QueryFilter |
|||
{ |
|||
[Preserve] |
|||
public QueryFilter(string field = default(string), string op = default(string), string value = default(string)) |
|||
{ |
|||
Field = field; |
|||
Op = op; |
|||
Value = value; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "field", EmitDefaultValue = false)] |
|||
public string Field{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "op", EmitDefaultValue = false)] |
|||
public string Op{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "value", EmitDefaultValue = false)] |
|||
public string Value{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: aec32cfe0966be2499a072c25a1b343f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Scripting; |
|||
using System.Runtime.Serialization; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
|
|||
|
|||
namespace Unity.Services.Rooms.Models |
|||
{ |
|||
[Preserve] |
|||
[DataContract(Name = "QueryRequest")] |
|||
public class QueryRequest |
|||
{ |
|||
[Preserve] |
|||
public QueryRequest(int? count = default(int?), List<QueryFilter> filter = default(List<QueryFilter>)) |
|||
{ |
|||
Count = count; |
|||
Filter = filter; |
|||
} |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "count", EmitDefaultValue = false)] |
|||
public int? Count{ get; } |
|||
|
|||
[Preserve] |
|||
[DataMember(Name = "filter", EmitDefaultValue = false)] |
|||
public List<QueryFilter> Filter{ get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 76314c266bb4f884e97618aa5031f131 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
部分文件因为文件数量过多而无法显示
撰写
预览
正在加载...
取消
保存
Reference in new issue