Skip to content

Commit

Permalink
com.unity.netcode@1.0.17
Browse files Browse the repository at this point in the history
## [1.0.17] - 2023-09-11

### Added

* defining ENABLE_UNITY_RPC_REGISTRATION_LOGGING will now log information about registered RPCs during netcode startup

### Changed

* NetcodePacket debug log filenames changed to include date/time and version information

### Fixed

* addressed a case where it was possible for an exception to be thrown on the server if an RPC was queued for a then dropped connection.
* "AssetDatabase.RegisterCustomDependency are restricted during importing" exception thrown by the NetCodeClientSettings, NetCodeClientServerSettings, NetCodeServerSettings in their OnDisable method, when using 2023.2 or newer.
  • Loading branch information
Unity Technologies committed Sep 11, 2023
1 parent 933c8cf commit d48c2f3
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 137 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
# Changelog


## [1.0.17] - 2023-09-11

### Added

* defining ENABLE_UNITY_RPC_REGISTRATION_LOGGING will now log information about registered RPCs during netcode startup

### Changed

* NetcodePacket debug log filenames changed to include date/time and version information

### Fixed

* addressed a case where it was possible for an exception to be thrown on the server if an RPC was queued for a then dropped connection.
* "AssetDatabase.RegisterCustomDependency are restricted during importing" exception thrown by the NetCodeClientSettings, NetCodeClientServerSettings, NetCodeServerSettings in their OnDisable method, when using 2023.2 or newer.


## [1.0.15] - 2023-07-27

### Changed

* Updated com.unity.entities dependency to 1.0.14

### Removed

* Use of non required TempJob allocation and use Allocator.Temp instead.

### Fixed
Expand Down
28 changes: 26 additions & 2 deletions Runtime/Authoring/Hybrid/NetCodeClientAndServerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,35 @@ internal void Save()
{
if (AssetDatabase.IsAssetImportWorkerProcess())
return;
Save(true);
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
Save(true);
AssetDatabase.Refresh();
}

private void OnDisable() => Save();
#if UNITY_2023_2_OR_NEWER
private void OnEnable()
{
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
}
#endif
private void OnDisable()
{
#if !UNITY_2023_2_OR_NEWER
Save();
#else
//But the depedency is going to be update when the scriptable is re-enabled.
if (AssetDatabase.IsAssetImportWorkerProcess())
return;
Save(true);
//This safeguard is necessary because the RegisterCustomDependency throw exceptions
//if this is called when the editor is refreshing the database.
if(!EditorApplication.isUpdating)
{
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
AssetDatabase.Refresh();
}
#endif
}
}
}
#endif
25 changes: 24 additions & 1 deletion Runtime/Authoring/Hybrid/NetCodeClientSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,33 @@ internal void Save()
{
if (AssetDatabase.IsAssetImportWorkerProcess())
return;
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
Save(true);
AssetDatabase.Refresh();
}
#if UNITY_2023_2_OR_NEWER
private void OnEnable()
{
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
}
private void OnDisable() { Save(); }
#endif
private void OnDisable()
{
#if !UNITY_2023_2_OR_NEWER
Save();
#else
//But the depedency is going to be update when the scriptable is re-enabled.
if (AssetDatabase.IsAssetImportWorkerProcess())
return;
//This safeguard is necessary because the RegisterCustomDependency throw exceptions
//if this is called when the editor is refreshing the database.
if(!EditorApplication.isUpdating)
{
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
AssetDatabase.Refresh();
}
#endif
}
}

internal class ClientSettings : DotsPlayerSettingsProvider
Expand Down
28 changes: 26 additions & 2 deletions Runtime/Authoring/Hybrid/NetCodeServerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,37 @@ ScriptableObject IEntitiesPlayerSettings.AsScriptableObject()
}
internal void Save()
{
//The asset importer should never save the data
if (AssetDatabase.IsAssetImportWorkerProcess())
return;
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
Save(true);
AssetDatabase.Refresh();
}

