Editor/VSIntergration.cs
Синтаксис:
Используется csharp
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using FlexibleGameServer;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class VSIntergration
{
static VSIntergration()
{
if (_instance == null) _instance = new VSIntergration();
}
static VSIntergration _instance;
#pragma warning disable 414
StreamWriter _fileLock;
#pragma warning restore 414
readonly StopwatchInt _lastChange = new StopwatchInt();
public VSIntergration()
{
var dir = Application.dataPath;
dir = Path.Combine(dir.Substring(0, dir.Length - "/Assets".Length).Replace('/', Path.DirectorySeparatorChar), "obj");
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
_fileLock = File.CreateText(Path.Combine(dir, "vs-integration-lock"));
_projectId = new MD5CryptoServiceProvider().GetHashString(Application.dataPath);
_watcher = new FileSystemWatcher(dir)
{
NotifyFilter =
NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite |
NotifyFilters.Size,
IncludeSubdirectories = true,
EnableRaisingEvents = true
};
_watcher.Deleted += (s, ev) => _lastChange.Restart();
_watcher.Created += (s, ev) => _lastChange.Restart();
_watcher.Changed += (s, ev) => _lastChange.Restart();
if (EditorApplication.timeSinceStartup < 10.0) _needPlay = false;
//UnityEngine.Debug.Log("_needPlay = " + _needPlay);
EditorApplication.update += EditorUpdate;
/*
var windowLayoutType = Assembly.GetAssembly(typeof(EditorUtility)).GetType("UnityEditor.WindowLayout");
var findMainWindowMethod = windowLayoutType.GetMethod("FindMainWindow", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var mainWindow = findMainWindowMethod.Invoke(null, new object[0]);
var mainWindowType = mainWindow.GetType();
var windowField = mainWindowType.BaseType.GetProperty("window", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var window = windowField.GetValue(mainWindow, null);
var windowType = window.GetType();
var ptrField = windowType.GetField("m_WindowPtr", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var ptr = ptrField.GetValue(window);
var ptrValueField = ptr.GetType().GetField("m_IntPtr", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var mainWindowPointer = (int)ptrValueField.GetValue(ptr);
*/
}
readonly FileSystemWatcher _watcher;
string _projectId;
bool _needPlay
{
get
{
return EditorPrefs.GetBool("VSIntegration-needPlay-" + _projectId, false);
}
set
{
if (_needPlay != value) EditorPrefs.SetBool("VSIntegration-needPlay-" + _projectId, value);
}
}
void EditorUpdate()
{
if (EditorApplication.isCompiling && (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused))
{
EditorApplication.isPlaying = false;
EditorApplication.isPaused = false;
}
if (!_needPlay && _lastChange.IsRunning && (_lastChange.ElapsedMilliseconds > 500))
{
if (EditorApplication.isPlayingOrWillChangePlaymode) EditorApplication.isPlaying = false;
UnityEngine.Debug.Log("set needPlay = true");
AssetDatabase.Refresh();
_lastChange.Stop();
_needPlay = true;
}
else if (_needPlay && !EditorApplication.isCompiling)
{
_needPlay = false;
_lastChange.Stop();
//Debug.Log("needPlay");
AssetDatabase.Refresh();
EditorApplication.isPlaying = true;
}
}
}
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using FlexibleGameServer;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class VSIntergration
{
static VSIntergration()
{
if (_instance == null) _instance = new VSIntergration();
}
static VSIntergration _instance;
#pragma warning disable 414
StreamWriter _fileLock;
#pragma warning restore 414
readonly StopwatchInt _lastChange = new StopwatchInt();
public VSIntergration()
{
var dir = Application.dataPath;
dir = Path.Combine(dir.Substring(0, dir.Length - "/Assets".Length).Replace('/', Path.DirectorySeparatorChar), "obj");
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
_fileLock = File.CreateText(Path.Combine(dir, "vs-integration-lock"));
_projectId = new MD5CryptoServiceProvider().GetHashString(Application.dataPath);
_watcher = new FileSystemWatcher(dir)
{
NotifyFilter =
NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite |
NotifyFilters.Size,
IncludeSubdirectories = true,
EnableRaisingEvents = true
};
_watcher.Deleted += (s, ev) => _lastChange.Restart();
_watcher.Created += (s, ev) => _lastChange.Restart();
_watcher.Changed += (s, ev) => _lastChange.Restart();
if (EditorApplication.timeSinceStartup < 10.0) _needPlay = false;
//UnityEngine.Debug.Log("_needPlay = " + _needPlay);
EditorApplication.update += EditorUpdate;
/*
var windowLayoutType = Assembly.GetAssembly(typeof(EditorUtility)).GetType("UnityEditor.WindowLayout");
var findMainWindowMethod = windowLayoutType.GetMethod("FindMainWindow", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var mainWindow = findMainWindowMethod.Invoke(null, new object[0]);
var mainWindowType = mainWindow.GetType();
var windowField = mainWindowType.BaseType.GetProperty("window", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var window = windowField.GetValue(mainWindow, null);
var windowType = window.GetType();
var ptrField = windowType.GetField("m_WindowPtr", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var ptr = ptrField.GetValue(window);
var ptrValueField = ptr.GetType().GetField("m_IntPtr", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
var mainWindowPointer = (int)ptrValueField.GetValue(ptr);
*/
}
readonly FileSystemWatcher _watcher;
string _projectId;
bool _needPlay
{
get
{
return EditorPrefs.GetBool("VSIntegration-needPlay-" + _projectId, false);
}
set
{
if (_needPlay != value) EditorPrefs.SetBool("VSIntegration-needPlay-" + _projectId, value);
}
}
void EditorUpdate()
{
if (EditorApplication.isCompiling && (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused))
{
EditorApplication.isPlaying = false;
EditorApplication.isPaused = false;
}
if (!_needPlay && _lastChange.IsRunning && (_lastChange.ElapsedMilliseconds > 500))
{
if (EditorApplication.isPlayingOrWillChangePlaymode) EditorApplication.isPlaying = false;
UnityEngine.Debug.Log("set needPlay = true");
AssetDatabase.Refresh();
_lastChange.Stop();
_needPlay = true;
}
else if (_needPlay && !EditorApplication.isCompiling)
{
_needPlay = false;
_lastChange.Stop();
//Debug.Log("needPlay");
AssetDatabase.Refresh();
EditorApplication.isPlaying = true;
}
}
}
Используется StopwatchInt.cs
Синтаксис:
Используется csharp
using System;
using System.Security.Cryptography;
using System.Text;
namespace FlexibleGameServer
{
public class StopwatchInt
{
int _startedAt;
int _ellapsed;
/// <summary>
/// Initializes a new instance of the <see cref="T:FlexibleGameServer.StopwatchInt"/> class.
/// </summary>
public StopwatchInt()
{
}
/// <summary>
/// Starts measuring elapsed time for an interval.
/// </summary>
/// <filterpriority>1</filterpriority>
public void Start()
{
if (IsRunning) throw new InvalidOperationException();
_ellapsed = 0;
_startedAt = Environment.TickCount;
IsRunning = true;
}
/// <summary>
/// Initializes a new <see cref="T:FlexibleGameServer.StopwatchInt"/> instance, sets the elapsed time property to zero, and starts measuring elapsed time.
/// </summary>
///
/// <returns>
/// A <see cref="T:FlexibleGameServer.StopwatchInt"/> that has just begun measuring elapsed time.
/// </returns>
/// <filterpriority>1</filterpriority>
public static StopwatchInt StartNew()
{
var sw = new StopwatchInt();
sw.Start();
return sw;
}
/// <summary>
/// Stops measuring elapsed time for an interval.
/// </summary>
/// <filterpriority>1</filterpriority>
public void Stop()
{
if (!IsRunning) return;
_ellapsed = GetTimeDiff(Environment.TickCount, _startedAt);
IsRunning = false;
}
int GetTimeDiff(int tickCount, int storedTickCount)
{
if (tickCount < storedTickCount)
{
return (int)((long)(Environment.TickCount - int.MinValue) + (long)(int.MaxValue - storedTickCount));
}
return tickCount - storedTickCount;
}
/// <summary>
/// Stops time interval measurement, resets the elapsed time to zero and starts again
/// </summary>
public void Restart()
{
Reset();
Start();
}
/// <summary>
/// Stops time interval measurement and resets the elapsed time to zero.
/// </summary>
/// <filterpriority>1</filterpriority>
public void Reset()
{
Stop();
_ellapsed = 0;
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:FlexibleGameServer.StopwatchInt"/> timer is running.
/// </summary>
///
/// <returns>
/// true if the <see cref="T:FlexibleGameServer.StopwatchInt"/> instance is currently running and measuring elapsed time for an interval; otherwise, false.
/// </returns>
/// <filterpriority>1</filterpriority>
public bool IsRunning { get; protected set; }
/// <summary>
/// Gets the total elapsed time measured by the current instance, in milliseconds.
/// </summary>
///
/// <returns>
/// A read-only long integer representing the total number of milliseconds measured by the current instance.
/// </returns>
/// <filterpriority>1</filterpriority>
public int ElapsedMilliseconds
{
get
{
if (IsRunning)
return GetTimeDiff(Environment.TickCount, _startedAt);
return this._ellapsed;
}
}
}
}
public static class MD5Extensions
{
public static string GetHashString(this MD5CryptoServiceProvider md5, string data)
{
var hash = new StringBuilder();
byte[] hashBytes = md5.ComputeHash(Encoding.ASCII.GetBytes(data));
foreach (byte b in hashBytes) hash.Append(b.ToString("x2"));
return hash.ToString();
}
}
using System.Security.Cryptography;
using System.Text;
namespace FlexibleGameServer
{
public class StopwatchInt
{
int _startedAt;
int _ellapsed;
/// <summary>
/// Initializes a new instance of the <see cref="T:FlexibleGameServer.StopwatchInt"/> class.
/// </summary>
public StopwatchInt()
{
}
/// <summary>
/// Starts measuring elapsed time for an interval.
/// </summary>
/// <filterpriority>1</filterpriority>
public void Start()
{
if (IsRunning) throw new InvalidOperationException();
_ellapsed = 0;
_startedAt = Environment.TickCount;
IsRunning = true;
}
/// <summary>
/// Initializes a new <see cref="T:FlexibleGameServer.StopwatchInt"/> instance, sets the elapsed time property to zero, and starts measuring elapsed time.
/// </summary>
///
/// <returns>
/// A <see cref="T:FlexibleGameServer.StopwatchInt"/> that has just begun measuring elapsed time.
/// </returns>
/// <filterpriority>1</filterpriority>
public static StopwatchInt StartNew()
{
var sw = new StopwatchInt();
sw.Start();
return sw;
}
/// <summary>
/// Stops measuring elapsed time for an interval.
/// </summary>
/// <filterpriority>1</filterpriority>
public void Stop()
{
if (!IsRunning) return;
_ellapsed = GetTimeDiff(Environment.TickCount, _startedAt);
IsRunning = false;
}
int GetTimeDiff(int tickCount, int storedTickCount)
{
if (tickCount < storedTickCount)
{
return (int)((long)(Environment.TickCount - int.MinValue) + (long)(int.MaxValue - storedTickCount));
}
return tickCount - storedTickCount;
}
/// <summary>
/// Stops time interval measurement, resets the elapsed time to zero and starts again
/// </summary>
public void Restart()
{
Reset();
Start();
}
/// <summary>
/// Stops time interval measurement and resets the elapsed time to zero.
/// </summary>
/// <filterpriority>1</filterpriority>
public void Reset()
{
Stop();
_ellapsed = 0;
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:FlexibleGameServer.StopwatchInt"/> timer is running.
/// </summary>
///
/// <returns>
/// true if the <see cref="T:FlexibleGameServer.StopwatchInt"/> instance is currently running and measuring elapsed time for an interval; otherwise, false.
/// </returns>
/// <filterpriority>1</filterpriority>
public bool IsRunning { get; protected set; }
/// <summary>
/// Gets the total elapsed time measured by the current instance, in milliseconds.
/// </summary>
///
/// <returns>
/// A read-only long integer representing the total number of milliseconds measured by the current instance.
/// </returns>
/// <filterpriority>1</filterpriority>
public int ElapsedMilliseconds
{
get
{
if (IsRunning)
return GetTimeDiff(Environment.TickCount, _startedAt);
return this._ellapsed;
}
}
}
}
public static class MD5Extensions
{
public static string GetHashString(this MD5CryptoServiceProvider md5, string data)
{
var hash = new StringBuilder();
byte[] hashBytes = md5.ComputeHash(Encoding.ASCII.GetBytes(data));
foreach (byte b in hashBytes) hash.Append(b.ToString("x2"));
return hash.ToString();
}
}
При компиляции в Visual Studio (F6) запуск или перезапуск игры в редакторе. К сожалению, не смог найти способ активировать окно редактора, но так тоже ничего.
Так же сделал остановку playmode при компиляции (если вы используете приватные поля в скриптах, вам это тоже пригодится). Если кому-то мешает - удалите это:
Синтаксис:
Используется csharp
if (EditorApplication.isCompiling && (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused))
{
EditorApplication.isPlaying = false;
EditorApplication.isPaused = false;
}
{
EditorApplication.isPlaying = false;
EditorApplication.isPaused = false;
}