chore: updated FishNet
This commit is contained in:
parent
79a147dead
commit
b69f2aff47
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f1525dbf8ebd59e438b504fa19c4fd6c
|
guid: baec5a367bebced4da1b56dbcedde312
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
|
|||||||
@ -8,11 +8,13 @@ using FishNet.Object.Helping;
|
|||||||
using FishNet.Serializing;
|
using FishNet.Serializing;
|
||||||
using FishNet.Serializing.Helping;
|
using FishNet.Serializing.Helping;
|
||||||
using FishNet.Utility.Performance;
|
using FishNet.Utility.Performance;
|
||||||
|
using GameKit.Dependencies.Utilities;
|
||||||
using MonoFN.Cecil;
|
using MonoFN.Cecil;
|
||||||
using MonoFN.Cecil.Cil;
|
using MonoFN.Cecil.Cil;
|
||||||
using MonoFN.Cecil.Rocks;
|
using MonoFN.Cecil.Rocks;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices.ComTypes;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using SR = System.Reflection;
|
using SR = System.Reflection;
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ namespace FishNet.CodeGenerating.Helping
|
|||||||
public TypeReference ActionT3_TypeRef;
|
public TypeReference ActionT3_TypeRef;
|
||||||
public MethodReference ActionT2Constructor_MethodRef;
|
public MethodReference ActionT2Constructor_MethodRef;
|
||||||
public MethodReference ActionT3Constructor_MethodRef;
|
public MethodReference ActionT3Constructor_MethodRef;
|
||||||
|
public TypeReference ObjectCaches_TypeRef;
|
||||||
|
|
||||||
private Dictionary<Type, TypeReference> _importedTypeReferences = new Dictionary<Type, TypeReference>();
|
private Dictionary<Type, TypeReference> _importedTypeReferences = new Dictionary<Type, TypeReference>();
|
||||||
private Dictionary<FieldDefinition, FieldReference> _importedFieldReferences = new Dictionary<FieldDefinition, FieldReference>();
|
private Dictionary<FieldDefinition, FieldReference> _importedFieldReferences = new Dictionary<FieldDefinition, FieldReference>();
|
||||||
@ -70,6 +73,7 @@ namespace FishNet.CodeGenerating.Helping
|
|||||||
private Dictionary<TypeReference, TypeDefinition> _typeReferenceResolves = new Dictionary<TypeReference, TypeDefinition>();
|
private Dictionary<TypeReference, TypeDefinition> _typeReferenceResolves = new Dictionary<TypeReference, TypeDefinition>();
|
||||||
private Dictionary<FieldReference, FieldDefinition> _fieldReferenceResolves = new Dictionary<FieldReference, FieldDefinition>();
|
private Dictionary<FieldReference, FieldDefinition> _fieldReferenceResolves = new Dictionary<FieldReference, FieldDefinition>();
|
||||||
private Dictionary<string, MethodDefinition> _comparerDelegates = new Dictionary<string, MethodDefinition>();
|
private Dictionary<string, MethodDefinition> _comparerDelegates = new Dictionary<string, MethodDefinition>();
|
||||||
|
private MethodReference _objectCaches_Retrieve_MethodRef;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Const.
|
#region Const.
|
||||||
@ -93,6 +97,9 @@ namespace FishNet.CodeGenerating.Helping
|
|||||||
ExcludeSerializationAttribute_FullName = typeof(ExcludeSerializationAttribute).FullName;
|
ExcludeSerializationAttribute_FullName = typeof(ExcludeSerializationAttribute).FullName;
|
||||||
NotSerializerAttribute_FullName = typeof(NotSerializerAttribute).FullName;
|
NotSerializerAttribute_FullName = typeof(NotSerializerAttribute).FullName;
|
||||||
|
|
||||||
|
TypeReference _objectCaches_TypeRef = base.ImportReference(typeof(ObjectCaches<>));
|
||||||
|
_objectCaches_Retrieve_MethodRef = _objectCaches_TypeRef.CachedResolve(base.Session).GetMethodReference(base.Session, nameof(ObjectCaches<int>.Retrieve));
|
||||||
|
|
||||||
tmpType = typeof(BasicQueue<>);
|
tmpType = typeof(BasicQueue<>);
|
||||||
base.ImportReference(tmpType);
|
base.ImportReference(tmpType);
|
||||||
foreach (SR.MethodInfo mi in tmpType.GetMethods())
|
foreach (SR.MethodInfo mi in tmpType.GetMethods())
|
||||||
@ -904,7 +911,23 @@ namespace FishNet.CodeGenerating.Helping
|
|||||||
|
|
||||||
#region SetVariableDef.
|
#region SetVariableDef.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes variableDef as a new object or collection of typeDef.
|
/// Initializes variableDef as an object or collection of typeDef using cachces.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="processor"></param>
|
||||||
|
/// <param name="variableDef"></param>
|
||||||
|
/// <param name="typeDef"></param>
|
||||||
|
public void SetVariableDefinitionFromCaches(ILProcessor processor, VariableDefinition variableDef, TypeDefinition typeDef)
|
||||||
|
{
|
||||||
|
TypeReference dataTr = variableDef.VariableType;
|
||||||
|
GenericInstanceType git = ObjectCaches_TypeRef.MakeGenericInstanceType(new TypeReference[] { dataTr });
|
||||||
|
|
||||||
|
MethodReference genericInstanceMethod = _objectCaches_Retrieve_MethodRef.MakeHostInstanceGeneric(base.Session, git);
|
||||||
|
processor.Emit(OpCodes.Call, genericInstanceMethod);
|
||||||
|
processor.Emit(OpCodes.Stloc, variableDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes variableDef as a new object or collection of typeDef using instantiation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="processor"></param>
|
/// <param name="processor"></param>
|
||||||
/// <param name="variableDef"></param>
|
/// <param name="variableDef"></param>
|
||||||
|
|||||||
@ -78,6 +78,7 @@ namespace FishNet.CodeGenerating.ILCore
|
|||||||
modified |= CreateDeclaredSerializerDelegates(session);
|
modified |= CreateDeclaredSerializerDelegates(session);
|
||||||
modified |= CreateDeclaredSerializers(session);
|
modified |= CreateDeclaredSerializers(session);
|
||||||
modified |= CreateDeclaredComparerDelegates(session);
|
modified |= CreateDeclaredComparerDelegates(session);
|
||||||
|
modified |= CreateIncludeSerializationSerializers(session);
|
||||||
modified |= CreateIBroadcast(session);
|
modified |= CreateIBroadcast(session);
|
||||||
#if !DISABLE_QOL_ATTRIBUTES
|
#if !DISABLE_QOL_ATTRIBUTES
|
||||||
modified |= CreateQOLAttributes(session);
|
modified |= CreateQOLAttributes(session);
|
||||||
@ -234,6 +235,43 @@ namespace FishNet.CodeGenerating.ILCore
|
|||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates serializers for types that use IncludeSerialization attribute.
|
||||||
|
/// </summary>
|
||||||
|
private bool CreateIncludeSerializationSerializers(CodegenSession session)
|
||||||
|
{
|
||||||
|
string attributeName = typeof(IncludeSerializationAttribute).FullName;
|
||||||
|
WriterProcessor wp = session.GetClass<WriterProcessor>();
|
||||||
|
ReaderProcessor rp = session.GetClass<ReaderProcessor>();
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
List<TypeDefinition> allTypeDefs = session.Module.Types.ToList();
|
||||||
|
foreach (TypeDefinition td in allTypeDefs)
|
||||||
|
{
|
||||||
|
if (!CanSerialize())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TypeReference tr = session.ImportReference(td);
|
||||||
|
if (wp.CreateWriter(tr) != null && rp.CreateReader(tr) != null)
|
||||||
|
modified = true;
|
||||||
|
else
|
||||||
|
session.LogError($"Failed to create serializers for {td.FullName}.");
|
||||||
|
|
||||||
|
bool CanSerialize()
|
||||||
|
{
|
||||||
|
foreach (CustomAttribute item in td.CustomAttributes)
|
||||||
|
{
|
||||||
|
if (item.AttributeType.FullName == attributeName)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creaters serializers and calls for IBroadcast.
|
/// Creaters serializers and calls for IBroadcast.
|
||||||
|
|||||||
@ -302,7 +302,7 @@ namespace FishNet.CodeGenerating.Processing
|
|||||||
{
|
{
|
||||||
if (inst.Operand is MethodReference mr)
|
if (inst.Operand is MethodReference mr)
|
||||||
{
|
{
|
||||||
if (mr.FullName == reconcileMd.FullName)
|
if (mr.Name == reconcileMd.Name)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,6 +372,8 @@ namespace FishNet.CodeGenerating.Processing
|
|||||||
{
|
{
|
||||||
if (!MethodIsPrivate(methodDef) || AlreadyFound(reconcileMd))
|
if (!MethodIsPrivate(methodDef) || AlreadyFound(reconcileMd))
|
||||||
error = true;
|
error = true;
|
||||||
|
else
|
||||||
|
reconcileMd = methodDef;
|
||||||
}
|
}
|
||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -11,6 +11,7 @@ using FishNet.CodeGenerating.Extension;
|
|||||||
using FishNet.Utility.Performance;
|
using FishNet.Utility.Performance;
|
||||||
using FishNet.Object;
|
using FishNet.Object;
|
||||||
using FishNet.Utility;
|
using FishNet.Utility;
|
||||||
|
using GameKit.Dependencies.Utilities;
|
||||||
|
|
||||||
namespace FishNet.CodeGenerating.Helping
|
namespace FishNet.CodeGenerating.Helping
|
||||||
{
|
{
|
||||||
@ -1045,8 +1046,18 @@ namespace FishNet.CodeGenerating.Helping
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If here then not null. */
|
/* If here then not null. */
|
||||||
|
//See if to use non-alloc reads.
|
||||||
|
if (objectTr.CachedResolve(base.Session).HasCustomAttribute<ReadUnallocated>())
|
||||||
|
{
|
||||||
|
//Make a new instance of object type and set to objectVariableDef.
|
||||||
|
base.GetClass<GeneralHelper>().SetVariableDefinitionFromCaches(processor, objectVariableDef, objectTypeDef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//Make a new instance of object type and set to objectVariableDef.
|
//Make a new instance of object type and set to objectVariableDef.
|
||||||
base.GetClass<GeneralHelper>().SetVariableDefinitionFromObject(processor, objectVariableDef, objectTypeDef);
|
base.GetClass<GeneralHelper>().SetVariableDefinitionFromObject(processor, objectVariableDef, objectTypeDef);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ReadFieldsAndProperties(createdReaderMd, readerParameterDef, objectVariableDef, objectTr))
|
if (!ReadFieldsAndProperties(createdReaderMd, readerParameterDef, objectVariableDef, objectTr))
|
||||||
return null;
|
return null;
|
||||||
/* //codegen scriptableobjects seem to climb too high up to UnityEngine.Object when
|
/* //codegen scriptableobjects seem to climb too high up to UnityEngine.Object when
|
||||||
|
|||||||
@ -218,10 +218,7 @@ namespace FishNet.CodeGenerating.Processing.Rpc
|
|||||||
{
|
{
|
||||||
RpcType rpcType = base.GetClass<AttributeHelper>().GetRpcAttributeType(customAttribute);
|
RpcType rpcType = base.GetClass<AttributeHelper>().GetRpcAttributeType(customAttribute);
|
||||||
if (rpcType != RpcType.None)
|
if (rpcType != RpcType.None)
|
||||||
{
|
|
||||||
count++;
|
count++;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,8 @@ namespace FishNet.CodeGenerating.Helping
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string[] EXCLUDED_ASSEMBLY_PREFIXES = new string[]
|
public static readonly string[] EXCLUDED_ASSEMBLY_PREFIXES = new string[]
|
||||||
{
|
{
|
||||||
"UnityEngine."
|
"UnityEngine.",
|
||||||
|
"Unity.Mathmatics",
|
||||||
};
|
};
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _Authenticator_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs: []
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ab6a9000f5ff83f45b6761c2a3be018d
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -362,7 +362,7 @@ MonoBehaviour:
|
|||||||
_objectPool: {fileID: 0}
|
_objectPool: {fileID: 0}
|
||||||
_persistence: 0
|
_persistence: 0
|
||||||
_logging: {fileID: 0}
|
_logging: {fileID: 0}
|
||||||
_spawnablePrefabs: {fileID: 11400000, guid: ab6a9000f5ff83f45b6761c2a3be018d, type: 2}
|
_spawnablePrefabs: {fileID: 11400000, guid: 68e79e63a16f2c74e81f070bd36822b8, type: 2}
|
||||||
--- !u!1 &7443408886491481971
|
--- !u!1 &7443408886491481971
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _ColliderRollback_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs:
|
|
||||||
- {fileID: 8475222101369129519, guid: 8cf33e8e99a9b0c4c8f29ff725650de6, type: 3}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d9693011b7416444aa06cafe900e23c0
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -309,6 +309,7 @@ MonoBehaviour:
|
|||||||
_predictionType: 0
|
_predictionType: 0
|
||||||
_graphicalObject: {fileID: 0}
|
_graphicalObject: {fileID: 0}
|
||||||
_enableStateForwarding: 1
|
_enableStateForwarding: 1
|
||||||
|
_networkTransform: {fileID: 0}
|
||||||
_ownerInterpolation: 1
|
_ownerInterpolation: 1
|
||||||
_enableTeleport: 0
|
_enableTeleport: 0
|
||||||
_teleportThreshold: 1
|
_teleportThreshold: 1
|
||||||
@ -833,6 +834,7 @@ MonoBehaviour:
|
|||||||
_predictionType: 0
|
_predictionType: 0
|
||||||
_graphicalObject: {fileID: 0}
|
_graphicalObject: {fileID: 0}
|
||||||
_enableStateForwarding: 1
|
_enableStateForwarding: 1
|
||||||
|
_networkTransform: {fileID: 0}
|
||||||
_ownerInterpolation: 1
|
_ownerInterpolation: 1
|
||||||
_enableTeleport: 0
|
_enableTeleport: 0
|
||||||
_teleportThreshold: 1
|
_teleportThreshold: 1
|
||||||
@ -1817,6 +1819,7 @@ Canvas:
|
|||||||
m_OverrideSorting: 0
|
m_OverrideSorting: 0
|
||||||
m_OverridePixelPerfect: 0
|
m_OverridePixelPerfect: 0
|
||||||
m_SortingBucketNormalizedSize: 0
|
m_SortingBucketNormalizedSize: 0
|
||||||
|
m_VertexColorAlwaysGammaSpace: 0
|
||||||
m_AdditionalShaderChannelsFlag: 0
|
m_AdditionalShaderChannelsFlag: 0
|
||||||
m_SortingLayerID: 0
|
m_SortingLayerID: 0
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
@ -2099,13 +2102,14 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3}
|
m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
_unreliableMTU: 1023
|
_dontRoute: 0
|
||||||
|
_unreliableMtu: 1023
|
||||||
_ipv4BindAddress:
|
_ipv4BindAddress:
|
||||||
|
_enableIpv6: 1
|
||||||
_ipv6BindAddress:
|
_ipv6BindAddress:
|
||||||
_port: 7770
|
_port: 7770
|
||||||
_maximumClients: 4095
|
_maximumClients: 4095
|
||||||
_clientAddress: localhost
|
_clientAddress: localhost
|
||||||
_timeout: 15
|
|
||||||
--- !u!114 &1016939666208092867
|
--- !u!114 &1016939666208092867
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -2699,6 +2703,7 @@ Canvas:
|
|||||||
m_OverrideSorting: 0
|
m_OverrideSorting: 0
|
||||||
m_OverridePixelPerfect: 0
|
m_OverridePixelPerfect: 0
|
||||||
m_SortingBucketNormalizedSize: 0
|
m_SortingBucketNormalizedSize: 0
|
||||||
|
m_VertexColorAlwaysGammaSpace: 0
|
||||||
m_AdditionalShaderChannelsFlag: 0
|
m_AdditionalShaderChannelsFlag: 0
|
||||||
m_SortingLayerID: 0
|
m_SortingLayerID: 0
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
@ -2797,7 +2802,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3}
|
m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
_autoStartType: 0
|
_autoStartType: 2
|
||||||
_stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
_stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
||||||
_changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1}
|
_changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1}
|
||||||
_startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1}
|
_startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1}
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _HashGrid_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs:
|
|
||||||
- {fileID: 4512293259955182956, guid: 44611030e61220d42ab7c37ba3c0ea92, type: 3}
|
|
||||||
- {fileID: 4512293259955182956, guid: 0d6d0f48b03b17f49a6340103cd9b9d0, type: 3}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2863463f6933f3f439a639f883f642f6
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -290,6 +290,14 @@ MonoBehaviour:
|
|||||||
_initializeOrder: 0
|
_initializeOrder: 0
|
||||||
_defaultDespawnType: 0
|
_defaultDespawnType: 0
|
||||||
NetworkObserver: {fileID: 0}
|
NetworkObserver: {fileID: 0}
|
||||||
|
_enablePrediction: 0
|
||||||
|
_predictionType: 0
|
||||||
|
_graphicalObject: {fileID: 0}
|
||||||
|
_enableStateForwarding: 1
|
||||||
|
_networkTransform: {fileID: 0}
|
||||||
|
_ownerInterpolation: 1
|
||||||
|
_enableTeleport: 0
|
||||||
|
_teleportThreshold: 1
|
||||||
<PrefabId>k__BackingField: 0
|
<PrefabId>k__BackingField: 0
|
||||||
<SpawnableCollectionId>k__BackingField: 0
|
<SpawnableCollectionId>k__BackingField: 0
|
||||||
_scenePathHash: 1046374546
|
_scenePathHash: 1046374546
|
||||||
@ -429,6 +437,7 @@ MonoBehaviour:
|
|||||||
- 90
|
- 90
|
||||||
- 100
|
- 100
|
||||||
_updateHostVisibility: 1
|
_updateHostVisibility: 1
|
||||||
|
_maximumTimedObserversDuration: 10
|
||||||
_defaultConditions:
|
_defaultConditions:
|
||||||
- {fileID: 11400000, guid: cc503f7541ebd424c94541e6a767efee, type: 2}
|
- {fileID: 11400000, guid: cc503f7541ebd424c94541e6a767efee, type: 2}
|
||||||
--- !u!114 &1424052073952814568
|
--- !u!114 &1424052073952814568
|
||||||
@ -854,6 +863,7 @@ Canvas:
|
|||||||
m_OverrideSorting: 0
|
m_OverrideSorting: 0
|
||||||
m_OverridePixelPerfect: 0
|
m_OverridePixelPerfect: 0
|
||||||
m_SortingBucketNormalizedSize: 0
|
m_SortingBucketNormalizedSize: 0
|
||||||
|
m_VertexColorAlwaysGammaSpace: 0
|
||||||
m_AdditionalShaderChannelsFlag: 0
|
m_AdditionalShaderChannelsFlag: 0
|
||||||
m_SortingLayerID: 0
|
m_SortingLayerID: 0
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
@ -1002,7 +1012,7 @@ MonoBehaviour:
|
|||||||
_objectPool: {fileID: 0}
|
_objectPool: {fileID: 0}
|
||||||
_persistence: 0
|
_persistence: 0
|
||||||
_logging: {fileID: 0}
|
_logging: {fileID: 0}
|
||||||
_spawnablePrefabs: {fileID: 11400000, guid: 2863463f6933f3f439a639f883f642f6, type: 2}
|
_spawnablePrefabs: {fileID: 11400000, guid: 68e79e63a16f2c74e81f070bd36822b8, type: 2}
|
||||||
--- !u!1 &7443408886575219563
|
--- !u!1 &7443408886575219563
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -1090,9 +1100,9 @@ MonoBehaviour:
|
|||||||
_ipv4BindAddress:
|
_ipv4BindAddress:
|
||||||
_enableIpv6: 1
|
_enableIpv6: 1
|
||||||
_ipv6BindAddress:
|
_ipv6BindAddress:
|
||||||
_port: 30681
|
_port: 7112
|
||||||
_maximumClients: 4095
|
_maximumClients: 4095
|
||||||
_clientAddress: 4d3a4e3f1ace.pr.edgegap.net
|
_clientAddress: localhost
|
||||||
--- !u!224 &9139860295505404435
|
--- !u!224 &9139860295505404435
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 90949fa81eb0c194080a75b84fa699d9
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _IntermediateLayer_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs: []
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: dcdf15fc89edd2546baf8ff544470626
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _Network LOD_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs:
|
|
||||||
- {fileID: 4512293259955182956, guid: 300370bdf7819da41937e0beac65b32c, type: 3}
|
|
||||||
- {fileID: 4512293259955182956, guid: f32d4c19de900e64cb73cedcb8ba6f70, type: 3}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0078a285cda09f349b2668a721a53212
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7e04426ec3811c4439a20fc6f21abb62
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: accc5b93ebf3b0040baaec2298c7d394
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: bdae6fa333d2d94449c27856e21d936a
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!21 &2100000
|
|
||||||
Material:
|
|
||||||
serializedVersion: 6
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_Name: BlueMat
|
|
||||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_ShaderKeywords:
|
|
||||||
m_LightmapFlags: 4
|
|
||||||
m_EnableInstancingVariants: 0
|
|
||||||
m_DoubleSidedGI: 0
|
|
||||||
m_CustomRenderQueue: -1
|
|
||||||
stringTagMap: {}
|
|
||||||
disabledShaderPasses: []
|
|
||||||
m_SavedProperties:
|
|
||||||
serializedVersion: 3
|
|
||||||
m_TexEnvs:
|
|
||||||
- _BumpMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _DetailAlbedoMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _DetailMask:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _DetailNormalMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _EmissionMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _MainTex:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _MetallicGlossMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _OcclusionMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
- _ParallaxMap:
|
|
||||||
m_Texture: {fileID: 0}
|
|
||||||
m_Scale: {x: 1, y: 1}
|
|
||||||
m_Offset: {x: 0, y: 0}
|
|
||||||
m_Floats:
|
|
||||||
- _BumpScale: 1
|
|
||||||
- _Cutoff: 0.5
|
|
||||||
- _DetailNormalMapScale: 1
|
|
||||||
- _DstBlend: 0
|
|
||||||
- _GlossMapScale: 1
|
|
||||||
- _Glossiness: 0.5
|
|
||||||
- _GlossyReflections: 1
|
|
||||||
- _Metallic: 0
|
|
||||||
- _Mode: 0
|
|
||||||
- _OcclusionStrength: 1
|
|
||||||
- _Parallax: 0.02
|
|
||||||
- _SmoothnessTextureChannel: 0
|
|
||||||
- _SpecularHighlights: 1
|
|
||||||
- _SrcBlend: 1
|
|
||||||
- _UVSec: 0
|
|
||||||
- _ZWrite: 1
|
|
||||||
m_Colors:
|
|
||||||
- _Color: {r: 0, g: 0.363446, b: 0.5471698, a: 1}
|
|
||||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a2ca0973c8f8a4846bb7f3894c3bc5cf
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 50d54accc2af0c746b0729b097981b93
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,202 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &303449598114786579
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 303449598114786577}
|
|
||||||
- component: {fileID: -2060332294883903109}
|
|
||||||
- component: {fileID: 201277550}
|
|
||||||
- component: {fileID: 4148834954576211901}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: CharacterControllerPrediction
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &303449598114786577
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: -4.80351, y: 0.18147132, z: 5.430528}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 6952090537135875148}
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &-2060332294883903109
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 53a6d84aa5d214e48a7308646e5d20da, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_componentIndexCache: 0
|
|
||||||
_addedNetworkObject: {fileID: 201277550}
|
|
||||||
_networkObjectCache: {fileID: 201277550}
|
|
||||||
--- !u!114 &201277550
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
<IsNested>k__BackingField: 0
|
|
||||||
<ComponentIndex>k__BackingField: 0
|
|
||||||
<PredictedSpawn>k__BackingField: {fileID: 0}
|
|
||||||
_networkBehaviours:
|
|
||||||
- {fileID: -2060332294883903109}
|
|
||||||
<SerializedRootNetworkBehaviour>k__BackingField: {fileID: 0}
|
|
||||||
<NestedRootNetworkBehaviours>k__BackingField: []
|
|
||||||
SerializedTransformProperties:
|
|
||||||
Position: {x: -4.80351, y: 0.18147132, z: 5.430528}
|
|
||||||
Rotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
_isNetworked: 1
|
|
||||||
_isSpawnable: 1
|
|
||||||
_isGlobal: 0
|
|
||||||
_initializeOrder: 0
|
|
||||||
_defaultDespawnType: 0
|
|
||||||
NetworkObserver: {fileID: 0}
|
|
||||||
<PrefabId>k__BackingField: 3
|
|
||||||
<SpawnableCollectionId>k__BackingField: 0
|
|
||||||
_scenePathHash: 0
|
|
||||||
<SceneId>k__BackingField: 0
|
|
||||||
<AssetPathHash>k__BackingField: 15176741689908595000
|
|
||||||
--- !u!143 &4148834954576211901
|
|
||||||
CharacterController:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_IsTrigger: 0
|
|
||||||
m_Enabled: 1
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Height: 2
|
|
||||||
m_Radius: 0.5
|
|
||||||
m_SlopeLimit: 45
|
|
||||||
m_StepOffset: 0.3
|
|
||||||
m_SkinWidth: 0.08
|
|
||||||
m_MinMoveDistance: 0.001
|
|
||||||
m_Center: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!1 &5873068582516782542
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 6952090537135875148}
|
|
||||||
- component: {fileID: 6605329024375725182}
|
|
||||||
- component: {fileID: 9006911641345807741}
|
|
||||||
- component: {fileID: 4946798872430241371}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: Capsule
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &6952090537135875148
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5873068582516782542}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0.01, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 303449598114786577}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!33 &6605329024375725182
|
|
||||||
MeshFilter:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5873068582516782542}
|
|
||||||
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
--- !u!23 &9006911641345807741
|
|
||||||
MeshRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5873068582516782542}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_CastShadows: 1
|
|
||||||
m_ReceiveShadows: 1
|
|
||||||
m_DynamicOccludee: 1
|
|
||||||
m_StaticShadowCaster: 0
|
|
||||||
m_MotionVectors: 1
|
|
||||||
m_LightProbeUsage: 1
|
|
||||||
m_ReflectionProbeUsage: 1
|
|
||||||
m_RayTracingMode: 2
|
|
||||||
m_RayTraceProcedural: 0
|
|
||||||
m_RenderingLayerMask: 1
|
|
||||||
m_RendererPriority: 0
|
|
||||||
m_Materials:
|
|
||||||
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_StaticBatchInfo:
|
|
||||||
firstSubMesh: 0
|
|
||||||
subMeshCount: 0
|
|
||||||
m_StaticBatchRoot: {fileID: 0}
|
|
||||||
m_ProbeAnchor: {fileID: 0}
|
|
||||||
m_LightProbeVolumeOverride: {fileID: 0}
|
|
||||||
m_ScaleInLightmap: 1
|
|
||||||
m_ReceiveGI: 1
|
|
||||||
m_PreserveUVs: 0
|
|
||||||
m_IgnoreNormalsForChartDetection: 0
|
|
||||||
m_ImportantGI: 0
|
|
||||||
m_StitchLightmapSeams: 1
|
|
||||||
m_SelectedEditorRenderState: 3
|
|
||||||
m_MinimumChartSize: 4
|
|
||||||
m_AutoUVMaxDistance: 0.5
|
|
||||||
m_AutoUVMaxAngle: 89
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_SortingLayerID: 0
|
|
||||||
m_SortingLayer: 0
|
|
||||||
m_SortingOrder: 0
|
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
|
||||||
--- !u!136 &4946798872430241371
|
|
||||||
CapsuleCollider:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5873068582516782542}
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_IsTrigger: 0
|
|
||||||
m_Enabled: 1
|
|
||||||
m_Radius: 0.5
|
|
||||||
m_Height: 2
|
|
||||||
m_Direction: 1
|
|
||||||
m_Center: {x: 0, y: 0, z: 0}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: eaf414b899169f04bb4b0d65424a40bf
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,152 +0,0 @@
|
|||||||
using FishNet;
|
|
||||||
using FishNet.Object;
|
|
||||||
using FishNet.Object.Prediction;
|
|
||||||
using FishNet.Transporting;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using static FishNet.PredictionV2.CharacterControllerPredictionV2;
|
|
||||||
|
|
||||||
namespace FishNet.PredictionV2
|
|
||||||
{
|
|
||||||
|
|
||||||
public class CharacterControllerPredictionV2 : NetworkBehaviour
|
|
||||||
{
|
|
||||||
#if !PREDICTION_1
|
|
||||||
|
|
||||||
|
|
||||||
public struct MoveData : IReplicateData
|
|
||||||
{
|
|
||||||
public uint SentTick;
|
|
||||||
public bool Jump;
|
|
||||||
public float Horizontal;
|
|
||||||
public float Vertical;
|
|
||||||
public MoveData(bool jump, float horizontal, float vertical, uint sentTick)
|
|
||||||
{
|
|
||||||
Jump = jump;
|
|
||||||
Horizontal = horizontal;
|
|
||||||
Vertical = vertical;
|
|
||||||
SentTick = sentTick;
|
|
||||||
_tick = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private uint _tick;
|
|
||||||
public void Dispose() { }
|
|
||||||
public uint GetTick() => _tick;
|
|
||||||
public void SetTick(uint value) => _tick = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct ReconcileData : IReconcileData
|
|
||||||
{
|
|
||||||
public Vector3 Position;
|
|
||||||
public float VerticalVelocity;
|
|
||||||
public ReconcileData(Vector3 position, float verticalVelocity)
|
|
||||||
{
|
|
||||||
Position = position;
|
|
||||||
VerticalVelocity = verticalVelocity;
|
|
||||||
_tick = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private uint _tick;
|
|
||||||
public void Dispose() { }
|
|
||||||
public uint GetTick() => _tick;
|
|
||||||
public void SetTick(uint value) => _tick = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private float _jumpForce = 15f;
|
|
||||||
[SerializeField]
|
|
||||||
private float _moveRate = 4f;
|
|
||||||
|
|
||||||
private CharacterController _characterController;
|
|
||||||
private bool _jump;
|
|
||||||
private float _verticalVelocity;
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (base.IsOwner)
|
|
||||||
{
|
|
||||||
if (Input.GetKeyDown(KeyCode.Space))
|
|
||||||
_jump = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnStartNetwork()
|
|
||||||
{
|
|
||||||
_characterController = GetComponent<CharacterController>();
|
|
||||||
base.TimeManager.OnTick += TimeManager_OnTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnStopNetwork()
|
|
||||||
{
|
|
||||||
base.TimeManager.OnTick -= TimeManager_OnTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void TimeManager_OnTick()
|
|
||||||
{
|
|
||||||
Move(BuildMoveData());
|
|
||||||
/* The base.IsServer check is not required but does save a little
|
|
||||||
* performance by not building the reconcileData if not server. */
|
|
||||||
CreateReconcile();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CreateReconcile()
|
|
||||||
{
|
|
||||||
if (base.IsServerStarted)
|
|
||||||
{
|
|
||||||
ReconcileData rd = new ReconcileData(transform.position, _verticalVelocity);
|
|
||||||
Reconciliation(rd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private MoveData BuildMoveData()
|
|
||||||
{
|
|
||||||
if (!base.IsOwner)
|
|
||||||
return default;
|
|
||||||
|
|
||||||
float horizontal = Input.GetAxisRaw("Horizontal");
|
|
||||||
float vertical = Input.GetAxisRaw("Vertical");
|
|
||||||
|
|
||||||
MoveData md;
|
|
||||||
if (horizontal != 0 || vertical != 0)
|
|
||||||
md = new MoveData(_jump, horizontal, vertical, base.TimeManager.LocalTick);
|
|
||||||
else
|
|
||||||
md = new MoveData(_jump, horizontal, vertical, 0);
|
|
||||||
_jump = false;
|
|
||||||
|
|
||||||
return md;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Replicate]
|
|
||||||
private void Move(MoveData md, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
|
|
||||||
{
|
|
||||||
if (state == ReplicateState.CurrentFuture)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (md.Jump)
|
|
||||||
_verticalVelocity = _jumpForce;
|
|
||||||
|
|
||||||
float delta = (float)base.TimeManager.TickDelta;
|
|
||||||
_verticalVelocity += (Physics.gravity.y * delta);
|
|
||||||
if (_verticalVelocity < -20f)
|
|
||||||
_verticalVelocity = -20f;
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 forces = new Vector3(md.Horizontal, _verticalVelocity, md.Vertical) * _moveRate;
|
|
||||||
_characterController.Move(forces * delta);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reconcile]
|
|
||||||
private void Reconciliation(ReconcileData rd, Channel channel = Channel.Unreliable)
|
|
||||||
{
|
|
||||||
transform.position = rd.Position;
|
|
||||||
_verticalVelocity = rd.VerticalVelocity;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
Prediction V2 is a work in progress and so are the examples.
|
|
||||||
|
|
||||||
The Rigidbody example may not smooth properly.
|
|
||||||
|
|
||||||
The CharacterController example is expected to work.
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 43f99d5241a617843a16537c3229c093
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1603123a7ba837c4892564f087decd80
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7f31e665d963214449f27dc0ad466dfb
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c147d08de81079a4c8f17246c4e49dc5
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,451 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &303449597948771942
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 303449597948771941}
|
|
||||||
- component: {fileID: 303449597948771939}
|
|
||||||
- component: {fileID: 303449597948771940}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: Cube (1)
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &303449597948771941
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449597948771942}
|
|
||||||
m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1.5, y: 0.25, z: 0.25}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 303449599178274091}
|
|
||||||
m_RootOrder: 1
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
|
|
||||||
--- !u!33 &303449597948771939
|
|
||||||
MeshFilter:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449597948771942}
|
|
||||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
--- !u!23 &303449597948771940
|
|
||||||
MeshRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449597948771942}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_CastShadows: 1
|
|
||||||
m_ReceiveShadows: 1
|
|
||||||
m_DynamicOccludee: 1
|
|
||||||
m_StaticShadowCaster: 0
|
|
||||||
m_MotionVectors: 1
|
|
||||||
m_LightProbeUsage: 1
|
|
||||||
m_ReflectionProbeUsage: 1
|
|
||||||
m_RayTracingMode: 2
|
|
||||||
m_RayTraceProcedural: 0
|
|
||||||
m_RenderingLayerMask: 1
|
|
||||||
m_RendererPriority: 0
|
|
||||||
m_Materials:
|
|
||||||
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_StaticBatchInfo:
|
|
||||||
firstSubMesh: 0
|
|
||||||
subMeshCount: 0
|
|
||||||
m_StaticBatchRoot: {fileID: 0}
|
|
||||||
m_ProbeAnchor: {fileID: 0}
|
|
||||||
m_LightProbeVolumeOverride: {fileID: 0}
|
|
||||||
m_ScaleInLightmap: 1
|
|
||||||
m_ReceiveGI: 1
|
|
||||||
m_PreserveUVs: 0
|
|
||||||
m_IgnoreNormalsForChartDetection: 0
|
|
||||||
m_ImportantGI: 0
|
|
||||||
m_StitchLightmapSeams: 1
|
|
||||||
m_SelectedEditorRenderState: 3
|
|
||||||
m_MinimumChartSize: 4
|
|
||||||
m_AutoUVMaxDistance: 0.5
|
|
||||||
m_AutoUVMaxAngle: 89
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_SortingLayerID: 0
|
|
||||||
m_SortingLayer: 0
|
|
||||||
m_SortingOrder: 0
|
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
|
||||||
--- !u!1 &303449598114786579
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 303449598114786577}
|
|
||||||
- component: {fileID: 4875864441162262683}
|
|
||||||
- component: {fileID: 303449598114786578}
|
|
||||||
- component: {fileID: 201277550}
|
|
||||||
- component: {fileID: 201277549}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: RigidbodyPrediction
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &303449598114786577
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: -4.80351, y: 0.18147132, z: 5.430528}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 303449599178274091}
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &4875864441162262683
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 1e66bfd8c92aad24e8526e7d3aae8b34, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_componentIndexCache: 0
|
|
||||||
_addedNetworkObject: {fileID: 201277550}
|
|
||||||
_networkObjectCache: {fileID: 201277550}
|
|
||||||
--- !u!135 &303449598114786578
|
|
||||||
SphereCollider:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_Material: {fileID: 13400000, guid: b31539408c1f95d4281bb4484bb6b78e, type: 2}
|
|
||||||
m_IsTrigger: 0
|
|
||||||
m_Enabled: 1
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Radius: 0.5
|
|
||||||
m_Center: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!114 &201277550
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
<IsNested>k__BackingField: 0
|
|
||||||
<ComponentIndex>k__BackingField: 0
|
|
||||||
<PredictedSpawn>k__BackingField: {fileID: 0}
|
|
||||||
_networkBehaviours:
|
|
||||||
- {fileID: 4875864441162262683}
|
|
||||||
<SerializedRootNetworkBehaviour>k__BackingField: {fileID: 0}
|
|
||||||
<NestedRootNetworkBehaviours>k__BackingField: []
|
|
||||||
SerializedTransformProperties:
|
|
||||||
Position: {x: -4.80351, y: 0.18147132, z: 5.430528}
|
|
||||||
Rotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
_isNetworked: 1
|
|
||||||
_isSpawnable: 1
|
|
||||||
_isGlobal: 0
|
|
||||||
_initializeOrder: 0
|
|
||||||
_defaultDespawnType: 0
|
|
||||||
NetworkObserver: {fileID: 0}
|
|
||||||
<PrefabId>k__BackingField: 21
|
|
||||||
<SpawnableCollectionId>k__BackingField: 0
|
|
||||||
_scenePathHash: 0
|
|
||||||
<SceneId>k__BackingField: 0
|
|
||||||
<AssetPathHash>k__BackingField: 12616697518120799840
|
|
||||||
--- !u!54 &201277549
|
|
||||||
Rigidbody:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598114786579}
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Mass: 1
|
|
||||||
m_Drag: 0
|
|
||||||
m_AngularDrag: 0.05
|
|
||||||
m_UseGravity: 1
|
|
||||||
m_IsKinematic: 0
|
|
||||||
m_Interpolate: 0
|
|
||||||
m_Constraints: 112
|
|
||||||
m_CollisionDetection: 1
|
|
||||||
--- !u!1 &303449598207636365
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 303449598207636364}
|
|
||||||
- component: {fileID: 303449598207636362}
|
|
||||||
- component: {fileID: 303449598207636363}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: Cube (2)
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &303449598207636364
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598207636365}
|
|
||||||
m_LocalRotation: {x: 0.5, y: 0.5, z: 0.5, w: 0.5}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1.5, y: 0.25, z: 0.25}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 303449599178274091}
|
|
||||||
m_RootOrder: 2
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 90, z: 90}
|
|
||||||
--- !u!33 &303449598207636362
|
|
||||||
MeshFilter:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598207636365}
|
|
||||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
--- !u!23 &303449598207636363
|
|
||||||
MeshRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598207636365}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_CastShadows: 1
|
|
||||||
m_ReceiveShadows: 1
|
|
||||||
m_DynamicOccludee: 1
|
|
||||||
m_StaticShadowCaster: 0
|
|
||||||
m_MotionVectors: 1
|
|
||||||
m_LightProbeUsage: 1
|
|
||||||
m_ReflectionProbeUsage: 1
|
|
||||||
m_RayTracingMode: 2
|
|
||||||
m_RayTraceProcedural: 0
|
|
||||||
m_RenderingLayerMask: 1
|
|
||||||
m_RendererPriority: 0
|
|
||||||
m_Materials:
|
|
||||||
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_StaticBatchInfo:
|
|
||||||
firstSubMesh: 0
|
|
||||||
subMeshCount: 0
|
|
||||||
m_StaticBatchRoot: {fileID: 0}
|
|
||||||
m_ProbeAnchor: {fileID: 0}
|
|
||||||
m_LightProbeVolumeOverride: {fileID: 0}
|
|
||||||
m_ScaleInLightmap: 1
|
|
||||||
m_ReceiveGI: 1
|
|
||||||
m_PreserveUVs: 0
|
|
||||||
m_IgnoreNormalsForChartDetection: 0
|
|
||||||
m_ImportantGI: 0
|
|
||||||
m_StitchLightmapSeams: 1
|
|
||||||
m_SelectedEditorRenderState: 3
|
|
||||||
m_MinimumChartSize: 4
|
|
||||||
m_AutoUVMaxDistance: 0.5
|
|
||||||
m_AutoUVMaxAngle: 89
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_SortingLayerID: 0
|
|
||||||
m_SortingLayer: 0
|
|
||||||
m_SortingOrder: 0
|
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
|
||||||
--- !u!1 &303449598691742042
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 303449598691742041}
|
|
||||||
- component: {fileID: 303449598691742039}
|
|
||||||
- component: {fileID: 303449598691742040}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: Cube
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &303449598691742041
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598691742042}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1.5, y: 0.25, z: 0.25}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 303449599178274091}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!33 &303449598691742039
|
|
||||||
MeshFilter:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598691742042}
|
|
||||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
--- !u!23 &303449598691742040
|
|
||||||
MeshRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449598691742042}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_CastShadows: 1
|
|
||||||
m_ReceiveShadows: 1
|
|
||||||
m_DynamicOccludee: 1
|
|
||||||
m_StaticShadowCaster: 0
|
|
||||||
m_MotionVectors: 1
|
|
||||||
m_LightProbeUsage: 1
|
|
||||||
m_ReflectionProbeUsage: 1
|
|
||||||
m_RayTracingMode: 2
|
|
||||||
m_RayTraceProcedural: 0
|
|
||||||
m_RenderingLayerMask: 1
|
|
||||||
m_RendererPriority: 0
|
|
||||||
m_Materials:
|
|
||||||
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_StaticBatchInfo:
|
|
||||||
firstSubMesh: 0
|
|
||||||
subMeshCount: 0
|
|
||||||
m_StaticBatchRoot: {fileID: 0}
|
|
||||||
m_ProbeAnchor: {fileID: 0}
|
|
||||||
m_LightProbeVolumeOverride: {fileID: 0}
|
|
||||||
m_ScaleInLightmap: 1
|
|
||||||
m_ReceiveGI: 1
|
|
||||||
m_PreserveUVs: 0
|
|
||||||
m_IgnoreNormalsForChartDetection: 0
|
|
||||||
m_ImportantGI: 0
|
|
||||||
m_StitchLightmapSeams: 1
|
|
||||||
m_SelectedEditorRenderState: 3
|
|
||||||
m_MinimumChartSize: 4
|
|
||||||
m_AutoUVMaxDistance: 0.5
|
|
||||||
m_AutoUVMaxAngle: 89
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_SortingLayerID: 0
|
|
||||||
m_SortingLayer: 0
|
|
||||||
m_SortingOrder: 0
|
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
|
||||||
--- !u!1 &303449599178274092
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 303449599178274091}
|
|
||||||
- component: {fileID: 303449599178274088}
|
|
||||||
- component: {fileID: 303449599178274089}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: Sphere (1)
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!4 &303449599178274091
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449599178274092}
|
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 303449598691742041}
|
|
||||||
- {fileID: 303449597948771941}
|
|
||||||
- {fileID: 303449598207636364}
|
|
||||||
m_Father: {fileID: 303449598114786577}
|
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!33 &303449599178274088
|
|
||||||
MeshFilter:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449599178274092}
|
|
||||||
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
--- !u!23 &303449599178274089
|
|
||||||
MeshRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 303449599178274092}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_CastShadows: 1
|
|
||||||
m_ReceiveShadows: 1
|
|
||||||
m_DynamicOccludee: 1
|
|
||||||
m_StaticShadowCaster: 0
|
|
||||||
m_MotionVectors: 1
|
|
||||||
m_LightProbeUsage: 1
|
|
||||||
m_ReflectionProbeUsage: 1
|
|
||||||
m_RayTracingMode: 2
|
|
||||||
m_RayTraceProcedural: 0
|
|
||||||
m_RenderingLayerMask: 1
|
|
||||||
m_RendererPriority: 0
|
|
||||||
m_Materials:
|
|
||||||
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_StaticBatchInfo:
|
|
||||||
firstSubMesh: 0
|
|
||||||
subMeshCount: 0
|
|
||||||
m_StaticBatchRoot: {fileID: 0}
|
|
||||||
m_ProbeAnchor: {fileID: 0}
|
|
||||||
m_LightProbeVolumeOverride: {fileID: 0}
|
|
||||||
m_ScaleInLightmap: 1
|
|
||||||
m_ReceiveGI: 1
|
|
||||||
m_PreserveUVs: 0
|
|
||||||
m_IgnoreNormalsForChartDetection: 0
|
|
||||||
m_ImportantGI: 0
|
|
||||||
m_StitchLightmapSeams: 1
|
|
||||||
m_SelectedEditorRenderState: 3
|
|
||||||
m_MinimumChartSize: 4
|
|
||||||
m_AutoUVMaxDistance: 0.5
|
|
||||||
m_AutoUVMaxAngle: 89
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_SortingLayerID: 0
|
|
||||||
m_SortingLayer: 0
|
|
||||||
m_SortingOrder: 0
|
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8ef354bfc16ca8a459074c3fa9b6727e
|
|
||||||
PrefabImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: bf02fdf4a8ce43c489e5b5d8e65cb87d
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,211 +0,0 @@
|
|||||||
using FishNet.Object;
|
|
||||||
using FishNet.Object.Prediction;
|
|
||||||
using FishNet.Transporting;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* See TransformPrediction.cs for more detailed notes.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace FishNet.PredictionV2
|
|
||||||
{
|
|
||||||
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
|
|
||||||
* AN EXAMPLE TO FOLLOW. */
|
|
||||||
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
|
|
||||||
* AN EXAMPLE TO FOLLOW. */
|
|
||||||
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
|
|
||||||
* AN EXAMPLE TO FOLLOW. */
|
|
||||||
/* THIS CLASS IS CURRENTLY USED FOR TESTING AND IS NOT CONSIDERED
|
|
||||||
* AN EXAMPLE TO FOLLOW. */
|
|
||||||
|
|
||||||
public class RigidbodyPredictionV2 : NetworkBehaviour
|
|
||||||
{
|
|
||||||
#if !PREDICTION_1
|
|
||||||
|
|
||||||
public struct MoveData : IReplicateData
|
|
||||||
{
|
|
||||||
public bool Jump;
|
|
||||||
public float Horizontal;
|
|
||||||
public float Vertical;
|
|
||||||
public Vector3 OtherImpulseForces;
|
|
||||||
public MoveData(bool jump, float horizontal, float vertical, Vector3 otherImpulseForces)
|
|
||||||
{
|
|
||||||
Jump = jump;
|
|
||||||
Horizontal = horizontal;
|
|
||||||
Vertical = vertical;
|
|
||||||
OtherImpulseForces = otherImpulseForces;
|
|
||||||
_tick = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private uint _tick;
|
|
||||||
public void Dispose() { }
|
|
||||||
public uint GetTick() => _tick;
|
|
||||||
public void SetTick(uint value) => _tick = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct ReconcileData : IReconcileData
|
|
||||||
{
|
|
||||||
public Vector3 Position;
|
|
||||||
public Quaternion Rotation;
|
|
||||||
public Vector3 Velocity;
|
|
||||||
public Vector3 AngularVelocity;
|
|
||||||
public ReconcileData(Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity)
|
|
||||||
{
|
|
||||||
Position = position;
|
|
||||||
Rotation = rotation;
|
|
||||||
Velocity = velocity;
|
|
||||||
AngularVelocity = angularVelocity;
|
|
||||||
_tick = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private uint _tick;
|
|
||||||
public void Dispose() { }
|
|
||||||
public uint GetTick() => _tick;
|
|
||||||
public void SetTick(uint value) => _tick = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//[SerializeField]
|
|
||||||
//private float _jumpForce = 15f;
|
|
||||||
[SerializeField]
|
|
||||||
private float _moveRate = 15f;
|
|
||||||
|
|
||||||
public Rigidbody Rigidbody { get; private set; }
|
|
||||||
private bool _jump;
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (base.IsOwner)
|
|
||||||
{
|
|
||||||
if (Input.GetKeyDown(KeyCode.Space))
|
|
||||||
_jump = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnStartNetwork()
|
|
||||||
{
|
|
||||||
Rigidbody = GetComponent<Rigidbody>();
|
|
||||||
base.TimeManager.OnTick += TimeManager_OnTick;
|
|
||||||
base.TimeManager.OnPostTick += TimeManager_OnPostTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnStopNetwork()
|
|
||||||
{
|
|
||||||
|
|
||||||
base.TimeManager.OnTick -= TimeManager_OnTick;
|
|
||||||
base.TimeManager.OnPostTick -= TimeManager_OnPostTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void TimeManager_OnTick()
|
|
||||||
{
|
|
||||||
Move(BuildMoveData());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TimeManager_OnPostTick()
|
|
||||||
{
|
|
||||||
CreateReconcile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MoveData BuildMoveData()
|
|
||||||
{
|
|
||||||
if (!IsOwner && Owner.IsValid)
|
|
||||||
return default;
|
|
||||||
|
|
||||||
float horizontal = Input.GetAxisRaw("Horizontal");
|
|
||||||
float vertical = Input.GetAxisRaw("Vertical");
|
|
||||||
//MoveData md = new MoveData(_jump, horizontal, vertical, (SpringForces + RocketForces));
|
|
||||||
MoveData md = new MoveData(_jump, horizontal, vertical, Vector3.zero);
|
|
||||||
|
|
||||||
//SpringForces = Vector3.zero;
|
|
||||||
//RocketForces = Vector3.zero;
|
|
||||||
|
|
||||||
_jump = false;
|
|
||||||
|
|
||||||
return md;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint LastMdTick;
|
|
||||||
|
|
||||||
[Replicate]
|
|
||||||
private void Move(MoveData md, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
|
|
||||||
{
|
|
||||||
LastMdTick = md.GetTick();
|
|
||||||
//if (base.IsOwner)
|
|
||||||
// Debug.Log(PredictionManager.ClientReplayTick + " > " + md.GetTick());
|
|
||||||
//if (state == ReplicateState.Future)
|
|
||||||
//{
|
|
||||||
// /* Reduce velocity slightly. This will be slightly less accurate if
|
|
||||||
// * the object continues to move in the same direction but can drastically
|
|
||||||
// * reduce jarring visuals if the object changes path rather than predicted(future)
|
|
||||||
// * forward. */
|
|
||||||
// _rigidbody.velocity *= 0.65f;
|
|
||||||
// _rigidbody.angularVelocity *= 0.65f;
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//Vector3 forces = new Vector3(md.Horizontal, 0f, md.Vertical) * _moveRate;
|
|
||||||
//Rigidbody.AddForce(forces);
|
|
||||||
|
|
||||||
//if (md.Jump)
|
|
||||||
// Rigidbody.AddForce(new Vector3(0f, _jumpForce, 0f), ForceMode.Impulse);
|
|
||||||
////Add gravity to make the object fall faster.
|
|
||||||
//Rigidbody.AddForce(Physics.gravity * 3f);
|
|
||||||
|
|
||||||
Vector3 forces = new Vector3(md.Horizontal, 0f, md.Vertical) * _moveRate;
|
|
||||||
//PRB.AddForce(forces);
|
|
||||||
forces += Physics.gravity * 3f;
|
|
||||||
//if (md.Jump)
|
|
||||||
// PRB.AddForce(new Vector3(0f, _jumpForce, 0f), ForceMode.Impulse);
|
|
||||||
////Add gravity to make the object fall faster.
|
|
||||||
//PRB.AddForce(forces);
|
|
||||||
|
|
||||||
|
|
||||||
//if (IsOwner)
|
|
||||||
//{
|
|
||||||
// if (state.IsReplayed())
|
|
||||||
// Debug.Log($"{md.GetTick()} -> {transform.position.x} -> {Rigidbody.velocity.x}");
|
|
||||||
// else
|
|
||||||
// Debug.LogWarning($"{md.GetTick()} -> {transform.position.x} -> {Rigidbody.velocity.x}");
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if ((!base.IsServerStarted && base.IsOwner) || (base.IsServerStarted && !base.IsOwner))
|
|
||||||
// Debug.LogWarning($"Frame {Time.frameCount}. State {state}, Horizontal {md.Horizontal}. MdTick {md.GetTick()}, PosX {transform.position.x.ToString("0.##")}. VelX {Rigidbody.velocity.x.ToString("0.###")}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CreateReconcile()
|
|
||||||
{
|
|
||||||
/* The base.IsServer check is not required but does save a little
|
|
||||||
* performance by not building the reconcileData if not server. */
|
|
||||||
if (IsServerStarted)
|
|
||||||
{
|
|
||||||
ReconcileData rd = new ReconcileData(transform.position, transform.rotation, Rigidbody.velocity, Rigidbody.angularVelocity);
|
|
||||||
//if (!base.IsOwner)
|
|
||||||
// Debug.LogError($"Frame {Time.frameCount}. Reconcile, MdTick {LastMdTick}, PosX {transform.position.x.ToString("0.##")}. VelX {Rigidbody.velocity.x.ToString("0.###")}.");
|
|
||||||
Reconciliation(rd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reconcile]
|
|
||||||
private void Reconciliation(ReconcileData rd, Channel channel = Channel.Unreliable)
|
|
||||||
{
|
|
||||||
transform.position = rd.Position;
|
|
||||||
transform.rotation = rd.Rotation;
|
|
||||||
Rigidbody.velocity = rd.Velocity;
|
|
||||||
Rigidbody.angularVelocity = rd.AngularVelocity;
|
|
||||||
|
|
||||||
//if (PrintForClient())
|
|
||||||
//{
|
|
||||||
// Debug.LogError($"Frame {Time.frameCount}. Reconcile, MdTick {rd.GetTick()}, PosX {transform.position.x.ToString("0.##")}. VelX {Rigidbody.velocity.x.ToString("0.###")}. RdPosX " +
|
|
||||||
// $"{rd.Position.x.ToString("0.##")}. RdVelX {Rigidbody.velocity.x.ToString("0.###")}");
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool PrintForClient() => ((!base.IsServerStarted && base.IsOwner) || (base.IsServerStarted && !base.IsOwner));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -28,9 +28,9 @@ RectTransform:
|
|||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: -1}
|
m_LocalPosition: {x: 0, y: 0, z: -1}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 4393252311501663115}
|
m_Father: {fileID: 4393252311501663115}
|
||||||
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
@ -60,7 +60,6 @@ MonoBehaviour:
|
|||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
@ -105,11 +104,11 @@ RectTransform:
|
|||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 4393252311652982283}
|
- {fileID: 4393252311652982283}
|
||||||
- {fileID: 4393252311501663115}
|
- {fileID: 4393252311501663115}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 0}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
@ -128,7 +127,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3}
|
m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
_autoStartType: 0
|
AutoStart: 0
|
||||||
_stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
_stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
||||||
_changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1}
|
_changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1}
|
||||||
_startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1}
|
_startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1}
|
||||||
@ -151,9 +150,7 @@ Canvas:
|
|||||||
m_OverrideSorting: 0
|
m_OverrideSorting: 0
|
||||||
m_OverridePixelPerfect: 0
|
m_OverridePixelPerfect: 0
|
||||||
m_SortingBucketNormalizedSize: 0
|
m_SortingBucketNormalizedSize: 0
|
||||||
m_VertexColorAlwaysGammaSpace: 0
|
|
||||||
m_AdditionalShaderChannelsFlag: 0
|
m_AdditionalShaderChannelsFlag: 0
|
||||||
m_UpdateRectTransformForStandalone: 0
|
|
||||||
m_SortingLayerID: 0
|
m_SortingLayerID: 0
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_TargetDisplay: 0
|
m_TargetDisplay: 0
|
||||||
@ -179,7 +176,6 @@ MonoBehaviour:
|
|||||||
m_FallbackScreenDPI: 96
|
m_FallbackScreenDPI: 96
|
||||||
m_DefaultSpriteDPI: 96
|
m_DefaultSpriteDPI: 96
|
||||||
m_DynamicPixelsPerUnit: 1
|
m_DynamicPixelsPerUnit: 1
|
||||||
m_PresetInfoIsWorld: 0
|
|
||||||
--- !u!114 &4393252310969058989
|
--- !u!114 &4393252310969058989
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -226,10 +222,10 @@ RectTransform:
|
|||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 9139860296052841449}
|
- {fileID: 9139860296052841449}
|
||||||
m_Father: {fileID: 4393252310969058990}
|
m_Father: {fileID: 4393252310969058990}
|
||||||
|
m_RootOrder: 1
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 1}
|
||||||
@ -259,7 +255,6 @@ MonoBehaviour:
|
|||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
@ -288,7 +283,6 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Navigation:
|
m_Navigation:
|
||||||
m_Mode: 3
|
m_Mode: 3
|
||||||
m_WrapAround: 0
|
|
||||||
m_SelectOnUp: {fileID: 0}
|
m_SelectOnUp: {fileID: 0}
|
||||||
m_SelectOnDown: {fileID: 0}
|
m_SelectOnDown: {fileID: 0}
|
||||||
m_SelectOnLeft: {fileID: 0}
|
m_SelectOnLeft: {fileID: 0}
|
||||||
@ -319,7 +313,6 @@ MonoBehaviour:
|
|||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 4393252310969058994}
|
- m_Target: {fileID: 4393252310969058994}
|
||||||
m_TargetAssemblyTypeName:
|
|
||||||
m_MethodName: OnClick_Client
|
m_MethodName: OnClick_Client
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
m_Arguments:
|
m_Arguments:
|
||||||
@ -359,10 +352,10 @@ RectTransform:
|
|||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 7233259200663826443}
|
- {fileID: 7233259200663826443}
|
||||||
m_Father: {fileID: 4393252310969058990}
|
m_Father: {fileID: 4393252310969058990}
|
||||||
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 1}
|
||||||
@ -392,7 +385,6 @@ MonoBehaviour:
|
|||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
@ -421,7 +413,6 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Navigation:
|
m_Navigation:
|
||||||
m_Mode: 3
|
m_Mode: 3
|
||||||
m_WrapAround: 0
|
|
||||||
m_SelectOnUp: {fileID: 0}
|
m_SelectOnUp: {fileID: 0}
|
||||||
m_SelectOnDown: {fileID: 0}
|
m_SelectOnDown: {fileID: 0}
|
||||||
m_SelectOnLeft: {fileID: 0}
|
m_SelectOnLeft: {fileID: 0}
|
||||||
@ -452,7 +443,6 @@ MonoBehaviour:
|
|||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 4393252310969058994}
|
- m_Target: {fileID: 4393252310969058994}
|
||||||
m_TargetAssemblyTypeName:
|
|
||||||
m_MethodName: OnClick_Server
|
m_MethodName: OnClick_Server
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
m_Arguments:
|
m_Arguments:
|
||||||
@ -491,9 +481,9 @@ RectTransform:
|
|||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: -1}
|
m_LocalPosition: {x: 0, y: 0, z: -1}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 4393252311652982283}
|
m_Father: {fileID: 4393252311652982283}
|
||||||
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
@ -523,7 +513,6 @@ MonoBehaviour:
|
|||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
|
|||||||
208
Assets/FishNet/Demos/Prefabs/NetworkManager.prefab
Normal file
208
Assets/FishNet/Demos/Prefabs/NetworkManager.prefab
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &7443408887813606051
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 7443408887813606049}
|
||||||
|
- component: {fileID: 7443408887813606050}
|
||||||
|
- component: {fileID: 934570884}
|
||||||
|
- component: {fileID: 7443408887813606060}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: NetworkManager
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &7443408887813606049
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7443408887813606051}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 4393252310584637084}
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &7443408887813606050
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7443408887813606051}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
_logging: {fileID: 0}
|
||||||
|
_spawnablePrefabs: {fileID: 11400000, guid: ec64eb18c93ab344892891f33edbf82a, type: 2}
|
||||||
|
_refreshDefaultPrefabs: 0
|
||||||
|
_runInBackground: 1
|
||||||
|
_dontDestroyOnLoad: 1
|
||||||
|
_persistence: 0
|
||||||
|
--- !u!114 &934570884
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7443408887813606051}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 7d331f979d46e8e4a9fc90070c596d44, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
_defaultConditions:
|
||||||
|
- {fileID: 11400000, guid: 2033f54fd2794464bae08fa5a55c8996, type: 2}
|
||||||
|
--- !u!114 &7443408887813606060
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7443408887813606051}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 211a9f6ec51ddc14f908f5acc0cd0423, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
_playerPrefab: {fileID: 0}
|
||||||
|
_addToDefaultScene: 1
|
||||||
|
Spawns: []
|
||||||
|
--- !u!1001 &2130063410
|
||||||
|
PrefabInstance:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Modification:
|
||||||
|
m_TransformParent: {fileID: 7443408887813606049}
|
||||||
|
m_Modifications:
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_Pivot.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_Pivot.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_RootOrder
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchorMax.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchorMax.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchorMin.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchorMin.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_SizeDelta.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_SizeDelta.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalPosition.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalRotation.w
|
||||||
|
value: 1
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalRotation.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalRotation.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalRotation.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4393252310969058995, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_Name
|
||||||
|
value: NetworkHudCanvas
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
m_RemovedComponents: []
|
||||||
|
m_SourcePrefab: {fileID: 100100000, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3}
|
||||||
|
--- !u!224 &4393252310584637084 stripped
|
||||||
|
RectTransform:
|
||||||
|
m_CorrespondingSourceObject: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0,
|
||||||
|
type: 3}
|
||||||
|
m_PrefabInstance: {fileID: 2130063410}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 5b712878ecece354ba4ffb026c0a221c
|
guid: 0b650fca685f2eb41a86538aa883e4c1
|
||||||
PrefabImporter:
|
PrefabImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@ -1,16 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _SceneManager_Old_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs:
|
|
||||||
- {fileID: 611616139817875448, guid: bf5f023b4017a5e41a9815ec5745df3d, type: 3}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b1b4d193fc9b1bb41a92600a22b3d34e
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!114 &11400000
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 0}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4489d77032a81ef42b0067acf2737d4d, type: 3}
|
|
||||||
m_Name: _SceneManager_Additive Scenes_Prefabs
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_prefabs:
|
|
||||||
- {fileID: 8192566354860284824, guid: 6331b3542e64a564c81bc39cedf70c8d, type: 3}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 223fa01133c52c7469e6520b901bcebd
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 11400000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,115 +1,115 @@
|
|||||||
//using System.Collections;
|
using System.Collections;
|
||||||
//using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
//namespace FishNet.Transporting.Bayou
|
namespace FishNet.Transporting.Bayou
|
||||||
//{
|
{
|
||||||
// internal class BidirectionalDictionary<T1, T2> : IEnumerable
|
internal class BidirectionalDictionary<T1, T2> : IEnumerable
|
||||||
// {
|
{
|
||||||
// private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
|
private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
|
||||||
// private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
|
private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
|
||||||
|
|
||||||
// public IEnumerable<T1> FirstTypes => t1ToT2Dict.Keys;
|
public IEnumerable<T1> FirstTypes => t1ToT2Dict.Keys;
|
||||||
// public IEnumerable<T2> SecondTypes => t2ToT1Dict.Keys;
|
public IEnumerable<T2> SecondTypes => t2ToT1Dict.Keys;
|
||||||
|
|
||||||
// public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator();
|
public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator();
|
||||||
|
|
||||||
// public int Count => t1ToT2Dict.Count;
|
public int Count => t1ToT2Dict.Count;
|
||||||
|
|
||||||
// public Dictionary<T1, T2> First => t1ToT2Dict;
|
public Dictionary<T1, T2> First => t1ToT2Dict;
|
||||||
// public Dictionary<T2, T1> Second => t2ToT1Dict;
|
public Dictionary<T2, T1> Second => t2ToT1Dict;
|
||||||
|
|
||||||
// public void Add(T1 key, T2 value)
|
public void Add(T1 key, T2 value)
|
||||||
// {
|
{
|
||||||
// if (t1ToT2Dict.ContainsKey(key))
|
if (t1ToT2Dict.ContainsKey(key))
|
||||||
// {
|
{
|
||||||
// Remove(key);
|
Remove(key);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// t1ToT2Dict[key] = value;
|
t1ToT2Dict[key] = value;
|
||||||
// t2ToT1Dict[value] = key;
|
t2ToT1Dict[value] = key;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public void Add(T2 key, T1 value)
|
public void Add(T2 key, T1 value)
|
||||||
// {
|
{
|
||||||
// if (t2ToT1Dict.ContainsKey(key))
|
if (t2ToT1Dict.ContainsKey(key))
|
||||||
// {
|
{
|
||||||
// Remove(key);
|
Remove(key);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// t2ToT1Dict[key] = value;
|
t2ToT1Dict[key] = value;
|
||||||
// t1ToT2Dict[value] = key;
|
t1ToT2Dict[value] = key;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public T2 Get(T1 key) => t1ToT2Dict[key];
|
public T2 Get(T1 key) => t1ToT2Dict[key];
|
||||||
|
|
||||||
// public T1 Get(T2 key) => t2ToT1Dict[key];
|
public T1 Get(T2 key) => t2ToT1Dict[key];
|
||||||
|
|
||||||
// public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value);
|
public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value);
|
||||||
|
|
||||||
// public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value);
|
public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value);
|
||||||
|
|
||||||
// public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key);
|
public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key);
|
||||||
|
|
||||||
// public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key);
|
public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key);
|
||||||
|
|
||||||
// public void Remove(T1 key)
|
public void Remove(T1 key)
|
||||||
// {
|
{
|
||||||
// if (First.TryGetValue(key, out T2 value))
|
if (First.TryGetValue(key, out T2 value))
|
||||||
// {
|
{
|
||||||
// t1ToT2Dict.Remove(key);
|
t1ToT2Dict.Remove(key);
|
||||||
// t2ToT1Dict.Remove(value);
|
t2ToT1Dict.Remove(value);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public void Clear()
|
public void Clear()
|
||||||
// {
|
{
|
||||||
// First.Clear();
|
First.Clear();
|
||||||
// Second.Clear();
|
Second.Clear();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public void Remove(T2 key)
|
public void Remove(T2 key)
|
||||||
// {
|
{
|
||||||
// if (Second.TryGetValue(key, out T1 value))
|
if (Second.TryGetValue(key, out T1 value))
|
||||||
// {
|
{
|
||||||
// t1ToT2Dict.Remove(value);
|
t1ToT2Dict.Remove(value);
|
||||||
// t2ToT1Dict.Remove(key);
|
t2ToT1Dict.Remove(key);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public void RemoveFirst(T1 key)
|
public void RemoveFirst(T1 key)
|
||||||
// {
|
{
|
||||||
// if (First.TryGetValue(key, out T2 value))
|
if (First.TryGetValue(key, out T2 value))
|
||||||
// {
|
{
|
||||||
// Second.Remove(value);
|
Second.Remove(value);
|
||||||
// First.Remove(key);
|
First.Remove(key);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public void RemoveSecond(T2 key)
|
public void RemoveSecond(T2 key)
|
||||||
// {
|
{
|
||||||
// if (Second.TryGetValue(key, out T1 value))
|
if (Second.TryGetValue(key, out T1 value))
|
||||||
// {
|
{
|
||||||
// First.Remove(value);
|
First.Remove(value);
|
||||||
// Second.Remove(key);
|
Second.Remove(key);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public T1 this[T2 key]
|
public T1 this[T2 key]
|
||||||
// {
|
{
|
||||||
// get => t2ToT1Dict[key];
|
get => t2ToT1Dict[key];
|
||||||
// set
|
set
|
||||||
// {
|
{
|
||||||
// Add(key, value);
|
Add(key, value);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// public T2 this[T1 key]
|
public T2 this[T1 key]
|
||||||
// {
|
{
|
||||||
// get => t1ToT2Dict[key];
|
get => t1ToT2Dict[key];
|
||||||
// set
|
set
|
||||||
// {
|
{
|
||||||
// Add(key, value);
|
Add(key, value);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
@ -56,7 +56,7 @@ namespace FishNet.Transporting.Bayou.Server
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Currently connected clients.
|
/// Currently connected clients.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private HashSet<int> _clients = new HashSet<int>();
|
private List<int> _clients = new List<int>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Server socket manager.
|
/// Server socket manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -129,7 +129,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Log.Verbose($"BufferBucket({arraySize}) create new");
|
Log.Verbose($"BufferBucket({arraySize}) create new");
|
||||||
return new ArrayBuffer(this, arraySize);
|
return new ArrayBuffer(this, arraySize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,13 +145,13 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
void IncrementCreated()
|
void IncrementCreated()
|
||||||
{
|
{
|
||||||
int next = Interlocked.Increment(ref _current);
|
int next = Interlocked.Increment(ref _current);
|
||||||
//Log.Verbose($"BufferBucket({arraySize}) count:{next}");
|
Log.Verbose($"BufferBucket({arraySize}) count:{next}");
|
||||||
}
|
}
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
void DecrementCreated()
|
void DecrementCreated()
|
||||||
{
|
{
|
||||||
int next = Interlocked.Decrement(ref _current);
|
int next = Interlocked.Decrement(ref _current);
|
||||||
//Log.Verbose($"BufferBucket({arraySize}) count:{next}");
|
Log.Verbose($"BufferBucket({arraySize}) count:{next}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
{
|
{
|
||||||
(Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue<Message> queue, BufferPool _) = config;
|
(Connection conn, int maxMessageSize, bool expectMask, ConcurrentQueue<Message> queue, BufferPool _) = config;
|
||||||
|
|
||||||
//Profiler.BeginThreadProfiling("SimpleWeb", $"ReceiveLoop {conn.connId}");
|
Profiler.BeginThreadProfiling("SimpleWeb", $"ReceiveLoop {conn.connId}");
|
||||||
|
|
||||||
byte[] readBuffer = new byte[Constants.HeaderSize + (expectMask ? Constants.MaskSize : 0) + maxMessageSize];
|
byte[] readBuffer = new byte[Constants.HeaderSize + (expectMask ? Constants.MaskSize : 0) + maxMessageSize];
|
||||||
try
|
try
|
||||||
@ -95,7 +95,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
//Profiler.EndThreadProfiling();
|
Profiler.EndThreadProfiling();
|
||||||
|
|
||||||
conn.Dispose();
|
conn.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
{
|
{
|
||||||
(Connection conn, int bufferSize, bool setMask) = config;
|
(Connection conn, int bufferSize, bool setMask) = config;
|
||||||
|
|
||||||
//Profiler.BeginThreadProfiling("SimpleWeb", $"SendLoop {conn.connId}");
|
Profiler.BeginThreadProfiling("SimpleWeb", $"SendLoop {conn.connId}");
|
||||||
|
|
||||||
// create write buffer for this thread
|
// create write buffer for this thread
|
||||||
byte[] writeBuffer = new byte[bufferSize];
|
byte[] writeBuffer = new byte[bufferSize];
|
||||||
@ -70,11 +70,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
while (conn.sendQueue.TryDequeue(out ArrayBuffer msg))
|
while (conn.sendQueue.TryDequeue(out ArrayBuffer msg))
|
||||||
{
|
{
|
||||||
// check if connected before sending message
|
// check if connected before sending message
|
||||||
if (!client.Connected)
|
if (!client.Connected) { Log.Info($"SendLoop {conn} not connected"); return; }
|
||||||
{
|
|
||||||
//Log.Info($"SendLoop {conn} not connected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int maxLength = msg.count + Constants.HeaderSize + Constants.MaskSize;
|
int maxLength = msg.count + Constants.HeaderSize + Constants.MaskSize;
|
||||||
|
|
||||||
@ -99,11 +95,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
while (conn.sendQueue.TryDequeue(out ArrayBuffer msg))
|
while (conn.sendQueue.TryDequeue(out ArrayBuffer msg))
|
||||||
{
|
{
|
||||||
// check if connected before sending message
|
// check if connected before sending message
|
||||||
if (!client.Connected)
|
if (!client.Connected) { Log.Info($"SendLoop {conn} not connected"); return; }
|
||||||
{
|
|
||||||
//Log.Info($"SendLoop {conn} not connected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = SendMessage(writeBuffer, 0, msg, setMask, maskHelper);
|
int length = SendMessage(writeBuffer, 0, msg, setMask, maskHelper);
|
||||||
stream.Write(writeBuffer, 0, length);
|
stream.Write(writeBuffer, 0, length);
|
||||||
@ -114,14 +106,8 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
|
|
||||||
Log.Info($"{conn} Not Connected");
|
Log.Info($"{conn} Not Connected");
|
||||||
}
|
}
|
||||||
catch (ThreadInterruptedException e)
|
catch (ThreadInterruptedException e) { Log.InfoException(e); }
|
||||||
{
|
catch (ThreadAbortException e) { Log.InfoException(e); }
|
||||||
Log.InfoException(e);
|
|
||||||
}
|
|
||||||
catch (ThreadAbortException e)
|
|
||||||
{
|
|
||||||
Log.InfoException(e);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Exception(e);
|
Log.Exception(e);
|
||||||
@ -149,7 +135,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
offset += msgLength;
|
offset += msgLength;
|
||||||
|
|
||||||
// dump before mask on
|
// dump before mask on
|
||||||
//Log.DumpBuffer("Send", buffer, startOffset, offset);
|
Log.DumpBuffer("Send", buffer, startOffset, offset);
|
||||||
|
|
||||||
if (setMask)
|
if (setMask)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -46,7 +46,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
|
|
||||||
if (!IsGet(getHeader.array))
|
if (!IsGet(getHeader.array))
|
||||||
{
|
{
|
||||||
//Log.Warn($"First bytes from client was not 'GET' for handshake, instead was {Log.BufferToString(getHeader.array, 0, GetSize)}");
|
Log.Warn($"First bytes from client was not 'GET' for handshake, instead was {Log.BufferToString(getHeader.array, 0, GetSize)}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendAll(HashSet<int> connectionIds, ArraySegment<byte> source)
|
public void SendAll(List<int> connectionIds, ArraySegment<byte> source)
|
||||||
{
|
{
|
||||||
ArrayBuffer buffer = bufferPool.Take(source.Count);
|
ArrayBuffer buffer = bufferPool.Take(source.Count);
|
||||||
buffer.CopyFrom(source);
|
buffer.CopyFrom(source);
|
||||||
@ -60,8 +60,10 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
|
|
||||||
// make copy of array before for each, data sent to each client is the same
|
// make copy of array before for each, data sent to each client is the same
|
||||||
foreach (int id in connectionIds)
|
foreach (int id in connectionIds)
|
||||||
|
{
|
||||||
server.Send(id, buffer);
|
server.Send(id, buffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void SendOne(int connectionId, ArraySegment<byte> source)
|
public void SendOne(int connectionId, ArraySegment<byte> source)
|
||||||
{
|
{
|
||||||
ArrayBuffer buffer = bufferPool.Take(source.Count);
|
ArrayBuffer buffer = bufferPool.Take(source.Count);
|
||||||
@ -80,15 +82,25 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
return server.GetClientAddress(connectionId);
|
return server.GetClientAddress(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes all messages.
|
/// Processes all new messages
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ProcessMessageQueue()
|
public void ProcessMessageQueue()
|
||||||
|
{
|
||||||
|
ProcessMessageQueue(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes all messages while <paramref name="behaviour"/> is enabled
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="behaviour"></param>
|
||||||
|
public void ProcessMessageQueue(MonoBehaviour behaviour)
|
||||||
{
|
{
|
||||||
int processedCount = 0;
|
int processedCount = 0;
|
||||||
|
bool skipEnabled = behaviour == null;
|
||||||
// check enabled every time incase behaviour was disabled after data
|
// check enabled every time incase behaviour was disabled after data
|
||||||
while (
|
while (
|
||||||
|
(skipEnabled || behaviour.enabled) &&
|
||||||
processedCount < maxMessagesPerTick &&
|
processedCount < maxMessagesPerTick &&
|
||||||
// Dequeue last
|
// Dequeue last
|
||||||
server.receiveQueue.TryDequeue(out Message next)
|
server.receiveQueue.TryDequeue(out Message next)
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
using FishNet.Connection;
|
|
||||||
using FishNet.Managing;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -33,7 +31,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
if (_idCache.Count == 0)
|
if (_idCache.Count == 0)
|
||||||
GrowIdCache(1000);
|
GrowIdCache(1000);
|
||||||
|
|
||||||
int result = NetworkConnection.UNSET_CLIENTID_VALUE;
|
int result;
|
||||||
_idCache.TryDequeue(out result);
|
_idCache.TryDequeue(out result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -43,7 +41,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void GrowIdCache(int value)
|
private void GrowIdCache(int value)
|
||||||
{
|
{
|
||||||
int over = (_nextId + value) - NetworkConnection.MAXIMUM_CLIENTID_VALUE;
|
int over = (_nextId + value) - int.MaxValue;
|
||||||
//Prevent overflow.
|
//Prevent overflow.
|
||||||
if (over > 0)
|
if (over > 0)
|
||||||
value -= over;
|
value -= over;
|
||||||
@ -112,7 +110,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
// this might not be a problem as HandshakeAndReceiveLoop checks for stop
|
// this might not be a problem as HandshakeAndReceiveLoop checks for stop
|
||||||
// and returns/disposes before sending message to queue
|
// and returns/disposes before sending message to queue
|
||||||
Connection conn = new Connection(client, AfterConnectionDisposed);
|
Connection conn = new Connection(client, AfterConnectionDisposed);
|
||||||
//Log.Info($"A client connected {conn}");
|
Log.Info($"A client connected {conn}");
|
||||||
|
|
||||||
// handshake needs its own thread as it needs to wait for message from client
|
// handshake needs its own thread as it needs to wait for message from client
|
||||||
Thread receiveThread = new Thread(() => HandshakeAndReceiveLoop(conn));
|
Thread receiveThread = new Thread(() => HandshakeAndReceiveLoop(conn));
|
||||||
@ -142,7 +140,7 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
bool success = sslHelper.TryCreateStream(conn);
|
bool success = sslHelper.TryCreateStream(conn);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
//Log.Error($"Failed to create SSL Stream {conn}");
|
Log.Error($"Failed to create SSL Stream {conn}");
|
||||||
conn.Dispose();
|
conn.Dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -151,11 +149,11 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
//Log.Info($"Sent Handshake {conn}");
|
Log.Info($"Sent Handshake {conn}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Log.Error($"Handshake Failed {conn}");
|
Log.Error($"Handshake Failed {conn}");
|
||||||
conn.Dispose();
|
conn.Dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -168,13 +166,6 @@ namespace JamesFrowen.SimpleWeb
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn.connId = GetNextId();
|
conn.connId = GetNextId();
|
||||||
if (conn.connId == NetworkConnection.UNSET_CLIENTID_VALUE)
|
|
||||||
{
|
|
||||||
NetworkManagerExtensions.LogWarning($"At maximum connections. A client attempting to connect to be rejected.");
|
|
||||||
conn.Dispose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
connections.TryAdd(conn.connId, conn);
|
connections.TryAdd(conn.connId, conn);
|
||||||
|
|
||||||
receiveQueue.Enqueue(new Message(conn.connId, EventType.Connected));
|
receiveQueue.Enqueue(new Message(conn.connId, EventType.Connected));
|
||||||
|
|||||||
@ -1,16 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "SimpleWebTransport",
|
"name": "SimpleWebTransport",
|
||||||
"rootNamespace": "",
|
"references": [],
|
||||||
"references": [
|
"optionalUnityReferences": [],
|
||||||
"GUID:7c88a4a7926ee5145ad2dfa06f454c67"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
"overrideReferences": false,
|
"overrideReferences": false,
|
||||||
"precompiledReferences": [],
|
"precompiledReferences": [],
|
||||||
"autoReferenced": true,
|
"autoReferenced": true,
|
||||||
"defineConstraints": [],
|
"defineConstraints": []
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
}
|
||||||
@ -23,7 +23,9 @@ namespace Edgegap
|
|||||||
|
|
||||||
public static BuildReport BuildServer()
|
public static BuildReport BuildServer()
|
||||||
{
|
{
|
||||||
IEnumerable<string> scenes = EditorBuildSettings.scenes.Select(s=>s.path);
|
IEnumerable<string> scenes = EditorBuildSettings.scenes
|
||||||
|
.Where(s => s.enabled)
|
||||||
|
.Select(s => s.path);
|
||||||
BuildPlayerOptions options = new BuildPlayerOptions
|
BuildPlayerOptions options = new BuildPlayerOptions
|
||||||
{
|
{
|
||||||
scenes = scenes.ToArray(),
|
scenes = scenes.ToArray(),
|
||||||
|
|||||||
@ -44,7 +44,6 @@ namespace Edgegap.Editor
|
|||||||
private string _deploymentRequestId;
|
private string _deploymentRequestId;
|
||||||
private string _userExternalIp;
|
private string _userExternalIp;
|
||||||
private bool _isAwaitingDeploymentReadyStatus;
|
private bool _isAwaitingDeploymentReadyStatus;
|
||||||
private bool _registered;
|
|
||||||
#endregion // Vars
|
#endregion // Vars
|
||||||
|
|
||||||
|
|
||||||
@ -151,7 +150,6 @@ namespace Edgegap.Editor
|
|||||||
unregisterClickEvents();
|
unregisterClickEvents();
|
||||||
unregisterFieldCallbacks();
|
unregisterFieldCallbacks();
|
||||||
SyncObjectWithForm();
|
SyncObjectWithForm();
|
||||||
_registered = false;
|
|
||||||
}
|
}
|
||||||
#endregion // Unity Funcs
|
#endregion // Unity Funcs
|
||||||
|
|
||||||
@ -163,7 +161,6 @@ namespace Edgegap.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitUIElements()
|
private void InitUIElements()
|
||||||
{
|
{
|
||||||
_registered = true;
|
|
||||||
setVisualElementsToFields();
|
setVisualElementsToFields();
|
||||||
assertVisualElementKeys();
|
assertVisualElementKeys();
|
||||||
closeDisableGroups();
|
closeDisableGroups();
|
||||||
@ -380,9 +377,6 @@ namespace Edgegap.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void unregisterFieldCallbacks()
|
private void unregisterFieldCallbacks()
|
||||||
{
|
{
|
||||||
if (!_registered)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_apiTokenInput.UnregisterValueChangedCallback(onApiTokenInputChanged);
|
_apiTokenInput.UnregisterValueChangedCallback(onApiTokenInputChanged);
|
||||||
_apiTokenInput.UnregisterCallback<FocusOutEvent>(onApiTokenInputFocusOut);
|
_apiTokenInput.UnregisterCallback<FocusOutEvent>(onApiTokenInputFocusOut);
|
||||||
|
|
||||||
@ -419,8 +413,6 @@ namespace Edgegap.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void unregisterClickEvents()
|
private void unregisterClickEvents()
|
||||||
{
|
{
|
||||||
if (!_registered)
|
|
||||||
return;
|
|
||||||
_debugBtn.clickable.clicked -= onDebugBtnClick;
|
_debugBtn.clickable.clicked -= onDebugBtnClick;
|
||||||
|
|
||||||
_apiTokenVerifyBtn.clickable.clicked -= onApiTokenVerifyBtnClick;
|
_apiTokenVerifyBtn.clickable.clicked -= onApiTokenVerifyBtnClick;
|
||||||
@ -612,8 +604,6 @@ namespace Edgegap.Editor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SyncObjectWithForm()
|
private void SyncObjectWithForm()
|
||||||
{
|
{
|
||||||
if (_appIconSpriteObjInput == null)
|
|
||||||
return;
|
|
||||||
_appIconSpriteObj = _appIconSpriteObjInput.value as Sprite;
|
_appIconSpriteObj = _appIconSpriteObjInput.value as Sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,10 +55,10 @@ namespace Edgegap
|
|||||||
switch (apiEnvironment)
|
switch (apiEnvironment)
|
||||||
{
|
{
|
||||||
case ApiEnvironment.Staging:
|
case ApiEnvironment.Staging:
|
||||||
apiUrl = "https://staging-docs.edgegap.com/docs";
|
apiUrl = "https://staging-docs.edgegap.com/docs/category/unity";
|
||||||
break;
|
break;
|
||||||
case ApiEnvironment.Console:
|
case ApiEnvironment.Console:
|
||||||
apiUrl = "https://docs.edgegap.com/docs";
|
apiUrl = "https://docs.edgegap.com/docs/category/unity";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
apiUrl = null;
|
apiUrl = null;
|
||||||
|
|||||||
@ -43,6 +43,7 @@ namespace Newtonsoft.Json
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResetWarnTime();
|
||||||
UnityEngine.Debug.LogWarning($"Edgegap requires Json.NET to be imported to function. To import Json.NET navigate to Window -> Package Manager -> Click the + symbol and choose 'Add package by name' -> com.unity.nuget.newtonsoft-json -> Leave version blank and click Add. If you are not currently using Edgegap you may ignore this message.");
|
UnityEngine.Debug.LogWarning($"Edgegap requires Json.NET to be imported to function. To import Json.NET navigate to Window -> Package Manager -> Click the + symbol and choose 'Add package by name' -> com.unity.nuget.newtonsoft-json -> Leave version blank and click Add. If you are not currently using Edgegap you may ignore this message.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,12 @@ namespace FishNet.CodeGenerating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class AllowMutableSyncTypeAttribute : Attribute { }
|
public class AllowMutableSyncTypeAttribute : Attribute { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type will be excluded from creating auto serializer creation.
|
/// Type will be included in auto serializer creation.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage((AttributeTargets.Class | AttributeTargets.Struct), Inherited = true, AllowMultiple = false)]
|
||||||
|
public class IncludeSerializationAttribute : Attribute { }
|
||||||
|
/// <summary>
|
||||||
|
/// Type will be excluded from auto serializer creation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ExcludeSerializationAttribute : Attribute { }
|
public class ExcludeSerializationAttribute : Attribute { }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,4 +35,10 @@ namespace FishNet.CodeGenerating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage((AttributeTargets.Class | AttributeTargets.Struct), Inherited = true, AllowMultiple = false)]
|
[AttributeUsage((AttributeTargets.Class | AttributeTargets.Struct), Inherited = true, AllowMultiple = false)]
|
||||||
public class UseGlobalCustomSerializerAttribute : Attribute { }
|
public class UseGlobalCustomSerializerAttribute : Attribute { }
|
||||||
|
/// <summary>
|
||||||
|
/// Uses built-in caches to retrieve read classes rather than initializing a new instance.
|
||||||
|
/// This attribute is primarily for internal use and may change at anytime without notice.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage((AttributeTargets.Class), Inherited = true, AllowMultiple = false)]
|
||||||
|
public class ReadUnallocated : Attribute { }
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ namespace FishNet.Connection
|
|||||||
* Modify reserve after making sendLast bundle
|
* Modify reserve after making sendLast bundle
|
||||||
* so that the wrong reserve is not passed into
|
* so that the wrong reserve is not passed into
|
||||||
* the sendLast bundle. */
|
* the sendLast bundle. */
|
||||||
reserve += TransportManager.TICK_BYTES;
|
reserve += TransportManager.UNPACKED_TICK_LENGTH;
|
||||||
_reserve = reserve;
|
_reserve = reserve;
|
||||||
//Add buffer requires the right reserve so call after setting.
|
//Add buffer requires the right reserve so call after setting.
|
||||||
AddBuffer();
|
AddBuffer();
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
using FishNet.Managing;
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
using FishNet.Managing;
|
||||||
using FishNet.Managing.Predicting;
|
using FishNet.Managing.Predicting;
|
||||||
using FishNet.Managing.Timing;
|
using FishNet.Managing.Timing;
|
||||||
|
using FishNet.Managing.Transporting;
|
||||||
using FishNet.Serializing;
|
using FishNet.Serializing;
|
||||||
using FishNet.Transporting;
|
using FishNet.Transporting;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -45,20 +49,21 @@ namespace FishNet.Connection
|
|||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
internal void WriteState(PooledWriter data)
|
internal void WriteState(PooledWriter data)
|
||||||
{
|
{
|
||||||
#if !DEVELOPMENT_BUILD && !UNITY_EDITOR
|
#if !DEVELOPMENT
|
||||||
//Do not send states to clientHost.
|
//Do not send states to clientHost.
|
||||||
if (IsLocalClient)
|
if (IsLocalClient)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TimeManager tm = NetworkManager.TimeManager;
|
TimeManager timeManager = NetworkManager.TimeManager;
|
||||||
uint ticksBehind = (IsLocalClient) ? 0 : PacketTick.LocalTickDifference(tm);
|
TransportManager transportManager = NetworkManager.TransportManager;
|
||||||
|
uint ticksBehind = (IsLocalClient) ? 0 : PacketTick.LocalTickDifference(timeManager);
|
||||||
/* If it's been a really long while the client could just be setting up
|
/* If it's been a really long while the client could just be setting up
|
||||||
* or dropping. Only send if they've communicated within 5 seconds. */
|
* or dropping. Only send if they've communicated within 5 seconds. */
|
||||||
if (ticksBehind > (tm.TickRate * 5))
|
if (ticksBehind > (timeManager.TickRate * 5))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int mtu = NetworkManager.TransportManager.GetLowestMTU((byte)Channel.Unreliable);
|
int mtu = transportManager.GetLowestMTU((byte)Channel.Unreliable);
|
||||||
PooledWriter stateWriter;
|
PooledWriter stateWriter;
|
||||||
int writerCount = PredictionStateWriters.Count;
|
int writerCount = PredictionStateWriters.Count;
|
||||||
/* Conditions to create a new writer are:
|
/* Conditions to create a new writer are:
|
||||||
@ -66,7 +71,7 @@ namespace FishNet.Connection
|
|||||||
* - data length + currentWriter length > mtu */
|
* - data length + currentWriter length > mtu */
|
||||||
Channel channel = Channel.Unreliable;
|
Channel channel = Channel.Unreliable;
|
||||||
if (writerCount > 0)
|
if (writerCount > 0)
|
||||||
NetworkManager.TransportManager.CheckSetReliableChannel((data.Length + PredictionStateWriters[writerCount - 1].Length), ref channel);
|
transportManager.CheckSetReliableChannel((data.Length + PredictionStateWriters[writerCount - 1].Length), ref channel);
|
||||||
/* If no writers or if channel would be forced reliable.
|
/* If no writers or if channel would be forced reliable.
|
||||||
*
|
*
|
||||||
* By checking if channel would be reliable this is
|
* By checking if channel would be reliable this is
|
||||||
@ -79,7 +84,10 @@ namespace FishNet.Connection
|
|||||||
{
|
{
|
||||||
stateWriter = WriterPool.Retrieve(mtu);
|
stateWriter = WriterPool.Retrieve(mtu);
|
||||||
PredictionStateWriters.Add(stateWriter);
|
PredictionStateWriters.Add(stateWriter);
|
||||||
stateWriter.Reserve(PredictionManager.STATE_HEADER_RESERVE_COUNT);
|
stateWriter.Reserve(PredictionManager.STATE_HEADER_RESERVE_LENGTH);
|
||||||
|
/// 2 PacketId.
|
||||||
|
/// 4 Last replicate tick run for connection.
|
||||||
|
/// 4 Length unpacked.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
using FishNet.Component.Observing;
|
using FishNet.CodeGenerating;
|
||||||
|
using FishNet.Component.Observing;
|
||||||
using FishNet.Documenting;
|
using FishNet.Documenting;
|
||||||
using FishNet.Managing;
|
using FishNet.Managing;
|
||||||
using FishNet.Managing.Timing;
|
using FishNet.Managing.Timing;
|
||||||
using FishNet.Object;
|
using FishNet.Object;
|
||||||
|
using GameKit.Dependencies.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@ -31,9 +33,28 @@ namespace FishNet.Connection
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A container for a connected client used to perform actions on and gather information for the declared client.
|
/// A container for a connected client used to perform actions on and gather information for the declared client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class NetworkConnection : IEquatable<NetworkConnection>
|
public partial class NetworkConnection : IResettable, IEquatable<NetworkConnection>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#region Internal.
|
||||||
|
/// <summary>
|
||||||
|
/// Tick when Disconnecting was set.
|
||||||
|
/// </summary>
|
||||||
|
internal uint DisconnectingTick { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// ObjectIds to use for predicted spawning.
|
||||||
|
/// </summary>
|
||||||
|
internal Queue<int> PredictedObjectIds = new Queue<int>();
|
||||||
|
/// <summary>
|
||||||
|
/// True if the client has sent the same version that the server is on.
|
||||||
|
/// </summary>
|
||||||
|
internal bool HasSentVersion;
|
||||||
|
/// <summary>
|
||||||
|
/// LocalTick of the server when this connection was established. This value is not set for clients.
|
||||||
|
/// </summary>
|
||||||
|
internal uint ServerConnectionTick;
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Public.
|
#region Public.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after this connection has loaded start scenes. Boolean will be true if asServer. Available to this connection and server.
|
/// Called after this connection has loaded start scenes. Boolean will be true if asServer. Available to this connection and server.
|
||||||
@ -66,18 +87,6 @@ namespace FishNet.Connection
|
|||||||
return _loadedStartScenesAsClient;
|
return _loadedStartScenesAsClient;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if loaded start scenes as server.
|
|
||||||
/// </summary>
|
|
||||||
private bool _loadedStartScenesAsServer;
|
|
||||||
/// <summary>
|
|
||||||
/// True if loaded start scenes as client.
|
|
||||||
/// </summary>
|
|
||||||
private bool _loadedStartScenesAsClient;
|
|
||||||
/// <summary>
|
|
||||||
/// ObjectIds to use for predicted spawning.
|
|
||||||
/// </summary>
|
|
||||||
internal Queue<int> PredictedObjectIds = new Queue<int>();
|
|
||||||
/// <summary>
|
|
||||||
/// TransportIndex this connection is on.
|
/// TransportIndex this connection is on.
|
||||||
/// For security reasons this value will be unset on clients if this is not their connection.
|
/// For security reasons this value will be unset on clients if this is not their connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -137,19 +146,11 @@ namespace FishNet.Connection
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Disconnecting { get; private set; }
|
public bool Disconnecting { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tick when Disconnecting was set.
|
|
||||||
/// </summary>
|
|
||||||
internal uint DisconnectingTick { get; private set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Custom data associated with this connection which may be modified by the user.
|
/// Custom data associated with this connection which may be modified by the user.
|
||||||
/// The value of this field are not synchronized over the network.
|
/// The value of this field are not synchronized over the network.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object CustomData = null;
|
public object CustomData = null;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LocalTick of the server when this connection was established. This value is not set for clients.
|
|
||||||
/// </summary>
|
|
||||||
internal uint ServerConnectionTick;
|
|
||||||
/// <summary>
|
|
||||||
/// Tick of the last packet received from this connection which was not out of order.
|
/// Tick of the last packet received from this connection which was not out of order.
|
||||||
/// This value is only available on the server.
|
/// This value is only available on the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -161,6 +162,17 @@ namespace FishNet.Connection
|
|||||||
public EstimatedTick LocalTick { get; private set; } = new EstimatedTick();
|
public EstimatedTick LocalTick { get; private set; } = new EstimatedTick();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Private.
|
||||||
|
/// <summary>
|
||||||
|
/// True if loaded start scenes as server.
|
||||||
|
/// </summary>
|
||||||
|
private bool _loadedStartScenesAsServer;
|
||||||
|
/// <summary>
|
||||||
|
/// True if loaded start scenes as client.
|
||||||
|
/// </summary>
|
||||||
|
private bool _loadedStartScenesAsClient;
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Const.
|
#region Const.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value used when ClientId has not been set.
|
/// Value used when ClientId has not been set.
|
||||||
@ -169,7 +181,11 @@ namespace FishNet.Connection
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum value a ClientId can be.
|
/// Maximum value a ClientId can be.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int MAXIMUM_CLIENTID_VALUE = (int.MaxValue - 1);
|
public const int MAXIMUM_CLIENTID_VALUE = int.MaxValue;
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum value a ClientId can be excluding simulated value.
|
||||||
|
/// </summary>
|
||||||
|
public const int MAXIMUM_CLIENTID_WITHOUT_SIMULATED_VALUE = (int.MaxValue - 1);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value to use as a ClientId when simulating a local client without actually using a socket.
|
/// Value to use as a ClientId when simulating a local client without actually using a socket.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -177,7 +193,7 @@ namespace FishNet.Connection
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes to reserve for a connectionId if writing the value uncompressed.
|
/// Number of bytes to reserve for a connectionId if writing the value uncompressed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CLIENTID_UNCOMPRESSED_RESERVE_BYTES = 4;
|
public const int CLIENTID_UNCOMPRESSED_RESERVE_LENGTH = 4;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Comparers.
|
#region Comparers.
|
||||||
@ -228,11 +244,6 @@ namespace FishNet.Connection
|
|||||||
Initialize(manager, clientId, transportIndex, asServer);
|
Initialize(manager, clientId, transportIndex, asServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Dispose()
|
|
||||||
{
|
|
||||||
Deinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Outputs data about this connection as a string.
|
/// Outputs data about this connection as a string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -271,40 +282,6 @@ namespace FishNet.Connection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deinitializes this NetworkConnection. This is called prior to resetting.
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
internal void Deinitialize()
|
|
||||||
{
|
|
||||||
MatchCondition.RemoveFromMatchesWithoutRebuild(this, NetworkManager);
|
|
||||||
|
|
||||||
foreach (PacketBundle p in _toClientBundles)
|
|
||||||
p.Dispose();
|
|
||||||
_toClientBundles.Clear();
|
|
||||||
|
|
||||||
ServerConnectionTick = 0;
|
|
||||||
PacketTick.Reset();
|
|
||||||
LocalTick.Reset();
|
|
||||||
TransportIndex = -1;
|
|
||||||
ClientId = -1;
|
|
||||||
ClearObjects();
|
|
||||||
IsAuthenticated = false;
|
|
||||||
NetworkManager = null;
|
|
||||||
_loadedStartScenesAsClient = false;
|
|
||||||
_loadedStartScenesAsServer = false;
|
|
||||||
SetDisconnecting(false);
|
|
||||||
Scenes.Clear();
|
|
||||||
PredictedObjectIds.Clear();
|
|
||||||
ResetPingPong();
|
|
||||||
ResetStates_Lod();
|
|
||||||
AllowedForcedLodUpdates = 0;
|
|
||||||
LastLevelOfDetailUpdate = 0;
|
|
||||||
LevelOfDetailInfractions = 0;
|
|
||||||
Observers_Reset();
|
|
||||||
Prediction_Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets Disconnecting boolean for this connection.
|
/// Sets Disconnecting boolean for this connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -341,18 +318,6 @@ namespace FishNet.Connection
|
|||||||
ServerDirty();
|
ServerDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private float _localTickUpdateTime = float.NegativeInfinity;
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to update the LocalTick for this connection after a number of conditions are checked.
|
|
||||||
/// </summary>
|
|
||||||
internal void TryUpdateLocalTick(uint tick)
|
|
||||||
{
|
|
||||||
bool resetValue = (Time.time - _localTickUpdateTime) > 1f;
|
|
||||||
LocalTick.Update(tick, OldTickOption.Discard, resetValue);
|
|
||||||
if (resetValue)
|
|
||||||
_localTickUpdateTime = Time.time;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns if just loaded start scenes and sets them as loaded if not.
|
/// Returns if just loaded start scenes and sets them as loaded if not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -468,6 +433,43 @@ namespace FishNet.Connection
|
|||||||
return Scenes.Remove(scene);
|
return Scenes.Remove(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets all states for re-use.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void ResetState()
|
||||||
|
{
|
||||||
|
MatchCondition.RemoveFromMatchesWithoutRebuild(this, NetworkManager);
|
||||||
|
|
||||||
|
foreach (PacketBundle p in _toClientBundles)
|
||||||
|
p.Dispose();
|
||||||
|
_toClientBundles.Clear();
|
||||||
|
|
||||||
|
ServerConnectionTick = 0;
|
||||||
|
PacketTick.Reset();
|
||||||
|
LocalTick.Reset();
|
||||||
|
TransportIndex = -1;
|
||||||
|
ClientId = -1;
|
||||||
|
ClearObjects();
|
||||||
|
IsAuthenticated = false;
|
||||||
|
HasSentVersion = false;
|
||||||
|
NetworkManager = null;
|
||||||
|
_loadedStartScenesAsClient = false;
|
||||||
|
_loadedStartScenesAsServer = false;
|
||||||
|
SetDisconnecting(false);
|
||||||
|
Scenes.Clear();
|
||||||
|
PredictedObjectIds.Clear();
|
||||||
|
ResetPingPong();
|
||||||
|
ResetStates_Lod();
|
||||||
|
AllowedForcedLodUpdates = 0;
|
||||||
|
LastLevelOfDetailUpdate = 0;
|
||||||
|
LevelOfDetailInfractions = 0;
|
||||||
|
Observers_Reset();
|
||||||
|
Prediction_Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitializeState() { }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using FishNet.Configuring;
|
using FishNet.Configuring;
|
||||||
|
using FishNet.Managing;
|
||||||
using FishNet.Managing.Object;
|
using FishNet.Managing.Object;
|
||||||
using FishNet.Object;
|
using FishNet.Object;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -437,7 +438,7 @@ namespace FishNet.Editing.PrefabCollectionGenerator
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the DefaultPrefabObjects file.
|
/// Returns the DefaultPrefabObjects file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static DefaultPrefabObjects GetDefaultPrefabObjects(PrefabGeneratorConfigurations settings = null)
|
internal static DefaultPrefabObjects GetDefaultPrefabObjects(PrefabGeneratorConfigurations settings = null)
|
||||||
{
|
{
|
||||||
if (settings == null)
|
if (settings == null)
|
||||||
settings = Configuration.Configurations.PrefabGenerator;
|
settings = Configuration.Configurations.PrefabGenerator;
|
||||||
@ -605,37 +606,15 @@ namespace FishNet.Editing.PrefabCollectionGenerator
|
|||||||
_ranOnce = true;
|
_ranOnce = true;
|
||||||
fullRebuild = true;
|
fullRebuild = true;
|
||||||
}
|
}
|
||||||
else
|
//Other conditions which a full rebuild may be required.
|
||||||
|
else if (!fullRebuild)
|
||||||
{
|
{
|
||||||
CheckForVersionFile(importedAssets);
|
const string fishnetVersionSave = "fishnet_version";
|
||||||
CheckForVersionFile(deletedAssets);
|
string savedVersion = EditorPrefs.GetString(fishnetVersionSave, string.Empty);
|
||||||
CheckForVersionFile(movedAssets);
|
if (savedVersion != NetworkManager.FISHNET_VERSION)
|
||||||
CheckForVersionFile(movedFromAssetPaths);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if any of the changed files are the version file.
|
|
||||||
* A new version file suggests an update. Granted, this could occur if
|
|
||||||
* other assets imported a new version file as well but better
|
|
||||||
* safe than sorry. */
|
|
||||||
void CheckForVersionFile(string[] arr)
|
|
||||||
{
|
|
||||||
string targetText = "VERSION.txt".ToLower();
|
|
||||||
int targetLength = targetText.Length;
|
|
||||||
|
|
||||||
for (int i = 0; i < arr.Length; i++)
|
|
||||||
{
|
|
||||||
string item = arr[i];
|
|
||||||
int itemLength = item.Length;
|
|
||||||
if (itemLength < targetLength)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
item = item.ToLower();
|
|
||||||
int startIndex = (itemLength - targetLength);
|
|
||||||
if (item.Substring(startIndex, targetLength) == targetText)
|
|
||||||
{
|
{
|
||||||
fullRebuild = true;
|
fullRebuild = true;
|
||||||
return;
|
EditorPrefs.SetString(fishnetVersionSave, NetworkManager.FISHNET_VERSION);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,8 @@ namespace FishNet
|
|||||||
foreach (string item in fishNetDefines)
|
foreach (string item in fishNetDefines)
|
||||||
modified |= definesHs.Add(item);
|
modified |= definesHs.Add(item);
|
||||||
|
|
||||||
|
//Remove old prediction defines.
|
||||||
|
modified |= definesHs.Remove("PREDICTION_V2");
|
||||||
/* Remove pro define if not on pro. This might look a little
|
/* Remove pro define if not on pro. This might look a little
|
||||||
* funny because the code below varies depending on if pro or not. */
|
* funny because the code below varies depending on if pro or not. */
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:894a6cc6ed5cd2645bb542978cbed6a9",
|
"GUID:894a6cc6ed5cd2645bb542978cbed6a9",
|
||||||
"GUID:1d82bdf40e2465b44b34adf79595e74c"
|
"GUID:1d82bdf40e2465b44b34adf79595e74c",
|
||||||
|
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
@ -17,6 +18,21 @@
|
|||||||
"name": "com.veriorpies.parrelsync",
|
"name": "com.veriorpies.parrelsync",
|
||||||
"expression": "1.2",
|
"expression": "1.2",
|
||||||
"define": "PARRELSYNC"
|
"define": "PARRELSYNC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.mathematics",
|
||||||
|
"expression": "1.2.6",
|
||||||
|
"define": "UNITYMATHEMATICS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.mathematics",
|
||||||
|
"expression": "1.3.1",
|
||||||
|
"define": "UNITYMATHEMATICS_131"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.mathematics",
|
||||||
|
"expression": "1.3.2",
|
||||||
|
"define": "UNITYMATHEMATICS_132"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace FishNet.Component.Animating.Editing
|
|||||||
{
|
{
|
||||||
private SerializedProperty _animator;
|
private SerializedProperty _animator;
|
||||||
private SerializedProperty _interpolation;
|
private SerializedProperty _interpolation;
|
||||||
//private SerializedProperty _synchronizeInterval;
|
private SerializedProperty _synchronizeWhenDisabled;
|
||||||
private SerializedProperty _smoothFloats;
|
private SerializedProperty _smoothFloats;
|
||||||
private SerializedProperty _clientAuthoritative;
|
private SerializedProperty _clientAuthoritative;
|
||||||
private SerializedProperty _sendToOwner;
|
private SerializedProperty _sendToOwner;
|
||||||
@ -23,13 +23,13 @@ namespace FishNet.Component.Animating.Editing
|
|||||||
|
|
||||||
protected virtual void OnEnable()
|
protected virtual void OnEnable()
|
||||||
{
|
{
|
||||||
_animator = serializedObject.FindProperty("_animator");
|
_animator = serializedObject.FindProperty(nameof(_animator));
|
||||||
_interpolation = serializedObject.FindProperty("_interpolation");
|
_interpolation = serializedObject.FindProperty(nameof(_interpolation));
|
||||||
//_synchronizeInterval = serializedObject.FindProperty("_synchronizeInterval");
|
_synchronizeWhenDisabled = serializedObject.FindProperty(nameof(_synchronizeWhenDisabled));
|
||||||
_smoothFloats = serializedObject.FindProperty("_smoothFloats");
|
_smoothFloats = serializedObject.FindProperty(nameof(_smoothFloats));
|
||||||
|
|
||||||
_clientAuthoritative = serializedObject.FindProperty("_clientAuthoritative");
|
_clientAuthoritative = serializedObject.FindProperty(nameof(_clientAuthoritative));
|
||||||
_sendToOwner = serializedObject.FindProperty("_sendToOwner");
|
_sendToOwner = serializedObject.FindProperty(nameof(_sendToOwner));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
public override void OnInspectorGUI()
|
||||||
@ -50,6 +50,7 @@ namespace FishNet.Component.Animating.Editing
|
|||||||
EditorGUILayout.LabelField("Animator", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Animator", EditorStyles.boldLabel);
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.PropertyField(_animator);
|
EditorGUILayout.PropertyField(_animator);
|
||||||
|
EditorGUILayout.PropertyField(_synchronizeWhenDisabled);
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
@ -57,7 +58,6 @@ namespace FishNet.Component.Animating.Editing
|
|||||||
EditorGUILayout.LabelField("Synchronization Processing", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Synchronization Processing", EditorStyles.boldLabel);
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.PropertyField(_interpolation);
|
EditorGUILayout.PropertyField(_interpolation);
|
||||||
//EditorGUILayout.PropertyField(_synchronizeInterval, new GUIContent("Synchronize Interval", "How often to synchronize this animator."));
|
|
||||||
EditorGUILayout.PropertyField(_smoothFloats);
|
EditorGUILayout.PropertyField(_smoothFloats);
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
using FishNet.Component.Transforming;
|
using FishNet.Component.Transforming;
|
||||||
using FishNet.Connection;
|
using FishNet.Connection;
|
||||||
using FishNet.Documenting;
|
using FishNet.Documenting;
|
||||||
@ -285,6 +288,12 @@ namespace FishNet.Component.Animating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Animator Animator { get { return _animator; } }
|
public Animator Animator { get { return _animator; } }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// True to synchronize changes even when the animator component is disabled.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("True to synchronize changes even when the animator component is disabled.")]
|
||||||
|
[SerializeField]
|
||||||
|
private bool _synchronizeWhenDisabled;
|
||||||
|
/// <summary>
|
||||||
/// True to smooth float value changes for spectators.
|
/// True to smooth float value changes for spectators.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Tooltip("True to smooth float value changes for spectators.")]
|
[Tooltip("True to smooth float value changes for spectators.")]
|
||||||
@ -297,13 +306,6 @@ namespace FishNet.Component.Animating
|
|||||||
[Range(1, NetworkTransform.MAX_INTERPOLATION)]
|
[Range(1, NetworkTransform.MAX_INTERPOLATION)]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private ushort _interpolation = 2;
|
private ushort _interpolation = 2;
|
||||||
///// <summary>
|
|
||||||
///// How often to synchronize this animator.
|
|
||||||
///// </summary>
|
|
||||||
//[Tooltip("How often to synchronize this animator.")]
|
|
||||||
//[Range(0.01f, 0.5f)]
|
|
||||||
//[SerializeField]
|
|
||||||
//private float _synchronizeInterval = 0.1f;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -356,13 +358,25 @@ namespace FishNet.Component.Animating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private List<byte[]> _toClientsBuffer = new List<byte[]>();
|
private List<byte[]> _toClientsBuffer = new List<byte[]>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns if the animator is exist and is active.
|
/// Returns if the animator is exist and can be synchronized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _isAnimatorEnabled
|
private bool _canSynchronizeAnimator
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
bool failedChecks = (_animator == null || !_animator.enabled || _animator.runtimeAnimatorController == null);
|
bool enabled = (_animator.enabled || _synchronizeWhenDisabled);
|
||||||
|
bool failedChecks = (!_isAnimatorSet || !enabled);
|
||||||
|
return !failedChecks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// True if the animator is valid but not enabled.
|
||||||
|
/// </summary>
|
||||||
|
private bool _isAnimatorSet
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
bool failedChecks = (_animator == null || _animator.runtimeAnimatorController == null);
|
||||||
return !failedChecks;
|
return !failedChecks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,10 +410,6 @@ namespace FishNet.Component.Animating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<int, StateChange> _unsynchronizedLayerStates = new Dictionary<int, StateChange>();
|
private Dictionary<int, StateChange> _unsynchronizedLayerStates = new Dictionary<int, StateChange>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layers which need to have their state blend synchronized. Key is ParameterIndex, Value is next state hash.
|
|
||||||
/// </summary>
|
|
||||||
//private Dictionary<int, int> _unsynchronizedLayerStates = new HashSet<int>();
|
|
||||||
/// <summary>
|
|
||||||
/// Last animator set.
|
/// Last animator set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Animator _lastAnimator;
|
private Animator _lastAnimator;
|
||||||
@ -469,7 +479,7 @@ namespace FishNet.Component.Animating
|
|||||||
[APIExclude]
|
[APIExclude]
|
||||||
public override void OnSpawnServer(NetworkConnection connection)
|
public override void OnSpawnServer(NetworkConnection connection)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (AnimatorUpdated(out ArraySegment<byte> updatedBytes, true))
|
if (AnimatorUpdated(out ArraySegment<byte> updatedBytes, true))
|
||||||
TargetAnimatorUpdated(connection, updatedBytes);
|
TargetAnimatorUpdated(connection, updatedBytes);
|
||||||
@ -531,7 +541,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void TimeManager_OnPreTick()
|
private void TimeManager_OnPreTick()
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
{
|
{
|
||||||
_fromServerBuffer.Clear();
|
_fromServerBuffer.Clear();
|
||||||
return;
|
return;
|
||||||
@ -565,7 +575,7 @@ namespace FishNet.Component.Animating
|
|||||||
private void TimeManager_OnPostTick()
|
private void TimeManager_OnPostTick()
|
||||||
{
|
{
|
||||||
//One check rather than per each method.
|
//One check rather than per each method.
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CheckSendToServer();
|
CheckSendToServer();
|
||||||
@ -574,7 +584,7 @@ namespace FishNet.Component.Animating
|
|||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (base.IsClientStarted)
|
if (base.IsClientStarted)
|
||||||
@ -593,7 +603,7 @@ namespace FishNet.Component.Animating
|
|||||||
if (!ApplicationState.IsPlaying())
|
if (!ApplicationState.IsPlaying())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
{
|
{
|
||||||
//Debug.LogWarning("Animator is null or not enabled; unable to initialize for animator. Use SetAnimator if animator was changed or enable the animator.");
|
//Debug.LogWarning("Animator is null or not enabled; unable to initialize for animator. Use SetAnimator if animator was changed or enable the animator.");
|
||||||
return;
|
return;
|
||||||
@ -1025,7 +1035,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// <param name="changedParameters"></param>
|
/// <param name="changedParameters"></param>
|
||||||
private void ApplyParametersUpdated(ref ArraySegment<byte> updatedParameters)
|
private void ApplyParametersUpdated(ref ArraySegment<byte> updatedParameters)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (_layerWeights == null)
|
if (_layerWeights == null)
|
||||||
return;
|
return;
|
||||||
@ -1153,7 +1163,7 @@ namespace FishNet.Component.Animating
|
|||||||
stateHash = 0;
|
stateHash = 0;
|
||||||
normalizedTime = 0f;
|
normalizedTime = 0f;
|
||||||
|
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
AnimatorStateInfo st = _animator.GetCurrentAnimatorStateInfo(layerIndex);
|
AnimatorStateInfo st = _animator.GetCurrentAnimatorStateInfo(layerIndex);
|
||||||
@ -1214,7 +1224,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Play(int hash, int layer, float normalizedTime)
|
public void Play(int hash, int layer, float normalizedTime)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (_animator.HasState(layer, hash) || hash == 0)
|
if (_animator.HasState(layer, hash) || hash == 0)
|
||||||
{
|
{
|
||||||
@ -1249,7 +1259,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void PlayInFixedTime(int hash, int layer, float fixedTime)
|
public void PlayInFixedTime(int hash, int layer, float fixedTime)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (_animator.HasState(layer, hash) || hash == 0)
|
if (_animator.HasState(layer, hash) || hash == 0)
|
||||||
{
|
{
|
||||||
@ -1282,7 +1292,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// <param name="normalizedTransitionTime"></param>
|
/// <param name="normalizedTransitionTime"></param>
|
||||||
public void CrossFade(int hash, float normalizedTransitionDuration, int layer, float normalizedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f)
|
public void CrossFade(int hash, float normalizedTransitionDuration, int layer, float normalizedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (_animator.HasState(layer, hash) || hash == 0)
|
if (_animator.HasState(layer, hash) || hash == 0)
|
||||||
{
|
{
|
||||||
@ -1312,7 +1322,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// <param name="normalizedTransitionTime"></param>
|
/// <param name="normalizedTransitionTime"></param>
|
||||||
public void CrossFadeInFixedTime(int hash, float fixedTransitionDuration, int layer, float fixedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f)
|
public void CrossFadeInFixedTime(int hash, float fixedTransitionDuration, int layer, float fixedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (_animator.HasState(layer, hash) || hash == 0)
|
if (_animator.HasState(layer, hash) || hash == 0)
|
||||||
{
|
{
|
||||||
@ -1329,7 +1339,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// <param name="hash"></param>
|
/// <param name="hash"></param>
|
||||||
public void SetTrigger(int hash)
|
public void SetTrigger(int hash)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
UpdateTrigger(hash, true);
|
UpdateTrigger(hash, true);
|
||||||
}
|
}
|
||||||
@ -1365,7 +1375,7 @@ namespace FishNet.Component.Animating
|
|||||||
/// <param name="set"></param>
|
/// <param name="set"></param>
|
||||||
private void UpdateTrigger(int hash, bool set)
|
private void UpdateTrigger(int hash, bool set)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool clientAuth = ClientAuthoritative;
|
bool clientAuth = ClientAuthoritative;
|
||||||
@ -1422,12 +1432,12 @@ namespace FishNet.Component.Animating
|
|||||||
[TargetRpc(ValidateTarget = false)]
|
[TargetRpc(ValidateTarget = false)]
|
||||||
private void TargetAnimatorUpdated(NetworkConnection connection, ArraySegment<byte> data)
|
private void TargetAnimatorUpdated(NetworkConnection connection, ArraySegment<byte> data)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if DEVELOPMENT
|
#if !DEVELOPMENT
|
||||||
//If receiver is client host then do nothing, clientHost need not process.
|
//If receiver is client host then do nothing, clientHost need not process.
|
||||||
if (base.IsServer && conn.IsLocalClient)
|
if (base.IsServerInitialized && connection.IsLocalClient)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
bool clientAuth = ClientAuthoritative;
|
bool clientAuth = ClientAuthoritative;
|
||||||
@ -1457,7 +1467,7 @@ namespace FishNet.Component.Animating
|
|||||||
[ServerRpc]
|
[ServerRpc]
|
||||||
private void ServerAnimatorUpdated(ArraySegment<byte> data)
|
private void ServerAnimatorUpdated(ArraySegment<byte> data)
|
||||||
{
|
{
|
||||||
if (!_isAnimatorEnabled)
|
if (!_canSynchronizeAnimator)
|
||||||
return;
|
return;
|
||||||
if (!ClientAuthoritative)
|
if (!ClientAuthoritative)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -336,6 +336,10 @@ namespace FishNet.Component.Transforming
|
|||||||
/// True if the local client used TakeOwnership and is awaiting an ownership change.
|
/// True if the local client used TakeOwnership and is awaiting an ownership change.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TakenOwnership { get; private set; }
|
public bool TakenOwnership { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// NetworkBehaviour this transform is a child of.
|
||||||
|
/// </summary>
|
||||||
|
public NetworkBehaviour ParentBehaviour { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Serialized.
|
#region Serialized.
|
||||||
@ -519,10 +523,6 @@ namespace FishNet.Component.Transforming
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _lastReceiveReliable = true;
|
private bool _lastReceiveReliable = true;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NetworkBehaviour this transform is a child of.
|
|
||||||
/// </summary>
|
|
||||||
private NetworkBehaviour _parentBehaviour;
|
|
||||||
/// <summary>
|
|
||||||
/// Last transform which this object was a child of.
|
/// Last transform which this object was a child of.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Transform _parentTransform;
|
private Transform _parentTransform;
|
||||||
@ -1098,7 +1098,7 @@ namespace FishNet.Component.Transforming
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_parentTransform = transform.parent;
|
_parentTransform = transform.parent;
|
||||||
_parentBehaviour = parentBehaviour;
|
ParentBehaviour = parentBehaviour;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1297,10 +1297,10 @@ namespace FishNet.Component.Transforming
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Childed.
|
//Childed.
|
||||||
if (ChangedContains(changed, ChangedDelta.Childed) && _parentBehaviour != null)
|
if (ChangedContains(changed, ChangedDelta.Childed) && ParentBehaviour != null)
|
||||||
{
|
{
|
||||||
flagsB |= UpdateFlagB.Child;
|
flagsB |= UpdateFlagB.Child;
|
||||||
writer.WriteNetworkBehaviour(_parentBehaviour);
|
writer.WriteNetworkBehaviour(ParentBehaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.FastInsertByte((byte)flagsB, startIndexB);
|
writer.FastInsertByte((byte)flagsB, startIndexB);
|
||||||
@ -1459,7 +1459,7 @@ namespace FishNet.Component.Transforming
|
|||||||
if (base.NetworkObject.RuntimeParentNetworkBehaviour != null)
|
if (base.NetworkObject.RuntimeParentNetworkBehaviour != null)
|
||||||
Debug.LogWarning($"{gameObject.name} parent object was removed without calling UnsetParent. Use networkObject.UnsetParent() to remove a NetworkObject from it's parent. This is being made a requirement in Fish-Networking v4.");
|
Debug.LogWarning($"{gameObject.name} parent object was removed without calling UnsetParent. Use networkObject.UnsetParent() to remove a NetworkObject from it's parent. This is being made a requirement in Fish-Networking v4.");
|
||||||
|
|
||||||
_parentBehaviour = null;
|
ParentBehaviour = null;
|
||||||
_parentTransform = null;
|
_parentTransform = null;
|
||||||
}
|
}
|
||||||
//Has a parent, see if eligible.
|
//Has a parent, see if eligible.
|
||||||
@ -1470,15 +1470,18 @@ namespace FishNet.Component.Transforming
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_parentTransform = parent;
|
_parentTransform = parent;
|
||||||
parent.TryGetComponent<NetworkBehaviour>(out _parentBehaviour);
|
NetworkBehaviour outParentBehaviour;
|
||||||
if (_parentBehaviour == null)
|
|
||||||
|
if (!parent.TryGetComponent<NetworkBehaviour>(out outParentBehaviour))
|
||||||
{
|
{
|
||||||
|
ParentBehaviour = null;
|
||||||
LogInvalidParent();
|
LogInvalidParent();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ParentBehaviour = outParentBehaviour;
|
||||||
//Check for being set without using nob.SetParent.
|
//Check for being set without using nob.SetParent.
|
||||||
if (base.NetworkObject.CurrentParentNetworkBehaviour != _parentBehaviour)
|
if (base.NetworkObject.CurrentParentNetworkBehaviour != ParentBehaviour)
|
||||||
Debug.LogWarning($"{gameObject.name} parent was set without calling SetParent. Use networkObject.SetParent(obj) to assign a NetworkObject a new parent. This is being made a requirement in Fish-Networking v4.");
|
Debug.LogWarning($"{gameObject.name} parent was set without calling SetParent. Use networkObject.SetParent(obj) to assign a NetworkObject a new parent. This is being made a requirement in Fish-Networking v4.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1689,7 +1692,7 @@ namespace FishNet.Component.Transforming
|
|||||||
Transform t = transform;
|
Transform t = transform;
|
||||||
/* If here a send for transform values will occur. Update last values.
|
/* If here a send for transform values will occur. Update last values.
|
||||||
* Tick doesn't need to be set for whoever controls transform. */
|
* Tick doesn't need to be set for whoever controls transform. */
|
||||||
lastSentData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, _parentBehaviour);
|
lastSentData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, ParentBehaviour);
|
||||||
|
|
||||||
SerializeChanged(changed, writer, lodIndex);
|
SerializeChanged(changed, writer, lodIndex);
|
||||||
}
|
}
|
||||||
@ -1764,7 +1767,7 @@ namespace FishNet.Component.Transforming
|
|||||||
/* If here a send for transform values will occur. Update last values.
|
/* If here a send for transform values will occur. Update last values.
|
||||||
* Tick doesn't need to be set for whoever controls transform. */
|
* Tick doesn't need to be set for whoever controls transform. */
|
||||||
Transform t = transform;
|
Transform t = transform;
|
||||||
lastSentTransformData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, _parentBehaviour);
|
lastSentTransformData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, ParentBehaviour);
|
||||||
|
|
||||||
//Send latest.
|
//Send latest.
|
||||||
PooledWriter writer = WriterPool.Retrieve();
|
PooledWriter writer = WriterPool.Retrieve();
|
||||||
@ -1876,7 +1879,7 @@ namespace FishNet.Component.Transforming
|
|||||||
changed |= ChangedDelta.ScaleZ;
|
changed |= ChangedDelta.ScaleZ;
|
||||||
|
|
||||||
//if (lastParentBehaviour != _parentBehaviour)
|
//if (lastParentBehaviour != _parentBehaviour)
|
||||||
if (_parentBehaviour != null)
|
if (ParentBehaviour != null)
|
||||||
changed |= ChangedDelta.Childed;
|
changed |= ChangedDelta.Childed;
|
||||||
|
|
||||||
//If added scale or childed then also add extended.
|
//If added scale or childed then also add extended.
|
||||||
@ -2271,7 +2274,6 @@ namespace FishNet.Component.Transforming
|
|||||||
{
|
{
|
||||||
SetCalculatedRates(lodIndex, prevTd, prevRd, nextGd, changedFull, hasChanged, channel, asServer);
|
SetCalculatedRates(lodIndex, prevTd, prevRd, nextGd, changedFull, hasChanged, channel, asServer);
|
||||||
}
|
}
|
||||||
prevTd.Update(nextTd);
|
|
||||||
|
|
||||||
_lastReceiveReliable = (channel == Channel.Reliable);
|
_lastReceiveReliable = (channel == Channel.Reliable);
|
||||||
/* If channel is reliable then this is a settled packet.
|
/* If channel is reliable then this is a settled packet.
|
||||||
|
|||||||
@ -59,16 +59,25 @@ namespace FishNet.Component.Prediction
|
|||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
protected bool IsTrigger;
|
protected bool IsTrigger;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum number of simultaneous hits to check for.
|
/// Maximum number of simultaneous hits to check for. Larger values decrease performance but allow detection to work for more overlapping colliders. Typically the default value of 16 is more than sufficient.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Tooltip("Maximum number of simultaneous hits to check for. Larger values decrease performance but allow detection to work for more overlapping colliders. Typically the default value of 16 is more than sufficient.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private ushort _maximumSimultaneousHits = 16;
|
private ushort _maximumSimultaneousHits = 16;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The duration of the history.
|
/// How long of collision history to keep. Lower values will result in marginally better memory usage at the cost of collision histories desynchronizing on clients with excessive latency.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Tooltip("How long of collision history to keep. Lower values will result in marginally better memory usage at the cost of collision histories desynchronizing on clients with excessive latency.")]
|
||||||
|
[Range(0.1f, 2f)]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float _historyDuration = 0.5f;
|
private float _historyDuration = 0.5f;
|
||||||
|
/// <summary>
|
||||||
|
/// Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.")]
|
||||||
|
[Range(0f, 100f)]
|
||||||
|
[SerializeField]
|
||||||
|
private float _additionalSize = 0.1f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The colliders on this object.
|
/// The colliders on this object.
|
||||||
@ -102,7 +111,8 @@ namespace FishNet.Component.Prediction
|
|||||||
|
|
||||||
protected virtual void Awake()
|
protected virtual void Awake()
|
||||||
{
|
{
|
||||||
_colliderDataHistory = ResettableCollectionCaches<ColliderData>.RetrieveRingBuffer();
|
//_colliderDataHistory = ResettableCollectionCaches<ColliderData>.RetrieveRingBuffer();
|
||||||
|
_colliderDataHistory = new();
|
||||||
_hits = CollectionCaches<Collider>.RetrieveArray();
|
_hits = CollectionCaches<Collider>.RetrieveArray();
|
||||||
if (_hits.Length < _maximumSimultaneousHits)
|
if (_hits.Length < _maximumSimultaneousHits)
|
||||||
_hits = new Collider[_maximumSimultaneousHits];
|
_hits = new Collider[_maximumSimultaneousHits];
|
||||||
@ -110,8 +120,8 @@ namespace FishNet.Component.Prediction
|
|||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
ResettableCollectionCaches<ColliderData>.StoreAndDefault(ref _colliderDataHistory);
|
//ResettableCollectionCaches<ColliderData>.StoreAndDefault(ref _colliderDataHistory);
|
||||||
CollectionCaches<Collider>.StoreAndDefault(ref _hits, -_hits.Length);
|
CollectionCaches<Collider>.StoreAndDefault(ref _hits, _hits.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnStartNetwork()
|
public override void OnStartNetwork()
|
||||||
@ -193,7 +203,7 @@ namespace FishNet.Component.Prediction
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.
|
/// Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual float GetAdditionalSize() => 0f;
|
public virtual float GetAdditionalSize() => _additionalSize;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks for any trigger changes;
|
/// Checks for any trigger changes;
|
||||||
@ -416,7 +426,7 @@ namespace FishNet.Component.Prediction
|
|||||||
{
|
{
|
||||||
sphereCollider.GetSphereOverlapParams(out Vector3 center, out float radius);
|
sphereCollider.GetSphereOverlapParams(out Vector3 center, out float radius);
|
||||||
radius += GetAdditionalSize();
|
radius += GetAdditionalSize();
|
||||||
return Physics.OverlapSphereNonAlloc(center, radius, _hits, layerMask);
|
return gameObject.scene.GetPhysicsScene().OverlapSphere(center, radius, _hits, layerMask, QueryTriggerInteraction.UseGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -427,7 +437,7 @@ namespace FishNet.Component.Prediction
|
|||||||
{
|
{
|
||||||
capsuleCollider.GetCapsuleCastParams(out Vector3 start, out Vector3 end, out float radius);
|
capsuleCollider.GetCapsuleCastParams(out Vector3 start, out Vector3 end, out float radius);
|
||||||
radius += GetAdditionalSize();
|
radius += GetAdditionalSize();
|
||||||
return Physics.OverlapCapsuleNonAlloc(start, end, radius, _hits, layerMask);
|
return gameObject.scene.GetPhysicsScene().OverlapCapsule(start, end, radius, _hits, layerMask, QueryTriggerInteraction.UseGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -440,7 +450,7 @@ namespace FishNet.Component.Prediction
|
|||||||
boxCollider.GetBoxOverlapParams(out Vector3 center, out Vector3 halfExtents);
|
boxCollider.GetBoxOverlapParams(out Vector3 center, out Vector3 halfExtents);
|
||||||
Vector3 additional = (Vector3.one * GetAdditionalSize());
|
Vector3 additional = (Vector3.one * GetAdditionalSize());
|
||||||
halfExtents += additional;
|
halfExtents += additional;
|
||||||
return Physics.OverlapBoxNonAlloc(center, halfExtents, _hits, rotation, layerMask);
|
return gameObject.scene.GetPhysicsScene().OverlapBox(center, halfExtents, _hits, rotation, layerMask, QueryTriggerInteraction.UseGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -59,16 +59,25 @@ namespace FishNet.Component.Prediction
|
|||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
protected bool IsTrigger;
|
protected bool IsTrigger;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum number of simultaneous hits to check for.
|
/// Maximum number of simultaneous hits to check for. Larger values decrease performance but allow detection to work for more overlapping colliders. Typically the default value of 16 is more than sufficient.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Tooltip("Maximum number of simultaneous hits to check for. Larger values decrease performance but allow detection to work for more overlapping colliders. Typically the default value of 16 is more than sufficient.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private ushort _maximumSimultaneousHits = 16;
|
private ushort _maximumSimultaneousHits = 16;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The duration of the history.
|
/// How long of collision history to keep. Lower values will result in marginally better memory usage at the cost of collision histories desynchronizing on clients with excessive latency.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Tooltip("How long of collision history to keep. Lower values will result in marginally better memory usage at the cost of collision histories desynchronizing on clients with excessive latency.")]
|
||||||
|
[Range(0.1f, 2f)]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private float _historyDuration = 0.5f;
|
private float _historyDuration = 0.5f;
|
||||||
|
/// <summary>
|
||||||
|
/// Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.")]
|
||||||
|
[Range(0f, 100f)]
|
||||||
|
[SerializeField]
|
||||||
|
private float _additionalSize = 0.1f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The colliders on this object.
|
/// The colliders on this object.
|
||||||
@ -102,7 +111,8 @@ namespace FishNet.Component.Prediction
|
|||||||
|
|
||||||
protected virtual void Awake()
|
protected virtual void Awake()
|
||||||
{
|
{
|
||||||
_colliderDataHistory = ResettableCollectionCaches<Collider2DData>.RetrieveRingBuffer();
|
_colliderDataHistory = new();
|
||||||
|
//_colliderDataHistory = ResettableCollectionCaches<Collider2DData>.RetrieveRingBuffer();
|
||||||
_hits = CollectionCaches<Collider2D>.RetrieveArray();
|
_hits = CollectionCaches<Collider2D>.RetrieveArray();
|
||||||
if (_hits.Length < _maximumSimultaneousHits)
|
if (_hits.Length < _maximumSimultaneousHits)
|
||||||
_hits = new Collider2D[_maximumSimultaneousHits];
|
_hits = new Collider2D[_maximumSimultaneousHits];
|
||||||
@ -110,8 +120,8 @@ namespace FishNet.Component.Prediction
|
|||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
ResettableCollectionCaches<Collider2DData>.StoreAndDefault(ref _colliderDataHistory);
|
//ResettableCollectionCaches<Collider2DData>.StoreAndDefault(ref _colliderDataHistory);
|
||||||
CollectionCaches<Collider2D>.StoreAndDefault(ref _hits, -_hits.Length);
|
CollectionCaches<Collider2D>.StoreAndDefault(ref _hits, _hits.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnStartNetwork()
|
public override void OnStartNetwork()
|
||||||
@ -205,11 +215,11 @@ namespace FishNet.Component.Prediction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the size multiplier.
|
/// Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
protected virtual float GetAdditionalSize() => _additionalSize;
|
||||||
protected virtual float GetSizeMultiplier() => 1f;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks for any trigger changes;
|
/// Checks for any trigger changes;
|
||||||
@ -429,8 +439,8 @@ namespace FishNet.Component.Prediction
|
|||||||
private int GetCircleCollider2DHits(CircleCollider2D circleCollider, int layerMask)
|
private int GetCircleCollider2DHits(CircleCollider2D circleCollider, int layerMask)
|
||||||
{
|
{
|
||||||
circleCollider.GetCircleOverlapParams(out Vector3 center, out float radius);
|
circleCollider.GetCircleOverlapParams(out Vector3 center, out float radius);
|
||||||
radius *= GetSizeMultiplier();
|
radius += GetAdditionalSize();
|
||||||
return Physics2D.OverlapCircleNonAlloc(center, radius, _hits, layerMask);
|
return gameObject.scene.GetPhysicsScene2D().OverlapCircle(center, radius, _hits, layerMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -440,8 +450,9 @@ namespace FishNet.Component.Prediction
|
|||||||
private int GetBoxCollider2DHits(BoxCollider2D boxCollider, Quaternion rotation, int layerMask)
|
private int GetBoxCollider2DHits(BoxCollider2D boxCollider, Quaternion rotation, int layerMask)
|
||||||
{
|
{
|
||||||
boxCollider.GetBox2DOverlapParams(out Vector3 center, out Vector3 halfExtents);
|
boxCollider.GetBox2DOverlapParams(out Vector3 center, out Vector3 halfExtents);
|
||||||
halfExtents *= GetSizeMultiplier();
|
Vector3 additional = (Vector3.one * GetAdditionalSize());
|
||||||
return Physics2D.OverlapBoxNonAlloc(center, halfExtents, rotation.z, _hits, layerMask);
|
halfExtents += additional;
|
||||||
|
return gameObject.scene.GetPhysicsScene2D().OverlapBox(center, halfExtents, rotation.z, _hits, layerMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -5,21 +5,11 @@ namespace FishNet.Component.Prediction
|
|||||||
public sealed class NetworkCollision : NetworkCollider
|
public sealed class NetworkCollision : NetworkCollider
|
||||||
{
|
{
|
||||||
#if !PREDICTION_1
|
#if !PREDICTION_1
|
||||||
[Tooltip("Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.")]
|
|
||||||
[Range(0f, 100f)]
|
|
||||||
[SerializeField]
|
|
||||||
private float _additionalSize = 0.1f;
|
|
||||||
|
|
||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
base.IsTrigger = false;
|
base.IsTrigger = false;
|
||||||
base.Awake();
|
base.Awake();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Units to extend collision traces by. This is used to prevent missed overlaps when colliders do not intersect enough.
|
|
||||||
/// </summary>
|
|
||||||
public override float GetAdditionalSize() => _additionalSize;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,22 +5,11 @@ namespace FishNet.Component.Prediction
|
|||||||
public sealed class NetworkCollision2D : NetworkCollider2D
|
public sealed class NetworkCollision2D : NetworkCollider2D
|
||||||
{
|
{
|
||||||
#if !PREDICTION_1
|
#if !PREDICTION_1
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Percentage larger than each collider for each overlap test. This is used to prevent missed overlaps when colliders do not intersect enough.
|
|
||||||
/// </summary>
|
|
||||||
[Tooltip("Percentage larger than each collider for each overlap test. This is used to prevent missed overlaps when colliders do not intersect enough.")]
|
|
||||||
[Range(0f, 0.2f)]
|
|
||||||
[SerializeField]
|
|
||||||
private float _sizeMultiplier = 0.05f;
|
|
||||||
|
|
||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
base.IsTrigger = false;
|
base.IsTrigger = false;
|
||||||
base.Awake();
|
base.Awake();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override float GetSizeMultiplier() => (1f + _sizeMultiplier);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -280,7 +280,7 @@ namespace FishNet.Component.Prediction
|
|||||||
/* If host then initialize owner smoother.
|
/* If host then initialize owner smoother.
|
||||||
* Host will use owner smoothing settings for more
|
* Host will use owner smoothing settings for more
|
||||||
* accurate results. */
|
* accurate results. */
|
||||||
if (base.IsHostInitialized)
|
if (base.IsHostStarted)
|
||||||
InitializeSmoother(true);
|
InitializeSmoother(true);
|
||||||
|
|
||||||
UpdateRigidbodiesCount(true);
|
UpdateRigidbodiesCount(true);
|
||||||
|
|||||||
@ -245,7 +245,7 @@ namespace FishNet.Component.Prediction
|
|||||||
_rigidbodyDatas[index] = rbData;
|
_rigidbodyDatas[index] = rbData;
|
||||||
rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
|
rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
|
||||||
rb.isKinematic = true;
|
rb.isKinematic = true;
|
||||||
rb.detectCollisions = false;
|
//rb.detectCollisions = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ namespace FishNet.Component.Prediction
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
rb.isKinematic = rbData.IsKinematic;
|
rb.isKinematic = rbData.IsKinematic;
|
||||||
rb.detectCollisions = rbData.DetectCollisions;
|
//rb.detectCollisions = rbData.DetectCollisions;
|
||||||
rb.collisionDetectionMode = rbData.CollisionDetectionMode;
|
rb.collisionDetectionMode = rbData.CollisionDetectionMode;
|
||||||
if (!rb.isKinematic)
|
if (!rb.isKinematic)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
using FishNet.Connection;
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
using FishNet.Connection;
|
||||||
using FishNet.Managing.Debugging;
|
using FishNet.Managing.Debugging;
|
||||||
using FishNet.Managing.Logging;
|
using FishNet.Managing.Logging;
|
||||||
using FishNet.Managing.Server;
|
using FishNet.Managing.Server;
|
||||||
@ -23,6 +26,11 @@ namespace FishNet.Managing.Client
|
|||||||
{
|
{
|
||||||
#region Public.
|
#region Public.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// This is set true if the server has notified the client it is using a development build.
|
||||||
|
/// Value is set before authentication.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsServerDevelopment { get; private set; }
|
||||||
|
/// <summary>
|
||||||
/// Called after local client has authenticated.
|
/// Called after local client has authenticated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action OnAuthenticated;
|
public event Action OnAuthenticated;
|
||||||
@ -127,7 +135,7 @@ namespace FishNet.Managing.Client
|
|||||||
/// Used to read splits.
|
/// Used to read splits.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SplitReader _splitReader = new SplitReader();
|
private SplitReader _splitReader = new SplitReader();
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logs data about parser to help debug.
|
/// Logs data about parser to help debug.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -179,7 +187,7 @@ namespace FishNet.Managing.Client
|
|||||||
OnRemoteConnectionState?.Invoke(rcs);
|
OnRemoteConnectionState?.Invoke(rcs);
|
||||||
if (Clients.TryGetValue(args.Id, out NetworkConnection c))
|
if (Clients.TryGetValue(args.Id, out NetworkConnection c))
|
||||||
{
|
{
|
||||||
c.Dispose();
|
c.ResetState();
|
||||||
Clients.Remove(args.Id);
|
Clients.Remove(args.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,6 +312,12 @@ namespace FishNet.Managing.Client
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_lastPacketTime = Time.unscaledTime;
|
_lastPacketTime = Time.unscaledTime;
|
||||||
|
//Send version.
|
||||||
|
PooledWriter writer = WriterPool.Retrieve();
|
||||||
|
writer.WritePacketId(PacketId.Version);
|
||||||
|
writer.WriteString(NetworkManager.FISHNET_VERSION);
|
||||||
|
NetworkManager.TransportManager.SendToServer((byte)Channel.Reliable, writer.GetArraySegment());
|
||||||
|
WriterPool.Store(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkManager.CanLog(LoggingType.Common))
|
if (NetworkManager.CanLog(LoggingType.Common))
|
||||||
@ -349,7 +363,7 @@ namespace FishNet.Managing.Client
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void ParseReceived(ClientReceivedDataArgs args)
|
private void ParseReceived(ClientReceivedDataArgs args)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
_parseLogger.Reset();
|
_parseLogger.Reset();
|
||||||
#endif
|
#endif
|
||||||
_lastPacketTime = Time.unscaledTime;
|
_lastPacketTime = Time.unscaledTime;
|
||||||
@ -361,7 +375,7 @@ namespace FishNet.Managing.Client
|
|||||||
segment = args.Data;
|
segment = args.Data;
|
||||||
|
|
||||||
NetworkManager.StatisticsManager.NetworkTraffic.LocalClientReceivedData((ulong)segment.Count);
|
NetworkManager.StatisticsManager.NetworkTraffic.LocalClientReceivedData((ulong)segment.Count);
|
||||||
if (segment.Count <= TransportManager.TICK_BYTES)
|
if (segment.Count <= TransportManager.UNPACKED_TICK_LENGTH)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PooledReader reader = ReaderPool.Retrieve(segment, NetworkManager, Reader.DataSource.Server);
|
PooledReader reader = ReaderPool.Retrieve(segment, NetworkManager, Reader.DataSource.Server);
|
||||||
@ -375,7 +389,7 @@ namespace FishNet.Managing.Client
|
|||||||
internal void ParseReader(PooledReader reader, Channel channel, bool print = false)
|
internal void ParseReader(PooledReader reader, Channel channel, bool print = false)
|
||||||
{
|
{
|
||||||
PacketId packetId = PacketId.Unset;
|
PacketId packetId = PacketId.Unset;
|
||||||
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
|
#if !DEVELOPMENT
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
@ -404,7 +418,7 @@ namespace FishNet.Managing.Client
|
|||||||
while (reader.Remaining > 0)
|
while (reader.Remaining > 0)
|
||||||
{
|
{
|
||||||
packetId = reader.ReadPacketId();
|
packetId = reader.ReadPacketId();
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (print)
|
if (print)
|
||||||
Debug.Log($"PacketId {packetId} - Remaining {reader.Remaining}.");
|
Debug.Log($"PacketId {packetId} - Remaining {reader.Remaining}.");
|
||||||
_parseLogger.AddPacket(packetId);
|
_parseLogger.AddPacket(packetId);
|
||||||
@ -480,7 +494,7 @@ namespace FishNet.Managing.Client
|
|||||||
}
|
}
|
||||||
else if (packetId == PacketId.TimingUpdate)
|
else if (packetId == PacketId.TimingUpdate)
|
||||||
{
|
{
|
||||||
NetworkManager.TimeManager.ParseTimingUpdate();
|
NetworkManager.TimeManager.ParseTimingUpdate(reader);
|
||||||
}
|
}
|
||||||
else if (packetId == PacketId.OwnershipChange)
|
else if (packetId == PacketId.OwnershipChange)
|
||||||
{
|
{
|
||||||
@ -495,18 +509,22 @@ namespace FishNet.Managing.Client
|
|||||||
reader.Clear();
|
reader.Clear();
|
||||||
StopConnection();
|
StopConnection();
|
||||||
}
|
}
|
||||||
|
else if (packetId == PacketId.Version)
|
||||||
|
{
|
||||||
|
ParseVersion(reader);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
NetworkManager.LogError($"Client received an unhandled PacketId of {(ushort)packetId} on channel {channel}. Remaining data has been purged.");
|
NetworkManager.LogError($"Client received an unhandled PacketId of {(ushort)packetId} on channel {channel}. Remaining data has been purged.");
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
_parseLogger.Print(NetworkManager);
|
_parseLogger.Print(NetworkManager);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (print)
|
if (print)
|
||||||
Debug.Log($"Reader remaining {reader.Remaining}");
|
Debug.Log($"Reader remaining {reader.Remaining}");
|
||||||
#endif
|
#endif
|
||||||
@ -519,7 +537,7 @@ namespace FishNet.Managing.Client
|
|||||||
* in doing this check multiple times as there's
|
* in doing this check multiple times as there's
|
||||||
* an exit early check. */
|
* an exit early check. */
|
||||||
Objects.IterateObjectCache();
|
Objects.IterateObjectCache();
|
||||||
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
|
#if !DEVELOPMENT
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -539,6 +557,17 @@ namespace FishNet.Managing.Client
|
|||||||
NetworkManager.TimeManager.ModifyPing(clientTick);
|
NetworkManager.TimeManager.ModifyPing(clientTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses a Version packet.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
private void ParseVersion(PooledReader reader)
|
||||||
|
{
|
||||||
|
IsServerDevelopment = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parses a received connectionId. This is received before client receives connection state change.
|
/// Parses a received connectionId. This is received before client receives connection state change.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -578,7 +607,7 @@ namespace FishNet.Managing.Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
//If predicted spawning is enabled also get reserved Ids.
|
//If predicted spawning is enabled also get reserved Ids.
|
||||||
if (NetworkManager.PredictionManager.GetAllowPredictedSpawning())
|
if (NetworkManager.ServerManager.GetAllowPredictedSpawning())
|
||||||
{
|
{
|
||||||
byte count = reader.ReadByte();
|
byte count = reader.ReadByte();
|
||||||
Queue<int> q = Connection.PredictedObjectIds;
|
Queue<int> q = Connection.PredictedObjectIds;
|
||||||
@ -629,7 +658,7 @@ namespace FishNet.Managing.Client
|
|||||||
return;
|
return;
|
||||||
if (_remoteServerTimeout == RemoteTimeoutType.Disabled)
|
if (_remoteServerTimeout == RemoteTimeoutType.Disabled)
|
||||||
return;
|
return;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
//If development but not set to development return.
|
//If development but not set to development return.
|
||||||
else if (_remoteServerTimeout != RemoteTimeoutType.Development)
|
else if (_remoteServerTimeout != RemoteTimeoutType.Development)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -94,7 +94,7 @@ namespace FishNet.Managing.Client
|
|||||||
{
|
{
|
||||||
foreach (NetworkObject n in Spawned.Values)
|
foreach (NetworkObject n in Spawned.Values)
|
||||||
{
|
{
|
||||||
n.InvokeStopCallbacks(false);
|
n.InvokeStopCallbacks(false, true);
|
||||||
n.SetInitializedStatus(false, false);
|
n.SetInitializedStatus(false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,7 +434,8 @@ namespace FishNet.Managing.Client
|
|||||||
if (sceneObject)
|
if (sceneObject)
|
||||||
{
|
{
|
||||||
ReadSceneObject(reader, out sceneId);
|
ReadSceneObject(reader, out sceneId);
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
|
if (NetworkManager.ClientManager.IsServerDevelopment)
|
||||||
base.CheckReadSceneObjectDetails(reader, ref sceneName, ref objectName);
|
base.CheckReadSceneObjectDetails(reader, ref sceneName, ref objectName);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -578,7 +578,7 @@ namespace FishNet.Managing.Client
|
|||||||
public Quaternion? LocalRotation;
|
public Quaternion? LocalRotation;
|
||||||
public Vector3? LocalScale;
|
public Vector3? LocalScale;
|
||||||
public ulong SceneId;
|
public ulong SceneId;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
public string SceneName = string.Empty;
|
public string SceneName = string.Empty;
|
||||||
public string ObjectName = string.Empty;
|
public string ObjectName = string.Empty;
|
||||||
#endif
|
#endif
|
||||||
@ -626,7 +626,7 @@ namespace FishNet.Managing.Client
|
|||||||
LocalRotation = localRotation;
|
LocalRotation = localRotation;
|
||||||
LocalScale = localScale;
|
LocalScale = localScale;
|
||||||
SceneId = sceneId;
|
SceneId = sceneId;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
SceneName = sceneName;
|
SceneName = sceneName;
|
||||||
ObjectName = objectName;
|
ObjectName = objectName;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
#if DEVELOPMENT
|
||||||
using FishNet.Managing.Logging;
|
using FishNet.Managing.Logging;
|
||||||
using FishNet.Object;
|
using FishNet.Object;
|
||||||
using FishNet.Serializing;
|
using FishNet.Serializing;
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
using FishNet.Documenting;
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
using FishNet.Documenting;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -61,13 +64,11 @@ namespace FishNet.Managing.Logging
|
|||||||
public override void InitializeOnce()
|
public override void InitializeOnce()
|
||||||
{
|
{
|
||||||
byte currentHighest = (byte)LoggingType.Off;
|
byte currentHighest = (byte)LoggingType.Off;
|
||||||
#if UNITY_SERVER //if headless.
|
#if UNITY_SERVER
|
||||||
currentHighest = Math.Max(currentHighest, (byte)_headlessLogging);
|
currentHighest = Math.Max(currentHighest, (byte)_headlessLogging);
|
||||||
#endif
|
#elif DEVELOPMENT
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD //if editor or development.
|
|
||||||
currentHighest = Math.Max(currentHighest, (byte)_developmentLogging);
|
currentHighest = Math.Max(currentHighest, (byte)_developmentLogging);
|
||||||
#endif
|
#else
|
||||||
#if !UNITY_EDITOR && !UNITY_SERVER //if a build.
|
|
||||||
currentHighest = Math.Max(currentHighest, (byte)_guiLogging);
|
currentHighest = Math.Max(currentHighest, (byte)_guiLogging);
|
||||||
#endif
|
#endif
|
||||||
_highestLoggingType = (LoggingType)currentHighest;
|
_highestLoggingType = (LoggingType)currentHighest;
|
||||||
@ -86,7 +87,7 @@ namespace FishNet.Managing.Logging
|
|||||||
|
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (Application.isPlaying)
|
if (Application.isPlaying)
|
||||||
Debug.LogError("CanLog called before being initialized.");
|
Debug.LogError("CanLog called before being initialized.");
|
||||||
else
|
else
|
||||||
|
|||||||
@ -23,8 +23,10 @@ using FishNet.Component.ColliderRollback;
|
|||||||
using FishNet.Managing.Predicting;
|
using FishNet.Managing.Predicting;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using GameKit.Dependencies.Utilities;
|
using GameKit.Dependencies.Utilities;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using FishNet.Editing.PrefabCollectionGenerator;
|
using FishNet.Editing.PrefabCollectionGenerator;
|
||||||
|
using UnityEditor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace FishNet.Managing
|
namespace FishNet.Managing
|
||||||
@ -191,6 +193,10 @@ namespace FishNet.Managing
|
|||||||
|
|
||||||
#region Const.
|
#region Const.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Version of this release.
|
||||||
|
/// </summary>
|
||||||
|
public const string FISHNET_VERSION = "4.3.1";
|
||||||
|
/// <summary>
|
||||||
/// Maximum framerate allowed.
|
/// Maximum framerate allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal const ushort MAXIMUM_FRAMERATE = 500;
|
internal const ushort MAXIMUM_FRAMERATE = 500;
|
||||||
@ -393,6 +399,19 @@ namespace FishNet.Managing
|
|||||||
//If null and object is in a scene.
|
//If null and object is in a scene.
|
||||||
if (SpawnablePrefabs == null && !string.IsNullOrEmpty(gameObject.scene.name))
|
if (SpawnablePrefabs == null && !string.IsNullOrEmpty(gameObject.scene.name))
|
||||||
{
|
{
|
||||||
|
//First try to fetch the file, only if editor and not in play mode.
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!ApplicationState.IsPlaying())
|
||||||
|
{
|
||||||
|
SpawnablePrefabs = Generator.GetDefaultPrefabObjects();
|
||||||
|
if (SpawnablePrefabs != null)
|
||||||
|
{
|
||||||
|
Debug.Log($"SpawnablePrefabs was set to DefaultPrefabObjects automatically on object {gameObject.name} in scene {gameObject.scene.name}.");
|
||||||
|
EditorUtility.SetDirty(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
//Always throw an error as this would cause failure.
|
//Always throw an error as this would cause failure.
|
||||||
if (print)
|
if (print)
|
||||||
Debug.LogError($"SpawnablePrefabs is null on {gameObject.name}. Select the NetworkManager in scene {gameObject.scene.name} and choose a prefabs file. Choosing DefaultPrefabObjects will automatically populate prefabs for you.");
|
Debug.LogError($"SpawnablePrefabs is null on {gameObject.name}. Select the NetworkManager in scene {gameObject.scene.name} and choose a prefabs file. Choosing DefaultPrefabObjects will automatically populate prefabs for you.");
|
||||||
@ -455,13 +474,13 @@ namespace FishNet.Managing
|
|||||||
if (value.TransportIndex == transportIndex)
|
if (value.TransportIndex == transportIndex)
|
||||||
{
|
{
|
||||||
cache.Add(kvp.Key);
|
cache.Add(kvp.Key);
|
||||||
value.Dispose();
|
value.ResetState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Not using transport index, no check required.
|
//Not using transport index, no check required.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value.Dispose();
|
value.ResetState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,19 +24,19 @@ namespace FishNet.Managing.Object
|
|||||||
protected void ReadTransformProperties(Reader reader, out Vector3? localPosition, out Quaternion? localRotation, out Vector3? localScale)
|
protected void ReadTransformProperties(Reader reader, out Vector3? localPosition, out Quaternion? localRotation, out Vector3? localScale)
|
||||||
{
|
{
|
||||||
//Read changed.
|
//Read changed.
|
||||||
ChangedTransformProperties ctp = (ChangedTransformProperties)reader.ReadByte();
|
TransformPropertiesFlag tpf = (TransformPropertiesFlag)reader.ReadByte();
|
||||||
//Position.
|
//Position.
|
||||||
if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalPosition))
|
if (tpf.FastContains(TransformPropertiesFlag.Position))
|
||||||
localPosition = reader.ReadVector3();
|
localPosition = reader.ReadVector3();
|
||||||
else
|
else
|
||||||
localPosition = null;
|
localPosition = null;
|
||||||
//Rotation.
|
//Rotation.
|
||||||
if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalRotation))
|
if (tpf.FastContains(TransformPropertiesFlag.Rotation))
|
||||||
localRotation = reader.ReadQuaternion(NetworkManager.ServerManager.SpawnPacking.Rotation);
|
localRotation = reader.ReadQuaternion(NetworkManager.ServerManager.SpawnPacking.Rotation);
|
||||||
else
|
else
|
||||||
localRotation = null;
|
localRotation = null;
|
||||||
//Scale.
|
//Scale.
|
||||||
if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalScale))
|
if (tpf.FastContains(TransformPropertiesFlag.LocalScale))
|
||||||
localScale = reader.ReadVector3();
|
localScale = reader.ReadVector3();
|
||||||
else
|
else
|
||||||
localScale = null;
|
localScale = null;
|
||||||
@ -213,28 +213,28 @@ namespace FishNet.Managing.Object
|
|||||||
protected void WriteChangedTransformProperties(NetworkObject nob, bool sceneObject, bool nested, Writer headerWriter)
|
protected void WriteChangedTransformProperties(NetworkObject nob, bool sceneObject, bool nested, Writer headerWriter)
|
||||||
{
|
{
|
||||||
/* Write changed transform properties. */
|
/* Write changed transform properties. */
|
||||||
ChangedTransformProperties ctp;
|
TransformPropertiesFlag tpf;
|
||||||
//If a scene object then get it from scene properties.
|
//If a scene object then get it from scene properties.
|
||||||
if (sceneObject || nested)
|
if (sceneObject || nested)
|
||||||
{
|
{
|
||||||
ctp = nob.GetTransformChanges(nob.SerializedTransformProperties);
|
tpf = nob.GetTransformChanges(nob.SerializedTransformProperties);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PrefabObjects po = NetworkManager.GetPrefabObjects<PrefabObjects>(nob.SpawnableCollectionId, false);
|
PrefabObjects po = NetworkManager.GetPrefabObjects<PrefabObjects>(nob.SpawnableCollectionId, false);
|
||||||
ctp = nob.GetTransformChanges(po.GetObject(true, nob.PrefabId).gameObject);
|
tpf = nob.GetTransformChanges(po.GetObject(true, nob.PrefabId).gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
headerWriter.WriteByte((byte)ctp);
|
headerWriter.WriteByte((byte)tpf);
|
||||||
//If properties have changed.
|
//If properties have changed.
|
||||||
if (ctp != ChangedTransformProperties.Unset)
|
if (tpf != TransformPropertiesFlag.Unset)
|
||||||
{
|
{
|
||||||
//Write any changed properties.
|
//Write any changed properties.
|
||||||
if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalPosition))
|
if (tpf.FastContains(TransformPropertiesFlag.Position))
|
||||||
headerWriter.WriteVector3(nob.transform.localPosition);
|
headerWriter.WriteVector3(nob.transform.localPosition);
|
||||||
if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalRotation))
|
if (tpf.FastContains(TransformPropertiesFlag.Rotation))
|
||||||
headerWriter.WriteQuaternion(nob.transform.localRotation, NetworkManager.ServerManager.SpawnPacking.Rotation);
|
headerWriter.WriteQuaternion(nob.transform.localRotation, NetworkManager.ServerManager.SpawnPacking.Rotation);
|
||||||
if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalScale))
|
if (tpf.FastContains(TransformPropertiesFlag.LocalScale))
|
||||||
headerWriter.WriteVector3(nob.transform.localScale);
|
headerWriter.WriteVector3(nob.transform.localScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,74 @@
|
|||||||
#if UNITY_EDITOR
|
#if !PREDICTION_1
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace FishNet.Managing.Predicting.Editing
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
[CustomEditor(typeof(PredictionManager), true)]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
public class PredictionManagerEditor : Editor
|
||||||
|
{
|
||||||
|
// private SerializedProperty _queuedInputs;
|
||||||
|
private SerializedProperty _dropExcessiveReplicates;
|
||||||
|
private SerializedProperty _maximumServerReplicates;
|
||||||
|
private SerializedProperty _maximumConsumeCount;
|
||||||
|
private SerializedProperty _stateInterpolation;
|
||||||
|
// private SerializedProperty _serverInterpolation;
|
||||||
|
|
||||||
|
protected virtual void OnEnable()
|
||||||
|
{
|
||||||
|
_dropExcessiveReplicates = serializedObject.FindProperty(nameof(_dropExcessiveReplicates));
|
||||||
|
_maximumServerReplicates = serializedObject.FindProperty(nameof(_maximumServerReplicates));
|
||||||
|
_maximumConsumeCount = serializedObject.FindProperty(nameof(_maximumConsumeCount));
|
||||||
|
_stateInterpolation = serializedObject.FindProperty(nameof(_stateInterpolation));
|
||||||
|
// _serverInterpolation = serializedObject.FindProperty(nameof(_serverInterpolation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
serializedObject.Update();
|
||||||
|
|
||||||
|
GUI.enabled = false;
|
||||||
|
EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((PredictionManager)target), typeof(PredictionManager), false);
|
||||||
|
GUI.enabled = true;
|
||||||
|
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Client", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_stateInterpolation);
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Server", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
// EditorGUILayout.PropertyField(_serverInterpolation);
|
||||||
|
EditorGUILayout.PropertyField(_dropExcessiveReplicates);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
if (_dropExcessiveReplicates.boolValue == true)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_maximumServerReplicates);
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
|
||||||
|
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -13,21 +83,14 @@ namespace FishNet.Managing.Predicting.Editing
|
|||||||
private SerializedProperty _queuedInputs;
|
private SerializedProperty _queuedInputs;
|
||||||
private SerializedProperty _dropExcessiveReplicates;
|
private SerializedProperty _dropExcessiveReplicates;
|
||||||
private SerializedProperty _maximumServerReplicates;
|
private SerializedProperty _maximumServerReplicates;
|
||||||
private SerializedProperty _maximumConsumeCount;
|
|
||||||
private SerializedProperty _redundancyCount;
|
private SerializedProperty _redundancyCount;
|
||||||
private SerializedProperty _allowPredictedSpawning;
|
|
||||||
private SerializedProperty _reservedObjectIds;
|
|
||||||
|
|
||||||
|
|
||||||
protected virtual void OnEnable()
|
protected virtual void OnEnable()
|
||||||
{
|
{
|
||||||
_queuedInputs = serializedObject.FindProperty(nameof(_queuedInputs));
|
_queuedInputs = serializedObject.FindProperty(nameof(_queuedInputs));
|
||||||
_dropExcessiveReplicates = serializedObject.FindProperty(nameof(_dropExcessiveReplicates));
|
_dropExcessiveReplicates = serializedObject.FindProperty(nameof(_dropExcessiveReplicates));
|
||||||
_maximumServerReplicates = serializedObject.FindProperty(nameof(_maximumServerReplicates));
|
_maximumServerReplicates = serializedObject.FindProperty(nameof(_maximumServerReplicates));
|
||||||
_maximumConsumeCount = serializedObject.FindProperty(nameof(_maximumConsumeCount));
|
|
||||||
_redundancyCount = serializedObject.FindProperty(nameof(_redundancyCount));
|
_redundancyCount = serializedObject.FindProperty(nameof(_redundancyCount));
|
||||||
_allowPredictedSpawning = serializedObject.FindProperty(nameof(_allowPredictedSpawning));
|
|
||||||
_reservedObjectIds = serializedObject.FindProperty(nameof(_reservedObjectIds));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
public override void OnInspectorGUI()
|
||||||
@ -41,16 +104,8 @@ namespace FishNet.Managing.Predicting.Editing
|
|||||||
|
|
||||||
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.PropertyField(_queuedInputs);
|
|
||||||
EditorGUILayout.PropertyField(_redundancyCount);
|
EditorGUILayout.PropertyField(_redundancyCount);
|
||||||
|
EditorGUILayout.PropertyField(_queuedInputs);
|
||||||
EditorGUILayout.PropertyField(_allowPredictedSpawning);
|
|
||||||
if (_allowPredictedSpawning.boolValue == true)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
EditorGUILayout.PropertyField(_reservedObjectIds);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
@ -59,16 +114,7 @@ namespace FishNet.Managing.Predicting.Editing
|
|||||||
EditorGUILayout.PropertyField(_dropExcessiveReplicates);
|
EditorGUILayout.PropertyField(_dropExcessiveReplicates);
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
if (_dropExcessiveReplicates.boolValue == true)
|
if (_dropExcessiveReplicates.boolValue == true)
|
||||||
{
|
|
||||||
EditorGUILayout.PropertyField(_maximumServerReplicates);
|
EditorGUILayout.PropertyField(_maximumServerReplicates);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if PREDICTION_1
|
|
||||||
EditorGUILayout.PropertyField(_maximumConsumeCount);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
|
||||||
|
|
||||||
@ -78,3 +124,6 @@ namespace FishNet.Managing.Predicting.Editing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -9,7 +9,7 @@ using GameKit.Dependencies.Utilities;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
namespace FishNet.Managing.Predicting
|
namespace FishNet.Managing.Predicting
|
||||||
{
|
{
|
||||||
@ -96,24 +96,24 @@ namespace FishNet.Managing.Predicting
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Serialized.
|
#region Serialized.
|
||||||
/// <summary>
|
///// <summary>
|
||||||
///
|
/////
|
||||||
/// </summary>
|
///// </summary>
|
||||||
[Tooltip("Number of inputs to keep in queue for server and clients. " +
|
//[Tooltip("Number of inputs to keep in queue for server and clients. " +
|
||||||
"Higher values will increase the likeliness of continous user created data to arrive successfully. " +
|
// "Higher values will increase the likeliness of continous user created data to arrive successfully. " +
|
||||||
"Lower values will increase processing rate of received replicates. +" +
|
// "Lower values will increase processing rate of received replicates. +" +
|
||||||
"This value cannot be higher than MaximumServerReplicates.")]
|
// "This value cannot be higher than MaximumServerReplicates.")]
|
||||||
[Range(0, 15)]
|
//[Range(0, 15)]
|
||||||
[SerializeField]
|
//[SerializeField]
|
||||||
private byte _queuedInputs = 1;
|
//private byte _queuedInputs = 1;
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Number of inputs to keep in queue for server and clients.
|
///// Number of inputs to keep in queue for server and clients.
|
||||||
/// Higher values will increase the likeliness of continous user created data to arrive successfully.
|
///// Higher values will increase the likeliness of continous user created data to arrive successfully.
|
||||||
/// Lower values will increase processing rate of received replicates.
|
///// Lower values will increase processing rate of received replicates.
|
||||||
/// This value cannot be higher than MaximumServerReplicates.
|
///// This value cannot be higher than MaximumServerReplicates.
|
||||||
/// </summary>
|
///// </summary>
|
||||||
//TODO: this is 0 until the rework on it is completed.
|
////TODO: this is 0 until the rework on it is completed.
|
||||||
public byte QueuedInputs => 0;// _queuedInputs;
|
//public byte QueuedInputs => 0;// _queuedInputs;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -144,39 +144,37 @@ namespace FishNet.Managing.Predicting
|
|||||||
_maximumServerReplicates = (byte)Mathf.Clamp(value, MINIMUM_REPLICATE_QUEUE_SIZE, MAXIMUM_REPLICATE_QUEUE_SIZE);
|
_maximumServerReplicates = (byte)Mathf.Clamp(value, MINIMUM_REPLICATE_QUEUE_SIZE, MAXIMUM_REPLICATE_QUEUE_SIZE);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clients should store no more than 2 seconds worth of replicates.
|
/// No more than this value of replicates should be stored as a buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal ushort MaximumClientReplicates => (ushort)(_networkManager.TimeManager.TickRate * 5);
|
internal ushort MaximumPastReplicates => (ushort)(_networkManager.TimeManager.TickRate * 5);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Tooltip("Maximum number of past inputs which may send.")]
|
[Tooltip("How many states to try and hold in a buffer before running them on clients. Larger values add resilience against network issues at the cost of running states later.")]
|
||||||
[Range(MINIMUM_PAST_INPUTS, MAXIMUM_PAST_INPUTS)]
|
[Range(0, MAXIMUM_PAST_INPUTS)]
|
||||||
|
[FormerlySerializedAs("_redundancyCount")] //Remove on V5.
|
||||||
|
[FormerlySerializedAs("_interpolation")] //Remove on V5.
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private byte _redundancyCount = 2;
|
private byte _stateInterpolation = 1;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of past inputs which may send and resend redundancy.
|
/// How many states to try and hold in a buffer before running them. Larger values add resilience against network issues at the cost of running states later.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal byte RedundancyCount => _redundancyCount;
|
internal byte StateInterpolation => _stateInterpolation;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True to allow clients to use predicted spawning. While true, each NetworkObject prefab you wish to predicted spawn must be marked as to allow this feature.
|
/// Number of past inputs to send, which is also the number of times to resend final datas.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal bool GetAllowPredictedSpawning() => _allowPredictedSpawning;
|
internal byte RedundancyCount => (byte)(_stateInterpolation + 1);
|
||||||
[Tooltip("True to allow clients to use predicted spawning and despawning. While true, each NetworkObject prefab you wish to predicted spawn must be marked as to allow this feature.")]
|
///// <summary>
|
||||||
[SerializeField]
|
/////
|
||||||
private bool _allowPredictedSpawning = false;
|
///// </summary>
|
||||||
/// <summary>
|
//[Tooltip("How many states to try and hold in a buffer before running them on server. Larger values add resilience against network issues at the cost of running states later.")]
|
||||||
///
|
//[Range(0, MAXIMUM_PAST_INPUTS + 30)]
|
||||||
/// </summary>
|
//[SerializeField]
|
||||||
[Tooltip("Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.")]
|
//private byte _serverInterpolation = 1;
|
||||||
[Range(1, 100)]
|
///// <summary>
|
||||||
[SerializeField]
|
///// How many states to try and hold in a buffer before running them on server. Larger values add resilience against network issues at the cost of running states later.
|
||||||
private byte _reservedObjectIds = 15;
|
///// </summary>
|
||||||
/// <summary>
|
//internal byte ServerInterpolation => _serverInterpolation;
|
||||||
/// Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal byte GetReservedObjectIds() => _reservedObjectIds;
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private.
|
#region Private.
|
||||||
@ -228,7 +226,7 @@ namespace FishNet.Managing.Predicting
|
|||||||
internal void InitializeOnce(NetworkManager manager)
|
internal void InitializeOnce(NetworkManager manager)
|
||||||
{
|
{
|
||||||
_networkManager = manager;
|
_networkManager = manager;
|
||||||
ClampQueuedInputs();
|
ClampInterpolation();
|
||||||
_networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState;
|
_networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,30 +236,27 @@ namespace FishNet.Managing.Predicting
|
|||||||
private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj)
|
private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj)
|
||||||
{
|
{
|
||||||
_droppedReconcilesCount = 0;
|
_droppedReconcilesCount = 0;
|
||||||
|
_lastOrderedReadReconcileTick = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Amount to reserve for the header of a state update.
|
/// Amount to reserve for the header of a state update.
|
||||||
/// 2 PacketId.
|
|
||||||
/// 4 Last replicate tick run for connection.
|
|
||||||
/// 4 Length unpacked.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal const int STATE_HEADER_RESERVE_COUNT = 10;
|
internal const int STATE_HEADER_RESERVE_LENGTH = (TransportManager.PACKETID_LENGTH + TransportManager.UNPACKED_TICK_LENGTH + TransportManager.UNPACKED_SIZE_LENGTH);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clamps queued inputs to a valid value.
|
/// Clamps queued inputs to a valid value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ClampQueuedInputs()
|
private void ClampInterpolation()
|
||||||
{
|
{
|
||||||
ushort startingValue = _queuedInputs;
|
ushort startingValue = _stateInterpolation;
|
||||||
//Check for setting if dropping.
|
//Check for setting if dropping.
|
||||||
if (_dropExcessiveReplicates && _queuedInputs > _maximumServerReplicates)
|
if (_dropExcessiveReplicates && _stateInterpolation > _maximumServerReplicates)
|
||||||
_queuedInputs = (byte)(_maximumServerReplicates - 1);
|
_stateInterpolation = (byte)(_maximumServerReplicates - 1);
|
||||||
|
|
||||||
//If changed.
|
//If changed.
|
||||||
if (_queuedInputs != startingValue)
|
if (_stateInterpolation != startingValue)
|
||||||
_networkManager.Log($"QueuedInputs has been set to {_queuedInputs}.");
|
_networkManager.Log($"Interpolation has been set to {_stateInterpolation}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StatePacket : IResettable
|
internal class StatePacket : IResettable
|
||||||
@ -321,70 +316,48 @@ namespace FishNet.Managing.Predicting
|
|||||||
TimeManager tm = _networkManager.TimeManager;
|
TimeManager tm = _networkManager.TimeManager;
|
||||||
uint localTick = tm.LocalTick;
|
uint localTick = tm.LocalTick;
|
||||||
uint estimatedLastRemoteTick = tm.LastPacketTick.Value();
|
uint estimatedLastRemoteTick = tm.LastPacketTick.Value();
|
||||||
//NOTESSTART
|
|
||||||
/* Don't run a reconcile unless it's possible for ticks queued
|
|
||||||
* that tick to be run already. Otherwise you are not replaying inputs
|
|
||||||
* at all, just snapping to corrections. This means states which arrive late or out of order
|
|
||||||
* will be ignored since they're before the reconcile, which means important actions
|
|
||||||
* could have gone missed.
|
|
||||||
*
|
|
||||||
* A system which synchronized all current states rather than what's only needed to correct
|
|
||||||
* the inputs would likely solve this. */
|
|
||||||
//NOTESEND
|
|
||||||
|
|
||||||
/* Only use the latest reconcile which passes the conditions to run.
|
/* When there is an excessive amount of states try to consume
|
||||||
* This will drop any excessive reconciles which built up from latency. */
|
* some.This only happens when the client gets really far behind
|
||||||
StatePacket sp = null;
|
* and has to catch up, such as a latency increase then drop.
|
||||||
/* If here then 'peeked' has met conditions.
|
* Limit the number of states consumed per tick so the clients
|
||||||
* Check if the next state also meets, if so then
|
* computer doesn't catch fire. */
|
||||||
* skip ahead to the next state. */
|
int iterations = 0;
|
||||||
|
|
||||||
while (_reconcileStates.Count > 0)
|
while (_reconcileStates.Count > 0)
|
||||||
{
|
{
|
||||||
//If next matches then set peeked to new.
|
iterations++;
|
||||||
if (ConditionsMet(_reconcileStates.Peek()))
|
/* Typically there should only be 'interpolation' amount in queue but
|
||||||
{
|
* there can be more if the clients network is unstable and they are
|
||||||
//Since this is being replaced, reset state first.
|
* arriving in burst.
|
||||||
if (sp != null)
|
* If there's more than interpolation (+1 for as a leniency buffer) then begin to
|
||||||
DisposeOfStatePacket(sp);
|
* consume multiple. */
|
||||||
sp = _reconcileStates.Dequeue();
|
byte stateInterpolation = StateInterpolation;
|
||||||
break;
|
int maxIterations = (_reconcileStates.Count > (stateInterpolation + 1)) ? 2 : 1;
|
||||||
}
|
//At most 2 iterations.
|
||||||
/* Conditions are not met on the next one, exit loop.
|
if (iterations > maxIterations)
|
||||||
* This will use the latest peeked. */
|
return;
|
||||||
|
|
||||||
|
StatePacket sp;
|
||||||
|
if (!ConditionsMet(_reconcileStates.Peek()))
|
||||||
|
return;
|
||||||
else
|
else
|
||||||
{
|
sp = _reconcileStates.Dequeue();
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Condition met. See if the next one matches condition, if so drop current.
|
//Condition met. See if the next one matches condition, if so drop current.
|
||||||
//Returns if a state has it's conditions met.
|
//Returns if a state has it's conditions met.
|
||||||
bool ConditionsMet(StatePacket spChecked)
|
bool ConditionsMet(StatePacket spChecked)
|
||||||
{
|
{
|
||||||
return ((spChecked != null) && (spChecked.ServerTick <= (estimatedLastRemoteTick - QueuedInputs - RedundancyCount - 1)) && spChecked.ClientTick < (localTick - QueuedInputs));
|
if (spChecked == null)
|
||||||
|
return false;
|
||||||
|
bool serverPass = (spChecked.ServerTick <= (estimatedLastRemoteTick - stateInterpolation));
|
||||||
|
bool clientPass = spChecked.ClientTick < (localTick - stateInterpolation);
|
||||||
|
return (serverPass && clientPass);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//If state is not valid then it was never set, thus condition is not met.
|
|
||||||
if (sp == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//StatePacket sp = _reconcileStates.Dequeue();
|
|
||||||
bool dropReconcile = false;
|
bool dropReconcile = false;
|
||||||
|
|
||||||
uint clientTick = sp.ClientTick;
|
uint clientTick = sp.ClientTick;
|
||||||
uint serverTick = sp.ServerTick;
|
uint serverTick = sp.ServerTick;
|
||||||
//uint ticksDifference = (localTick - clientTick);
|
|
||||||
////Target ticks are based on QueuedInputs, redundancy count, and latency. An extra bit is added as a buffer for variance.
|
|
||||||
//uint varianceAllowance = tm.TimeToTicks(0.2f, TickRounding.RoundUp);
|
|
||||||
//uint targetTicks = (varianceAllowance + (uint)QueuedInputs + (uint)RedundancyCount + tm.TimeToTicks((double)((double)tm.RoundTripTime / 1000d), TickRounding.RoundDown));
|
|
||||||
//long ticksOverTarget = (long)ticksDifference - (long)targetTicks;
|
|
||||||
////ReduceClientTiming = (ticksOverTarget > 0);
|
|
||||||
///* If the reconcile is behind more ticks than hoped then slow
|
|
||||||
// * down the client simulation so it ticks very slightly
|
|
||||||
// * slower allowing fewer replays. This typically is only required after
|
|
||||||
// * the player encounters a sudden ping drop, such as a spike in latency,
|
|
||||||
// * then ping returns to norrmal. */
|
|
||||||
//if (ticksOverTarget > 0)
|
|
||||||
//{
|
|
||||||
|
|
||||||
/* If client has a low frame rate
|
/* If client has a low frame rate
|
||||||
* then limit the number of reconciles to prevent further performance loss. */
|
* then limit the number of reconciles to prevent further performance loss. */
|
||||||
@ -432,7 +405,7 @@ namespace FishNet.Managing.Predicting
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool timeManagerPhysics = (tm.PhysicsMode == PhysicsMode.TimeManager);
|
bool timeManagerPhysics = (tm.PhysicsMode == PhysicsMode.TimeManager);
|
||||||
float tickDelta = (float)tm.TickDelta;
|
float tickDelta = ((float)tm.TickDelta * _networkManager.TimeManager.GetPhysicsTimeScale());
|
||||||
|
|
||||||
OnPreReconcile?.Invoke(ClientStateTick, ServerStateTick);
|
OnPreReconcile?.Invoke(ClientStateTick, ServerStateTick);
|
||||||
OnReconcile?.Invoke(ClientStateTick, ServerStateTick);
|
OnReconcile?.Invoke(ClientStateTick, ServerStateTick);
|
||||||
@ -456,7 +429,6 @@ namespace FishNet.Managing.Predicting
|
|||||||
ClientReplayTick = ClientStateTick;
|
ClientReplayTick = ClientStateTick;
|
||||||
ServerReplayTick = ServerStateTick;
|
ServerReplayTick = ServerStateTick;
|
||||||
|
|
||||||
int replays = 0;
|
|
||||||
/* Only replay up to this tick excluding queuedInputs.
|
/* Only replay up to this tick excluding queuedInputs.
|
||||||
* This will prevent the client from replaying into
|
* This will prevent the client from replaying into
|
||||||
* it's authorative/owned inputs which have not run
|
* it's authorative/owned inputs which have not run
|
||||||
@ -467,7 +439,6 @@ namespace FishNet.Managing.Predicting
|
|||||||
* since the OnTick has not run yet. */
|
* since the OnTick has not run yet. */
|
||||||
while (ClientReplayTick < localTick - 1)
|
while (ClientReplayTick < localTick - 1)
|
||||||
{
|
{
|
||||||
replays++;
|
|
||||||
OnPreReplicateReplay?.Invoke(ClientReplayTick, ServerReplayTick);
|
OnPreReplicateReplay?.Invoke(ClientReplayTick, ServerReplayTick);
|
||||||
OnReplicateReplay?.Invoke(ClientReplayTick, ServerReplayTick);
|
OnReplicateReplay?.Invoke(ClientReplayTick, ServerReplayTick);
|
||||||
if (timeManagerPhysics)
|
if (timeManagerPhysics)
|
||||||
@ -491,35 +462,28 @@ namespace FishNet.Managing.Predicting
|
|||||||
|
|
||||||
DisposeOfStatePacket(sp);
|
DisposeOfStatePacket(sp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends written states for clients.
|
/// Sends written states for clients.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void SendStateUpdate()
|
internal void SendStateUpdate()
|
||||||
{
|
{
|
||||||
|
byte stateInterpolation = StateInterpolation;
|
||||||
|
uint recentReplicateToTicks = _networkManager.TimeManager.TimeToTicks(0.25f, TickRounding.RoundUp);
|
||||||
TransportManager tm = _networkManager.TransportManager;
|
TransportManager tm = _networkManager.TransportManager;
|
||||||
foreach (NetworkConnection nc in _networkManager.ServerManager.Clients.Values)
|
foreach (NetworkConnection nc in _networkManager.ServerManager.Clients.Values)
|
||||||
{
|
{
|
||||||
uint lastReplicateTick;
|
uint lastReplicateTick;
|
||||||
//If client has performed a replicate.
|
//If client has performed a replicate recently.
|
||||||
if (!nc.ReplicateTick.IsUnset)
|
if (!nc.ReplicateTick.IsUnset && nc.ReplicateTick.LocalTickDifference(_networkManager.TimeManager) < recentReplicateToTicks)
|
||||||
{
|
|
||||||
/* If it's been longer than queued inputs since
|
|
||||||
* server has received a replicate then
|
|
||||||
* use estimated value. Otherwise use LastRemoteTick. */
|
|
||||||
if (nc.ReplicateTick.LocalTickDifference(_networkManager.TimeManager) > QueuedInputs)
|
|
||||||
lastReplicateTick = nc.ReplicateTick.Value();
|
lastReplicateTick = nc.ReplicateTick.Value();
|
||||||
else
|
|
||||||
lastReplicateTick = nc.ReplicateTick.LastRemoteTick;
|
|
||||||
}
|
|
||||||
/* If not then use what is estimated to be the clients
|
/* If not then use what is estimated to be the clients
|
||||||
* current tick along with desired prediction queue count.
|
* current tick along with desired prediction queue count.
|
||||||
* This should be just about the same as if the client used replicate,
|
* This should be just about the same as if the client used replicate,
|
||||||
* but even if it's not it doesn't matter because the client
|
* but even if it's not it doesn't matter because the client
|
||||||
* isn't replicating himself, just reconciling and replaying other objects. */
|
* isn't replicating himself, just reconciling and replaying other objects. */
|
||||||
else
|
else
|
||||||
{
|
lastReplicateTick = nc.LocalTick.Value() - stateInterpolation;
|
||||||
lastReplicateTick = (nc.PacketTick.Value() + QueuedInputs);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (PooledWriter writer in nc.PredictionStateWriters)
|
foreach (PooledWriter writer in nc.PredictionStateWriters)
|
||||||
{
|
{
|
||||||
@ -536,7 +500,7 @@ namespace FishNet.Managing.Predicting
|
|||||||
* the reserve count of the header. The header reserve
|
* the reserve count of the header. The header reserve
|
||||||
* count will always be the same so that can be parsed
|
* count will always be the same so that can be parsed
|
||||||
* off immediately upon receiving. */
|
* off immediately upon receiving. */
|
||||||
int dataLength = (segment.Count - STATE_HEADER_RESERVE_COUNT);
|
int dataLength = (segment.Count - STATE_HEADER_RESERVE_LENGTH);
|
||||||
//Write length.
|
//Write length.
|
||||||
writer.WriteInt32(dataLength, AutoPackType.Unpacked);
|
writer.WriteInt32(dataLength, AutoPackType.Unpacked);
|
||||||
//Channel is defaulted to unreliable.
|
//Channel is defaulted to unreliable.
|
||||||
@ -576,7 +540,7 @@ namespace FishNet.Managing.Predicting
|
|||||||
* a limit a little beyond to prevent reconciles from building up.
|
* a limit a little beyond to prevent reconciles from building up.
|
||||||
* This is more of a last result if something went terribly
|
* This is more of a last result if something went terribly
|
||||||
* wrong with the network. */
|
* wrong with the network. */
|
||||||
int maxAllowedStates = Mathf.Max(QueuedInputs * 4, 4);
|
int maxAllowedStates = Mathf.Max(StateInterpolation * 4, 4);
|
||||||
while (_reconcileStates.Count > maxAllowedStates)
|
while (_reconcileStates.Count > maxAllowedStates)
|
||||||
{
|
{
|
||||||
StatePacket oldSp = _reconcileStates.Dequeue();
|
StatePacket oldSp = _reconcileStates.Dequeue();
|
||||||
@ -622,7 +586,7 @@ namespace FishNet.Managing.Predicting
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
ClampQueuedInputs();
|
ClampInterpolation();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -772,28 +736,9 @@ namespace FishNet.Managing.Predicting
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private byte _redundancyCount = 2;
|
private byte _redundancyCount = 2;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of past inputs which may send and resend redundancy.
|
/// Maximum number of past inputs which may send.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal byte RedundancyCount => _redundancyCount;
|
internal byte RedundancyCount => _redundancyCount;
|
||||||
/// <summary>
|
|
||||||
/// True to allow clients to use predicted spawning. While true, each NetworkObject prefab you wish to predicted spawn must be marked as to allow this feature.
|
|
||||||
/// </summary>
|
|
||||||
internal bool GetAllowPredictedSpawning() => _allowPredictedSpawning;
|
|
||||||
[Tooltip("True to allow clients to use predicted spawning and despawning. While true, each NetworkObject prefab you wish to predicted spawn must be marked as to allow this feature.")]
|
|
||||||
[SerializeField]
|
|
||||||
private bool _allowPredictedSpawning = false;
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[Tooltip("Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.")]
|
|
||||||
[Range(1, 100)]
|
|
||||||
[SerializeField]
|
|
||||||
private byte _reservedObjectIds = 15;
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal byte GetReservedObjectIds() => _reservedObjectIds;
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private.
|
#region Private.
|
||||||
|
|||||||
@ -782,7 +782,7 @@ namespace FishNet.Managing.Scened
|
|||||||
return WarnAndReturnFalse($"NetworkObject {nob.name} cannot be moved because it is not the root object. Unity can only move root objects between scenes.");
|
return WarnAndReturnFalse($"NetworkObject {nob.name} cannot be moved because it is not the root object. Unity can only move root objects between scenes.");
|
||||||
//In DDOL and IsGlobal.
|
//In DDOL and IsGlobal.
|
||||||
if (nob.IsGlobal && (nob.gameObject.scene.name == DDOL.GetDDOL().gameObject.scene.name))
|
if (nob.IsGlobal && (nob.gameObject.scene.name == DDOL.GetDDOL().gameObject.scene.name))
|
||||||
return WarnAndReturnFalse("NetworkObject {nob.name} cannot be moved because it is global. Global objects must remain in the DontDestroyOnLoad scene.");
|
return WarnAndReturnFalse($"NetworkObject {nob.name} cannot be moved because it is global. Global objects must remain in the DontDestroyOnLoad scene.");
|
||||||
|
|
||||||
//Fall through success.
|
//Fall through success.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -19,6 +19,8 @@ namespace FishNet.Managing.Server.Editing
|
|||||||
private SerializedProperty _frameRate;
|
private SerializedProperty _frameRate;
|
||||||
private SerializedProperty _shareIds;
|
private SerializedProperty _shareIds;
|
||||||
private SerializedProperty _startOnHeadless;
|
private SerializedProperty _startOnHeadless;
|
||||||
|
private SerializedProperty _allowPredictedSpawning;
|
||||||
|
private SerializedProperty _reservedObjectIds;
|
||||||
|
|
||||||
protected virtual void OnEnable()
|
protected virtual void OnEnable()
|
||||||
{
|
{
|
||||||
@ -31,6 +33,9 @@ namespace FishNet.Managing.Server.Editing
|
|||||||
_frameRate = serializedObject.FindProperty(nameof(_frameRate));
|
_frameRate = serializedObject.FindProperty(nameof(_frameRate));
|
||||||
_shareIds = serializedObject.FindProperty(nameof(_shareIds));
|
_shareIds = serializedObject.FindProperty(nameof(_shareIds));
|
||||||
_startOnHeadless = serializedObject.FindProperty(nameof(_startOnHeadless));
|
_startOnHeadless = serializedObject.FindProperty(nameof(_startOnHeadless));
|
||||||
|
_allowPredictedSpawning = serializedObject.FindProperty(nameof(_allowPredictedSpawning));
|
||||||
|
_reservedObjectIds = serializedObject.FindProperty(nameof(_reservedObjectIds));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
public override void OnInspectorGUI()
|
||||||
@ -43,15 +48,6 @@ namespace FishNet.Managing.Server.Editing
|
|||||||
|
|
||||||
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_authenticator);
|
|
||||||
EditorGUILayout.PropertyField(_remoteClientTimeout);
|
|
||||||
if ((RemoteTimeoutType)_remoteClientTimeout.intValue != RemoteTimeoutType.Disabled)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
EditorGUILayout.PropertyField(_remoteClientTimeoutDuration,new GUIContent("Timeout"));
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
EditorGUILayout.PropertyField(_syncTypeRate);
|
EditorGUILayout.PropertyField(_syncTypeRate);
|
||||||
EditorGUILayout.PropertyField(SpawnPacking);
|
EditorGUILayout.PropertyField(SpawnPacking);
|
||||||
EditorGUILayout.PropertyField(_changeFrameRate);
|
EditorGUILayout.PropertyField(_changeFrameRate);
|
||||||
@ -61,11 +57,36 @@ namespace FishNet.Managing.Server.Editing
|
|||||||
EditorGUILayout.PropertyField(_frameRate);
|
EditorGUILayout.PropertyField(_frameRate);
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
EditorGUILayout.PropertyField(_shareIds);
|
|
||||||
EditorGUILayout.PropertyField(_startOnHeadless);
|
EditorGUILayout.PropertyField(_startOnHeadless);
|
||||||
|
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Connections", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_remoteClientTimeout);
|
||||||
|
if ((RemoteTimeoutType)_remoteClientTimeout.intValue != RemoteTimeoutType.Disabled)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_remoteClientTimeoutDuration,new GUIContent("Timeout"));
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(_shareIds);
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Security", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_authenticator);
|
||||||
|
|
||||||
|
EditorGUILayout.PropertyField(_allowPredictedSpawning);
|
||||||
|
if (_allowPredictedSpawning.boolValue == true)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_reservedObjectIds);
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -251,7 +251,7 @@ namespace FishNet.Managing.Server
|
|||||||
/* Only shuffle when NOT in editor and not
|
/* Only shuffle when NOT in editor and not
|
||||||
* development build.
|
* development build.
|
||||||
* Debugging could be easier when Ids are ordered. */
|
* Debugging could be easier when Ids are ordered. */
|
||||||
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
|
#if !DEVELOPMENT
|
||||||
shuffledCache.Shuffle();
|
shuffledCache.Shuffle();
|
||||||
#endif
|
#endif
|
||||||
//Add shuffled to objectIdCache.
|
//Add shuffled to objectIdCache.
|
||||||
@ -458,7 +458,7 @@ namespace FishNet.Managing.Server
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Server has predicted spawning disabled.
|
//Server has predicted spawning disabled.
|
||||||
if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning())
|
if (!NetworkManager.ServerManager.GetAllowPredictedSpawning())
|
||||||
{
|
{
|
||||||
base.NetworkManager.LogWarning("Cannot spawn object because server is not active and predicted spawning is not enabled.");
|
base.NetworkManager.LogWarning("Cannot spawn object because server is not active and predicted spawning is not enabled.");
|
||||||
return;
|
return;
|
||||||
@ -809,7 +809,7 @@ namespace FishNet.Managing.Server
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Server has predicted spawning disabled.
|
//Server has predicted spawning disabled.
|
||||||
if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning())
|
if (!NetworkManager.ServerManager.GetAllowPredictedSpawning())
|
||||||
{
|
{
|
||||||
base.NetworkManager.LogWarning("Cannot despawn object because server is not active and predicted spawning is not enabled.");
|
base.NetworkManager.LogWarning("Cannot despawn object because server is not active and predicted spawning is not enabled.");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
using FishNet.Authenticating;
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
using FishNet.Authenticating;
|
||||||
using FishNet.Component.Observing;
|
using FishNet.Component.Observing;
|
||||||
using FishNet.Connection;
|
using FishNet.Connection;
|
||||||
using FishNet.Managing.Debugging;
|
using FishNet.Managing.Debugging;
|
||||||
@ -102,6 +105,26 @@ namespace FishNet.Managing.Server
|
|||||||
_remoteClientTimeoutDuration = duration;
|
_remoteClientTimeoutDuration = duration;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// True to allow clients to use predicted spawning. While true, each NetworkObject you wish this feature to apply towards must have a PredictedSpawn component.
|
||||||
|
/// Predicted spawns can have custom validation on the server.
|
||||||
|
/// </summary>
|
||||||
|
internal bool GetAllowPredictedSpawning() => _allowPredictedSpawning;
|
||||||
|
[Tooltip("True to allow clients to use predicted spawning. While true, each NetworkObject you wish this feature to apply towards must have a PredictedSpawn component. Predicted spawns can have custom validation on the server.")]
|
||||||
|
[SerializeField]
|
||||||
|
private bool _allowPredictedSpawning = false;
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.")]
|
||||||
|
[Range(1, 100)]
|
||||||
|
[SerializeField]
|
||||||
|
private byte _reservedObjectIds = 15;
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal byte GetReservedObjectIds() => _reservedObjectIds;
|
||||||
|
/// <summary>
|
||||||
/// Default send rate for SyncTypes. A value of 0f will send changed values every tick.
|
/// Default send rate for SyncTypes. A value of 0f will send changed values every tick.
|
||||||
/// SyncTypeRate cannot yet be changed at runtime because this would require recalculating rates on SyncBase, which is not yet implemented.
|
/// SyncTypeRate cannot yet be changed at runtime because this would require recalculating rates on SyncBase, which is not yet implemented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -180,7 +203,7 @@ namespace FishNet.Managing.Server
|
|||||||
/// Used to read splits.
|
/// Used to read splits.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SplitReader _splitReader = new SplitReader();
|
private SplitReader _splitReader = new SplitReader();
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logs data about parser to help debug.
|
/// Logs data about parser to help debug.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -329,7 +352,7 @@ namespace FishNet.Managing.Server
|
|||||||
{
|
{
|
||||||
if (_remoteClientTimeout == RemoteTimeoutType.Disabled)
|
if (_remoteClientTimeout == RemoteTimeoutType.Disabled)
|
||||||
return;
|
return;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
//If development but not set to development return.
|
//If development but not set to development return.
|
||||||
else if (_remoteClientTimeout != RemoteTimeoutType.Development)
|
else if (_remoteClientTimeout != RemoteTimeoutType.Development)
|
||||||
return;
|
return;
|
||||||
@ -505,6 +528,54 @@ namespace FishNet.Managing.Server
|
|||||||
OnServerConnectionState?.Invoke(args);
|
OnServerConnectionState?.Invoke(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks to make sure the client is on the same version.
|
||||||
|
/// This is to help developers make sure their builds are on the same FishNet version.
|
||||||
|
/// </summary>
|
||||||
|
private void ParseVersion(PooledReader reader, NetworkConnection conn, int transportId)
|
||||||
|
{
|
||||||
|
//Cannot be authenticated if havent sent version yet. This is a duplicate version send, likely exploit attempt.
|
||||||
|
if (conn.HasSentVersion)
|
||||||
|
{
|
||||||
|
conn.Kick(reader, KickReason.ExploitAttempt, LoggingType.Common, $"Connection {conn.ToString()} has sent their FishNet version after being authenticated; this is not possible under normal conditions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.HasSentVersion = true;
|
||||||
|
string version = reader.ReadString();
|
||||||
|
//Version match.
|
||||||
|
if (version == NetworkManager.FISHNET_VERSION)
|
||||||
|
{
|
||||||
|
/* Send to client if server is in development build or not.
|
||||||
|
* This is to allow the client to utilize some features/information
|
||||||
|
* received from the server only when it's in dev mode. */
|
||||||
|
bool isDevelopmentBuild;
|
||||||
|
#if DEVELOPMENT
|
||||||
|
isDevelopmentBuild = true;
|
||||||
|
#else
|
||||||
|
isDevelopmentBuild = false;
|
||||||
|
#endif
|
||||||
|
PooledWriter writer = WriterPool.Retrieve();
|
||||||
|
writer.WritePacketId(PacketId.Version);
|
||||||
|
writer.WriteBoolean(isDevelopmentBuild);
|
||||||
|
conn.SendToClient((byte)Channel.Reliable, writer.GetArraySegment());
|
||||||
|
WriterPool.Store(writer);
|
||||||
|
|
||||||
|
/* If there is an authenticator
|
||||||
|
* and the transport is not a local transport. */
|
||||||
|
Authenticator auth = GetAuthenticator();
|
||||||
|
if (auth != null && !NetworkManager.TransportManager.IsLocalTransport(transportId))
|
||||||
|
auth.OnRemoteConnection(conn);
|
||||||
|
else
|
||||||
|
ClientAuthenticated(conn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conn.Kick(reader, KickReason.UnexpectedProblem, LoggingType.Warning, $"Connection {conn.ToString()} has been kicked for being on FishNet version {version}. Server version is {NetworkManager.FISHNET_VERSION}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when a connection state changes for a remote client.
|
/// Called when a connection state changes for a remote client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -512,10 +583,9 @@ namespace FishNet.Managing.Server
|
|||||||
{
|
{
|
||||||
//Sanity check to make sure transports are following proper types/ranges.
|
//Sanity check to make sure transports are following proper types/ranges.
|
||||||
int id = args.ConnectionId;
|
int id = args.ConnectionId;
|
||||||
int maxIdValue = short.MaxValue;
|
if (id < 0 || id > NetworkConnection.MAXIMUM_CLIENTID_VALUE)
|
||||||
if (id < 0 || id > maxIdValue)
|
|
||||||
{
|
{
|
||||||
Kick(args.ConnectionId, KickReason.UnexpectedProblem, LoggingType.Error, $"The transport you are using supplied an invalid connection Id of {id}. Connection Id values must range between 0 and {maxIdValue}. The client has been disconnected.");
|
Kick(args.ConnectionId, KickReason.UnexpectedProblem, LoggingType.Error, $"The transport you are using supplied an invalid connection Id of {id}. Connection Id values must range between 0 and {NetworkConnection.MAXIMUM_CLIENTID_VALUE}. The client has been disconnected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Valid Id.
|
//Valid Id.
|
||||||
@ -528,16 +598,8 @@ namespace FishNet.Managing.Server
|
|||||||
NetworkConnection conn = new NetworkConnection(NetworkManager, id, args.TransportIndex, true);
|
NetworkConnection conn = new NetworkConnection(NetworkManager, id, args.TransportIndex, true);
|
||||||
Clients.Add(args.ConnectionId, conn);
|
Clients.Add(args.ConnectionId, conn);
|
||||||
OnRemoteConnectionState?.Invoke(conn, args);
|
OnRemoteConnectionState?.Invoke(conn, args);
|
||||||
//Connection is no longer valid. This can occur if the user changes the state using the OnRemoteConnectionState event.
|
|
||||||
if (!conn.IsValid)
|
//Do nothing else until the client sends it's version.
|
||||||
return;
|
|
||||||
/* If there is an authenticator
|
|
||||||
* and the transport is not a local transport. */
|
|
||||||
Authenticator auth = GetAuthenticator();
|
|
||||||
if (auth != null && !NetworkManager.TransportManager.IsLocalTransport(id))
|
|
||||||
auth.OnRemoteConnection(conn);
|
|
||||||
else
|
|
||||||
ClientAuthenticated(conn);
|
|
||||||
}
|
}
|
||||||
//If stopping.
|
//If stopping.
|
||||||
else if (args.ConnectionState == RemoteConnectionState.Stopped)
|
else if (args.ConnectionState == RemoteConnectionState.Stopped)
|
||||||
@ -556,7 +618,7 @@ namespace FishNet.Managing.Server
|
|||||||
while (pqId.Count > 0)
|
while (pqId.Count > 0)
|
||||||
Objects.CacheObjectId(pqId.Dequeue());
|
Objects.CacheObjectId(pqId.Dequeue());
|
||||||
|
|
||||||
conn.Dispose();
|
conn.ResetState();
|
||||||
NetworkManager.Log($"Remote connection stopped for Id {id}.");
|
NetworkManager.Log($"Remote connection stopped for Id {id}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,9 +638,9 @@ namespace FishNet.Managing.Server
|
|||||||
* reserved objectIds. */
|
* reserved objectIds. */
|
||||||
;
|
;
|
||||||
PredictionManager pm = NetworkManager.PredictionManager;
|
PredictionManager pm = NetworkManager.PredictionManager;
|
||||||
if (pm.GetAllowPredictedSpawning())
|
if (GetAllowPredictedSpawning())
|
||||||
{
|
{
|
||||||
int count = Mathf.Min(Objects.GetObjectIdCache().Count, pm.GetReservedObjectIds());
|
int count = Mathf.Min(Objects.GetObjectIdCache().Count, GetReservedObjectIds());
|
||||||
writer.WriteByte((byte)count);
|
writer.WriteByte((byte)count);
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
@ -606,7 +668,7 @@ namespace FishNet.Managing.Server
|
|||||||
/// <param name="args"></param>
|
/// <param name="args"></param>
|
||||||
private void ParseReceived(ServerReceivedDataArgs args)
|
private void ParseReceived(ServerReceivedDataArgs args)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
_parseLogger.Reset();
|
_parseLogger.Reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -621,7 +683,7 @@ namespace FishNet.Managing.Server
|
|||||||
segment = args.Data;
|
segment = args.Data;
|
||||||
|
|
||||||
NetworkManager.StatisticsManager.NetworkTraffic.LocalServerReceivedData((ulong)segment.Count);
|
NetworkManager.StatisticsManager.NetworkTraffic.LocalServerReceivedData((ulong)segment.Count);
|
||||||
if (segment.Count <= TransportManager.TICK_BYTES)
|
if (segment.Count <= TransportManager.UNPACKED_TICK_LENGTH)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//FishNet internally splits packets so nothing should ever arrive over MTU.
|
//FishNet internally splits packets so nothing should ever arrive over MTU.
|
||||||
@ -633,17 +695,19 @@ namespace FishNet.Managing.Server
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeManager timeManager = NetworkManager.TimeManager;
|
||||||
|
|
||||||
bool hasIntermediateLayer = NetworkManager.TransportManager.HasIntermediateLayer;
|
bool hasIntermediateLayer = NetworkManager.TransportManager.HasIntermediateLayer;
|
||||||
PacketId packetId = PacketId.Unset;
|
PacketId packetId = PacketId.Unset;
|
||||||
PooledReader reader = null;
|
PooledReader reader = null;
|
||||||
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
|
#if !DEVELOPMENT
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
Reader.DataSource dataSource = Reader.DataSource.Client;
|
Reader.DataSource dataSource = Reader.DataSource.Client;
|
||||||
reader = ReaderPool.Retrieve(segment, NetworkManager, dataSource);
|
reader = ReaderPool.Retrieve(segment, NetworkManager, dataSource);
|
||||||
uint tick = reader.ReadTickUnpacked();
|
uint tick = reader.ReadTickUnpacked();
|
||||||
NetworkManager.TimeManager.LastPacketTick.Update(tick);
|
timeManager.LastPacketTick.Update(tick);
|
||||||
/* This is a special condition where a message may arrive split.
|
/* This is a special condition where a message may arrive split.
|
||||||
* When this occurs buffer each packet until all packets are
|
* When this occurs buffer each packet until all packets are
|
||||||
* received. */
|
* received. */
|
||||||
@ -654,8 +718,8 @@ namespace FishNet.Managing.Server
|
|||||||
|
|
||||||
int expectedMessages;
|
int expectedMessages;
|
||||||
_splitReader.GetHeader(reader, out expectedMessages);
|
_splitReader.GetHeader(reader, out expectedMessages);
|
||||||
//If here split message can be written.
|
//If here split message is to be read into splitReader.
|
||||||
_splitReader.Write(NetworkManager.TimeManager.LastPacketTick.LastRemoteTick, reader, expectedMessages);
|
_splitReader.Write(tick, reader, expectedMessages);
|
||||||
|
|
||||||
/* If fullMessage returns 0 count then the split
|
/* If fullMessage returns 0 count then the split
|
||||||
* has not written fully yet. Otherwise, if there is
|
* has not written fully yet. Otherwise, if there is
|
||||||
@ -681,7 +745,7 @@ namespace FishNet.Managing.Server
|
|||||||
while (reader.Remaining > 0)
|
while (reader.Remaining > 0)
|
||||||
{
|
{
|
||||||
packetId = reader.ReadPacketId();
|
packetId = reader.ReadPacketId();
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
_parseLogger.AddPacket(packetId);
|
_parseLogger.AddPacket(packetId);
|
||||||
#endif
|
#endif
|
||||||
NetworkConnection conn;
|
NetworkConnection conn;
|
||||||
@ -693,20 +757,20 @@ namespace FishNet.Managing.Server
|
|||||||
Kick(args.ConnectionId, KickReason.UnexpectedProblem, LoggingType.Error, $"ConnectionId {args.ConnectionId} not found within Clients. Connection will be kicked immediately.");
|
Kick(args.ConnectionId, KickReason.UnexpectedProblem, LoggingType.Error, $"ConnectionId {args.ConnectionId} not found within Clients. Connection will be kicked immediately.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
conn.TryUpdateLocalTick(tick);
|
conn.LocalTick.Update(timeManager, tick, EstimatedTick.OldTickOption.Discard);
|
||||||
conn.PacketTick.Update(NetworkManager.TimeManager, tick, Timing.EstimatedTick.OldTickOption.SetLastRemoteTick);
|
conn.PacketTick.Update(timeManager, tick, EstimatedTick.OldTickOption.SetLastRemoteTick);
|
||||||
/* If connection isn't authenticated and isn't a broadcast
|
/* If connection isn't authenticated and isn't a broadcast
|
||||||
* then disconnect client. If a broadcast then process
|
* then disconnect client. If a broadcast then process
|
||||||
* normally; client may still become disconnected if the broadcast
|
* normally; client may still become disconnected if the broadcast
|
||||||
* does not allow to be called while not authenticated. */
|
* does not allow to be called while not authenticated. */
|
||||||
if (!conn.IsAuthenticated && packetId != PacketId.Broadcast)
|
if (!conn.IsAuthenticated && packetId != PacketId.Version && packetId != PacketId.Broadcast)
|
||||||
{
|
{
|
||||||
conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a Broadcast without being authenticated. Connection will be kicked immediately.");
|
conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent packetId {packetId} without being authenticated. Connection will be kicked immediately.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only check if not developer build because users pay pause editor.
|
//Only check if not developer build because users pay pause editor.
|
||||||
#if !DEVELOPMENT_BUILD && !UNITY_EDITOR
|
#if !DEVELOPMENT
|
||||||
/* If hasn't sent LOD recently enough. LODs are sent every half a second, so
|
/* If hasn't sent LOD recently enough. LODs are sent every half a second, so
|
||||||
* by multiplaying interval by 60 this gives the client a 30 second window. */
|
* by multiplaying interval by 60 this gives the client a 30 second window. */
|
||||||
if (_cachedUseLod && conn.IsLateForLevelOfDetail(_cachedLevelOfDetailInterval * 60))
|
if (_cachedUseLod && conn.IsLateForLevelOfDetail(_cachedLevelOfDetailInterval * 60))
|
||||||
@ -725,7 +789,7 @@ namespace FishNet.Managing.Server
|
|||||||
}
|
}
|
||||||
else if (packetId == PacketId.ObjectSpawn)
|
else if (packetId == PacketId.ObjectSpawn)
|
||||||
{
|
{
|
||||||
if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning())
|
if (!GetAllowPredictedSpawning())
|
||||||
{
|
{
|
||||||
conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a predicted spawn while predicted spawning is not enabled. Connection will be kicked immediately.");
|
conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a predicted spawn while predicted spawning is not enabled. Connection will be kicked immediately.");
|
||||||
return;
|
return;
|
||||||
@ -734,7 +798,7 @@ namespace FishNet.Managing.Server
|
|||||||
}
|
}
|
||||||
else if (packetId == PacketId.ObjectDespawn)
|
else if (packetId == PacketId.ObjectDespawn)
|
||||||
{
|
{
|
||||||
if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning())
|
if (!GetAllowPredictedSpawning())
|
||||||
{
|
{
|
||||||
conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a predicted spawn while predicted spawning is not enabled. Connection will be kicked immediately.");
|
conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a predicted spawn while predicted spawning is not enabled. Connection will be kicked immediately.");
|
||||||
return;
|
return;
|
||||||
@ -753,9 +817,13 @@ namespace FishNet.Managing.Server
|
|||||||
{
|
{
|
||||||
ParsePingPong(reader, conn);
|
ParsePingPong(reader, conn);
|
||||||
}
|
}
|
||||||
|
else if (packetId == PacketId.Version)
|
||||||
|
{
|
||||||
|
ParseVersion(reader, conn, args.TransportIndex);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
NetworkManager.LogError($"Server received an unhandled PacketId of {(ushort)packetId} on channel {args.Channel} from connectionId {args.ConnectionId}. Remaining data has been purged.");
|
NetworkManager.LogError($"Server received an unhandled PacketId of {(ushort)packetId} on channel {args.Channel} from connectionId {args.ConnectionId}. Remaining data has been purged.");
|
||||||
_parseLogger.Print(NetworkManager);
|
_parseLogger.Print(NetworkManager);
|
||||||
#else
|
#else
|
||||||
@ -765,7 +833,7 @@ namespace FishNet.Managing.Server
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
|
#if !DEVELOPMENT
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -831,6 +899,9 @@ namespace FishNet.Managing.Server
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void BroadcastClientConnectionChange(bool connected, NetworkConnection conn)
|
private void BroadcastClientConnectionChange(bool connected, NetworkConnection conn)
|
||||||
{
|
{
|
||||||
|
//Only send if the connection was authenticated.
|
||||||
|
if (!conn.IsAuthenticated)
|
||||||
|
return;
|
||||||
//If sharing Ids then send all connected client Ids first if is a connected state.
|
//If sharing Ids then send all connected client Ids first if is a connected state.
|
||||||
if (ShareIds)
|
if (ShareIds)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -60,9 +60,11 @@ namespace FishNet.Managing.Timing.Editing
|
|||||||
//Physics.
|
//Physics.
|
||||||
EditorGUILayout.LabelField("Physics", EditorStyles.boldLabel);
|
EditorGUILayout.LabelField("Physics", EditorStyles.boldLabel);
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
|
if (_physicsMode.intValue == (int)FishNet.Managing.Timing.PhysicsMode.TimeManager)
|
||||||
|
EditorGUILayout.HelpBox($"Time.fixedDeltaTime will be overriden with TimeManager.TickDelta ({(1f / (float)_tickRate.intValue).ToString("0.###")})", MessageType.Info);
|
||||||
|
else
|
||||||
|
EditorGUILayout.HelpBox("If you are using physics interactions be sure to change the PhysicsMode to TimeManager and implement physics within the TimeManager tick events. NetworkTransform may also jitter when not using PhysicsMode.TimeManager.", MessageType.Warning);
|
||||||
EditorGUILayout.PropertyField(_physicsMode);
|
EditorGUILayout.PropertyField(_physicsMode);
|
||||||
if (_physicsMode.intValue != (int)FishNet.Managing.Timing.PhysicsMode.TimeManager)
|
|
||||||
EditorGUILayout.HelpBox("If you are using physics interactions be sure to change the PhysicsMode to TimeManager and implement physics within the TimeManager tick events.", MessageType.None);
|
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
|
||||||
////Prediction.
|
////Prediction.
|
||||||
|
|||||||
@ -1,12 +1,6 @@
|
|||||||
using FishNet.Connection;
|
using FishNet.Connection;
|
||||||
using FishNet.Documenting;
|
|
||||||
using FishNet.Managing.Transporting;
|
|
||||||
using FishNet.Object;
|
|
||||||
using FishNet.Serializing;
|
using FishNet.Serializing;
|
||||||
using FishNet.Serializing.Helping;
|
|
||||||
using FishNet.Transporting;
|
using FishNet.Transporting;
|
||||||
using FishNet.Utility;
|
|
||||||
using FishNet.Utility.Extension;
|
|
||||||
using GameKit.Dependencies.Utilities;
|
using GameKit.Dependencies.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@ -47,63 +41,6 @@ namespace FishNet.Managing.Timing
|
|||||||
BeforeTick = 0,
|
BeforeTick = 0,
|
||||||
AfterTick = 1,
|
AfterTick = 1,
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// Synchronizes tick timing between server and client.
|
|
||||||
/// </summary>
|
|
||||||
private class TimingSync
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Last server tick passed in.
|
|
||||||
/// </summary>
|
|
||||||
private uint _lastServerTick;
|
|
||||||
/// <summary>
|
|
||||||
/// Last local tick passed in.
|
|
||||||
/// </summary>
|
|
||||||
private uint _lastLocalTick;
|
|
||||||
/// <summary>
|
|
||||||
/// Last difference between server and client.
|
|
||||||
/// </summary>
|
|
||||||
private long? _lastServerClientDifference;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets differences between last server and local tick.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if values exist, false if unable to process.</returns>
|
|
||||||
public bool GetTickDifference(uint currentServerTick, uint currentLocalTick, out long tickDifference)
|
|
||||||
{
|
|
||||||
if (currentServerTick < _lastServerTick)
|
|
||||||
{
|
|
||||||
tickDifference = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint serverDifference = (currentServerTick - _lastServerTick);
|
|
||||||
uint localDifference = (currentLocalTick - _lastLocalTick);
|
|
||||||
|
|
||||||
long td = ((long)serverDifference - (long)localDifference);
|
|
||||||
//Average tick differences over 2 updates to help with unstable connections.
|
|
||||||
if (_lastServerClientDifference.HasValue)
|
|
||||||
{
|
|
||||||
long totalTd = (td + _lastServerClientDifference.Value);
|
|
||||||
tickDifference = (totalTd / (long)2);
|
|
||||||
}
|
|
||||||
//Last tick difference not set yet, use current values only.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tickDifference = td;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Also update last values.
|
|
||||||
_lastServerTick = currentServerTick;
|
|
||||||
_lastLocalTick = currentLocalTick;
|
|
||||||
_lastServerClientDifference = td;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public.
|
#region Public.
|
||||||
@ -210,14 +147,14 @@ namespace FishNet.Managing.Timing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Tooltip("While true clients may drop local ticks if their devices are unable to maintain the tick rate. This could result in a temporary desynchronization but will prevent the client falling further behind on ticks by repeatedly running the logic cycle multiple times per frame.")]
|
[Tooltip("While true clients may drop local ticks if their devices are unable to maintain the tick rate. This could result in a temporary desynchronization but will prevent the client falling further behind on ticks by repeatedly running the logic cycle multiple times per frame.")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool _allowTickDropping;
|
private bool _allowTickDropping = true;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of ticks which may occur in a single frame before remainder are dropped for the frame.
|
/// Maximum number of ticks which may occur in a single frame before remainder are dropped for the frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Tooltip("Maximum number of ticks which may occur in a single frame before remainder are dropped for the frame.")]
|
[Tooltip("Maximum number of ticks which may occur in a single frame before remainder are dropped for the frame.")]
|
||||||
[Range(1, 25)]
|
[Range(1, 25)]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private byte _maximumFrameTicks = 2;
|
private byte _maximumFrameTicks = 3;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -308,9 +245,24 @@ namespace FishNet.Managing.Timing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _fixedUpdateTimeStep;
|
private bool _fixedUpdateTimeStep;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Synchronizes tick deltas between server and client.
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private TimingSync _timing = new TimingSync();
|
private float _physicsTimeScale = 1f;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current physics time scale.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public float GetPhysicsTimeScale() => _physicsTimeScale;
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the physics time scale.
|
||||||
|
/// This is not automatically synchronized.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">New value.</param>
|
||||||
|
public void SetPhysicsTimeScale(float value)
|
||||||
|
{
|
||||||
|
value = Mathf.Clamp(value, 0f, float.PositiveInfinity);
|
||||||
|
_physicsTimeScale = value;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Const.
|
#region Const.
|
||||||
@ -538,8 +490,8 @@ namespace FishNet.Managing.Timing
|
|||||||
//Preserve user tick rate.
|
//Preserve user tick rate.
|
||||||
PlayerPrefs.SetFloat(SAVED_FIXED_TIME_TEXT, Time.fixedDeltaTime);
|
PlayerPrefs.SetFloat(SAVED_FIXED_TIME_TEXT, Time.fixedDeltaTime);
|
||||||
//Let the player know.
|
//Let the player know.
|
||||||
if (Time.fixedDeltaTime != (float)TickDelta)
|
//if (Time.fixedDeltaTime != (float)TickDelta)
|
||||||
Debug.LogWarning("Time.fixedDeltaTime is being overriden with TimeManager.TickDelta");
|
// Debug.LogWarning("Time.fixedDeltaTime is being overriden with TimeManager.TickDelta");
|
||||||
#endif
|
#endif
|
||||||
Time.fixedDeltaTime = (float)TickDelta;
|
Time.fixedDeltaTime = (float)TickDelta;
|
||||||
/* Only check this if network manager
|
/* Only check this if network manager
|
||||||
@ -668,8 +620,7 @@ namespace FishNet.Managing.Timing
|
|||||||
bool isClient = NetworkManager.IsClientStarted;
|
bool isClient = NetworkManager.IsClientStarted;
|
||||||
bool isServer = NetworkManager.IsServerStarted;
|
bool isServer = NetworkManager.IsServerStarted;
|
||||||
|
|
||||||
double tickDelta = TickDelta;
|
double timePerSimulation = (isServer) ? TickDelta : _adjustedTickDelta;
|
||||||
double timePerSimulation = (isServer) ? tickDelta : _adjustedTickDelta;
|
|
||||||
if (timePerSimulation == 0d)
|
if (timePerSimulation == 0d)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Simulation delta cannot be 0. Network timing will not continue.");
|
Debug.LogWarning($"Simulation delta cannot be 0. Network timing will not continue.");
|
||||||
@ -692,7 +643,7 @@ namespace FishNet.Managing.Timing
|
|||||||
if (ticksCount > 1)
|
if (ticksCount > 1)
|
||||||
_lastMultipleTicksTime = Time.unscaledDeltaTime;
|
_lastMultipleTicksTime = Time.unscaledDeltaTime;
|
||||||
|
|
||||||
if (_allowTickDropping && !NetworkManager.IsServerStarted)
|
if (_allowTickDropping)
|
||||||
{
|
{
|
||||||
//If ticks require dropping. Set exactly to maximum ticks.
|
//If ticks require dropping. Set exactly to maximum ticks.
|
||||||
if (ticksCount > _maximumFrameTicks)
|
if (ticksCount > _maximumFrameTicks)
|
||||||
@ -701,6 +652,7 @@ namespace FishNet.Managing.Timing
|
|||||||
|
|
||||||
bool variableTiming = (_timingType == TimingType.Variable);
|
bool variableTiming = (_timingType == TimingType.Variable);
|
||||||
bool frameTicked = FrameTicked;
|
bool frameTicked = FrameTicked;
|
||||||
|
float tickDelta = ((float)TickDelta * GetPhysicsTimeScale());
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -727,11 +679,10 @@ namespace FishNet.Managing.Timing
|
|||||||
|
|
||||||
if (PhysicsMode == PhysicsMode.TimeManager)
|
if (PhysicsMode == PhysicsMode.TimeManager)
|
||||||
{
|
{
|
||||||
float tick = (float)TickDelta;
|
OnPrePhysicsSimulation?.Invoke(tickDelta);
|
||||||
OnPrePhysicsSimulation?.Invoke(tick);
|
Physics.Simulate(tickDelta);
|
||||||
Physics.Simulate(tick);
|
Physics2D.Simulate(tickDelta);
|
||||||
Physics2D.Simulate(tick);
|
OnPostPhysicsSimulation?.Invoke(tickDelta);
|
||||||
OnPostPhysicsSimulation?.Invoke(tick);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPostTick?.Invoke();
|
OnPostTick?.Invoke();
|
||||||
@ -1097,12 +1048,16 @@ namespace FishNet.Managing.Timing
|
|||||||
{
|
{
|
||||||
//Now send using a packetId.
|
//Now send using a packetId.
|
||||||
PooledWriter writer = WriterPool.Retrieve();
|
PooledWriter writer = WriterPool.Retrieve();
|
||||||
writer.WritePacketId(PacketId.TimingUpdate);
|
|
||||||
foreach (NetworkConnection item in NetworkManager.ServerManager.Clients.Values)
|
foreach (NetworkConnection item in NetworkManager.ServerManager.Clients.Values)
|
||||||
{
|
{
|
||||||
if (!item.IsAuthenticated)
|
if (!item.IsAuthenticated)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
writer.WritePacketId(PacketId.TimingUpdate);
|
||||||
|
writer.WriteTickUnpacked(item.PacketTick.Value());
|
||||||
item.SendToClient((byte)Channel.Unreliable, writer.GetArraySegment());
|
item.SendToClient((byte)Channel.Unreliable, writer.GetArraySegment());
|
||||||
|
writer.Reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.Store();
|
writer.Store();
|
||||||
@ -1113,12 +1068,17 @@ namespace FishNet.Managing.Timing
|
|||||||
/// Called on client when server sends a timing update.
|
/// Called on client when server sends a timing update.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ta"></param>
|
/// <param name="ta"></param>
|
||||||
internal void ParseTimingUpdate()
|
internal void ParseTimingUpdate(Reader reader)
|
||||||
{
|
{
|
||||||
|
uint clientTick = reader.ReadTickUnpacked();
|
||||||
//Don't adjust timing on server.
|
//Don't adjust timing on server.
|
||||||
if (NetworkManager.IsServerStarted)
|
if (NetworkManager.IsServerStarted)
|
||||||
return;
|
return;
|
||||||
|
/* This should never be possible since the server is sending a tick back
|
||||||
|
* that the client previously sent. In other words, the value returned should
|
||||||
|
* always be in the past. */
|
||||||
|
if (LocalTick < clientTick)
|
||||||
|
return;
|
||||||
/* Use the last ordered remote tick rather than
|
/* Use the last ordered remote tick rather than
|
||||||
* lastPacketTick. This will help with out of order
|
* lastPacketTick. This will help with out of order
|
||||||
* packets where the timing update sent before
|
* packets where the timing update sent before
|
||||||
@ -1127,43 +1087,27 @@ namespace FishNet.Managing.Timing
|
|||||||
* ticks really passed rather than the difference
|
* ticks really passed rather than the difference
|
||||||
* between the out of order/late packet. */
|
* between the out of order/late packet. */
|
||||||
uint lastPacketTick = LastPacketTick.RemoteTick;
|
uint lastPacketTick = LastPacketTick.RemoteTick;
|
||||||
//If difference could not be updated then something went wrong. Most likely an old timing update.
|
//Set Tick based on difference between localTick and clientTick, added onto lastPacketTick.
|
||||||
if (!_timing.GetTickDifference(lastPacketTick, LocalTick, out long tickDifference))
|
uint prevTick = Tick;
|
||||||
return;
|
uint nextTick = (LocalTick - clientTick) + lastPacketTick;
|
||||||
|
long difference = ((long)nextTick - (long)prevTick);
|
||||||
|
Tick = nextTick;
|
||||||
|
|
||||||
//Maximum difference allowed before resetting values.
|
//Maximum difference allowed before resetting values.
|
||||||
const int maximumDifference = 4;
|
const int maximumDifference = 4;
|
||||||
|
|
||||||
TryRecalculateTick();
|
|
||||||
|
|
||||||
////Do not change timing if client is slowing down due to latency issues.
|
|
||||||
//if (Time.unscaledTime - NetworkManager.PredictionManager.SlowDownTime > 3f)
|
|
||||||
//{
|
|
||||||
//Pefect!
|
|
||||||
if (tickDifference == 0) { }
|
|
||||||
//Difference is extreme, reset to default timings. Client probably had an issue.
|
//Difference is extreme, reset to default timings. Client probably had an issue.
|
||||||
else if (Mathf.Abs(tickDifference) > maximumDifference)
|
if (Mathf.Abs(difference) > maximumDifference)
|
||||||
{
|
{
|
||||||
_adjustedTickDelta = TickDelta;
|
_adjustedTickDelta = TickDelta;
|
||||||
}
|
}
|
||||||
//Otherwise adjust the delta marginally.
|
//Otherwise adjust the delta marginally.
|
||||||
else
|
else if (difference != 0)
|
||||||
{
|
{
|
||||||
/* A negative tickDifference indicates the client is
|
/* A negative tickDifference indicates the client is
|
||||||
* moving too fast, while positive indicates too slow. */
|
* moving too fast, while positive indicates too slow. */
|
||||||
bool speedUp = (tickDifference > 0);
|
bool speedUp = (difference > 0);
|
||||||
ChangeAdjustedTickDelta(speedUp);
|
ChangeAdjustedTickDelta(speedUp);
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
//Recalculates Tick value if it exceeds maximum difference.
|
|
||||||
void TryRecalculateTick()
|
|
||||||
{
|
|
||||||
uint rttTicks = TimeToTicks((RoundTripTime / 2) / 1000f);
|
|
||||||
uint newValue = lastPacketTick + rttTicks;
|
|
||||||
long difference = (long)Mathf.Abs((long)Tick - (long)newValue);
|
|
||||||
if (difference > maximumDifference)
|
|
||||||
Tick = newValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
using FishNet.Connection;
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
using FishNet.Connection;
|
||||||
using FishNet.Managing.Timing;
|
using FishNet.Managing.Timing;
|
||||||
using FishNet.Object;
|
using FishNet.Object;
|
||||||
using FishNet.Serializing;
|
using FishNet.Serializing;
|
||||||
@ -128,27 +131,31 @@ namespace FishNet.Managing.Transporting
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes sent for PacketId.
|
/// Number of bytes sent for PacketId.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const byte PACKET_ID_BYTES = 2;
|
public const byte PACKETID_LENGTH = 2;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes sent for ObjectId.
|
/// Number of bytes sent for ObjectId.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const byte OBJECT_ID_BYTES = 2;
|
public const byte OBJECT_ID_LENGTH = 2;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes sent for ComponentIndex.
|
/// Number of bytes sent for ComponentIndex.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const byte COMPONENT_INDEX_BYTES = 1;
|
public const byte COMPONENT_INDEX_LENGTH = 1;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes sent for Tick.
|
/// Number of bytes sent for Tick.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const byte TICK_BYTES = 4;
|
public const byte UNPACKED_TICK_LENGTH = 4;
|
||||||
|
/// <summary>
|
||||||
|
/// Number of bytes sent for an unpacked size, such as a collection or array size.
|
||||||
|
/// </summary>
|
||||||
|
public const byte UNPACKED_SIZE_LENGTH = 4;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes sent to indicate split count.
|
/// Number of bytes sent to indicate split count.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const byte SPLIT_COUNT_BYTES = 4;
|
private const byte SPLIT_COUNT_LENGTH = 4;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes required for split data.
|
/// Number of bytes required for split data.
|
||||||
/// </summary> //todo: This shouldn't have to include TickBytes but there is a parse error if it's not included. Figure out why.
|
/// </summary> //todo: This shouldn't have to include TickBytes but there is a parse error if it's not included. Figure out why.
|
||||||
public const byte SPLIT_INDICATOR_SIZE = (TICK_BYTES + PACKET_ID_BYTES + SPLIT_COUNT_BYTES);
|
public const byte SPLIT_INDICATOR_LENGTH = (UNPACKED_TICK_LENGTH + PACKETID_LENGTH + SPLIT_COUNT_LENGTH);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of channels supported.
|
/// Number of channels supported.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -176,7 +183,7 @@ namespace FishNet.Managing.Transporting
|
|||||||
InitializeToServerBundles();
|
InitializeToServerBundles();
|
||||||
if (_intermediateLayer != null)
|
if (_intermediateLayer != null)
|
||||||
_intermediateLayer.InitializeOnce(this);
|
_intermediateLayer.InitializeOnce(this);
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
_latencySimulator.Initialize(manager, Transport);
|
_latencySimulator.Initialize(manager, Transport);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -621,7 +628,7 @@ namespace FishNet.Managing.Transporting
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private int GetRequiredMessageCount(byte channelId, int segmentSize, out int maxMessageSize)
|
private int GetRequiredMessageCount(byte channelId, int segmentSize, out int maxMessageSize)
|
||||||
{
|
{
|
||||||
maxMessageSize = GetLowestMTU(channelId) - SPLIT_INDICATOR_SIZE;
|
maxMessageSize = GetLowestMTU(channelId) - SPLIT_INDICATOR_LENGTH;
|
||||||
return Mathf.CeilToInt((float)segmentSize / maxMessageSize);
|
return Mathf.CeilToInt((float)segmentSize / maxMessageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +725,7 @@ namespace FishNet.Managing.Transporting
|
|||||||
OnIterateOutgoingStart?.Invoke();
|
OnIterateOutgoingStart?.Invoke();
|
||||||
int channelCount = CHANNEL_COUNT;
|
int channelCount = CHANNEL_COUNT;
|
||||||
ulong sentBytes = 0;
|
ulong sentBytes = 0;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
bool latencySimulatorEnabled = LatencySimulator.CanSimulate;
|
bool latencySimulatorEnabled = LatencySimulator.CanSimulate;
|
||||||
#endif
|
#endif
|
||||||
/* If sending to the client. */
|
/* If sending to the client. */
|
||||||
@ -756,7 +763,7 @@ namespace FishNet.Managing.Transporting
|
|||||||
ArraySegment<byte> segment = new ArraySegment<byte>(bb.Data, 0, bb.Length);
|
ArraySegment<byte> segment = new ArraySegment<byte>(bb.Data, 0, bb.Length);
|
||||||
if (HasIntermediateLayer)
|
if (HasIntermediateLayer)
|
||||||
segment = ProcessIntermediateOutgoing(segment, false);
|
segment = ProcessIntermediateOutgoing(segment, false);
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (latencySimulatorEnabled)
|
if (latencySimulatorEnabled)
|
||||||
_latencySimulator.AddOutgoing(channel, segment, false, conn.ClientId);
|
_latencySimulator.AddOutgoing(channel, segment, false, conn.ClientId);
|
||||||
else
|
else
|
||||||
@ -829,7 +836,7 @@ namespace FishNet.Managing.Transporting
|
|||||||
ArraySegment<byte> segment = new ArraySegment<byte>(bb.Data, 0, bb.Length);
|
ArraySegment<byte> segment = new ArraySegment<byte>(bb.Data, 0, bb.Length);
|
||||||
if (HasIntermediateLayer)
|
if (HasIntermediateLayer)
|
||||||
segment = ProcessIntermediateOutgoing(segment, true);
|
segment = ProcessIntermediateOutgoing(segment, true);
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (latencySimulatorEnabled)
|
if (latencySimulatorEnabled)
|
||||||
_latencySimulator.AddOutgoing(channel, segment);
|
_latencySimulator.AddOutgoing(channel, segment);
|
||||||
else
|
else
|
||||||
@ -847,7 +854,7 @@ namespace FishNet.Managing.Transporting
|
|||||||
_networkManager.StatisticsManager.NetworkTraffic.LocalClientSentData(sentBytes);
|
_networkManager.StatisticsManager.NetworkTraffic.LocalClientSentData(sentBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (latencySimulatorEnabled)
|
if (latencySimulatorEnabled)
|
||||||
_latencySimulator.IterateOutgoing(toServer);
|
_latencySimulator.IterateOutgoing(toServer);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,35 +1 @@
|
|||||||
using FishNet.Documenting;
|
//Remove on V5
|
||||||
|
|
||||||
namespace FishNet.Object
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Properties which have changed on a transform.
|
|
||||||
/// </summary>
|
|
||||||
[System.Flags]
|
|
||||||
[APIExclude]
|
|
||||||
internal enum ChangedTransformProperties : byte
|
|
||||||
{
|
|
||||||
Unset = 0,
|
|
||||||
LocalPosition = 1,
|
|
||||||
LocalRotation = 2,
|
|
||||||
LocalScale = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
[APIExclude]
|
|
||||||
internal static partial class ChangedTransformPropertiesEnum
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Returns if whole contains part.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="whole"></param>
|
|
||||||
/// <param name="part"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static bool Contains(ChangedTransformProperties whole, ChangedTransformProperties part)
|
|
||||||
{
|
|
||||||
return (whole & part) == part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
#if !PREDICTION_1
|
#if !PREDICTION_1
|
||||||
|
using FishNet.Object.Prediction;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -21,7 +22,13 @@ namespace FishNet.Object.Editing
|
|||||||
private SerializedProperty _networkTransform;
|
private SerializedProperty _networkTransform;
|
||||||
private SerializedProperty _predictionType;
|
private SerializedProperty _predictionType;
|
||||||
private SerializedProperty _graphicalObject;
|
private SerializedProperty _graphicalObject;
|
||||||
|
private SerializedProperty _detachGraphicalObject;
|
||||||
|
|
||||||
|
private SerializedProperty _ownerSmoothedProperties;
|
||||||
|
private SerializedProperty _spectatorSmoothedProperties;
|
||||||
private SerializedProperty _ownerInterpolation;
|
private SerializedProperty _ownerInterpolation;
|
||||||
|
private SerializedProperty _adaptiveInterpolation;
|
||||||
|
private SerializedProperty _spectatorInterpolation;
|
||||||
private SerializedProperty _enableTeleport;
|
private SerializedProperty _enableTeleport;
|
||||||
private SerializedProperty _teleportThreshold;
|
private SerializedProperty _teleportThreshold;
|
||||||
|
|
||||||
@ -40,11 +47,15 @@ namespace FishNet.Object.Editing
|
|||||||
_networkTransform = serializedObject.FindProperty(nameof(_networkTransform));
|
_networkTransform = serializedObject.FindProperty(nameof(_networkTransform));
|
||||||
_predictionType = serializedObject.FindProperty(nameof(_predictionType));
|
_predictionType = serializedObject.FindProperty(nameof(_predictionType));
|
||||||
_graphicalObject = serializedObject.FindProperty(nameof(_graphicalObject));
|
_graphicalObject = serializedObject.FindProperty(nameof(_graphicalObject));
|
||||||
|
_detachGraphicalObject = serializedObject.FindProperty(nameof(_detachGraphicalObject));
|
||||||
|
|
||||||
|
_ownerSmoothedProperties = serializedObject.FindProperty(nameof(_ownerSmoothedProperties));
|
||||||
|
_ownerInterpolation = serializedObject.FindProperty(nameof(_ownerInterpolation));
|
||||||
|
_adaptiveInterpolation = serializedObject.FindProperty(nameof(_adaptiveInterpolation));
|
||||||
|
_spectatorSmoothedProperties = serializedObject.FindProperty(nameof(_spectatorSmoothedProperties));
|
||||||
|
_spectatorInterpolation = serializedObject.FindProperty(nameof(_spectatorInterpolation));
|
||||||
_enableTeleport = serializedObject.FindProperty(nameof(_enableTeleport));
|
_enableTeleport = serializedObject.FindProperty(nameof(_enableTeleport));
|
||||||
_teleportThreshold = serializedObject.FindProperty(nameof(_teleportThreshold));
|
_teleportThreshold = serializedObject.FindProperty(nameof(_teleportThreshold));
|
||||||
|
|
||||||
|
|
||||||
_ownerInterpolation = serializedObject.FindProperty(nameof(_ownerInterpolation));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
public override void OnInspectorGUI()
|
||||||
@ -80,9 +91,23 @@ namespace FishNet.Object.Editing
|
|||||||
EditorGUILayout.PropertyField(_networkTransform);
|
EditorGUILayout.PropertyField(_networkTransform);
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool graphicalSet = (_graphicalObject.objectReferenceValue != null);
|
||||||
EditorGUILayout.PropertyField(_graphicalObject);
|
EditorGUILayout.PropertyField(_graphicalObject);
|
||||||
|
if (graphicalSet)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_detachGraphicalObject);
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
EditorGUILayout.LabelField("Smoothing", EditorStyles.boldLabel);
|
||||||
|
if (!graphicalSet)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox($"More smoothing settings will be displayed when a graphicalObject is set.", MessageType.Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
EditorGUI.indentLevel++;
|
EditorGUI.indentLevel++;
|
||||||
EditorGUILayout.PropertyField(_ownerInterpolation, new GUIContent("Interpolation"));
|
|
||||||
EditorGUILayout.PropertyField(_enableTeleport);
|
EditorGUILayout.PropertyField(_enableTeleport);
|
||||||
if (_enableTeleport.boolValue == true)
|
if (_enableTeleport.boolValue == true)
|
||||||
{
|
{
|
||||||
@ -91,7 +116,25 @@ namespace FishNet.Object.Editing
|
|||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Owner", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_ownerInterpolation, new GUIContent("Interpolation"));
|
||||||
|
EditorGUILayout.PropertyField(_ownerSmoothedProperties, new GUIContent("Smoothed Properties"));
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField("Spectator", EditorStyles.boldLabel);
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_adaptiveInterpolation);
|
||||||
|
if (_adaptiveInterpolation.intValue == (int)AdaptiveInterpolationType.Off)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
EditorGUILayout.PropertyField(_spectatorInterpolation, new GUIContent("Interpolation"));
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
EditorGUILayout.PropertyField(_spectatorSmoothedProperties, new GUIContent("Smoothed Properties"));
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
}
|
}
|
||||||
EditorGUI.indentLevel--;
|
EditorGUI.indentLevel--;
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
#if !PREDICTION_1
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
#if !PREDICTION_1
|
||||||
using FishNet.CodeGenerating;
|
using FishNet.CodeGenerating;
|
||||||
using FishNet.Connection;
|
using FishNet.Connection;
|
||||||
using FishNet.Documenting;
|
using FishNet.Documenting;
|
||||||
@ -324,7 +327,7 @@ namespace FishNet.Object
|
|||||||
methodWriter.Write(reconcileData);
|
methodWriter.Write(reconcileData);
|
||||||
|
|
||||||
PooledWriter writer;
|
PooledWriter writer;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (NetworkManager.DebugManager.ReconcileRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (NetworkManager.DebugManager.ReconcileRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
#else
|
#else
|
||||||
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
@ -438,26 +441,37 @@ namespace FishNet.Object
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected internal void Replicate_Replay_NonAuthoritative<T>(uint replayTick, ReplicateUserLogicDelegate<T> del, List<T> replicatesHistory, Channel channel) where T : IReplicateData
|
protected internal void Replicate_Replay_NonAuthoritative<T>(uint replayTick, ReplicateUserLogicDelegate<T> del, List<T> replicatesHistory, Channel channel) where T : IReplicateData
|
||||||
{
|
{
|
||||||
ReplicateTickFinder.DataPlacementResult findResult;
|
|
||||||
int replicateIndex = ReplicateTickFinder.GetReplicateHistoryIndex<T>(replayTick, replicatesHistory, out findResult);
|
|
||||||
|
|
||||||
T data;
|
T data;
|
||||||
ReplicateState state;
|
ReplicateState state;
|
||||||
//If found then the replicate has been received by the server.
|
//If the first replay.
|
||||||
|
if (replayTick == (_networkObjectCache.PredictionManager.ServerStateTick + 1))
|
||||||
|
{
|
||||||
|
ReplicateTickFinder.DataPlacementResult findResult;
|
||||||
|
int replicateIndex = ReplicateTickFinder.GetReplicateHistoryIndex<T>(replayTick, replicatesHistory, out findResult);
|
||||||
|
//If not found then something went wrong.
|
||||||
if (findResult == ReplicateTickFinder.DataPlacementResult.Exact)
|
if (findResult == ReplicateTickFinder.DataPlacementResult.Exact)
|
||||||
{
|
{
|
||||||
data = replicatesHistory[replicateIndex];
|
data = replicatesHistory[replicateIndex];
|
||||||
state = ReplicateState.ReplayedCreated;
|
state = ReplicateState.ReplayedCreated;
|
||||||
}
|
}
|
||||||
//If not not found then it's being run as predicted.
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
SetDataToDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Not the first replay tick.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetDataToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetDataToDefault()
|
||||||
{
|
{
|
||||||
data = default;
|
data = default;
|
||||||
data.SetTick(replayTick);
|
data.SetTick(replayTick);
|
||||||
if (replicatesHistory.Count == 0 || replicatesHistory[^1].GetTick() < replayTick)
|
|
||||||
state = ReplicateState.ReplayedFuture;
|
state = ReplicateState.ReplayedFuture;
|
||||||
else
|
|
||||||
state = ReplicateState.ReplayedCreated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
del.Invoke(data, state, channel);
|
del.Invoke(data, state, channel);
|
||||||
@ -581,36 +595,19 @@ namespace FishNet.Object
|
|||||||
PredictionManager pm = NetworkManager.PredictionManager;
|
PredictionManager pm = NetworkManager.PredictionManager;
|
||||||
uint localTick = TimeManager.LocalTick;
|
uint localTick = TimeManager.LocalTick;
|
||||||
|
|
||||||
data.SetTick(localTick);
|
/* The following code is to remove replicates from replicatesHistory
|
||||||
replicatesHistory.Add(data);
|
* which exceed the buffer allowance. Replicates are kept for up to
|
||||||
//Check to reset resends.
|
* x seconds to clients can re-run them during a reconcile. The reconcile
|
||||||
bool isDefault = isDefaultDel.Invoke(data);
|
* method removes old histories but given the server does not reconcile,
|
||||||
bool mayChange = false;// PredictedTransformMayChange();
|
* it will never perform that operation.
|
||||||
bool resetResends = (mayChange || !isDefault);
|
* The server would not actually need to keep replicates history except
|
||||||
/* If remaining resends is more than 0 then that means
|
* when it is also client(clientHost). This is because the clientHost must
|
||||||
* redundancy is still in effect. When redundancy is not
|
* send redundancies to other clients still, therefor that redundancyCount
|
||||||
* in effect then histories to send can be 1 for this iteration. */
|
* must be the allowance when clientHost. */
|
||||||
int pastInputs = (_remainingResends > 0) ? PredictionManager.RedundancyCount : 1;
|
if (IsHostStarted)
|
||||||
//pastInputs = PredictionManager.RedundancyCount;
|
|
||||||
if (resetResends)
|
|
||||||
_remainingResends = pm.RedundancyCount;
|
|
||||||
|
|
||||||
bool sendData = (_remainingResends > 0);
|
|
||||||
if (sendData)
|
|
||||||
{
|
{
|
||||||
int replicatesHistoryCount = replicatesHistory.Count;
|
int replicatesHistoryCount = replicatesHistory.Count;
|
||||||
/* Remove the number of replicates which are over maximum.
|
int maxCount = pm.RedundancyCount;
|
||||||
*
|
|
||||||
* The clientHost object must keep redundancy count
|
|
||||||
* to send past inputs to others.
|
|
||||||
*
|
|
||||||
* Otherwise use maximum client replicates which will be a variable
|
|
||||||
* rate depending on tick rate. The value returned is several seconds
|
|
||||||
* worth of owner inputs to be able to replay during a reconcile.
|
|
||||||
*
|
|
||||||
* Server does not reconcile os it only needs enough for redundancy.
|
|
||||||
*/
|
|
||||||
int maxCount = (IsServerStarted) ? pm.RedundancyCount : pm.MaximumClientReplicates;
|
|
||||||
//Number to remove which is over max count.
|
//Number to remove which is over max count.
|
||||||
int removeCount = (replicatesHistoryCount - maxCount);
|
int removeCount = (replicatesHistoryCount - maxCount);
|
||||||
//If there are any to remove.
|
//If there are any to remove.
|
||||||
@ -623,11 +620,26 @@ namespace FishNet.Object
|
|||||||
//Then remove range.
|
//Then remove range.
|
||||||
replicatesHistory.RemoveRange(0, removeCount);
|
replicatesHistory.RemoveRange(0, removeCount);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.SetTick(localTick);
|
||||||
|
replicatesHistory.Add(data);
|
||||||
|
//Check to reset resends.
|
||||||
|
bool isDefault = isDefaultDel.Invoke(data);
|
||||||
|
bool mayChange = false;// PredictedTransformMayChange();
|
||||||
|
bool resetResends = (mayChange || !isDefault);
|
||||||
|
|
||||||
|
byte redundancyCount = PredictionManager.RedundancyCount;
|
||||||
|
if (resetResends)
|
||||||
|
_remainingResends = redundancyCount;
|
||||||
|
|
||||||
|
bool sendData = (_remainingResends > 0);
|
||||||
|
if (sendData)
|
||||||
|
{
|
||||||
/* If not server then send to server.
|
/* If not server then send to server.
|
||||||
* If server then send to clients. */
|
* If server then send to clients. */
|
||||||
bool toServer = !IsServerStarted;
|
bool toServer = !IsServerStarted;
|
||||||
Replicate_SendAuthoritative(toServer, methodHash, pastInputs, replicatesHistory, localTick, channel);
|
Replicate_SendAuthoritative(toServer, methodHash, redundancyCount, replicatesHistory, localTick, channel);
|
||||||
_remainingResends--;
|
_remainingResends--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,7 +647,6 @@ namespace FishNet.Object
|
|||||||
_networkObjectCache.SetReplicateTick(data.GetTick(), true);
|
_networkObjectCache.SetReplicateTick(data.GetTick(), true);
|
||||||
//Owner always replicates with new data.
|
//Owner always replicates with new data.
|
||||||
del.Invoke(data, ReplicateState.CurrentCreated, channel);
|
del.Invoke(data, ReplicateState.CurrentCreated, channel);
|
||||||
//TODO: dispose replicate datas from history on replays.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -771,7 +782,6 @@ namespace FishNet.Object
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends data from a reader which only contains the replicate packet.
|
/// Sends data from a reader which only contains the replicate packet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tick">Tick of the last replicate entry.</param>
|
|
||||||
[MakePublic]
|
[MakePublic]
|
||||||
internal void Replicate_SendNonAuthoritative<T>(uint hash, BasicQueue<T> replicatesQueue, Channel channel) where T : IReplicateData
|
internal void Replicate_SendNonAuthoritative<T>(uint hash, BasicQueue<T> replicatesQueue, Channel channel) where T : IReplicateData
|
||||||
{
|
{
|
||||||
@ -781,12 +791,11 @@ namespace FishNet.Object
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
int queueCount = replicatesQueue.Count;
|
int queueCount = replicatesQueue.Count;
|
||||||
//Limit history count to max of queued amount, or queued inputs, whichever is lesser.
|
|
||||||
int historyCount = (int)Mathf.Min(_networkObjectCache.PredictionManager.RedundancyCount, queueCount);
|
|
||||||
//None to send.
|
//None to send.
|
||||||
if (historyCount == 0)
|
if (queueCount == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
int redundancyCount = (int)Mathf.Min(_networkObjectCache.PredictionManager.RedundancyCount, queueCount);
|
||||||
//If the only observer is the owner then there is no need to write.
|
//If the only observer is the owner then there is no need to write.
|
||||||
int observersCount = Observers.Count;
|
int observersCount = Observers.Count;
|
||||||
//Quick exit for no observers other than owner.
|
//Quick exit for no observers other than owner.
|
||||||
@ -810,7 +819,7 @@ namespace FishNet.Object
|
|||||||
//Write the run tick now.
|
//Write the run tick now.
|
||||||
methodWriter.WriteTickUnpacked(runTickOflastEntry);
|
methodWriter.WriteTickUnpacked(runTickOflastEntry);
|
||||||
//Write the replicates.
|
//Write the replicates.
|
||||||
methodWriter.WriteReplicate<T>(replicatesQueue, historyCount, runTickOflastEntry);
|
methodWriter.WriteReplicate<T>(replicatesQueue, redundancyCount, runTickOflastEntry);
|
||||||
|
|
||||||
PooledWriter writer = CreateRpc(hash, methodWriter, PacketId.Replicate, channel);
|
PooledWriter writer = CreateRpc(hash, methodWriter, PacketId.Replicate, channel);
|
||||||
|
|
||||||
@ -837,7 +846,7 @@ namespace FishNet.Object
|
|||||||
* handled on unowned objects. */
|
* handled on unowned objects. */
|
||||||
PredictionManager pm = PredictionManager;
|
PredictionManager pm = PredictionManager;
|
||||||
//Maximum number of replicates allowed to be queued at once.
|
//Maximum number of replicates allowed to be queued at once.
|
||||||
int maximmumReplicates = (IsServerStarted) ? pm.GetMaximumServerReplicates() : pm.MaximumClientReplicates;
|
int maximmumReplicates = (IsServerStarted) ? pm.GetMaximumServerReplicates() : pm.MaximumPastReplicates;
|
||||||
for (int i = 0; i < receivedReplicatesCount; i++)
|
for (int i = 0; i < receivedReplicatesCount; i++)
|
||||||
{
|
{
|
||||||
T entry = arrBuffer[i];
|
T entry = arrBuffer[i];
|
||||||
@ -917,7 +926,8 @@ namespace FishNet.Object
|
|||||||
* by holding reconcile x ticks rather than not running received
|
* by holding reconcile x ticks rather than not running received
|
||||||
* x ticks. */
|
* x ticks. */
|
||||||
if (_networkObjectCache.IsServerInitialized && startQueueCount == 0 && replicatesQueue.Count > 0)
|
if (_networkObjectCache.IsServerInitialized && startQueueCount == 0 && replicatesQueue.Count > 0)
|
||||||
_replicateStartTick = (_networkObjectCache.TimeManager.LocalTick + pm.QueuedInputs);
|
//_replicateStartTick = (_networkObjectCache.TimeManager.LocalTick);
|
||||||
|
_replicateStartTick = (_networkObjectCache.TimeManager.LocalTick + pm.StateInterpolation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1336,7 +1346,7 @@ namespace FishNet.Object
|
|||||||
methodWriter.Write(reconcileData);
|
methodWriter.Write(reconcileData);
|
||||||
|
|
||||||
PooledWriter writer;
|
PooledWriter writer;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (NetworkManager.DebugManager.ReconcileRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (NetworkManager.DebugManager.ReconcileRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
#else
|
#else
|
||||||
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
using FishNet.CodeGenerating;
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||||
|
#define DEVELOPMENT
|
||||||
|
#endif
|
||||||
|
using FishNet.CodeGenerating;
|
||||||
using FishNet.Connection;
|
using FishNet.Connection;
|
||||||
using FishNet.Documenting;
|
using FishNet.Documenting;
|
||||||
using FishNet.Managing;
|
using FishNet.Managing;
|
||||||
@ -249,7 +252,7 @@ namespace FishNet.Object
|
|||||||
_transportManagerCache.CheckSetReliableChannel(methodWriter.Length + MAXIMUM_RPC_HEADER_SIZE, ref channel);
|
_transportManagerCache.CheckSetReliableChannel(methodWriter.Length + MAXIMUM_RPC_HEADER_SIZE, ref channel);
|
||||||
|
|
||||||
PooledWriter writer;
|
PooledWriter writer;
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (NetworkManager.DebugManager.ObserverRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (NetworkManager.DebugManager.ObserverRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
#else
|
#else
|
||||||
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
@ -314,7 +317,7 @@ namespace FishNet.Object
|
|||||||
|
|
||||||
PooledWriter writer;
|
PooledWriter writer;
|
||||||
|
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
#if DEVELOPMENT
|
||||||
if (NetworkManager.DebugManager.TargetRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (NetworkManager.DebugManager.TargetRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
#else
|
#else
|
||||||
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link))
|
||||||
|
|||||||
@ -6,11 +6,22 @@ namespace FishNet.Object
|
|||||||
{
|
{
|
||||||
public partial class NetworkObject : MonoBehaviour
|
public partial class NetworkObject : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
#region Private.
|
||||||
|
/// <summary>
|
||||||
|
/// True if OnStartServer was called.
|
||||||
|
/// </summary>
|
||||||
|
private bool _onStartServerCalled;
|
||||||
|
/// <summary>
|
||||||
|
/// True if OnStartClient was called.
|
||||||
|
/// </summary>
|
||||||
|
private bool _onStartClientCalled;
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after all data is synchronized with this NetworkObject.
|
/// Called after all data is synchronized with this NetworkObject.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void InitializeCallbacks(bool asServer, bool invokeSyncTypeCallbacks)
|
private void InvokeStartCallbacks(bool asServer, bool invokeSyncTypeCallbacks)
|
||||||
{
|
{
|
||||||
/* Note: When invoking OnOwnership here previous owner will
|
/* Note: When invoking OnOwnership here previous owner will
|
||||||
* always be an empty connection, since the object is just
|
* always be an empty connection, since the object is just
|
||||||
@ -25,6 +36,7 @@ namespace FishNet.Object
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].OnStartServer_Internal();
|
NetworkBehaviours[i].OnStartServer_Internal();
|
||||||
|
_onStartServerCalled = true;
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].OnOwnershipServer_Internal(FishNet.Managing.NetworkManager.EmptyConnection);
|
NetworkBehaviours[i].OnOwnershipServer_Internal(FishNet.Managing.NetworkManager.EmptyConnection);
|
||||||
}
|
}
|
||||||
@ -33,12 +45,17 @@ namespace FishNet.Object
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].OnStartClient_Internal();
|
NetworkBehaviours[i].OnStartClient_Internal();
|
||||||
|
_onStartClientCalled = true;
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].OnOwnershipClient_Internal(FishNet.Managing.NetworkManager.EmptyConnection);
|
NetworkBehaviours[i].OnOwnershipClient_Internal(FishNet.Managing.NetworkManager.EmptyConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invokeSyncTypeCallbacks)
|
if (invokeSyncTypeCallbacks)
|
||||||
InvokeOnStartSyncTypeCallbacks(true);
|
InvokeOnStartSyncTypeCallbacks(true);
|
||||||
|
|
||||||
|
#if !PREDICTION_1
|
||||||
|
InvokeStartCallbacks_Prediction(asServer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -88,48 +105,35 @@ namespace FishNet.Object
|
|||||||
/// Invokes OnStop callbacks.
|
/// Invokes OnStop callbacks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="asServer"></param>
|
/// <param name="asServer"></param>
|
||||||
internal void InvokeStopCallbacks(bool asServer)
|
internal void InvokeStopCallbacks(bool asServer, bool invokeSyncTypeCallbacks)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
#if !PREDICTION_1
|
||||||
NetworkBehaviours[i].InvokeSyncTypeOnStopCallbacks(asServer);
|
InvokeStopCallbacks_Prediction(asServer);
|
||||||
|
#endif
|
||||||
|
if (invokeSyncTypeCallbacks)
|
||||||
|
InvokeOnStopSyncTypeCallbacks(asServer);
|
||||||
|
|
||||||
if (asServer)
|
bool invokeOnNetwork = (!asServer || (asServer && !_onStartClientCalled));
|
||||||
|
if (asServer && _onStartServerCalled)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].OnStopServer_Internal();
|
NetworkBehaviours[i].OnStopServer_Internal();
|
||||||
|
_onStartServerCalled = false;
|
||||||
}
|
}
|
||||||
else
|
else if (!asServer && _onStartClientCalled)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].OnStopClient_Internal();
|
NetworkBehaviours[i].OnStopClient_Internal();
|
||||||
|
_onStartClientCalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Several conditions determine if OnStopNetwork can
|
if (invokeOnNetwork)
|
||||||
* be called.
|
|
||||||
*
|
|
||||||
* - If asServer and pending destroy from clientHost.
|
|
||||||
* - If !asServer and not ServerInitialized. */
|
|
||||||
bool callStopNetwork;
|
|
||||||
if (asServer)
|
|
||||||
{
|
|
||||||
if (!IsClientStarted)
|
|
||||||
callStopNetwork = true;
|
|
||||||
else
|
|
||||||
callStopNetwork = (ServerManager.Objects.GetFromPending(ObjectId) == null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* When not as server only perform OnStopNetwork if
|
|
||||||
* not initialized for the server. The object could be
|
|
||||||
* server initialized if it were spawned, despawned, then spawned again
|
|
||||||
* before client ran this method. */
|
|
||||||
callStopNetwork = !IsServerInitialized;
|
|
||||||
}
|
|
||||||
if (callStopNetwork)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].InvokeOnNetwork(false);
|
NetworkBehaviours[i].InvokeOnNetwork(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -33,6 +33,10 @@ namespace FishNet.Object
|
|||||||
/// True if a reconcile is occuring on any NetworkBehaviour that is on or nested of this NetworkObject. Runtime NetworkBehaviours are not included, such as if you child a NetworkObject to another at runtime.
|
/// True if a reconcile is occuring on any NetworkBehaviour that is on or nested of this NetworkObject. Runtime NetworkBehaviours are not included, such as if you child a NetworkObject to another at runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsObjectReconciling { get; internal set; }
|
public bool IsObjectReconciling { get; internal set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Graphical smoother to use when using set for owner.
|
||||||
|
/// </summary>
|
||||||
|
public ChildTransformTickSmoother PredictionSmoother { get; private set; }
|
||||||
#endif
|
#endif
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Last tick this object replicated.
|
/// Last tick this object replicated.
|
||||||
@ -74,6 +78,28 @@ namespace FishNet.Object
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private Transform _graphicalObject;
|
private Transform _graphicalObject;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Gets the current graphical object for prediction.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Transform GetGraphicalObject() => _graphicalObject;
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a new graphical object for prediction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
public void SetGraphicalObject(Transform t)
|
||||||
|
{
|
||||||
|
_graphicalObject = t;
|
||||||
|
InitializeTickSmoother();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// True to detach and re-attach the graphical object at runtime when the client initializes/deinitializes the item.
|
||||||
|
/// This can resolve camera jitter or be helpful objects child of the graphical which do not handle reconiliation well, such as certain animation rigs.
|
||||||
|
/// Transform is detached after OnStartClient, and reattached before OnStopClient.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("True to detach and re-attach the graphical object at runtime when the client initializes/deinitializes the item. This can resolve camera jitter or be helpful objects child of the graphical which do not handle reconiliation well, such as certain animation rigs. Transform is detached after OnStartClient, and reattached before OnStopClient.")]
|
||||||
|
[SerializeField]
|
||||||
|
private bool _detachGraphicalObject;
|
||||||
|
/// <summary>
|
||||||
/// True to forward replicate and reconcile states to all clients. This is ideal with games where you want all clients and server to run the same inputs. False to only use prediction on the owner, and synchronize to spectators using other means such as a NetworkTransform.
|
/// True to forward replicate and reconcile states to all clients. This is ideal with games where you want all clients and server to run the same inputs. False to only use prediction on the owner, and synchronize to spectators using other means such as a NetworkTransform.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableStateForwarding => (_enablePrediction && _enableStateForwarding);
|
public bool EnableStateForwarding => (_enablePrediction && _enableStateForwarding);
|
||||||
@ -94,6 +120,29 @@ namespace FishNet.Object
|
|||||||
[SerializeField]
|
[SerializeField]
|
||||||
private byte _ownerInterpolation = 1;
|
private byte _ownerInterpolation = 1;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Properties of the graphicalObject to smooth when owned.
|
||||||
|
/// </summary>
|
||||||
|
[SerializeField]
|
||||||
|
private TransformPropertiesFlag _ownerSmoothedProperties = (TransformPropertiesFlag)~(-1 << 8);
|
||||||
|
/// <summary>
|
||||||
|
/// Interpolation amount of adaptive interpolation to use on non-owned objects. Higher levels result in more interpolation. When off spectatorInterpolation is used; when on interpolation based on strength and local client latency is used.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("Interpolation amount of adaptive interpolation to use on non-owned objects. Higher levels result in more interpolation. When off spectatorInterpolation is used; when on interpolation based on strength and local client latency is used.")]
|
||||||
|
[SerializeField]
|
||||||
|
private AdaptiveInterpolationType _adaptiveInterpolation = AdaptiveInterpolationType.Medium;
|
||||||
|
/// <summary>
|
||||||
|
/// Properties of the graphicalObject to smooth when the object is spectated.
|
||||||
|
/// </summary>
|
||||||
|
[SerializeField]
|
||||||
|
private TransformPropertiesFlag _spectatorSmoothedProperties = (TransformPropertiesFlag)~(-1 << 8);
|
||||||
|
/// <summary>
|
||||||
|
/// How many ticks to interpolate graphics on objects when not owned by the client.
|
||||||
|
/// </summary>
|
||||||
|
[Tooltip("How many ticks to interpolate graphics on objects when not owned by the client.")]
|
||||||
|
[Range(1, byte.MaxValue)]
|
||||||
|
[SerializeField]
|
||||||
|
private byte _spectatorInterpolation = 2;
|
||||||
|
/// <summary>
|
||||||
/// True to enable teleport threshhold.
|
/// True to enable teleport threshhold.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Tooltip("True to enable teleport threshhold.")]
|
[Tooltip("True to enable teleport threshhold.")]
|
||||||
@ -111,10 +160,6 @@ namespace FishNet.Object
|
|||||||
|
|
||||||
#region Private.
|
#region Private.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Graphical smoother to use when using set for owner.
|
|
||||||
/// </summary>
|
|
||||||
private LocalTransformTickSmoother _tickSmoother;
|
|
||||||
/// <summary>
|
|
||||||
/// NetworkBehaviours which use prediction.
|
/// NetworkBehaviours which use prediction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<NetworkBehaviour> _predictionBehaviours = new List<NetworkBehaviour>();
|
private List<NetworkBehaviour> _predictionBehaviours = new List<NetworkBehaviour>();
|
||||||
@ -125,16 +170,7 @@ namespace FishNet.Object
|
|||||||
if (!_enablePrediction)
|
if (!_enablePrediction)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_tickSmoother?.Update();
|
PredictionSmoother?.Update();
|
||||||
}
|
|
||||||
|
|
||||||
private void TimeManager_OnPreTick()
|
|
||||||
{
|
|
||||||
_tickSmoother?.OnPreTick();
|
|
||||||
}
|
|
||||||
private void TimeManager_OnPostTick()
|
|
||||||
{
|
|
||||||
_tickSmoother?.OnPostTick();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Prediction_Preinitialize(NetworkManager manager, bool asServer)
|
private void Prediction_Preinitialize(NetworkManager manager, bool asServer)
|
||||||
@ -146,19 +182,14 @@ namespace FishNet.Object
|
|||||||
_networkTransform.ConfigureForPrediction(_predictionType);
|
_networkTransform.ConfigureForPrediction(_predictionType);
|
||||||
|
|
||||||
ReplicateTick.Initialize(manager.TimeManager);
|
ReplicateTick.Initialize(manager.TimeManager);
|
||||||
|
if (!asServer)
|
||||||
InitializeSmoothers();
|
InitializeSmoothers();
|
||||||
|
|
||||||
if (asServer)
|
if (asServer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_predictionBehaviours.Count > 0)
|
if (_predictionBehaviours.Count > 0)
|
||||||
{
|
ChangePredictionSubscriptions(true, manager);
|
||||||
manager.PredictionManager.OnReconcile += PredictionManager_OnReconcile;
|
|
||||||
manager.PredictionManager.OnReplicateReplay += PredictionManager_OnReplicateReplay;
|
|
||||||
manager.PredictionManager.OnPostReconcile += PredictionManager_OnPostReconcile;
|
|
||||||
manager.TimeManager.OnPreTick += TimeManager_OnPreTick;
|
|
||||||
manager.TimeManager.OnPostTick += TimeManager_OnPostTick;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Prediction_Deinitialize(bool asServer)
|
private void Prediction_Deinitialize(bool asServer)
|
||||||
@ -170,13 +201,37 @@ namespace FishNet.Object
|
|||||||
/* Only the client needs to unsubscribe from these but
|
/* Only the client needs to unsubscribe from these but
|
||||||
* asServer may not invoke as false if the client is suddenly
|
* asServer may not invoke as false if the client is suddenly
|
||||||
* dropping their connection. */
|
* dropping their connection. */
|
||||||
if (_predictionBehaviours.Count > 0 && NetworkManager != null)
|
if (_predictionBehaviours.Count > 0)
|
||||||
|
ChangePredictionSubscriptions(false, NetworkManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes subscriptions to use callbacks for prediction.
|
||||||
|
/// </summary>
|
||||||
|
private void ChangePredictionSubscriptions(bool subscribe, NetworkManager manager)
|
||||||
{
|
{
|
||||||
NetworkManager.PredictionManager.OnReconcile -= PredictionManager_OnReconcile;
|
if (manager == null)
|
||||||
NetworkManager.PredictionManager.OnReplicateReplay -= PredictionManager_OnReplicateReplay;
|
return;
|
||||||
NetworkManager.PredictionManager.OnPostReconcile -= PredictionManager_OnPostReconcile;
|
|
||||||
NetworkManager.TimeManager.OnPreTick -= TimeManager_OnPreTick;
|
if (subscribe)
|
||||||
NetworkManager.TimeManager.OnPostTick -= TimeManager_OnPostTick;
|
{
|
||||||
|
manager.PredictionManager.OnPreReconcile += PredictionManager_OnPreReconcile;
|
||||||
|
manager.PredictionManager.OnReconcile += PredictionManager_OnReconcile;
|
||||||
|
manager.PredictionManager.OnReplicateReplay += PredictionManager_OnReplicateReplay;
|
||||||
|
manager.PredictionManager.OnPostReplicateReplay += PredictionManager_OnPostReplicateReplay;
|
||||||
|
manager.PredictionManager.OnPostReconcile += PredictionManager_OnPostReconcile;
|
||||||
|
manager.TimeManager.OnPreTick += TimeManager_OnPreTick;
|
||||||
|
manager.TimeManager.OnPostTick += TimeManager_OnPostTick;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
manager.PredictionManager.OnPreReconcile -= PredictionManager_OnPreReconcile;
|
||||||
|
manager.PredictionManager.OnReconcile -= PredictionManager_OnReconcile;
|
||||||
|
manager.PredictionManager.OnReplicateReplay -= PredictionManager_OnReplicateReplay;
|
||||||
|
manager.PredictionManager.OnPostReplicateReplay -= PredictionManager_OnPostReplicateReplay;
|
||||||
|
manager.PredictionManager.OnPostReconcile -= PredictionManager_OnPostReconcile;
|
||||||
|
manager.TimeManager.OnPreTick -= TimeManager_OnPreTick;
|
||||||
|
manager.TimeManager.OnPostTick -= TimeManager_OnPostTick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,25 +256,75 @@ namespace FishNet.Object
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_tickSmoother == null)
|
if (PredictionSmoother == null)
|
||||||
_tickSmoother = ResettableObjectCaches<LocalTransformTickSmoother>.Retrieve();
|
PredictionSmoother = ResettableObjectCaches<ChildTransformTickSmoother>.Retrieve();
|
||||||
float teleportT = (_enableTeleport) ? _teleportThreshold : MoveRatesCls.UNSET_VALUE;
|
InitializeTickSmoother();
|
||||||
_tickSmoother.InitializeOnce(_graphicalObject, teleportT, (float)TimeManager.TickDelta, _ownerInterpolation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the tick smoother.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeTickSmoother()
|
||||||
|
{
|
||||||
|
if (PredictionSmoother == null)
|
||||||
|
return;
|
||||||
|
float teleportT = (_enableTeleport) ? _teleportThreshold : MoveRatesCls.UNSET_VALUE;
|
||||||
|
PredictionSmoother.Initialize(this, _graphicalObject, _detachGraphicalObject, teleportT, (float)TimeManager.TickDelta, _ownerInterpolation, _ownerSmoothedProperties, _spectatorInterpolation, _spectatorSmoothedProperties, _adaptiveInterpolation);
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes tick smoothing.
|
/// Initializes tick smoothing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void DeinitializeSmoothers()
|
private void DeinitializeSmoothers()
|
||||||
{
|
{
|
||||||
if (_tickSmoother != null)
|
if (PredictionSmoother != null)
|
||||||
{
|
{
|
||||||
ResettableObjectCaches<LocalTransformTickSmoother>.StoreAndDefault(ref _tickSmoother);
|
PredictionSmoother.Deinitialize();
|
||||||
|
ResettableObjectCaches<ChildTransformTickSmoother>.Store(PredictionSmoother);
|
||||||
|
PredictionSmoother = null;
|
||||||
ResettableObjectCaches<RigidbodyPauser>.StoreAndDefault(ref _rigidbodyPauser);
|
ResettableObjectCaches<RigidbodyPauser>.StoreAndDefault(ref _rigidbodyPauser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void InvokeStartCallbacks_Prediction(bool asServer)
|
||||||
|
{
|
||||||
|
if (_predictionBehaviours.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!asServer)
|
||||||
|
PredictionSmoother?.OnStartClient();
|
||||||
|
}
|
||||||
|
private void InvokeStopCallbacks_Prediction(bool asServer)
|
||||||
|
{
|
||||||
|
if (_predictionBehaviours.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!asServer)
|
||||||
|
PredictionSmoother?.OnStopClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TimeManager_OnPreTick()
|
||||||
|
{
|
||||||
|
PredictionSmoother?.OnPreTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PredictionManager_OnPostReplicateReplay(uint clientTick, uint serverTick)
|
||||||
|
{
|
||||||
|
PredictionSmoother?.OnPostReplay(clientTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TimeManager_OnPostTick()
|
||||||
|
{
|
||||||
|
PredictionSmoother?.OnPostTick(NetworkManager.TimeManager.LocalTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PredictionManager_OnPreReconcile(uint clientTick, uint serverTick)
|
||||||
|
{
|
||||||
|
PredictionSmoother?.OnPreReconcile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PredictionManager_OnReconcile(uint clientReconcileTick, uint serverReconcileTick)
|
private void PredictionManager_OnReconcile(uint clientReconcileTick, uint serverReconcileTick)
|
||||||
{
|
{
|
||||||
if (!IsObjectReconciling)
|
if (!IsObjectReconciling)
|
||||||
|
|||||||
@ -337,9 +337,25 @@ namespace FishNet.Object
|
|||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
//Already being deinitialized by FishNet.
|
/* If already deinitializing then FishNet is in the process of,
|
||||||
|
* or has finished cleaning up this object. */
|
||||||
|
//callStopNetwork = (ServerManager.Objects.GetFromPending(ObjectId) == null);
|
||||||
if (IsDeinitializing)
|
if (IsDeinitializing)
|
||||||
|
{
|
||||||
|
/* There is however chance the object can get destroyed before deinitializing
|
||||||
|
* as clientHost. If not clientHost its safe to skip deinitializing again.
|
||||||
|
* But if clientHost, check if the client has deinitialized. If not then do
|
||||||
|
* so now for the client side. */
|
||||||
|
if (IsHostStarted)
|
||||||
|
{
|
||||||
|
if (!_onStartClientCalled)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Owner?.RemoveObject(this);
|
Owner?.RemoveObject(this);
|
||||||
NetworkObserver?.Deinitialize(true);
|
NetworkObserver?.Deinitialize(true);
|
||||||
@ -349,12 +365,12 @@ namespace FishNet.Object
|
|||||||
//Was destroyed without going through the proper methods.
|
//Was destroyed without going through the proper methods.
|
||||||
if (NetworkManager.IsServerStarted)
|
if (NetworkManager.IsServerStarted)
|
||||||
{
|
{
|
||||||
DeinitializePrediction_V2(true);
|
Deinitialize_Prediction(true);
|
||||||
NetworkManager.ServerManager.Objects.NetworkObjectUnexpectedlyDestroyed(this, true);
|
NetworkManager.ServerManager.Objects.NetworkObjectUnexpectedlyDestroyed(this, true);
|
||||||
}
|
}
|
||||||
if (NetworkManager.IsClientStarted)
|
if (NetworkManager.IsClientStarted)
|
||||||
{
|
{
|
||||||
DeinitializePrediction_V2(false);
|
Deinitialize_Prediction(false);
|
||||||
NetworkManager.ClientManager.Objects.NetworkObjectUnexpectedlyDestroyed(this, false);
|
NetworkManager.ClientManager.Objects.NetworkObjectUnexpectedlyDestroyed(this, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,9 +380,9 @@ namespace FishNet.Object
|
|||||||
* the server or client side, so send callbacks
|
* the server or client side, so send callbacks
|
||||||
* for both. */
|
* for both. */
|
||||||
if (IsServerStarted)
|
if (IsServerStarted)
|
||||||
InvokeStopCallbacks(true);
|
InvokeStopCallbacks(true, true);
|
||||||
if (IsClientStarted)
|
if (IsClientStarted)
|
||||||
InvokeStopCallbacks(false);
|
InvokeStopCallbacks(false, true);
|
||||||
|
|
||||||
/* If owner exist then remove object from owner.
|
/* If owner exist then remove object from owner.
|
||||||
* This has to be called here as well OnDisable because
|
* This has to be called here as well OnDisable because
|
||||||
@ -392,7 +408,7 @@ namespace FishNet.Object
|
|||||||
//Do not need to set state if being destroyed.
|
//Do not need to set state if being destroyed.
|
||||||
//Don't need to reset sync types if object is being destroyed.
|
//Don't need to reset sync types if object is being destroyed.
|
||||||
|
|
||||||
void DeinitializePrediction_V2(bool asServer)
|
void Deinitialize_Prediction(bool asServer)
|
||||||
{
|
{
|
||||||
#if !PREDICTION_1
|
#if !PREDICTION_1
|
||||||
Prediction_Deinitialize(asServer);
|
Prediction_Deinitialize(asServer);
|
||||||
@ -817,7 +833,7 @@ namespace FishNet.Object
|
|||||||
internal void Initialize(bool asServer, bool invokeSyncTypeCallbacks)
|
internal void Initialize(bool asServer, bool invokeSyncTypeCallbacks)
|
||||||
{
|
{
|
||||||
SetInitializedStatus(true, asServer);
|
SetInitializedStatus(true, asServer);
|
||||||
InitializeCallbacks(asServer, invokeSyncTypeCallbacks);
|
InvokeStartCallbacks(asServer, invokeSyncTypeCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -828,7 +844,7 @@ namespace FishNet.Object
|
|||||||
#if !PREDICTION_1
|
#if !PREDICTION_1
|
||||||
Prediction_Deinitialize(asServer);
|
Prediction_Deinitialize(asServer);
|
||||||
#endif
|
#endif
|
||||||
InvokeStopCallbacks(asServer);
|
InvokeStopCallbacks(asServer, true);
|
||||||
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
for (int i = 0; i < NetworkBehaviours.Length; i++)
|
||||||
NetworkBehaviours[i].Deinitialize(asServer);
|
NetworkBehaviours[i].Deinitialize(asServer);
|
||||||
|
|
||||||
@ -1025,35 +1041,35 @@ namespace FishNet.Object
|
|||||||
/// Returns if this NetworkObject is a scene object, and has changed.
|
/// Returns if this NetworkObject is a scene object, and has changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal ChangedTransformProperties GetTransformChanges(TransformProperties stp)
|
internal TransformPropertiesFlag GetTransformChanges(TransformProperties stp)
|
||||||
{
|
{
|
||||||
ChangedTransformProperties ctp = ChangedTransformProperties.Unset;
|
TransformPropertiesFlag tpf = TransformPropertiesFlag.Unset;
|
||||||
if (transform.localPosition != stp.Position)
|
if (transform.localPosition != stp.Position)
|
||||||
ctp |= ChangedTransformProperties.LocalPosition;
|
tpf |= TransformPropertiesFlag.Position;
|
||||||
if (transform.localRotation != stp.Rotation)
|
if (transform.localRotation != stp.Rotation)
|
||||||
ctp |= ChangedTransformProperties.LocalRotation;
|
tpf |= TransformPropertiesFlag.Rotation;
|
||||||
if (transform.localScale != stp.LocalScale)
|
if (transform.localScale != stp.LocalScale)
|
||||||
ctp |= ChangedTransformProperties.LocalScale;
|
tpf |= TransformPropertiesFlag.LocalScale;
|
||||||
|
|
||||||
return ctp;
|
return tpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns if this NetworkObject is a scene object, and has changed.
|
/// Returns if this NetworkObject is a scene object, and has changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal ChangedTransformProperties GetTransformChanges(GameObject prefab)
|
internal TransformPropertiesFlag GetTransformChanges(GameObject prefab)
|
||||||
{
|
{
|
||||||
Transform t = prefab.transform;
|
Transform t = prefab.transform;
|
||||||
ChangedTransformProperties ctp = ChangedTransformProperties.Unset;
|
TransformPropertiesFlag tpf = TransformPropertiesFlag.Unset;
|
||||||
if (transform.position != t.position)
|
if (transform.position != t.position)
|
||||||
ctp |= ChangedTransformProperties.LocalPosition;
|
tpf |= TransformPropertiesFlag.Position;
|
||||||
if (transform.rotation != t.rotation)
|
if (transform.rotation != t.rotation)
|
||||||
ctp |= ChangedTransformProperties.LocalRotation;
|
tpf |= TransformPropertiesFlag.Rotation;
|
||||||
if (transform.localScale != t.localScale)
|
if (transform.localScale != t.localScale)
|
||||||
ctp |= ChangedTransformProperties.LocalScale;
|
tpf |= TransformPropertiesFlag.LocalScale;
|
||||||
|
|
||||||
return ctp;
|
return tpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Editor.
|
#region Editor.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user