#if UNITY_2023_2_OR_NEWER
private void OnEnable()
{
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
}
private void OnDisable() { Save(); }
#endif
private void OnDisable()
{
#if !UNITY_2023_2_OR_NEWER
Save();
#else
//But the depedency is going to be update when the scriptable is re-enabled.
if (AssetDatabase.IsAssetImportWorkerProcess())
return;
Save(true);
//This safeguard is necessary because the RegisterCustomDependency throw exceptions
//if this is called when the editor is refreshing the database.
if(!EditorApplication.isUpdating)
{
((IEntitiesPlayerSettings)this).RegisterCustomDependency();
AssetDatabase.Refresh();
}
#endif
}
}

internal class ServerSettings : DotsPlayerSettingsProvider
Expand Down
17 changes: 16 additions & 1 deletion Runtime/Debug/NetDebug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,25 @@ public void Init(ref FixedString512Bytes logFolder, ref FixedString128Bytes worl
parameters.InitialBufferCapacity *= 64;
parameters.OverflowBufferSize *= 32;

var dateTime = DateTime.Now.ToString("yyyy-MM-dd--HH-mm-ss");
var fileName = $"{logFolder}/NetcodePackets-New-{worldName}-{connectionId}-{dateTime}.log";

var next = 0;
while (File.Exists(fileName))
{
fileName = $"{logFolder}/NetcodePackets-New-{worldName}-{connectionId}-{dateTime}-{next}.log";
next++;

if (next >= 100)
{
break;
}
}

m_NetDebugPacketLoggerHandle = new LoggerConfig()
.OutputTemplate("{Message}")
.MinimumLevel.Set(LogLevel.Verbose)
.WriteTo.File($"{logFolder}/NetcodePacket-{worldName}-{connectionId}.log")
.WriteTo.File(fileName)
.CreateLogger(parameters).Handle;
}

Expand Down
10 changes: 9 additions & 1 deletion Runtime/Rpc/RpcCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal struct RpcData : IComparable<RpcData>
{
public ulong TypeHash;
public PortableFunctionPointer<RpcExecutor.ExecuteDelegate> Execute;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG
public ComponentType RpcType;
#endif
public int CompareTo(RpcData other)
Expand Down Expand Up @@ -169,6 +169,14 @@ internal ulong CalculateVersionHash()
for (int i = 0; i < m_RpcData.Length; ++i)
{
m_RpcTypeHashToIndex.Add(m_RpcData[i].TypeHash, i);

#if ENABLE_UNITY_RPC_REGISTRATION_LOGGING
#if UNITY_DOTS_DEBUG
UnityEngine.Debug.Log(String.Format("NetCode RPC Method hash 0x{0:X} index {1} type {2}", m_RpcData[i].TypeHash, i, m_RpcData[i].RpcType));
#else
UnityEngine.Debug.Log(String.Format("NetCode RPC Method hash {0} index {1}", m_RpcData[i].TypeHash, i));
#endif
#endif
}

ulong hash = m_RpcData[0].TypeHash;
Expand Down
9 changes: 5 additions & 4 deletions Runtime/Rpc/RpcCommandRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,9 @@ void LambdaMethod(Entity entity, int orderIndex, in SendRpcCommandRequest dest,
if (!rpcFromEntity.HasBuffer(dest.TargetConnection))
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
throw new InvalidOperationException("Cannot send RPC with no remote connection.");
#else
return;
UnityEngine.Debug.LogWarning("Cannot send RPC with no remote connection.");
#endif
return;
}
var buffer = rpcFromEntity[dest.TargetConnection];
rpcQueue.Schedule(buffer, ghostFromEntity, action);
Expand All @@ -166,7 +165,9 @@ void LambdaMethod(Entity entity, int orderIndex, in SendRpcCommandRequest dest,
#if ENABLE_UNITY_COLLECTIONS_CHECKS
else
{
throw new InvalidOperationException("Cannot send RPC with no remote connection.");
UnityEngine.Debug.LogWarning("Cannot send RPC with no remote connection.");

return;
}
#endif
}
Expand Down
110 changes: 0 additions & 110 deletions Tests/Editor/DotsGlobalSettingsTests.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
using System.IO;
using System.Linq;
using Unity.NetCode.Hybrid;
using UnityEditor;
using NUnit.Framework;
using Unity.Entities.Build;
using Unity.Entities.Conversion;
using Unity.NetCode.PrespawnTests;
using Unity.NetCode.Tests;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.TestTools;

namespace Unity.Scenes.Editor.Tests
{
Expand All @@ -36,107 +28,5 @@ public void NetCodeDebugDefine_IsSetForDevelopmentBuild()
EditorUserBuildSettings.development = originalValue;
}
}

