Skip to content

Instantly share code, notes, and snippets.

@sommerper
Last active May 23, 2020 18:25
Show Gist options
  • Select an option

  • Save sommerper/ae19737f74d3d4f08753d39b25832cf7 to your computer and use it in GitHub Desktop.

Select an option

Save sommerper/ae19737f74d3d4f08753d39b25832cf7 to your computer and use it in GitHub Desktop.
Some example files for building and running multiple instances of a multiplayer Unity game
using System;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Diagnostics;
public static class MultiplayersBuildAndRun
{
[MenuItem("Multiplayer/Build and Run %#z")]
static void BuildAndRun()
{
PerformMacOSBuild();
string dataPathRev = Reverse(Application.dataPath);
string scriptPath = dataPathRev.Substring(dataPathRev.IndexOf("/"), dataPathRev.Length - dataPathRev.IndexOf("/"));
string path = Reverse(scriptPath);
scriptPath = path + "run.sh";
UnityEngine.Debug.Log(path);
UnityEngine.Debug.Log(scriptPath);
using (var process = new Process())
{
process.StartInfo.FileName = "osascript";
process.StartInfo.Arguments = string.Format("-e 'tell application \"Terminal\" to do script \"cd {0} && ./{1} \"'", path, "run.sh");
process.StartInfo.WorkingDirectory = path;
process.StartInfo.UseShellExecute = false;
process.Start();
// string strOutput = process.StandardOutput.ReadToEnd();
process.WaitForExit();
// UnityEngine.Debug.Log(strOutput);
process.Close();
}
}
static void PerformMacOSBuild()
{
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneOSX);
BuildPipeline.BuildPlayer(GetScenePaths(), "Builds/MacOS/" + GetProjectName(), BuildTarget.StandaloneOSX, BuildOptions.AllowDebugging);
}
static string GetProjectName()
{
string[] s = Application.dataPath.Split('/');
return s[s.Length - 2];
}
static string[] GetScenePaths()
{
string[] scenes = new string[EditorBuildSettings.scenes.Length];
for (int i = 0; i < scenes.Length; i++)
{
scenes[i] = EditorBuildSettings.scenes[i].path;
}
return scenes;
}
public static string Reverse(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
using System;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public static class MultiplayersBuildAndRun
{
[MenuItem("Multiplayer/Build and Run %#z")]
static void BuildAndRun ()
{
PerformWin64Build(1);
string dataPathRev = Reverse(Application.dataPath);
string batPath = dataPathRev.Substring(dataPathRev.IndexOf("/"), dataPathRev.Length - dataPathRev.IndexOf("/"));
batPath = Reverse(batPath) + "Builds/run.bat";
Debug.Log(batPath);
System.Diagnostics.Process.Start(batPath);
}
static void PerformWin64Build (int playerCount)
{
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows);
for (int i = 1; i <= playerCount; i++)
{
BuildPipeline.BuildPlayer(GetScenePaths(), "Builds/Win64/" + GetProjectName() + i.ToString() + ".exe", BuildTarget.StandaloneWindows64, BuildOptions.AllowDebugging);
}
}
static string GetProjectName ()
{
string[] s = Application.dataPath.Split('/');
return s[s.Length - 2];
}
static string[] GetScenePaths ()
{
string[] scenes = new string[EditorBuildSettings.scenes.Length];
for (int i = 0; i < scenes.Length; i++)
{
scenes[i] = EditorBuildSettings.scenes[i].path;
}
return scenes;
}
public static string Reverse (string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;
using TMPro;
public class PlaceWindow : MonoBehaviour
{
public TextMeshProUGUI outputText;
#if UNITY_STANDALONE_WIN
[DllImport("user32.dll", EntryPoint = "SetWindowText")]
public static extern bool SetWindowText (System.IntPtr hwnd, System.String lpString);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern bool SetWindowPos (IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow (System.String className, System.String windowName);
public static void SetPosition (string name, int x, int y, int resX = 0, int resY = 0)
{
System.IntPtr windowPtr = FindWindow(null, "GAME WINDOW NAME");
SetWindowText(windowPtr, name);
SetWindowPos(FindWindow(null, name), 0, x, y, resX, resY, resX * resY == 0 ? 1 : 0);
}
public void PositionWindow(string name, int x, int y)
{
SetPosition(name, x, y);
}
#endif
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using TMPro;
using UnityEngine;
public class ReadCommandArgs : MonoBehaviour
{
public TextMeshProUGUI outputText;
void Start ()
{
string[] args = System.Environment.GetCommandLineArgs();
outputText.text += "\n";
string type = "editor";
string name = "";
string posX = "";
string posY = "";
int x = 0;
int y = 0;
for (int i = 0; i < args.Length; i++)
{
string input = "";
Debug.Log("ARG " + i + ": " + args[i]);
outputText.text += "ARG " + i + ": " + args[i] + "\n";
if (args[i] == "-type")
{
input = args[i + 1];
type = input;
outputText.text += "type " + type + "\n";
}
if (args[i] == "-name")
{
input = args[i + 1];
name = input;
}
if (args[i] == "-posX")
{
input = args[i + 1];
posX = input;
x = Int32.Parse(posX);
}
if (args[i] == "-posY")
{
input = args[i + 1];
posY = input;
y = Int32.Parse(posY);
}
}
if (type == "server" || type == "editor")
{
outputText.text += "initializing server \n";
string windowName = type;
GetComponent<PlaceWindow>().PositionWindow(windowName, x, y);
//MasterGameServer sc = gameObject.AddComponent(typeof(MasterGameServer)) as MasterGameServer;
MasterGameServer masterGameServer = gameObject.AddComponent<MasterGameServer>();
masterGameServer.Initialize();
}
else if (type == "client")
{
outputText.text += "initializing client \n";
string windowName = type + " " + name;
GetComponent<PlaceWindow>().PositionWindow(windowName, x, y);
GameClient gameClient = gameObject.AddComponent<GameClient>();
gameClient.Initialize();
}
}
}
start Builds/Win64/GAME.exe -type server -posX 0 -posY 0
timeout 4
start Builds/Win64/GAME.exe -type client -name player1 -posX 0 -posY 520
timeout 3
start Builds/Win64/GAME.exe -type client -name player2 -posX 650 -posY 520
# osascript <<'END'
# display dialog "It Works"
# END
open -n Builds/MacOS/GAME_NAME.app --args -type server
sleep 5
open -n Builds/MacOS/GAME_NAME.app --args -type client -name player1
sleep 5
open -n Builds/MacOS/GAME_NAME.app --args -type client -name player2
sleep 5
osascript <<'END'
set thePosition to {100, 100}
tell application "System Events"
set pidList to the unix id of (processes whose name contains "GAME PROCESS ID")
repeat with someID in pidList -- loop
tell (first process whose unix id is someID)
set position of window "GAME_NAME" to thePosition
end tell
set item 1 of thePosition to (item 1 of thePosition) + 500 -- add 500 to the left (for the next window)
end repeat
end tell
END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment