(LocalVersionFilePath).text;
22 |
23 | string localVersionText = LocalVersion;
24 | Debug.Log("Local version text : " + LocalVersion);
25 |
26 | string latesteVersionText = client.DownloadString(ExternalLinks.RemoteVersionURL);
27 | Debug.Log("latest version text got: " + latesteVersionText);
28 | string messageBody = "Current Version: " + localVersionText +"\n"
29 | +"Latest Version: " + latesteVersionText + "\n";
30 | var latestVersion = new Version(latesteVersionText);
31 | var localVersion = new Version(localVersionText);
32 |
33 | if (latestVersion > localVersion)
34 | {
35 | Debug.Log("There's a newer version");
36 | messageBody += "There's a newer version available";
37 | if(EditorUtility.DisplayDialog("Check for update.", messageBody, "Get latest release", "Close"))
38 | {
39 | Application.OpenURL(ExternalLinks.Releases);
40 | }
41 | }
42 | else
43 | {
44 | Debug.Log("Current version is up-to-date.");
45 | messageBody += "Current version is up-to-date.";
46 | EditorUtility.DisplayDialog("Check for update.", messageBody,"OK");
47 | }
48 |
49 | }
50 | catch (Exception exp)
51 | {
52 | Debug.LogError("Error with checking update. Exception: " + exp);
53 | EditorUtility.DisplayDialog("Update Error","Error with checking update. \nSee console for more details.",
54 | "OK"
55 | );
56 | }
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ParrelSync/Editor/UpdateChecker.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d3453b3f1a20ea148b5028f8556a7be5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs:
--------------------------------------------------------------------------------
1 | namespace ParrelSync
2 | {
3 | using UnityEditor;
4 | using UnityEngine;
5 | using System;
6 | using System.Text;
7 | using System.Security.Cryptography;
8 | using System.IO;
9 | using System.Linq;
10 |
11 | [InitializeOnLoad]
12 | public class ValidateCopiedFoldersIntegrity
13 | {
14 | const string SessionStateKey = "ValidateCopiedFoldersIntegrity_Init";
15 | ///
16 | /// Called once on editor startup.
17 | /// Validate copied folders integrity in clone project
18 | ///
19 | static ValidateCopiedFoldersIntegrity()
20 | {
21 | if (!SessionState.GetBool(SessionStateKey, false))
22 | {
23 | SessionState.SetBool(SessionStateKey, true);
24 | if (!ClonesManager.IsClone()) { return; }
25 |
26 | ValidateFolder(ClonesManager.GetCurrentProjectPath(), ClonesManager.GetOriginalProjectPath(), "Packages");
27 | }
28 | }
29 |
30 | public static void ValidateFolder(string targetRoot, string originalRoot, string folderName)
31 | {
32 | var targetFolderPath = Path.Combine(targetRoot, folderName);
33 | var targetFolderHash = CreateMd5ForFolder(targetFolderPath);
34 |
35 | var originalFolderPath = Path.Combine(originalRoot, folderName);
36 | var originalFolderHash = CreateMd5ForFolder(originalFolderPath);
37 |
38 | if (targetFolderHash != originalFolderHash)
39 | {
40 | Debug.Log("ParrelSync: Detected changes in '" + folderName + "' directory. Updating cloned project...");
41 | FileUtil.ReplaceDirectory(originalFolderPath, targetFolderPath);
42 | }
43 | }
44 |
45 | static string CreateMd5ForFolder(string path)
46 | {
47 | // assuming you want to include nested folders
48 | var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
49 | .OrderBy(p => p).ToList();
50 |
51 | MD5 md5 = MD5.Create();
52 |
53 | for (int i = 0; i < files.Count; i++)
54 | {
55 | string file = files[i];
56 |
57 | // hash path
58 | string relativePath = file.Substring(path.Length + 1);
59 | byte[] pathBytes = Encoding.UTF8.GetBytes(relativePath.ToLower());
60 | md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
61 |
62 | // hash contents
63 | byte[] contentBytes = File.ReadAllBytes(file);
64 | if (i == files.Count - 1)
65 | md5.TransformFinalBlock(contentBytes, 0, contentBytes.Length);
66 | else
67 | md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0);
68 | }
69 |
70 | return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower();
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/ParrelSync/Editor/ValidateCopiedFoldersIntegrity.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d8fb344b9abf5274abd744833474b087
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ParrelSync/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.veriorpies.parrelsync",
3 | "displayName": "ParrelSync",
4 | "version": "1.5.2",
5 | "unity": "2018.4",
6 | "description": "ParrelSync is a Unity editor extension that allows users to test multiplayer gameplay without building the project by having another Unity editor window opened and mirror the changes from the original project.",
7 | "license": "MIT",
8 | "keywords": [ "Networking", "Utils", "Editor", "Extensions" ],
9 | "dependencies": {}
10 | }
--------------------------------------------------------------------------------
/ParrelSync/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a2a889c264e34b47a7349cbcb2cbedd7
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/ParrelSync/projectCloner.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ParrelSync",
3 | "references": [],
4 | "includePlatforms": [
5 | "Editor"
6 | ],
7 | "excludePlatforms": [],
8 | "allowUnsafeCode": false,
9 | "overrideReferences": false,
10 | "precompiledReferences": [],
11 | "autoReferenced": true,
12 | "defineConstraints": [],
13 | "versionDefines": [],
14 | "noEngineReferences": false
15 | }
--------------------------------------------------------------------------------
/ParrelSync/projectCloner.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 894a6cc6ed5cd2645bb542978cbed6a9
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ParrelSync
2 | [](https://github.com/VeriorPies/ParrelSync/releases) [](https://github.com/VeriorPies/ParrelSync/wiki) [](https://github.com/VeriorPies/ParrelSync/blob/master/LICENSE.md) [](https://github.com/VeriorPies/ParrelSync/pulls) [](https://discord.gg/TmQk2qG)
3 |
4 | ParrelSync is a Unity editor extension that allows users to test multiplayer gameplay without building the project by having another Unity editor window opened and mirror the changes from the original project.
5 |
6 |
7 |
8 | 
9 |
10 | Test project changes on clients and server within seconds - both in editor
11 |
12 |
13 |
14 |
15 | ## Features
16 | 1. Test multiplayer gameplay without building the project
17 | 2. GUI tools for managing all project clones
18 | 3. Protected assets from being modified by other clone instances
19 | 4. Handy APIs to speed up testing workflows
20 | ## Installation
21 |
22 | 1. Backup your project folder or use a version control system such as [Git](https://git-scm.com/) or [SVN](https://subversion.apache.org/)
23 | 2. Download .unitypackage from the [latest release](https://github.com/VeriorPies/ParrelSync/releases) and import it to your project.
24 | 3. ParrelSync should appreared in the menu item bar after imported
25 | 
26 |
27 | Check out the [Installation-and-Update](https://github.com/VeriorPies/ParrelSync/wiki/Installation-and-Update) page for more details.
28 |
29 | ### UPM Package
30 | ParrelSync can also be installed via UPM package.
31 | After Unity 2019.3.4f1, Unity 2020.1a21, which support path query parameter of git package. You can install ParrelSync by adding the following to Package Manager.
32 |
33 | ```
34 | https://github.com/VeriorPies/ParrelSync.git?path=/ParrelSync
35 | ```
36 |
37 |
38 |  
39 |
40 | or by adding
41 |
42 | ```
43 | "com.veriorpies.parrelsync": "https://github.com/VeriorPies/ParrelSync.git?path=/ParrelSync"
44 | ```
45 |
46 | to the `Packages/manifest.json` file
47 |
48 |
49 | ## Supported Platform
50 | Currently, ParrelSync supports Windows, macOS and Linux editors.
51 |
52 | ParrelSync has been tested with the following Unity version. However, it should also work with other versions as well.
53 | * *2022.3.56f1 LTS*
54 | * *2021.3.29f1 LTS*
55 | * *2020.3.1f1 LTS*
56 |
57 |
58 | ## APIs
59 | There's some useful APIs for speeding up the multiplayer testing workflow.
60 | Here's a basic example:
61 | ```
62 | if (ClonesManager.IsClone()) {
63 | // Automatically connect to local host if this is the clone editor
64 | }else{
65 | // Automatically start server if this is the original editor
66 | }
67 | ```
68 | Check out [the doc](https://github.com/VeriorPies/ParrelSync/wiki/List-of-APIs) to view the complete API list.
69 |
70 | ## How does it work?
71 | For each clone instance, ParrelSync will make a copy of the original project folder and reference the ```Asset```, ```Packages``` and ```ProjectSettings``` folder back to the original project with [symbolic link](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mklink). Other folders such as ```Library```, ```Temp```, and ```obj``` will remain independent for each clone project.
72 |
73 | All clones are placed right next to the original project with suffix *```_clone_x```*, which will be something like this in the folder hierarchy.
74 | ```
75 | /ProjectName
76 | /ProjectName_clone_0
77 | /ProjectName_clone_1
78 | ...
79 | ```
80 | ## Discord Server
81 | We have a [Discord server](https://discord.gg/TmQk2qG).
82 |
83 | ## Need Help?
84 | Some common questions and troubleshooting can be found under the [Troubleshooting & FAQs](https://github.com/VeriorPies/ParrelSync/wiki/Troubleshooting-&-FAQs) page.
85 | You can also [create a question post](https://github.com/VeriorPies/ParrelSync/issues/new/choose), or ask on [Discord](https://discord.gg/TmQk2qG) if you prefer to have a real-time conversation.
86 |
87 | ## Support this project
88 | A star will be appreciated :)
89 |
90 | ## Credits
91 | This project is originated from hwaet's [UnityProjectCloner](https://github.com/hwaet/UnityProjectCloner)
92 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fa3f2fa6aced9b54b970c8996957df3b
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/VERSION.txt:
--------------------------------------------------------------------------------
1 | 1.5.2
--------------------------------------------------------------------------------
/VERSION.txt.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9833b240625d4e14995c296b87e34b96
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------