#if false
// APV doesn't respect the Ignore attribute to disable tests, so ifdef explicitly
// https://unity.slack.com/archives/C04UGPY27S9/p1683136704435259
[Test]
public void SuccessfulClientBuildTest()
{
// Temporary hack to work around issue where headless no-graphics CI pass would spit out
// `RenderTexture.Create with shadow sampling failed` error, causing this test to fail.
// Feature has been requested to NOT log this error when running headless.
LogAssert.ignoreFailingMessages = true;

var dotsSettings = DotsGlobalSettings.Instance;
var originalPlayerType = dotsSettings.GetPlayerType();
var originalNetCodeClientTarget = NetCodeClientSettings.instance.ClientTarget;
try
{
bool isOSXEditor = Application.platform == RuntimePlatform.OSXEditor;

var buildOptions = new BuildPlayerOptions();
buildOptions.subtarget = 0;
buildOptions.target = EditorUserBuildSettings.activeBuildTarget;

var scene = SubSceneHelper.CreateEmptyScene(ScenePath, "Parent");
SubSceneHelper.CreateSubScene(scene, Path.GetDirectoryName(scene.path), "Sub0", 5, 5, null, Vector3.zero);

buildOptions.scenes = new string[] {scene.path};
var uniqueTempPath = FileUtil.GetUniqueTempPathInProject();
buildOptions.locationPathName = uniqueTempPath + "/Test.exe";

if(isOSXEditor)
buildOptions.locationPathName = uniqueTempPath + "/Test.app";
buildOptions.extraScriptingDefines = new string[] {"UNITY_CLIENT"};

NetCodeClientSettings.instance.ClientTarget = NetCodeClientTarget.Client;

var report = BuildPipeline.BuildPlayer(buildOptions);

EnsureResourceCatalogHasBeenDeployed(uniqueTempPath, isOSXEditor, report);
}
finally
{
NetCodeClientSettings.instance.ClientTarget = originalNetCodeClientTarget;
}
}

[Test]
public void SuccessfulClientAndServerBuildTest()
{
// Temporary hack to work around issue where headless no-graphics CI pass would spit out
// `RenderTexture.Create with shadow sampling failed` error, causing this test to fail.
// Feature has been requested to NOT log this error when running headless.
LogAssert.ignoreFailingMessages = true;

var dotsSettings = DotsGlobalSettings.Instance;
var originalPlayerType = dotsSettings.GetPlayerType();
var originalNetCodeClientTarget = NetCodeClientSettings.instance.ClientTarget;
try
{
bool isOSXEditor = Application.platform == RuntimePlatform.OSXEditor;

var buildOptions = new BuildPlayerOptions();
buildOptions.subtarget = 0;
buildOptions.target = EditorUserBuildSettings.activeBuildTarget;

var scene = SubSceneHelper.CreateEmptyScene(ScenePath, "Parent");
SubSceneHelper.CreateSubScene(scene, Path.GetDirectoryName(scene.path), "Sub0", 5, 5, null, Vector3.zero);
buildOptions.scenes = new string[] {scene.path};
var uniqueTempPath = FileUtil.GetUniqueTempPathInProject();
buildOptions.locationPathName = uniqueTempPath + "/Test.exe";

if(isOSXEditor)
buildOptions.locationPathName = uniqueTempPath + "/Test.app";

NetCodeClientSettings.instance.ClientTarget = NetCodeClientTarget.ClientAndServer;

var report = BuildPipeline.BuildPlayer(buildOptions);

EnsureResourceCatalogHasBeenDeployed(uniqueTempPath, isOSXEditor, report);
}
finally
{
NetCodeClientSettings.instance.ClientTarget = originalNetCodeClientTarget;
}
}
#endif

static void EnsureResourceCatalogHasBeenDeployed(string uniqueTempPath, bool isOSXEditor, BuildReport report)
{
var locationPath = Application.dataPath + "/../" + uniqueTempPath;
var streamingAssetPath = locationPath + "/Test_Data/StreamingAssets/";
if(isOSXEditor)
streamingAssetPath = locationPath + $"/Test.app/Contents/Resources/Data/StreamingAssets/";

// REDO: Just check the resource catalog has been deployed
var sceneInfoFileRelativePath = EntityScenesPaths.FullPathForFile(streamingAssetPath, EntityScenesPaths.RelativePathForSceneInfoFile);
var resourceCatalogFileExists = File.Exists(sceneInfoFileRelativePath);
var reportMessages = string.Join('\n', report.steps.SelectMany(x => x.messages).Select(x => $"[{x.type}] {x.content}"));
var stringReport = $"[{report.summary.result}, {report.summary.totalErrors} totalErrors, {report.summary.totalWarnings} totalWarnings, resourceCatalogFileExists: {resourceCatalogFileExists}]\nBuild logs ----------\n{reportMessages} ------ ";
Assert.AreEqual(BuildResult.Succeeded, report.summary.result, $"Expected build success! Report: {stringReport}");
Assert.IsTrue(resourceCatalogFileExists, $"Expected '{sceneInfoFileRelativePath}' file to exist! Report: {stringReport}");
}
}
}
4 changes: 2 additions & 2 deletions Tests/Editor/RpcTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public void Rpc_ServerBroadcast_Works()
}

[Test]
public void Rpc_SendingBeforeGettingNetworkId_Throws()
public void Rpc_SendingBeforeGettingNetworkId_LogWarning()
{
using (var testWorld = new NetCodeTestWorld())
{
Expand All @@ -145,7 +145,7 @@ public void Rpc_SendingBeforeGettingNetworkId_Throws()
// Connect and make sure the connection could be established
Assert.IsTrue(testWorld.Connect(frameTime, 4));

LogAssert.Expect(LogType.Exception, new Regex("InvalidOperationException: Cannot send RPC with no remote connection."));
LogAssert.Expect(LogType.Warning, new Regex("Cannot send RPC with no remote connection."));
for (int i = 0; i < 33; ++i)
testWorld.Tick(1f / 60f);

Expand Down
26 changes: 18 additions & 8 deletions ValidationExceptions.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
{
"ErrorExceptions": [
{
"ValidationTest": "Package Unity Version Validation",
"ExceptionMessage": "The Unity version requirement is more strict than in the previous version of the package. Increment the minor version of the package to leave patch versions available for previous version. Read more about this error and potential solutions at https://docs.unity3d.com/Packages/com.unity.package-validation-suite@latest/index.html?preview=1&subfolder=/manual/package_unity_version_validation_error.html#the-unity-version-requirement-is-more-strict-than-in-the-previous-version-of-the-package",
"PackageVersion": "1.0.15"
}
],
"WarningExceptions": []
"ErrorExceptions": [
{
"ValidationTest": "Package Unity Version Validation",
"ExceptionMessage": "The Unity version requirement is more strict than in the previous version of the package. Increment the minor version of the package to leave patch versions available for previous version. Read more about this error and potential solutions at https://docs.unity3d.com/Packages/com.unity.package-validation-suite@latest/index.html?preview=1&subfolder=/manual/package_unity_version_validation_error.html#the-unity-version-requirement-is-more-strict-than-in-the-previous-version-of-the-package",
"PackageVersion": "1.0.17"
},
{
"ValidationTest": "API Validation",
"ExceptionMessage": "New assembly \"Unity.NetCode.TestsUtils\" may only be added in a new minor or major version.",
"PackageVersion": "1.0.17"
},
{
"ValidationTest": "API Validation",
"ExceptionMessage": "Additions require a new minor or major version.",
"PackageVersion": "1.0.17"
}
],
"WarningExceptions": []
}
Loading

0 comments on commit d48c2f3

Please sign in to comment.